Delivery status now reports the delivery lifecycle

The top-level status field on delivery responses now reports the delivery lifecycle — the same vocabulary emitted by pickup_status.changed webhooks — instead of the internal order state machine. This resolves a long-standing inconsistency where the GET endpoint could report PENDING while webhooks were progressing through ASSIGNED, EN_ROUTE_TO_STORE, and beyond.

What changed

  • POST /dd/v1/deliveries now returns status: "SCHEDULED" for a newly created delivery (previously "PENDING").
  • GET /dd/v1/deliveries and GET /dd/v1/deliveries/{external_delivery_id} now return the delivery lifecycle status at the top level: SCHEDULED, ASSIGNED, EN_ROUTE_TO_STORE, ARRIVED_AT_STORE, WAITING_FOR_LOAD, LOADED, EN_ROUTE_TO_CUSTOMER, ARRIVED_AT_CUSTOMER, COMPLETED, FAILED, CANCELLED, or EXPIRED. The GET response and the webhook stream now always agree.
  • The list endpoint’s ?status= filter accepts the same lifecycle values. The legacy order-status vocabulary (PENDING, READY, ACCEPTED, dispatching, en_route, arriving, arrived, waiting_for_pickup, returning) is no longer accepted and returns 400 VALIDATION_ERROR.
  • estimated_arrival in pickup_status.changed webhook payloads is now populated with the delivery ETA (estimated arrival at the customer, locked at quote time). Previously this field was always null.
  • Sandbox vehicle_location is now populated: the synthetic vehicle records a location fix at every portal advance, so status-change payloads for subscribers of pickup.vehicle_location.changed carry a fresh position instead of null.

Migration

If your integration reads the top-level status or filters the list endpoint by status, switch to the lifecycle vocabulary:

Before (order status)After (delivery lifecycle)
PENDINGSCHEDULED
READYSCHEDULED (until dispatch) or the current dispatch state
ACCEPTEDreturningThe corresponding ASSIGNEDARRIVED_AT_CUSTOMER states
CANCELLEDCANCELLED (unchanged)
EXPIREDEXPIRED (unchanged)

The nested pickup.status field is unchanged and now always matches the top-level status; prefer reading the top-level field.