Skip to main content
POST
Create Fulfillment
Creates a fulfillment record on the order and, when status is a terminal success state, automatically bumps order.status to shipped (or delivered). Shipping apps don’t need a second call to update the order — one POST writes the tracking number, courier, and status in a single request.
This endpoint is the write-back half of the live-rate flow. For the full lifecycle (quote → checkout pick → orders/create webhook → push to carrier → call this endpoint with the AWB), see Live Rate Providers and Build a shipping app.

When the order status changes

Each Fulfillment row represents one shipment. After every write, the platform recomputes coverage by summing lineItems[].quantity across all success-state Fulfillment rows for the order and updates order.status accordingly:
Coverageorder.status becomes
0% — no success fulfillments yetunchanged
> 0% but < 100% — some packages outpartial
100% — every ordered quantity shippedshipped (or delivered if the fulfillment status is delivered)
The order lifecycle is:
order.status is only mutated from pending, confirmed, paid, or partial. Manual overrides (shipped set by the merchant) and terminal states (canceled/delivered) are never trampled.

Multi-package orders

For orders that ship in multiple packages, POST one fulfillment per shipment and include only the items in that package in line_items. The platform tracks coverage per line_item.id:
Omitting line_items is the back-compat shortcut for single-shipment orders: the fulfillment is treated as covering everything, so a single POST flips order.status straight to shipped (skipping partial).

Path Parameters

order_id
string
required
The order ID

Body Parameters

status
string
default:"pending"
Initial fulfillment status. Set to success to immediately mark the shipment as out the door — this is what bumps order.status to shipped. Allowed: pending, open, success, cancelled, error, failure.
tracking_number
string
Carrier tracking number (e.g. AWB code).
tracking_company
string
Carrier name (e.g. "UPS", "FedEx", "USPS", "DHL", "Shiprocket").
tracking_url
string
Public, shopper-facing tracking URL. Must be a valid URL.
service_id
string
Optional. The ID of the fulfillment service that produced this shipment, returned by Create Fulfillment Service. Caching this on a shop metafield after registration avoids a list-call on every push.
line_items
array
Optional. Items being fulfilled in this shipment. Omit for single-shipment orders where every line item ships together.
notify_customer
boolean
default:"true"
Send shipment notification email to the customer.

Side effects

When the call succeeds:
  1. A fulfillment record is created on the order.
  2. If status triggers a status flip (see table above), order.status is updated in the same request.
  3. A fulfillments/create webhook is dispatched to every subscriber on the store (3-retry exponential backoff: 1m / 5m / 15m).

Required scope

write_orders

Request example

Response

order.status is not returned in this response — the order row is updated as a side effect. Re-fetch the order via Get Order if you need the new status in the same flow.