Register a fulfillment service

POST /fulfillment_services
Returns the service with its auto-created location_id. Manage with GET /fulfillment_services, PUT /fulfillment_services/{id}, DELETE /fulfillment_services/{id}.
supplier_id is the routing key. Any paid order line whose product (or variant) is tagged with this same supplier_id is automatically assigned to your service’s location and submitted to you as a FulfillmentOrder. Set it at registration (or later via PUT); the merchant tags their products with the matching value. Omit it and your service receives only lines a merchant manually moves to your location.

Pull assigned work

GET /assigned_fulfillment_orders?assignment_status=fulfillment_requested&limit=50&cursor=… assignment_statusfulfillment_requested · cancellation_requested · fulfillment_accepted · fulfillment_unsubmitted. Only FOs assigned to your own location are returned.
Per line item, product_title, image_url, option1..3 and option_names are joined from product.product + product.product_variant so a 3PL can source/purchase without a second API call. option_names labels what option1..3 hold (e.g. ["Color","Size"], positionally aligned — option_names[0] names option1) so you don’t have to guess which column is which. title / sku remain the order-time snapshot (never mutated after the order was placed); the enrichment fields reflect the CURRENT product state (rename-safe on your side).At the FO top level, merchant_id and store_id let a supplier receiving orders from more than one merchant demux inbound FOs per tenant. Per-merchant integrations can ignore both — they are additive to the previous shape.
GET /fulfillment_orders/{id} returns a single FO. The supported_actions array tells you exactly what’s allowed in the current state.

Sandbox: create a test order

POST /test_orders (no body) Spins up a sandbox assigned FulfillmentOrder against your own location so you can exercise the whole loop without a real order or payment — no merchant order is created.
The test FO carries a TEST-SKU-001 line at request_status: submitted — pull it like any other FO (above), then accept and ship it. Call again any time for a fresh test order. Clean up when you’re done. DELETE /test_orders removes every sandbox order you created (and their fulfillments) in one call. Real orders are never touched.

Accept

POST /fulfillment_orders/{id}/fulfillment_request/accept
Moves the FO to request_status: accepted, status: in_progress. You can now create fulfillments.

Reject

POST /fulfillment_orders/{id}/fulfillment_request/reject
The FO returns to the merchant (status: open). Valid reason values: incorrect_address · incorrect_product_info · ineligible_product · international_shipping_unavailable · invalid_contact_information · invalid_sku · inventory_out_of_stock · merchant_blocked_or_suspended · missing_customs_info · order_too_large · package_preference_not_set · payment_declined · undeliverable_destination · other.

Cancellation handshake

If a merchant requests cancellation of an accepted FO, you receive a {"kind":"CANCELLATION_REQUEST"} callback and the FO appears under assignment_status=cancellation_requested. Respond with:
  • POST /fulfillment_orders/{id}/cancellation_request/accept → FO cancelled.
  • POST /fulfillment_orders/{id}/cancellation_request/reject → FO returns to in_progress.

State machine