Place a click-and-collect order
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_idreferences 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_addressyou 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:
- Collection is created in
openwhen the FO is fulfilled. - Staff confirms the parcel is at the collection counter and the
Collection moves to
ready_to_collect. - OTP is sent to the customer's email.
- Customer presents the OTP; staff verifies; Collection moves to
collected. - 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_addressshould be provided for COLLECTION orders. If omitted, the order is still created but no Customer Collection entity will be created downstream. Sendingdelivery_addresson a COLLECTION order is ignored.- Pass the location by
partner_location_code(orpartner_location_id) rather than by full address. The service resolves the code to a Location, enriches the response with the full address, and populatespartner_location_idfor you. partner_order_referenceis 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_locationflag (set in the Dashboard); only Locations with this flag enabled can be used as a customer collection point.