Call for Testing: WooCommerce Order Fulfillments

A beta guide to WooCommerce Order Fulfillments

We’re excited to announce the beta release of WooCommerce Order Fulfillments, a new core feature that helps merchants track shipments, manage partial fulfillments, and share shipping updates with customers.

This system combines a user-friendly interface for store owners and a robust API for developers, enabling programmatic control and extension.


What are fulfillments?

A fulfillment represents the process of shipping items from an order. Each fulfillment may include:

  • Items – products and quantities shipped.
  • Status – Draft (prepared) or Fulfilled (shipped).
  • Shipping Information – carrier, tracking number, tracking URL.
  • Metadata – custom shipment details.

Orders can have multiple fulfillments, making split or partial shipments simple and trackable.


Guide for store owners

Accessing fulfillments

  • Orders list – use the Fulfillment button in the “Fulfillment” column.
  • Order details page – open the fulfillments panel.

Creating a fulfillment

  1. Select which items to ship.
  2. Add tracking information (choose from 70+ providers or enter manually).
  3. Choose whether to Save as Draft (no customer notification) or Fulfill (customer is notified).

Managing fulfillments

  • Edit – update details or add tracking (customers can be notified if desired).
  • Delete – remove incorrect fulfillments. If it was marked fulfilled, customers may receive a cancellation email.

Fulfillment statuses

  • Draft – shipment prepared but not sent; no customer emails.
  • Fulfilled – shipment sent; customer notified by default.
  • Order-level status – calculated automatically:
    • No Fulfillments
    • Partially Fulfilled
    • Fulfilled

3rd-party extensions can add custom statuses.

Customer notifications

  • Customers can receive emails for new, updated, or canceled fulfillments.
  • Emails include shipment details, items, and tracking links.
  • Drafts never trigger notifications.

Automatic fulfillment of digital items

Automatic fulfillment of digital items can all be changed via the settings screen. The following settings are dynamic: 

  • Downloadable items are auto-fulfilled by default.
  • Virtual items can be set to auto-fulfill.
  • In mixed orders, digital items are fulfilled automatically while physical items remain pending.

Guide for developers

REST API reference

The fulfillments system provides a comprehensive REST API under the /wc/v3/orders/{order_id}/fulfillments namespace. Refer to the Fulfillments REST API doc for more information.

Available hooks and filters

Refer to Fulfillment Hooks for detailed information.

Architecture

  • Core classes – Fulfillment, FulfillmentsManager, FulfillmentsDataStore.
  • REST API – /wc/v3/orders/{order_id}/fulfillments.
  • React UI – with state in order/fulfillments data store.

Here are examples using PHP and React to help you extend and customize the feature:

PHP example

$fulfillment = new Fulfillment();

$fulfillment->set_entity_type( WC_Order::class );

$fulfillment->set_entity_id( 123 );

$fulfillment->set_status( 'fulfilled' );

$fulfillment->set_items( [ [ 'item_id' => 456, 'qty' => 2 ] ] );

$fulfillment->add_meta_data( '_tracking_number', '1Z999AA1234567890' );

$fulfillment->save();

JS example (frontend)

import { useSelect, useDispatch } from '@wordpress/data';

function MyComponent( { orderId } ) {

  const { fulfillments, isLoading } = useSelect( ( select ) => ({

    fulfillments: select( 'order/fulfillments' ).readFulfillments( orderId ),

    isLoading: select( 'order/fulfillments' ).isLoading( orderId ),

  }));

  const { saveFulfillment } = useDispatch( 'order/fulfillments' );

}

Extensibility

Order Fulfillments does allow for extensibility, particularly with the ability to:

  • Extend fulfillment statuses.
  • Override notification behavior.

Below is an example of extending your choice of a shipping provider:

Add a Custom Shipping Provider
class MyCustomShippingProvider extends AbstractShippingProvider {
    
    public function get_key(): string {
        return 'my_custom_provider';
    }
    
    public function get_name(): string {
        return 'My Custom Provider';
    }
    
    public function try_parse_tracking_number( string $tracking_number, string $shipping_from, string $shipping_to ): ?array {
        // Custom tracking number validation logic
        if ( $this->validate_tracking_format( $tracking_number ) ) {
            return array(
                'url' => "https://mycarrier.com/track/{$tracking_number}",
                'ambiguity_score' => 100,
            );
        }
        return null;
    }
    
    private function validate_tracking_format( string $tracking_number ): bool {
        // Your validation logic here
        return preg_match( '/^MC[0-9]{10}$/', $tracking_number );
    }
}

// Attach your custom shipping provider
add_filter( 'woocommerce_fulfillment_shipping_providers', function( $providers ) {
    $providers['my_custom_shipping_provider'] = MyCustomShippingProvider::class;
    return $providers;
});

Best practices

For store owners

  • Keep tracking numbers updated.
  • Use partial fulfillments for multi-package shipments.
  • Always verify carrier details before saving.

For developers

  • Validate fulfillment data before saving.
  • Wrap API calls in try/catch for error handling.
  • Respect user permissions.
  • Use batch operations for performance in bulk updates.

Troubleshooting

  • Fulfillment not saving? Check permissions, order ID, and data format.
  • Tracking not recognized? Verify format or enter provider manually.
  • No notifications sent? Ensure the “Notify Customer” toggle is on and WooCommerce email settings are correct.

Try it out

Order Fulfillments feature is available starting with WooCommerce 10.2. To enable the beta:

wp option update woocommerce_feature_fulfillments_enabled yes

Once enabled, the Fulfillment status column will appear in the Orders screen.


NOTE: A UI toggle to enable/disable this feature will be available in future releases.


Share Your Feedback

We’d love to hear how it works for you!

  • Join the GitHub Discussion
  • Drop by the WooCommerce Community Slack, channel #developer-chat

Not in Slack yet? Join here.

Special thanks to @tpaksu for the original guide that shaped this release.



9 responses to “Call for Testing: WooCommerce Order Fulfillments”

  1. Hey team,

    This sounds great and a very welcome change for core.

    Do you have a timeline for the beta and public release target? This will likely impact 1 or 2 of our WooCommerce extension plugins.

    We are in the process of organizing the remainder of 2025 and early 2026 development efforts. I’d love to get this on the map 😉

  2. Hi,
    Great that we are getting this new feature to core.
    One question. Is there no method for adding shipppment tacking other than
    $fulfillment->add_meta_data( ‘_tracking_number’, ‘1Z999AA1234567890’ );
    This seems very old school and does not promote type information and static checkers. I would rather have clear php api that has add/remove tracking number together with the shipping carrier, which would also make it more future proof.

    Thanks

    1. tahapaksu Avatar

      Hi Ignacy,

      Thank you for the review!

      Is there no method for adding shipppment tacking other than
      $fulfillment->add_meta_data( ‘_tracking_number’, ‘1Z999AA1234567890’ );

      This, and all other meta data used for fulfillments are saved as metadata, because we didn’t want to add constraints to this plugin, so everybody can utilize this new fulfillment system to match their needs. There are some helper functions in the Fulfillment entity that allow users to easily access information, such as get_items and set_items, set_fulfillment_status, etc. But we didn’t add more to allow other developers add their own. This feature is built as flexible as it can be, so others can add their own:

      shipment providers
      helper functions
      custom public and private metadata
      custom fulfillment statuses (other than “fulfilled” and “unfulfilled”)
      custom order fulfillment statuses (other than “fulfilled”, “partially fulfilled”, “unfulfilled”, “no fulfillments”)
      their own screens and workflows

      This is built this way because we wanted WooCommerce developers get as much as possible from this feature. The UI we added is just an example of what can be built with this API, and like you outlined, what others can do more with it. If you can check the tracking number parser system we added to the fulfillments drawer, you can see that we built some kind of validation, but we didn’t dictate that when saving the tracking number.

      Some developers may want to store associative arrays that contain all the tracking number information, such as the provider, link, possible delivery date, in the _tracking_number metadata, to show it in their UI, and this is possible by using their own entity type. and even the _tracking_number name isn’t a standard name for saving the tracking number. It can all be changed to what the developer building around the fulfillment feature needs.

      Hope it makes sense.

      Best regards, Taha

  3. Fantastic news!

    Partial shipments/tracking native in Woo 🙂

    Will start testing. Any ETA for production ready in the roadmap?

    1. Brian Coords Avatar
      Brian Coords

      Let us know how testing goes! Moving the feature out of beta will be dependent on how the testing and feedback goes, so no confirmed ETA yet.

  4. Will do. I assume the Github discussion the best place?

    1. Brian Coords Avatar
      Brian Coords

      Yes, definitely add any feedback on the Github discussion: https://github.com/woocommerce/woocommerce/discussions/60922

  5. Hey team, that’s a great feature, I’ve seen that this was under development before and wasn’t sure what to expect, so I built a custom fulfillment plugin/code for a store that needs certain fulfillment features, but I don’t see this replacing it. We would like to have something more native, but I didn’t see automatic splitting mentioned anywhere, different products might be available from different locations, so shop managers should normally only have the access to the orders they need to fulfill which requires splitting orders based on specific criteria. I know this is very specific, but it’s a common process for many stores and would be great to allow such flexibility.

    1. Shani Banerjee Avatar
      Shani Banerjee

      Hey Ali,

      Thank you for this feedback! If you are able to drop this into the discussion so other devs can join in and comment, that would be very helpful. Hoping to get feedback into GH directly so we can slice off nice-to-haves/future planning.

Leave a Reply

Your email address will not be published. Required fields are marked *