Place a home delivery order
The foundational order-ingestion flow. Your storefront posts a customer order to Carriyo with a single delivery method and address. Carriyo's allocation engine picks the fulfillment location and returns the resulting order with its fulfillment orders attached. No checkout-side delivery option, no collection method: just standard home delivery.
Scenario
A customer in London is buying two accessories, a pair of
wireless earbuds and a USB-C cable, total £92.98. You send the order to
Carriyo with a delivery_method of DELIVERY and a
single shipping address. Carriyo's allocation engine has both
items in stock at the London warehouse and produces a single
fulfillment order.
Prerequisites
- API credentials: see Getting started for the one-time setup.
- At least one fulfillment location configured for the merchant
whose coverage (
fulfillment_zonesorfulfillment_radius) includes the delivery address. With inventory management enabled, it also needs stock for the SKUs being ordered. - Automatic allocation enabled in the tenant's order management
settings (
enable_automatic_order_allocation). It is off until those settings are created. With it off, the order is created inopen, its fulfillment order carries afulfillment_location_missingerror, and it waits for manual allocation. See Allocation engine.
Create the order
Submit the order to Carriyo. No delivery_option is set: Carriyo
allocates on location coverage (and stock, when inventory management
is on) without a customer-chosen delivery option. Identify each
product by sku or product_ref; Carriyo fills in its own
product_id on the response.
curl -X POST 'https://api.carriyo.com/orders' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'tenant-id: YOUR_TENANT_ID' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"merchant": "ACME",
"partner_order_reference": "YOUR_ORDER_REF",
"delivery_method": "DELIVERY",
"order_date": "2026-05-10T09:15:22.000Z",
"sales_channel": "web",
"payment": {
"currency": "GBP",
"order_total": 92.98
},
"customer": {
"contact_name": "Oliver Bennett",
"contact_email": "oliver.bennett@example.co.uk",
"contact_phone": "+44 7700 900123"
},
"delivery_address": {
"contact_name": "Oliver Bennett",
"contact_email": "oliver.bennett@example.co.uk",
"contact_phone": "+44 7700 900123",
"address1": "45 Gloucester Place",
"address2": "Marylebone",
"city": "London",
"country": "GB",
"postcode": "W1U 8HU"
},
"billing_address": {
"contact_name": "Oliver Bennett",
"contact_email": "oliver.bennett@example.co.uk",
"contact_phone": "+44 7700 900123",
"address1": "45 Gloucester Place",
"address2": "Marylebone",
"city": "London",
"country": "GB",
"postcode": "W1U 8HU"
},
"line_items": [
{
"sku": "SKU-EAR-003",
"description": "Wireless Earbuds",
"quantity": 1,
"unit_price": 79.99
},
{
"sku": "SKU-CBL-004",
"description": "USB-C Cable",
"quantity": 1,
"unit_price": 12.99
}
]
}'
The response, abridged here, is the created order with allocation already applied. The London warehouse covers the address and holds both items, so Carriyo produces a single fulfillment order:
{
"tenant": "your-tenant",
"order_id": "OMP1A8B7C2D9KZ",
"merchant": "ACME",
"partner_order_reference": "YOUR_ORDER_REF",
"order_date": "2026-05-10T09:15:22.000Z",
"sales_channel": "web",
"status": "allocated",
"payment": {
"currency": "GBP",
"order_total": 92.98
},
"customer": {
"contact_name": "Oliver Bennett",
"contact_email": "oliver.bennett@example.co.uk",
"contact_phone": "+44 7700 900123"
},
"line_items": [
{ "id": "K7M3X", "sku": "SKU-EAR-003", "product_ref": "SKU-EAR-003", "product_id": "PDTHDMCY4YN4Z7L0Q", "quantity": 1, "unit_price": 79.99 },
{ "id": "P9N4R", "sku": "SKU-CBL-004", "product_ref": "SKU-CBL-004", "product_id": "PDTHDMCY4YN4Z7L0R", "quantity": 1, "unit_price": 12.99 }
],
"fulfillment_orders": [
{
"fulfillment_order_id": "FOMP1A8B7VJAMFZ",
"fulfillment_location": {
"partner_location_id": "ACCOUNT_b5c325c0-edeb-4559-803c-d1b0ca3ec9c2",
"partner_location_code": "LDN-WH-01",
"partner_location_name": "London Warehouse"
},
"status": "allocated",
"delivery_method": "DELIVERY",
"delivery_address": {
"contact_name": "Oliver Bennett",
"address1": "45 Gloucester Place",
"address2": "Marylebone",
"city": "London",
"postcode": "W1U 8HU",
"country": "GB"
},
"line_items": [
{ "id": "K7M3X", "quantity": 1, "status": "allocated" },
{ "id": "P9N4R", "quantity": 1, "status": "allocated" }
],
"creation_date": "2026-05-10T09:15:23.105Z"
}
],
"creation_date": "2026-05-10T09:15:23.000Z"
}
What just happened
- The order was accepted and immediately moved to
allocated. - The allocation engine found one fulfillment location covering the address that can supply both line items (the London warehouse). It produced a single fulfillment order, the simplest possible outcome.
- Both line items are in
allocatedstatus under the FO and will move through the pick and pack statuses tofulfilledas the warehouse picks, packs, and ships them. - Fulfilling the FO creates and books its shipment.
Variation: items split across locations
The request you send is identical, but the response can change if
no single location has stock for every line item. In that case the
allocation engine produces multiple fulfillment orders, one
per chosen location. For example, say the earbuds are in stock at
the London warehouse and the cable only at the Manchester
warehouse. The fulfillment_orders array would then contain
two entries:
"fulfillment_orders": [
{
"fulfillment_order_id": "FOMP1A8B7VJAMFZ",
"fulfillment_location": {
"partner_location_id": "ACCOUNT_b5c325c0-edeb-4559-803c-d1b0ca3ec9c2",
"partner_location_code": "LDN-WH-01",
"partner_location_name": "London Warehouse"
},
"status": "allocated",
"delivery_method": "DELIVERY",
"delivery_address": { /* same shipping address */ },
"line_items": [{ "id": "K7M3X", "quantity": 1, "status": "allocated" }]
},
{
"fulfillment_order_id": "FOMP1A8B7XJ9YZ2",
"fulfillment_location": {
"partner_location_id": "ACCOUNT_64c72d0e-19f5-4ec1-b572-d51c97688606",
"partner_location_code": "MAN-WH-01",
"partner_location_name": "Manchester Warehouse"
},
"status": "allocated",
"delivery_method": "DELIVERY",
"delivery_address": { /* same shipping address */ },
"line_items": [{ "id": "P9N4R", "quantity": 1, "status": "allocated" }]
}
]
Both FOs ship to the same address (the customer didn't ask for
two destinations) but originate from different warehouses, so
each will produce its own shipment. The order itself remains a
single record with status: allocated.
How splits are decided is covered on the Allocation engine page; Splits and merges explains the downstream consequences.
Pitfalls
partner_order_referenceis the dedupe key. Re-sending the same value returns an error rather than upserting. Generate it deterministically per customer order and reuse it on retries.- Payment is amount-based, not mode-based. Orders don't carry
a
payment_modeenum. Express cash-on-delivery by settingpayment.payment_on_deliveryto the amount due at delivery (omit or leave at zero for fully prepaid orders). - Allocation can land in
partially_allocated. If some items can be allocated and others can't (e.g. stock-out), the Order status ispartially_allocatedrather thanallocated. Listen for the order webhook and send the unallocated lines to ops.