Start a Scan to pay sale
- Credentials, one of
- Station token
- OAuth access token
- Scopes
orders:write- Subscription
- Needs an active plan. Otherwise
403 subscription_locked. - Idempotency
- Send an
Idempotency-Keyheader. A retry with the same key does the work once.
The customer pays on their own phone. The sale is priced from the catalogue as the till prices it (a keyed-in custom line, a price agreed at the till and the shelf check included), made as an UNPAID order, and the answer is the link for its pay page to show as a QR. It charges through the merchant's own card partner (Yoco, iKhokha or Peach: the first connected one the storefront charges through); the link carries a pass for this one order and works with the online shop switched off. Nothing is charged by this call: the partner confirms the payment like any online one, so VAT, the platform fee and stock follow the online rules. Poll getScanToPayStatus.
The Idempotency-Key makes a retry return the first answer, so one tap makes one order and one link. No card partner connected is 422 validation_error; an item that shows out of stock is 409 out_of_stock (send allowOversell to sell it anyway).
An order the customer never pays is cancelled with cancelOrder; a paid one is handed over with fulfilOrder.
Till PINs: when the store uses them, the cashier is the one cashierTicket names (403 cashier_required without one).
Access: OAuth scope orders:write; write-gated by the subscription.
AuthorizationBearer <token>It may call only the operations whose x-stations lists its kind, on its own store, and acts through the access of the owner or admin who paired it. Unpairing it, or that person leaving the business, ends it (401 station_revoked).
storeId*stringA store the person can reach. Any other id answers 404, never 403.
Idempotency-Key*stringRequired on every write. Minted on the device when the person taps, reused on every retry. A write without one, or with one that does not match the pattern, is refused with 422 validation_error. Scoped to the token's subject, remembered 24 hours. A replay returns the first 2xx response with Idempotent-Replay: true; a request still running answers 409 in_flight; the same key with a different method, path or body answers 409 idempotency_key_reused; non-2xx results are not remembered. If the key store cannot be read nothing is processed and the answer is 503 idempotency_unavailable: retry with the same key.
^[A-Za-z0-9_-]{8,128}$application/json- body
lines*array<>items <= 50customer?allowOversell?booleanSell an item that shows out of stock.
discountMinor?integerOff the whole sale, in cents. Less than the sale.
0 <= valuecashierTicket?stringNeeded when the store uses till PINs.
Created
application/json- response
data*curl -X POST 'https://api.shopeazy.co/v1/merchant/stores/<storeId>/till/scan-to-pay' \ -H 'Authorization: Bearer <access_token>' \ -H 'Idempotency-Key: <unique_key>' \ -H 'Content-Type: application/json' \ -d '{ "lines": [ { "itemId": "string" } ]}'{ "data": { "orderId": "string", "number": "string", "totalMinor": 0, "url": "string", "expiresAt": 0, "partner": "string" }}Void a sale rung up at the till by mistake POST
Moves money. A full refund with the stock put back (the lines already handed over too: the goods come back across the counter), posted to the ledger like any refund: the same VAT, platform-fee and stock rules as `refundOrder`, which it runs. The `Idempotency-Key` is the refund's own key, so a retry books the money back once. Already voided is not an error: the order comes back with `alreadyVoided: true`. Only a till sale (channel `manual`), only within a day of being rung up, and only money taken at the counter (Cash, Card, EFT, SnapScan, Zapper, Other): a sale paid through the card partner (Scan to pay) is refunded with `refundOrder`, where the partner is asked to pay it back. Otherwise 422 `validation_error` with the sentence. An order that is not paid is 422. The order gets the note "Voided at the till" and the call joins the Activity log. No email goes to the customer, as at the console's till. Till PINs: when the store uses them, the cashier is the one `cashierTicket` names (403 `cashier_required` without one). Access: OAuth scope `orders:refund` (opt-in on the consent screen, owner/admin grants only, never in a preset); write-gated by the subscription. Unlike `refundOrder` a staff member can void at the till, as in the console.
Has the customer paid yet GET
`waiting`, `paid`, or `cancelled` (the order was cancelled). The till asks every few seconds while the QR is up and stops when it is closed: one order, read by id. Nothing is charged or changed. Access: OAuth scope `orders:read`; not write-gated.