Record a waiting sale as paid another way
- 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 paid without the link: cash later, a card on the merchant's own machine, an EFT. Recorded as a counter payment, with no platform fee; the stock already left when the sale was kept. 422 when it is already paid (the money is never taken twice), cancelled, never kept for later, or the method is not Cash, Card, EFT, SnapScan, Zapper or Other. The Idempotency-Key makes a retry return the first answer.
Till PINs: the cashier is the one cashierTicket names.
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.
orderId*stringIdempotency-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
method*stringCash, Card (the merchant's own machine), EFT, SnapScan, Zapper or Other.
reference?stringlength <= 80cashierTicket?stringNeeded when the store uses till PINs.
OK
application/json- response
data*curl -X POST 'https://api.shopeazy.co/v1/merchant/stores/<storeId>/till/waiting/<orderId>/paid' \ -H 'Authorization: Bearer <access_token>' \ -H 'Idempotency-Key: <unique_key>' \ -H 'Content-Type: application/json' \ -d '{ "method": "string"}'{ "data": { "order": { "id": "string", "number": "string", "channel": "online", "customerName": "string", "soldByName": "string", "total": { "amount": 0, "currency": "ZAR" }, "status": "open", "paymentStatus": "unpaid", "fulfillmentStatus": "unfulfilled", "placedAt": 0, "lineCount": 0, "kinds": [ "physical" ], "currency": "string", "customerEmail": "string", "customerPhone": "string", "lines": [ { "id": "string", "kind": "physical", "requiresShipping": true, "title": "string", "variantTitle": "string", "customisations": [ { "groupName": "string", "choiceName": "string", "price": { "amount": 0, "currency": "ZAR" } } ], "quantity": 0, "unitPrice": { "amount": 0, "currency": "ZAR" }, "lineTotal": { "amount": 0, "currency": "ZAR" }, "fulfilled": true, "imageUrl": "string" } ], "subtotal": { "amount": 0, "currency": "ZAR" }, "shipping": { "amount": 0, "currency": "ZAR" }, "discount": { "amount": 0, "currency": "ZAR" }, "paid": { "amount": 0, "currency": "ZAR" }, "refunded": { "amount": 0, "currency": "ZAR" }, "kept": { "amount": 0, "currency": "ZAR" }, "refundable": { "amount": 0, "currency": "ZAR" }, "pendingRefunds": [ { "amount": { "amount": 0, "currency": "ZAR" }, "providerName": "string" } ], "eft": { "reference": "string", "overdue": true, "overdueAt": 0, "bankName": "string", "account": "string" }, "customerNote": "string", "giftNote": "string", "notes": [ { "at": 0, "message": "string", "author": "string" } ], "timeline": [ { "at": 0, "type": "created", "message": "string", "author": "string" } ], "fulfilment": { "method": "delivery", "serviceName": "string", "lockerName": "string", "address": "string", "provider": "string", "serviceCode": "string", "locker": { "id": "string", "name": "string", "provider": "string", "courier": "string", "address": "string", "hours": "string" }, "fellBack": true }, "shippingAddress": "string", "shippingAddressParts": { "addressLine": "string", "localArea": "string", "city": "string", "province": "string", "postalCode": "string" }, "shippingAddressMissing": [ "string" ], "needsCourier": true, "shipment": { "provider": "string", "trackingReference": "string", "state": "pending", "estimate": "string" } }, "receipt": { "storeName": "string", "address": "string", "phone": "string", "vatNumber": "string", "orderId": "string", "number": "string", "at": 0, "servedBy": "string", "customerName": "string", "customerEmail": "string", "customerPhone": "string", "lines": [ { "title": "string", "quantity": 0, "totalMinor": 0 } ], "discountMinor": 0, "totalMinor": 0, "taxMinor": 0, "payments": [ { "method": "string", "amountMinor": 0, "tenderedMinor": 0, "changeMinor": 0 } ] } }}A fresh pay link for a sale still waiting POST
Mints a new pass for the sale's pay page, to send again (WhatsApp, a copy). It lasts a week like the first. 422 when the sale is paid, cancelled or was never kept for later. Nothing is charged. Access: OAuth scope `orders:write`; write-gated by the subscription.
Cancel a sale that was waiting to be paid POST
They won't pay after all: the sale is cancelled, its stock goes back on the shelf and the link stops working. Never once money landed: then `status: paid`, and the sale is finished, not cancelled. Till PINs: the cashier is the one `cashierTicket` names. Access: OAuth scope `orders:write`; write-gated by the subscription.