Fulfillment tracks how an order is delivered after payment. A fulfillment covers a set of the order's line items and has a type: shipment, pickup, local_delivery, digital, or service. Create one with POST /v1/orders/{order_id}/fulfillments, then use its supported_actions to decide which command to offer next.
Every supported action maps directly to a command route on the fulfillment. Convert underscores to hyphens when building the route. For example, mark_ready maps to POST /v1/fulfillments/{fulfillment_id}/mark-ready. The full command set is accept, schedule, hold, start, mark_preparing, mark_picked, mark_packed, mark_ready, dispatch, fail, mark_no_show, complete, and cancel. schedule requires scheduled_start_at and scheduled_end_at. fail accepts release_quantity, which defaults to true, to decide whether the failed quantity becomes available for another fulfillment.
Command responses include the updated fulfillment and a status-change event. Buyer notifications are sent by default. Set buyer_notification_behavior to suppress when a command should not notify the buyer.
Physical shipping has three levels. A fulfillment holds one or more shipments, each shipment holds packages, and each package holds items that allocate order line-item quantities to that box. Create and manage item allocations under /v1/packages/{package_id}/items. A shipment can therefore split one fulfillment across multiple parcels without treating package items as unrelated top-level resources.
Carrier tracking belongs to packages. Create a shipment to group one carrier leg, then create one package per physical parcel. Put carrier, service_code, tracking_number, tracking_url, dimensions, weight, and label information on each package, including single-parcel shipments. A shipment can remain empty only as a created draft. Its read-only status and movement timestamps are derived from its package states. Package exceptions dominate the aggregate; otherwise the least advanced active package determines shipment progress.
A shipment also has a direction. Outbound is the default and carries goods to the buyer. A return shipment carries them back: set direction to return, then provide return_id and return_line_items, each allocating a whole-number quantity against a return_line_item_id on that Return. The two shapes do not mix. Direction is fixed at creation. List shipments by return_id to find the inbound leg for a return.
Use nested event ingestion for carrier and 3PL facts:
POST /v1/fulfillments/{fulfillment_id}/eventsPOST /v1/shipments/{shipment_id}/eventsPOST /v1/packages/{package_id}/events
Events accept observational types such as shipped, in_transit, out_for_delivery, delivered, delivery_attempted, tracking_updated, exception, returned, and custom. Use external_event_id for idempotent carrier ingestion, with external_system, external_status, occurred_at, and location details for provenance.
All observational events and command-driven status changes appear in one timeline at GET /v1/fulfillment-events. Filter it by order_id, fulfillment_id, shipment_id, package_id, or event_type. Status-change events include previous_status, current_status, quantity_effect, reason, and created_at, so no separate status-update resource is needed.
A package event such as delivered records carrier telemetry. It does not complete the fulfillment. Use the fulfillment's complete command when the merchant accepts that the obligation is discharged.
Order-level fulfillment_status distinguishes not_applicable for orders with nothing to fulfill and closed for obligations resolved through a mix of completed and canceled quantities.
Fulfillment also consumes inventory. Stock committed when an order is paid stays physically on hand until the handoff event for that fulfillment type. Canceling before handoff releases the claim without moving stock, and a refund alone never restocks anything. Returned units re-enter stock through Return operations.
Configure delivery methods and quote buyer choices in Delivery configuration.
