The Fulfillment API lets a third-party logistics (3PL) or dropship supplier receive the orders routed to them, accept and ship them with tracking, and keep stock in sync. It follows Shopify’s FulfillmentOrder model and field names — if you’ve integrated with Shopify before, most of your code carries over.

The flow in five steps

1

Get your key

PlatformDTC issues you a scoped key (sq_agt_*) and a webhook secret. Scopes: read_assigned_fulfillment_orders, write_assigned_fulfillment_orders, write_fulfillments.
2

Register your service

POST /fulfillment_services with your callback_url. We auto-create a dedicated location for you; every order line routed to you becomes an assigned FulfillmentOrder.
3

Get notified

When a merchant requests fulfillment, we POST {callback_url}/fulfillment_order_notification with {"kind":"FULFILLMENT_REQUEST"} and fire the fulfillment_orders/fulfillment_request_submitted webhook. You then pull the details.
4

Accept & ship

Accept the request, then create a fulfillment with tracking. Partial shipments are supported.
5

Sync stock

Serve GET {callback_url}/fetch_stock (we poll it) or push levels via /inventory_levels/set.

Key concepts

  • FulfillmentOrder (FO) — one order is split into one or more FOs; each FO is the slice of line items assigned to your location. You only ever see FOs assigned to you.
  • statusopen · scheduled · in_progress · on_hold · incomplete · closed (fully shipped) · cancelled.
  • request_status — what the merchant is asking of you: unsubmitted · submitted (please fulfill) · accepted · rejected · cancellation_requested · cancellation_accepted · cancellation_rejected.
  • Fulfillment — a shipment you create against an FO. Multiple per FO (partials), each with tracking.

Conventions

  • Auth: X-Agent-Key: sq_agt_* (or Authorization: Bearer). See Authentication.
  • Idempotency: send Idempotency-Key: <uuid> on every POST — duplicates return the original result.
  • Envelope: { "success": true, "data": … } on success; { "success": false, "message": "…" } on error.
You only ever see and act on FulfillmentOrders assigned to your own service location — scope isolation is structural, enforced on top of your key’s scopes.

Multi-merchant suppliers

A fulfillment service is scoped to a single merchant by default — one merchant’s orders route to one supplier registration. Some suppliers serve multiple merchants on PlatformDTC from a single registration; this is set up by the PlatformDTC team during onboarding, not something you configure yourself. If that applies to you, every FO you pull carries merchant_id and store_id at the top level (same fields also appear on topic-webhook payloads) so you can tell tenants apart, and the lightweight callback body is extended with merchant_id, store_id, and fulfillment_order_id so you can route inbound pings without a pull — all additive, so per-merchant integrations can ignore them. Optional URL templating. If your callback_url contains {store_id}, {merchant_id} or {fulfillment_order_id}, those tokens are substituted per outgoing POST. A callback URL with no tokens is used verbatim (per-merchant clients are unaffected).
Bootstrapping is not self-serve. The initial sq_agt_* key + webhook_secret are minted by the PlatformDTC team; send us your callback_url and whether you’ll be receiving orders from more than one merchant.