Place a click-and-collect order

Updated May 29, 20263 min read

The COLLECTION variant of order ingestion. Instead of a delivery address, the order carries a customer collection address, the store or pickup point where the customer will collect the parcel. Carriyo's allocation engine treats the collection point as the target and produces a fulfillment order anchored there.

This is a single-endpoint recipe. The downstream Customer collection entity tracks the in-store handover and OTP verification. It is created by the Fulfillment App at fulfillment time, not at order create.

Scenario

A customer in London is buying a single pair of wireless earbuds for £79.99 and wants to collect them from the Acme Marylebone store the same evening. You send the order to Carriyo with delivery_method set to COLLECTION and a customer_collection_address pointing to the store. Carriyo produces a single fulfillment order at that store.

Prerequisites

  • API credentials: see Getting started for the one-time setup.
  • At least one collection point configured for the merchant: a Location with the customer-collection capability and inventory for the SKUs being ordered.
  • Auto-allocation enabled (the default).

Create the order

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": "COLLECTION",
    "order_date": "2026-05-10T13:42:00.000Z",
    "sales_channel": "web",
    "payment": {
      "currency": "GBP",
      "order_total": 79.99
    },
    "customer": {
      "contact_name": "Oliver Bennett",
      "contact_email": "oliver.bennett@example.co.uk",
      "contact_phone": "+44 7700 900123"
    },
    "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"
    },
    "customer_collection_address": {
      "partner_location_code": "STORE-UK-LON-MARYLEBONE"
    },
    "line_items": [
      {
        "product_id": "SKU-EAR-003",
        "sku": "SKU-EAR-003",
        "description": "Wireless Earbuds",
        "quantity": 1,
        "unit_price": 79.99
      }
    ]
  }'

The response carries the created Order with a single Fulfillment Order anchored at the collection point:

{
  "tenant": "your-tenant",
  "order_id": "OMP1B9C8D3EAYZ",
  "merchant": "ACME",
  "partner_order_reference": "YOUR_ORDER_REF",
  "order_date": "2026-05-10T13:42:00.000Z",
  "sales_channel": "web",
  "status": "allocated",
  "payment": {
    "currency": "GBP",
    "order_total": 79.99
  },
  "customer": {
    "contact_name": "Oliver Bennett",
    "contact_email": "oliver.bennett@example.co.uk",
    "contact_phone": "+44 7700 900123"
  },
  "customer_collection_address": {
    "partner_location_id": "ACCOUNT_a1b2c3d4-store-marylebone",
    "partner_location_code": "STORE-UK-LON-MARYLEBONE",
    "partner_location_name": "Acme Marylebone Store",
    "contact_name": "Acme Marylebone Store",
    "address1": "120 Marylebone High Street",
    "city": "London",
    "postcode": "W1U 4SD",
    "country": "GB"
  },
  "line_items": [
    { "id": "Q3R7T", "sku": "SKU-EAR-003", "quantity": 1, "unit_price": 79.99 }
  ],
  "fulfillment_orders": [
    {
      "fulfillment_order_id": "FOMP1B9C8VKGNHY",
      "location_id": "ACCOUNT_a1b2c3d4-store-marylebone",
      "status": "allocated",
      "delivery_method": "COLLECTION",
      "customer_collection_address": {
        "partner_location_id": "ACCOUNT_a1b2c3d4-store-marylebone",
        "partner_location_code": "STORE-UK-LON-MARYLEBONE",
        "partner_location_name": "Acme Marylebone Store",
        "contact_name": "Acme Marylebone Store",
        "address1": "120 Marylebone High Street",
        "city": "London",
        "postcode": "W1U 4SD",
        "country": "GB"
      },
      "line_items": [
        { "id": "Q3R7T", "quantity": 1, "status": "allocated" }
      ],
      "creation_date": "2026-05-10T13:42:01.205Z"
    }
  ],
  "creation_date": "2026-05-10T13:42:01.000Z"
}

What just happened

  • The Order was accepted and immediately moved to allocated.
  • Carriyo allocated the line item to the Marylebone store (location_id references the store's Location record), since the store is configured as a collection point and has the SKU in stock.
  • The FO carries the same customer_collection_address you submitted; downstream events (notifications, OTP send) use it.
  • No Shipment is created in this scenario: the parcel is already at the collection point. This is local collection.

For the remote collection variant, where stock lives at a warehouse and a Shipment carries it to the collection point, see Fulfillment orders → what a fulfillment order produces.

After this call

The customer collection entity (which tracks the in-store handover, OTP verification, and expiry) isn't created synchronously. It is created when the Fulfillment App completes packing and appears in open status. From that point the lifecycle is:

  1. Collection is created in open when the FO is fulfilled.
  2. Staff confirms the parcel is at the collection counter and the Collection moves to ready_to_collect.
  3. OTP is sent to the customer's email.
  4. Customer presents the OTP; staff verifies; Collection moves to collected.
  5. The line item closes, the FO closes, and the Order auto-closes.

The full lifecycle, OTP rules, and auto-expiry behavior are in Customer collection.

Pitfalls

  • customer_collection_address should be provided for COLLECTION orders. If omitted, the order is still created but no Customer Collection entity will be created downstream. Sending delivery_address on a COLLECTION order is ignored.
  • Pass the location by partner_location_code (or partner_location_id) rather than by full address. The service resolves the code to a Location, enriches the response with the full address, and populates partner_location_id for you.
  • partner_order_reference is the dedupe key. Re-sending the same value returns an error rather than upserting.
  • The collection point must be a collection-capable Location. Each Location carries a collection_location flag (set in the Dashboard); only Locations with this flag enabled can be used as a customer collection point.