Delivery lifecycle
The order lifecycle has two related views:
- the order state returned by the Orders API; and
- normalized webhook events sent as fulfillment progresses.
Persist the First Delivery order.id returned by order creation. It is the stable correlation key across API reads, webhook payloads, provider attempts, and support investigations.
End-to-end lifecycle
Section titled “End-to-end lifecycle”ready_now is an event layered on the current lifecycle state. It does not replace status_v3. Refunded is also an event rather than an order lifecycle state.
Status and webhook mapping
Section titled “Status and webhook mapping”| Lifecycle meaning | Typical API status | Webhook status_v3 |
Legacy webhook status |
|---|---|---|---|
| Scheduled for later | scheduled |
scheduled |
Pending |
| Waiting for assignment | pending_assign |
— | Pending |
| Waiting for merchant acceptance | pending_merchant |
— | Pending |
| Courier assigned / travelling to pickup | en_route_pickup |
en_route_pickup |
Assigned |
| Courier at pickup | arrived_pickup |
arrived_pickup |
AtPickup |
| Picked up / travelling to customer | en_route_dropoff |
en_route_dropoff |
InTransit |
| Courier at customer | arrived_dropoff |
arrived_dropoff |
AtDestination |
| Delivered | completed |
completed |
Delivered |
| Cancelled | cancelled |
cancelled |
Cancelled |
| Provider changed after another attempt | commonly pending_assign until courier assignment |
reassign |
Reassign |
Not every provider emits every intermediate event. Driver, GPS, ETA, proof-of-delivery, and provider tracking fields are conditional.
The public Orders API normalizes several internal queue states: internal pending_dispatch, pending_reassign, and staging are exposed as pending_assign; internal pending_vendor becomes pending_merchant; and internal queued becomes scheduled. Raw internal state can appear separately as _status.
Internal pending_reassign does not always mean a second provider is being tried. It is also used after an external delivery is created while First waits for that provider to assign a courier. The reassign webhook event is narrower: it signals that the external provider delivery changed.
What your integration should do
Section titled “What your integration should do”- Save
order.id, yourexternal_id, and_request_id. - Acknowledge webhook requests quickly and process them asynchronously.
- Make webhook processing idempotent.
- Never assume webhook ordering or completeness.
- Reconcile critical workflows by reading the order after a webhook, timeout, or suspected gap.
- Treat
completedandcancelledas terminal unless a documentedreassignbegins a new provider lifecycle.
Cancellation
Section titled “Cancellation”Use the published cancel endpoint with the First Delivery order ID. Do not simulate cancellation by locally changing status.
Cancellation can be rejected after fulfillment has progressed too far. Provider-specific cutoffs differ, so persist the response and refetch the order before deciding whether to retry or escalate.
Reassignment
Section titled “Reassignment”Reassignment can occur after a provider release, a routing retry, or an enabled auto-reassign threshold. During a reassignment race, more than one provider attempt can temporarily exist for the same order. The first attempt that obtains a courier wins; First cancels the remaining active attempts.
Your integration should correlate by orderId, accept a later reassign as a new fulfillment lifecycle, and avoid treating repeated statuses as separate customer orders.
See Auto-routing strategies for provider selection and fallback behavior.

