WooCommerce Order Fulfillments API Setup Guide (2026)
Complete WooCommerce Order Fulfillments API setup guide with working code examples, partial shipment workflows, and carrier tracking for WooCommerce 10.5+
WooCommerce Order Fulfillments API Setup: Your First Implementation Guide
Beta feature; API endpoints may change before stable release. Last verified: WooCommerce 10.5.2
What the Fulfillments API Solves
Before WooCommerce 10.2, there was no native way to track individual shipments within an order. If a customer ordered three items and you shipped them in two boxes, your only options were unstructured order notes or third-party plugins. The WooCommerce Order Fulfillments API changes that.
Introduced as a beta in WooCommerce 10.2 (September 2025), the Fulfillments API provides dedicated REST endpoints at /wc/v3/orders/{order_id}/fulfillments for creating, managing, and tracking per-item shipments. It supports partial fulfillments, carrier tracking with over 70 built-in shipping providers, and extensible metadata. Here is how to set it up from scratch. For a broader overview of recent API changes, see WooCommerce 10.5 REST API changes.
Prerequisites and Feature Activation
You need WooCommerce 10.2 or later (10.5.2 is current as of February 2026). If you have completed your WooCommerce HPOS migration checklist, you are on the custom order tables architecture that the Fulfillments API builds upon. The API sits behind a feature flag with no admin UI toggle, so enable it via WP-CLI:
wp option update woocommerce_feature_fulfillments_enabled yes
Two other requirements before you make your first API call:
- Permalinks must be set to anything other than “Plain” (Settings > Permalinks). The REST API will not route correctly with plain permalinks.
- HTTPS is strongly recommended for any authenticated API requests.
Authentication Setup
The Fulfillments API uses standard WooCommerce REST API authentication. Generate API keys under WooCommerce > Settings > Advanced > REST API. Grant Read/Write permissions.
All examples in this guide use Basic Auth over HTTPS with your consumer key and secret:
curl -u "ck_your_consumer_key:cs_your_consumer_secret" \
https://example.com/wp-json/wc/v3/orders/123/fulfillments
For production, consider OAuth 1.0a or application passwords (see WooCommerce MCP protocol setup for similar authentication patterns). Never expose credentials in client-side code.
Creating Your First Fulfillment
This is the core workflow. Create a fulfillment by sending a POST request to an order’s fulfillment endpoint with line items and tracking metadata.
Here is a complete example that ships two units of item 456 from order 123 via UPS:
curl -X POST "https://example.com/wp-json/wc/v3/orders/123/fulfillments" \
-u "ck_your_consumer_key:cs_your_consumer_secret" \
-H "Content-Type: application/json" \
-d '{
"status": "fulfilled",
"items": [
{ "item_id": 456, "qty": 2 }
],
"meta_data": [
{ "id": 0, "key": "_tracking_number", "value": "1Z999AA1234567890" },
{ "id": 0, "key": "_shipment_provider", "value": "ups" },
{ "id": 0, "key": "_tracking_provider", "value": "ups" }
]
}'
Three details to note in this request:
id: 0is required on every metadata entry. Without it, metadata silently fails to persist. This is the most common mistake in community testing.- Set both
_shipment_providerand_tracking_providerto the same value. A known beta inconsistency means the admin UI reads from one key while the API reads from the other. Setting both ensures tracking displays correctly everywhere. item_idrefers to the order line item ID, not the product ID. Retrieve it from the order’sline_itemsarray viaGET /wc/v3/orders/123.
Verify your fulfillment was created:
curl -X GET "https://example.com/wp-json/wc/v3/orders/123/fulfillments" \
-u "ck_your_consumer_key:cs_your_consumer_secret"
The response returns an array of fulfillment objects with their statuses, items, and metadata.
Partial Shipment Workflow
Partial fulfillments are where this API delivers the most value. Consider a three-item order (items 456, 457, and 458) that ships in two packages.
Shipment 1 — Ship items 456 and 457 via UPS:
curl -X POST "https://example.com/wp-json/wc/v3/orders/123/fulfillments" \
-u "ck_your_consumer_key:cs_your_consumer_secret" \
-H "Content-Type: application/json" \
-d '{
"status": "fulfilled",
"items": [
{ "item_id": 456, "qty": 1 },
{ "item_id": 457, "qty": 1 }
],
"meta_data": [
{ "id": 0, "key": "_tracking_number", "value": "1Z999AA1111111111" },
{ "id": 0, "key": "_shipment_provider", "value": "ups" },
{ "id": 0, "key": "_tracking_provider", "value": "ups" }
]
}'
After this request, the order-level status transitions from No Fulfillments to Partially Fulfilled. WooCommerce calculates this automatically based on how many line items remain unfulfilled.
Shipment 2 — Ship the remaining item 458 via FedEx:
Send the same POST structure with item 458 and its FedEx tracking number. Once all items are accounted for, the order-level status moves to Fulfilled. Each fulfillment maintains its own tracking number, carrier, and metadata independently.
The two fulfillment statuses are draft (created but not shipped) and fulfilled (shipped). Order-level statuses (No Fulfillments, Partially Fulfilled, Fulfilled) are calculated automatically — you do not set them directly.
Adding Tracking Information
The Fulfillments API includes over 70 built-in shipping carriers. Use the provider’s slug in the _shipment_provider and _tracking_provider fields. Common slugs include ups, fedex, usps, dhl, royal-mail, and australia-post.
To check available providers, query the v4 providers endpoint:
GET /wc/v4/fulfillments/providers
For carriers not in the built-in list, register a custom provider with this filter:
add_filter( 'woocommerce_fulfillment_shipment_providers', function( $providers ) {
$providers['my_regional_carrier'] = MyRegionalCarrier::class;
return $providers;
} );
Important: Always set both _shipment_provider and _tracking_provider meta keys to the same value. This dual-key workaround addresses a known beta inconsistency where the admin order screen and REST API read from different keys.
Hooks for Custom Workflows
The Fulfillments API fires several hooks you can use to build custom order status automation. The most practical is woocommerce_fulfillments_after_fulfill, which fires after a fulfillment status changes to fulfilled:
add_action( 'woocommerce_fulfillments_after_fulfill', function( $fulfillment ) {
$order = wc_get_order( $fulfillment->get_entity_id() );
// Check if all items are fulfilled, then auto-complete:
// $order->update_status( 'completed' );
} );
This pattern lets you auto-complete orders when the final shipment goes out, or trigger downstream notifications to external systems via webhooks.
Known Issues and Workarounds
Four gotchas from community testing that will save you debugging time:
-
Metadata requires
id: 0. Everymeta_dataentry must include"id": 0or the data silently does not persist. This is the single most reported issue in the GitHub testing discussion. -
Dual meta key mismatch. The admin UI reads
_tracking_providerwhile other parts of the system read_shipment_provider. Set both to the same value until this is resolved in a future release. -
WP Activity Log conflict. If you use the WP Activity Log plugin, fulfillment creation may trigger errors or unexpected log entries. Disable fulfillment-related logging or update to the latest version of the plugin.
-
Carrier auto-detection edge cases. The tracking number parser uses an ambiguity scoring system to identify carriers. Overlapping formats (for example, DPD Romania and DHL) can occasionally misidentify the carrier. Explicitly setting the provider slug avoids this.
What to Watch Next
The Fulfillments API is still in beta, but the ecosystem is already moving. TrackShip for WooCommerce v1.9.8 (released February 10, 2026) became the first plugin to formally integrate with the native API. That is a strong signal that the feature is approaching stability.
Test in a staging environment and monitor the WooCommerce developer blog for graduation from beta. Once tracking data is flowing, integrate it with WooCommerce transactional email customization to surface tracking numbers in customer-facing emails. The entity_type and entity_id architecture hints at future expansion beyond orders — subscriptions and bookings are plausible candidates.
If you are building fulfillment workflows, start with the POST and GET patterns above, layer in partial shipments as needed, and use the hooks to connect fulfillment events to your order management process.
Sources & References
This article draws from authoritative sources including:
Official Documentation:
- Call for Testing: WooCommerce Order Fulfillments — Primary technical specification
- WooCommerce 10.2 Release Announcement — Feature introduction
- WooCommerce REST API Documentation — Authentication reference
- WooCommerce 10.5 Release Post — Current stable version
Community Resources:
- GitHub Discussion #60922: Order Fulfillments Testing — Developer testing feedback and bug reports
- TrackShip for WooCommerce Changelog — First plugin integration (v1.9.8)