Place a home delivery order

Updated May 29, 20263 min read

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 with inventory for the SKUs being ordered.
  • Auto-allocation enabled for the merchant (the default). With auto-allocation off, the order would land in open and wait for manual allocation, see Allocation engine.

Create the order

Submit the order to Carriyo. No delivery_option is set: Carriyo allocates against inventory without a customer-chosen delivery option.

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": [
      {
        "product_id": "SKU-EAR-003",
        "sku": "SKU-EAR-003",
        "description": "Wireless Earbuds",
        "quantity": 1,
        "unit_price": 79.99
      },
      {
        "product_id": "SKU-CBL-004",
        "sku": "SKU-CBL-004",
        "description": "USB-C Cable",
        "quantity": 1,
        "unit_price": 12.99
      }
    ]
  }'

The response carries the created Order with allocation already applied. The two items are both available at the London warehouse, 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"
  },
  "delivery_address": {
    "contact_name": "Oliver Bennett",
    "address1": "45 Gloucester Place",
    "address2": "Marylebone",
    "city": "London",
    "postcode": "W1U 8HU",
    "country": "GB"
  },
  "line_items": [
    { "id": "K7M3X", "sku": "SKU-EAR-003", "quantity": 1, "unit_price": 79.99 },
    { "id": "P9N4R", "sku": "SKU-CBL-004", "quantity": 1, "unit_price": 12.99 }
  ],
  "fulfillment_orders": [
    {
      "fulfillment_order_id": "FOMP1A8B7VJAMFZ",
      "location_id": "ACCOUNT_b5c325c0-edeb-4559-803c-d1b0ca3ec9c2",
      "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 both line items in stock at one fulfillment location (the London warehouse), so it produced a single fulfillment order, the simplest possible outcome.
  • Both line items are in allocated status under the FO and will move to processing and then fulfilled as the warehouse picks, packs, and ships them.
  • The FO will produce a shipment when it's booked with a carrier.

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, if the earbuds are in stock at the London warehouse and the cable is only in stock at the Manchester warehouse, the fulfillment_orders array would contain two entries:

"fulfillment_orders": [
  {
    "fulfillment_order_id": "FOMP1A8B7VJAMFZ",
    "location_id": "ACCOUNT_b5c325c0-edeb-4559-803c-d1b0ca3ec9c2",
    "status": "allocated",
    "delivery_method": "DELIVERY",
    "delivery_address": { /* same shipping address */ },
    "line_items": [{ "id": "K7M3X", "quantity": 1, "status": "allocated" }]
  },
  {
    "fulfillment_order_id": "FOMP1A8B7XJ9YZ2",
    "location_id": "ACCOUNT_64c72d0e-19f5-4ec1-b572-d51c97688606",
    "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_reference is 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_mode enum. Express cash-on-delivery by setting payment.payment_on_delivery to 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 is partially_allocated rather than allocated. Listen for the order webhook and send the unallocated lines to ops.