Fulfillment endpoints cover the path from an accepted order to a package ready to go out: preparation, carrier selection, label generation, and tracking updates. There are two families:
Per order (/orders/{orderId}/prepare, /orders/{orderId}/fulfill): built for interactive flows, one order at a time.
Batch (/orders/fulfillment/*): built to process many orders in a single call, typically from the merchant dashboard or a scheduled task.
Response envelope
Every successful single-resource response follows { "data": {...} }; lists use { "data": [...], "meta": { "pagination": {...} } }. Errors are always { "error": { "code", "message", "details?" } } with namespace:snake_case codes (e.g. orders:cannot_fulfill).
For post-shipment events (marking as delivered, uploading delivery evidence, attaching an external label) see Delivery and Shipping.
Despite what the name suggests, items is not optional: at least one element with itemIndex and quantityToPrepare is required. Sending an empty array or only a list of SKUs is rejected.
Marks the indicated items as fulfilled. Does not accept tracking information directly.
orderIdstringrequired
Order ID
itemsstring[]required
Identifiers of the items to mark as fulfilled. Minimum 1 element.
{ "items": ["65f3a1b2c4d5e6f7a8b9c0e0"]}
204No body
(no content)
Required permission:orders:fulfill
204 No Content — no body
This endpoint always responds with 204 No Content and no body. It does not include trackingNumber or carrier in the request or the response — those fields don't exist on this endpoint. To attach tracking, use POST /orders/fulfillment/tracking or POST /orders/{orderId}/attach-shipment.
Each capabilities object carries more flags beyond the ones shown above (around 13 fields per order in total). The ones listed here are confirmed; for the exhaustive list, check with support before depending on an undocumented field.
format and size travel inside options, not at the root of the body: { "orderIds": [...], "options": { "format": "zpl", "size": "small" } }.
Shape of labels[] not audited in detail
summary is confirmed exactly as shown. The exact shape of each element in labels[] (and the optional mergedLabel field) was not audited field-by-field against the source code — confirm the exact contract with support before depending on a specific field inside each result.
Inside tracking, only trackingNumber is required; carrierId, carrierName, and trackingUrl are optional.
This endpoint processes a batch, not a single order
The body is not{ "orderId", "trackingNumber", "carrier" } at the root level — it's an updates[] array, and the tracking information is nested under the tracking key. The field carrier (on its own) does not exist on this endpoint.
Returns the available carriers, depending on how you query it: by orders, by channel, or the default catalog.
orderIdsstring[]
Order IDs — if you send these, the response is resolved per order.
channelTypestring
Channel type — if you send this (without orderIds), the response is resolved per channel.
credentialsobject
Map of channelId → credentials, for orchestrated use.
{ "orderIds": ["65f3a1b2c4d5e6f7a8b9c0d1"]}
200
{ "data": { "mode": "by-orders" }}
Required permission:orders:read
Response shape discriminated by mode
All parameters are optional. The exact shape of the response depends on the resolved mode (by-orders, by-channel, or default) and was not audited field-by-field for each variant — the mode field is confirmed as the discriminator. Before parsing the response programmatically, validate the shape of each mode with support.