# Orders

> How WhatsApp carts become server-priced orders with delivery and promotions, the order statuses, the Orders API and order webhooks.

Source: https://docs.nexafone.so/v1/commerce/orders/

## From cart to order

1. The customer sends a cart from the store’s catalog.
2. Nexafon maps each item to the store’s variant, drops unavailable ones with a note, and **prices the order from the
   store’s current data**, never from the cart: if a price changed, the customer sees the new total before paying.
   Promotions and the delivery fee apply.
3. The customer gets the order summary and a **Continue** button that opens the checkout: delivery or pickup, area,
   address, contact number and an optional coupon, with a live total.
4. The order then awaits payment ([PayPoint store payments](/v1/commerce/payments/)). Stores can also ask for a
   location pin.

Each step fires a webhook: `order.created`, then `order.paid` or `order.payment_failed`, `order.status_changed` and
`order.cancelled` ([events](/v1/webhooks/events/)).

## Statuses

`new` → `awaiting_payment` → `paid` → `preparing` → `out_for_delivery` → `delivered`, plus `cancelled` and
`refunded`. Statuses only move forward. Payment moves an order to `paid`; the store (or your platform) sets
`preparing`, `out_for_delivery` (delivery orders only), `delivered` and `cancelled`. Each order lists its allowed
`nextStatuses`; others answer `order_status_not_allowed`.

The customer gets a WhatsApp message on the statuses the store chooses (by default paid, out for delivery, delivered
and cancelled): a normal reply inside the 24-hour window, otherwise an approved `order_update` template billed to the
wallet.

## The Orders API

| Operation | Permission |
| --- | --- |
| `GET /api/v1/workspaces/{workspaceId}/commerce/orders` | `orders:view` |
| `GET …/commerce/orders/{orderId}` (items, delivery, status history) | `orders:view` |
| `POST …/commerce/orders/{orderId}/status` with `{"status": "preparing"}` | `orders:manage` |
| `POST …/commerce/orders/{orderId}/cancel` with a reason | `orders:manage` |

Stock is not reserved: your platform sends stock through [catalog sync](/v1/commerce/catalog/) and can reject an
order by cancelling it.

## Delivery

`GET`/`PUT …/commerce/delivery` sets delivery and pickup: the delivery **areas** with their fees, free delivery above
an amount, the pickup address, whether to ask for a location pin, and which statuses notify the customer. The
customer’s address is remembered per number for the next order.

## Promotions

`…/commerce/promotions` manages three kinds:

| Kind | |
| --- | --- |
| `flash_sale` | Lowers prices of products in scope inside its window; also shown in the WhatsApp catalog |
| `number_list` | A discount for the numbers of a list (`…/commerce/number-lists`, up to 10,000 numbers; or past customers) |
| `coupon` | Applies when the customer enters its code at checkout; limits per customer and overall |

A promotion takes `percentOff` or `amountOffCents`, a scope (all, products or categories), an optional window and
minimum subtotal. By default **only the best discount applies**; promotions marked `combinable` add up. Wrong coupon
codes are rate-limited per order and per customer.
