Submit Fulfillment
POST/api/storefront/instances/:id/fulfillments/:id2/submit
Push one shipment to the store and wait for the answer. The path id (812 here) is the SKU.io SALES ORDER FULFILLMENT id — not the id of a row returned by the list endpoint. No request body.
This endpoint currently requires session authentication; Personal Access Token scope support is in progress.
What it sends: one create-fulfillment call against the mirrored store order, carrying the carrier, service, tracking number, tracking URL, shipped-at timestamp, and the SKU/quantity lines. Bundle components are folded back into the bundle SKU the buyer ordered, and lines without a SKU are dropped. Carrier and service come from the fulfilled (or requested) shipping method; for a manual shipment they are recovered from the free-text method label. A missing tracking URL is derived from the carrier when it can be.
On success (200): the shipment row is stored as submitted with submitted_at set and external_id taken from the store's answer, the SKU.io fulfillment is marked as submitted to the sales channel, and the store order gets an activity entry. The response data is the stored shipment row, in the same shape as a list row.
Idempotent on repeat: a shipment already recorded as submitted returns 200 with the existing row and the store is not called again.
On failure (422): the shipment row is stored as failed with the reason in error, and the response carries message (the reason) plus data — the stored row when one exists, or null when nothing could be recorded. data is null for: outbound tracking sync switched off for the connection, the sales order is not a store order, or the store order mirror is missing. data is the failed row for: no shippable lines with a SKU, the store refusing the shipment, and connection or store API errors.
Retrying: call the same endpoint again — a pending or failed shipment is re-sent (only a submitted one short-circuits), and a successful retry flips the row to submitted and clears error. Transport and rate-limit failures are worth retrying as-is; a rejection naming a SKU or an order needs the underlying data fixed first.
Requires the sales_orders.fulfill permission.
Authentication: Bearer token (session or PAT).
Request
Responses
- 200
- 401
- 403
- 404
- 422
- 429
OK
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden
Response Headers
Not found — no record with the given identifier (or the route does not exist). Verify the ID before retrying.
Unprocessable Entity
Response Headers
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.