# Order lifecycle

> Every status, event and reason an order can have, and how to handle them.

Source: https://docs.delivr.no/guides/order-lifecycle/

An order's `status` is one of a small, stable set. Each change sends a webhook and increases the order's `version`.

<StatusFlow
  label="On demand"
  steps={["placed", "awaiting_goods", "searching", "driver_assigned", "picked_up", "delivered"]}
  ends={["cancelled", "failed"]}
/>

<StatusFlow label="Window" steps={["placed", "scheduled", "picked_up", "delivered"]} ends={["cancelled", "failed"]} />

## Statuses

| Status            | Type      | Meaning                                                                              | Webhook                 |
| ----------------- | --------- | ------------------------------------------------------------------------------------ | ----------------------- |
| `placed`          | both      | Booked and billed to you. Transport is being arranged.                               | `order.placed`          |
| `awaiting_goods`  | on demand | Waiting for your goods. The driver search has not started.                           | `order.placed`          |
| `searching`       | on demand | Goods released; Delivr is finding a driver.                                          | `order.searching`       |
| `scheduled`       | window    | Booked on its window's route.                                                        | `order.scheduled`       |
| `driver_assigned` | on demand | A driver accepted and is on the way to the store.                                    | `order.driver_assigned` |
| `picked_up`       | both      | The driver has the goods.                                                            | `order.picked_up`       |
| `delivered`       | both      | Handed over. `proofOfDelivery` has `deliveredAt` and, when recorded, `receiverName`. | `order.delivered`       |
| `cancelled`       | both      | Cancelled, with a `reason`.                                                          | `order.cancelled`       |
| `failed`          | both      | Could not be delivered, with a `reason`.                                             | `order.failed`          |

`placed` and `awaiting_goods` both send `order.placed`: that is the moment to create the delivery in your system. An on-demand order goes straight to `awaiting_goods` while it waits for the goods.

## Reasons

`cancelled` and `failed` orders carry a `reason`:

| Reason                  | Ends as     | Meaning                                                                                                     |
| ----------------------- | ----------- | ----------------------------------------------------------------------------------------------------------- |
| `no_driver`             | `failed`    | No driver accepted the on-demand order in time. Your [fallback](/guides/fallbacks/) may follow.             |
| `goods_not_ready`       | `failed`    | The goods were never reported ready, and the ready deadline and its grace passed. Your fallback may follow. |
| `no_capacity`           | `failed`    | The transport could not be booked, for example the window filled up.                                        |
| `undeliverable`         | `failed`    | The transport partner could not complete the delivery.                                                      |
| `cancelled_by_merchant` | `cancelled` | You cancelled.                                                                                              |
| `cancelled_by_delivr`   | `cancelled` | Delivr's operators cancelled.                                                                               |
| `other`                 | either      | Anything else.                                                                                              |

New reasons may be added. Treat an unknown one like `other`.

## Other events

Some webhooks are not status changes:

| Event                      | When                                                                                       |
| -------------------------- | ------------------------------------------------------------------------------------------ |
| `order.ready_at_changed`   | You reported when the goods will be ready (`readyAt`).                                     |
| `order.ready_overdue`      | The goods are due (`readyBy`) and not reported ready.                                      |
| `order.window_changed`     | Booked on another window than quoted (`previousWindow`), after `onWindowFull: reschedule`. |
| `order.awaiting_recipient` | A failed order waits for the recipient to choose a window, until `choiceDeadline`.         |
| `order.successor_created`  | A failed order got a successor order (`successorId`).                                      |
| `order.fallback_cancelled` | No successor follows (`fallbackReason`: `expired` or `no_window`).                         |
| `order.held`               | An assisted checkout order is held for a pending sale.                                     |

See [Event types](/webhooks/events/) for the payloads.

## Reading orders

- `GET /v1/merchant/orders/{order}` takes Delivr's `id` or the `DD-` reference. It is the source of truth.
- `GET /v1/merchant/orders` is a change feed. Page through `nextCursor` to see every change once, and filter by `updatedSince`, `status` or `externalRef`. A nightly reconciliation with `updatedSince` catches anything a webhook missed.
- `version` increases with every change. Keep the highest you have seen, and ignore older data.

## Times on an order

| Field                   | Meaning                                                              |
| ----------------------- | -------------------------------------------------------------------- |
| `createdAt`, `placedAt` | When the order was created and placed.                               |
| `readyBy`               | On demand. When the goods are due.                                   |
| `readyAt`               | On demand. When the goods are (or are assumed to be) ready.          |
| `window`                | Window orders. The delivery window.                                  |
| `confirmedAt`           | A driver accepted (on demand), or the transport was booked (window). |
| `updatedAt`             | The last change.                                                     |