Skip to main content

Create a paid order

POST 

/orders

Sends a paid delivery, takeaway or pickup order from your application. A new order answers 201.

Before you call​

  • Register your source with PUT /order-source first.
  • X-User-ID is optional. Without it the order runs as your source and needs no open shift.
  • X-User-ID is needed to use manual_price, a line discount, order_discount, a manual SKU line or a cash tender.
  • Whenever you send X-User-ID, the user needs an open shift at the outlet and the cashier app permission to create sales.

Request​

  • POS prices every line itself: you send items and quantities, never prices, and expected_total is your check of the result.
  • Active outlet rollout cohorts use their assigned outlet's canonical current base, including active finite plans and due permanent assignments. Zero is configured; reads do not materialize plans. Legacy and first-preparing cohorts use the legacy engine.
  • A live catalog item without that base answers 422 PRICE_OUTLET_PRICE_MISSING; there is no compatibility-scalar fallback in enabled mode.
  • Source-specific manual-price, promotion/member and idempotency rules still apply. A previously activated outlet pauses on master/company disablement; it never reverts to legacy. Both rail-pricing passes use one mode observation, revalidated in the financial transaction before writes. Committed replay retains its existing result.
  • A catalog line needs variant_id and a manual line a manual_* sku, never both. Any other sku is refused on lines[i].sku.
  • A manual line needs X-User-ID, manual_price and product_name.

Behaviour​

  • POS writes the order, its payments and a ticket on the outlet's kitchen board in one step, and sends order.paid.
  • Stock, loyalty points and the voucher are applied when the ticket is accepted: at once with accepted_type auto, or when the cashier accepts it with manual (the default).
  • When the cashier rejects the ticket, POS records a refund to the original payment, and refunding your customer is up to you.
  • An external_order_id your source already sent answers 409 DUPLICATE_EXTERNAL_ORDER_ID with data.order_id, the id of the first order, whatever the Idempotency-Key and the body (even for an order sent to another outlet of the same merchant).

Retries and idempotency​

  • To retry safely after a timeout or a network error, send the same Idempotency-Key and the same body: you get the stored answer.
  • An error from this call is stored under its Idempotency-Key: after you fix the cause, send a new key.

Errors​

StatusCodeWhen
400VALIDATION_FAILEDA field is wrong, with data.fields. A tender problem names tenders[i].payment_method_id (an unknown method, a method that GET /payment-methods does not list at the outlet, with code NOT_ALLOWED, or a cash tender without X-User-ID), and tenders when the tenders plus the payment fee do not add up to the total. An unknown voucher names voucher_code. A line that breaks a line rule of Request.
400IDEMPOTENCY_KEY_REQUIREDIdempotency-Key is missing.
403PERMISSION_DENIEDYou sent X-User-ID and the user has no cashier app permission to create sales.
403PLAN_FEATURE_REQUIREDThe plan has no kitchen order management, or no Public API add-on. For the kitchen feature, data.reason is not_in_plan or disabled (the merchant can turn it on in Settings > Features) and data.feature is the feature key; the add-on answer has no data.
403OUTLET_FORBIDDENThe outlet is not allowed.
409DUPLICATE_EXTERNAL_ORDER_IDYour source already sent this external_order_id; data.order_id is the first order.
409CART_REPRICEDexpected_total differs from the total POS priced. data holds the POS amounts and includes total, subtotal, line_discount, tax, service_fee, payment_fee and rounding. Nothing is recorded, so send the order again with the POS total.
409PRICE_ROLLOUT_PAUSEDNew outlet price decisions are paused, including after master/company disablement.
409PRICE_ROLLOUT_CHANGEDThe rollout mode or version changed after pricing; nothing is recorded.
409ORDER_SOURCE_NOT_REGISTEREDYour source is not registered with PUT /order-source.
409SHIFT_NOT_OPENYou sent X-User-ID and the user has no open shift at the outlet.
409SALES_TYPE_DISABLEDThe outlet does not sell this sales_type.
409IDEMPOTENCY_KEY_REUSEDThe key was used with another body.
409IDEMPOTENCY_IN_PROGRESSThe first request with this key is still running.
422INVALID_USERX-User-ID is an unknown user.
422KITCHEN_ACCEPT_STOCK_INSUFFICIENTOnly with accepted_type auto: stock is short, data.shortages names the items, and nothing is recorded.

Request​

Responses​

The new order