Tutorial: Create and Fulfill an Order
This walks the full order lifecycle over the API: create a customer, place a sales order for them, dispatch a fulfillment, then read the order back to confirm. It assumes you've done the Quickstart and have a token with customers:write and orders:write scopes.
Throughout, the base URL is your tenant domain — https://acme.sku.io/api in these examples. Substitute your own tenant and token.
1. Create the customer
If the customer already exists, skip to step 2 and use their id. Otherwise create one — this is POST /api/customers:
curl -X POST "https://acme.sku.io/api/customers" \
-H "Authorization: Bearer $SKU_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Smith",
"email": "jane.smith@example.com",
"address1": "456 Commerce Ave",
"city": "Los Angeles",
"province_code": "CA",
"zip": "90001",
"country_code": "US"
}'
The response envelope returns the new customer under data. Grab data.id — call it 87 — you'll reference it as the order's customer.
2. Create the sales order
Now place the order with POST /api/sales-orders. Reference the customer by id and add one or more line items by product SKU or id:
curl -X POST "https://acme.sku.io/api/sales-orders" \
-H "Authorization: Bearer $SKU_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"customer_id": 87,
"order_date": "07/08/2026",
"lines": [
{ "sku": "WDG-001", "quantity": 2, "price": 19.99 },
{ "sku": "WDG-002", "quantity": 1, "price": 12.50 }
]
}'
The response returns the created order. Note its id (say 1042) and its status. Dates use the app timezone in m/d/Y form on input — see Dates & Timezones for the full rule.
The exact accepted fields (discounts, shipping, tax, per-line metadata) are on the Create Sales Order reference. Only customer_id and at least one line are required for a basic order.
3. Fulfill the order
With stock allocated, dispatch a shipment using POST /api/sales-orders/{salesOrder}/fulfill. Fulfill the whole order or specific lines:
curl -X POST "https://acme.sku.io/api/sales-orders/1042/fulfill" \
-H "Authorization: Bearer $SKU_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"warehouse_id": 1,
"lines": [
{ "sku": "WDG-001", "quantity": 2 },
{ "sku": "WDG-002", "quantity": 1 }
]
}'
This creates a fulfillment (shipment) against the order and moves inventory. If a line can't be fully allocated you'll get a 422 explaining the shortfall — see Errors.
4. Read it back
Confirm the final state with GET /api/sales-orders/{salesOrder}:
curl "https://acme.sku.io/api/sales-orders/1042" \
-H "Authorization: Bearer $SKU_TOKEN" \
-H "Accept: application/json"
The order now shows its fulfillment status and shipment records. To poll the dispatch feed instead of a single order, use GET /api/fulfillment-orders.
Where to next
- Sync Inventory Levels — keep stock accurate after fulfillment
- Webhooks — get pushed order and shipment events instead of polling step 4
- Sales Orders reference — every order endpoint, including discounts, credits, and OCR