Skip to content

Order synchronisation

Online and platform orders flow into POS so the business sees every sale in one place and stock is deducted once.

Submitting

POST /api/v1/businesses/{id}/orders (orders:write)

{
  "externalRef": "RD-ORD-20261105-0042",
  "customer": { "externalId": "buyer-77", "name": "Lerato M", "phone": "+27 82 …" },
  "lines": [
    { "externalVariantId": "menu-981", "quantity": 2, "modifierIds": [] },
    { "variantId": "cm…", "quantity": 1, "unitPrice": "18.00" }
  ],
  "payment": { "method": "OTHER", "amount": "148.00", "provider": "rekadijo", "reference": "PAY-8812" },
  "fulfilment": "delivery",
  "note": "Gate code 1234"
}
  • Idempotent on externalRef (per application). Resubmitting returns the same order with "replayed": true — retry freely.
  • Lines name a variant by your externalVariantId (from product sync) or by POS variantId. unitPrice records what the customer was actually charged on your platform; omit it to use the POS price.
  • discount (optional, { "kind": "FIXED" | "PERCENT", "value": "10.00" }) records an order-level discount such as a platform promotion; it is spread across lines before VAT.
  • Send only what belongs to the business's sale. Delivery fees and tips collected for a driver or the platform are not part of the seller's order.
  • With payment the order is completed: stock is deducted (ONLINE_ORDER movements), cost of sales and VAT are posted, and the payment is recorded against "Other payments clearing" (money your platform collected and will settle to the business). payment.amount must equal the order total POS computes, or the request is rejected — so totals can never silently disagree.
  • Without payment the order is OPEN: stock is reserved (shown as reserved, removed from available) but not deducted, and nothing is posted to the books.

Updating

PATCH /api/v1/businesses/{id}/orders/{orderId}

action Body Effect
pay payment Completes an OPEN order: releases the reservation, deducts stock, posts the books
cancel reason Voids an unpaid order and releases its reservation. A paid order is refunded instead (POST …/sales/{id}/refunds)
fulfil fulfilmentStatus received → accepted → preparing → ready → out_for_delivery → delivered / collected

Kitchen and counter staff see these in POS. Changes emit order.updated (and order.cancelled).

GET …/orders/{orderId} accepts a POS id or ext:<externalRef>.

Quotation-first platforms (RekaDijo)

Do not push a quotation as an order. Push when the buyer accepts and the order exists on your side: unpaid → reserve; paid → complete. Your payment and settlement logic stays where it is; POS records the outcome.

Keeping channels distinct

Orders from an application have channel: "PLATFORM"; orders from a business API key are ONLINE; register sales are POS. Reports and the Control Centre split by channel, so online and in-store sales are never confused.