Customer collection

Updated September 28, 20266 min read

A customer collection is the entity that represents a customer picking up their order in person at one of your locations. It tracks the parcel from when it's ready at the collection point through to handover. OTP verification confirms who physically receives the goods.

A collection is the pickup counterpart of a shipment. A delivery order ends in a shipment that a carrier moves to the customer; a collection order ends in a collection the customer picks up in person. Each marks the end of fulfillment for its delivery method.

A customer collection always belongs to a fulfillment order with delivery_method = COLLECTION. The two entities are split because they answer different questions:

  • The fulfillment order says which lines, from which location, going to which collection point.
  • The customer collection says the parcel is ready, the customer has been verified, the handover happened.

The model

A collection carries:

  • collection_id. Unique identifier, prefixed COL_ (e.g. COL_58).
  • status. The lifecycle state (see below).
  • partner_location_id. The Carriyo location id of the collection point: the fulfilling location for a local collection, the location the parcel was shipped to for a remote one.
  • address. The collection point address, copied from the fulfillment order's customer_collection_address.
  • packages. The parcels available for pickup, copied from the pack that created this collection.
  • customer. Name, phone, and email of the person collecting. The email is where the OTP is sent.
  • verification. The OTP verification state: method (always OTP), status (pending, verified, or overridden), and when it was verified.
  • pack_id. The pack that created this collection.
  • customer_collection_schedule. The customer's preferred pickup window, copied from the fulfillment order.
  • notes and carriyo_metadata. Free-text notes and custom key-value pairs.

Creation triggers

A customer collection is created automatically when a pack completes: one per fulfillment order whose delivery_method is COLLECTION and that carries a customer_collection_address. There is no create endpoint.

The two collection scenarios from the Fulfillment orders page both produce one collection:

  • Local collection. The customer collects at the fulfilling location, which is also the collection point. No shipment is created.
  • Remote collection. The parcel is shipped from the fulfilling location to another location, and the customer collects it there. The pack creates that shipment before it completes, and the collection tracks the handover.

A COLLECTION fulfillment order without a customer_collection_address needs no shipment, but it never gets a collection.

Lifecycle states

A customer collection moves through five states:

open ─▶ ready_to_collect ─▶ collected
  ▲           │
  │ reopen    ├─▶ expired ─▶ cancelled (auto)
  └───────────┤      ▲
              │      │  unexpire
              │      ▼
              └─▶ cancelled (manual)
StatusMeaning
openCreated but not yet at the collection point. The location is still preparing the parcel or it's in transit.
ready_to_collectAt the collection point. The customer can be notified and verified.
collectedHanded over to the customer. Terminal: success.
expiredThe customer didn't collect within the configured window. Recoverable via unexpire if they show up late.
cancelledEither explicitly cancelled or auto-cancelled after expiry. Terminal.

Transitions

FromToTrigger
openready_to_collectPOST /orders/collections/{collectionId}/ready. Staff confirm the parcel is at the counter.
ready_to_collectcollectedPOST /orders/collections/{collectionId}/verification/verify-and-collect. Successful OTP verification, or staff override.
ready_to_collectexpiredAuto-expire scheduler (see below).
ready_to_collectopenPOST /orders/collections/{collectionId}/reopen. The parcel is no longer at the counter; the ready date is cleared and verification is reset to pending.
expiredready_to_collectPOST /orders/collections/{collectionId}/unexpire. Customer turned up late, give them another window.
expiredcancelledAuto-cancel scheduler (see below).
open, ready_to_collect, expiredcancelledPOST /orders/collections/{collectionId}/cancel. Manual cancellation with optional cancellation_reason.

OTP verification

Handover is gated on OTP verification, and there is no setting to turn it off. The flow:

  1. Send OTP. POST /orders/collections/{collectionId}/verification/send-otp generates a 6-digit code and emails it to the customer. The response includes masked_email and otp_expires_at so staff can see where the code went without seeing the address.
  2. Verify and collect. POST /orders/collections/{collectionId}/verification/verify-and-collect accepts the OTP from the customer. On match, the collection moves to collected.
  3. Override. Same endpoint with override = true and no OTP. For staff exceptions where the customer can prove identity but can't access the OTP. An OTP must still have been sent first; the endpoint refuses when no verification is in progress. Recorded as verification.status = overridden for audit. If a request carries both an OTP and override = true, the override wins and the OTP isn't checked. override defaults to false.

Constraints baked into the verification flow:

  • 6 digits.
  • 5-minute expiry from send.
  • After 5 failed attempts, every further verify is refused until a new OTP is sent. Sending again issues a fresh code and resets the counter.
  • 60-second cooldown between sends.
  • The collection must be in ready_to_collect for both send and verify-and-collect.

A customer with no email can never be collected. Send OTP needs the email, and verify-and-collect, override included, needs the verification that only Send OTP creates. There is no other way to reach collected, so make sure collection orders carry a customer email.

Auto-expiry and auto-cancellation

Four order management settings govern the unattended timers:

SettingEffect
customer_collection_auto_expire_enabledWhen on, a ready_to_collect collection moves to expired after customer_collection_auto_expire_days days (default 7 when unset).
customer_collection_auto_cancel_enabledWhen on, an expired collection moves to cancelled after customer_collection_auto_cancel_days days (no default; unset or zero skips auto-cancel). Has no effect unless auto-expire is also on.

Both flags are checked again when a timer fires. A timer scheduled while a flag was on does nothing if the flag is off by then. If the customer turns up after expiry, unexpire puts the collection back into ready_to_collect and re-schedules auto-expiry.

How the order closes after handover

When a collection is collected, Carriyo checks the parent fulfillment-order line items. Cancelling a collection does not close anything:

Collection eventLine-item effect
Collected (OTP verified or overridden)If every collection the line item belongs to is now collected or cancelled, the line item moves to closed.
CancelledNo line-item change: the line items stay fulfilled, and no new collection can be created for them. The collection's verification state and timers are cleared.

A line item can belong to more than one collection. It closes only when every one of them is collected or cancelled, and that check runs on collect, not on cancel. An order stays open while any customer still has goods to collect.

No collection operation sends an order webhook, collecting included. The only message Carriyo sends is the OTP email, so poll the order or read the collection to follow a handover.

Lookup endpoints vs full record

Lookups by order, fulfillment order and pack return only collection_id, tenant, partner_location_id, status and creation_date per collection; use GET /orders/collections/{collectionId} for the full record.

How it fits with other modules

  • Fulfillment orders. Every customer collection belongs to a delivery_method = COLLECTION fulfillment order.
  • Order lifecycle. A collected collection closes its fulfillment order's line items, which the order status follows.
  • Locations. The collection point is a location with the collection_location flag on.
  • Click and collect. The upstream checkout flow that produces a COLLECTION order.