Place an order
Places an order for an item and charges your balance. Returns 201
immediately with status: "pending"; the final result arrives via
your webhook and is readable from GET /v1/orders/{id}.
Request fields
item_id(required) — the numeric item id.quantity— required for top-up items (a decimal amount) and for key items (an integer count, defaults to1); omit for service items (always1). Must be within the item’s min/max range.merchant_order_id(optional) — your own reference, unique per account: letters, digits and_-:~, up to 100 characters. Read the order back by it withGET /v1/orders/merchant/{merchant_order_id}.fields— required for top-up and service items only, keyed by the item’s field names. Send a text field’s value as a string; send a choice field’s value as the numeric choice id. Key items take nofields.price(optional) — the order total you expect to be charged. When sent, a price that no longer matches is rejected with400 price_mismatch(carryingactual_price) instead of charging a different amount. Omit it to be charged at the current price.
Discover an item’s item_id, product type, quantity bounds and field
definitions from your catalog snapshot (see the Catalog guide).
Authentication
Bearer authentication of the form Bearer <token>, where token is your auth token.
Request
Integer count for key items (default 1); decimal amount for
top-up items (required); omit for service items.
Your reference id, unique per account (optional): letters, digits
and _ - : ~. Read the order back by it with
GET /v1/orders/merchant/{merchant_order_id}.
Item input fields (top-up / service only), keyed by field name. Each value is a string — a text value, or a choice field’s id.
Optional price guard: the order total you expect to be charged
(same units as the response’s price, max 2 decimals, already
multiplied by quantity). When sent, the order is rejected
with 400 price_mismatch — creating and charging nothing — unless
it equals the amount actually charged. Omit it to be charged at the
current price.
Response
Order accepted; fulfillment is in progress.
Units delivered so far (relevant for key items / partials).
Amount refunded for undelivered units (partial / failed).
The submitted input fields (choice values shown as their display name).
The order’s current state. Three are non-terminal (it will still move) and three are terminal (it never changes again):
pending— accepted and charged; fulfillment has not started. Non-terminal.processing— fulfillment is running at the provider. Non-terminal.need_client_code— PAUSED awaiting a confirmation code the provider sent to your end customer. Polling stops until you submit it withPOST /v1/orders/{id}/client-code, after which the order returns toprocessing. Only login-method top-ups reach this state, and it is the only status that needs anything from you. Non-terminal.completed— every unit delivered (codes,delivered_quantity). Terminal.partial— some units delivered, the rest refunded (refund_amount,delivered_quantity;erroris usually empty here). Terminal.failed— nothing delivered, charge fully refunded (error,error_message). Terminal.
An order never returns to pending and never moves between terminal statuses;
need_client_code -> processing is the only backwards transition, and only because
you submitted a code.
Stable machine error code (e.g. OUT_OF_STOCK, NOT_ENOUGH_STOCK, INVALID_FIELDS, INSUFFICIENT_BALANCE, ORDER_TIMEOUT); empty otherwise. Always populated when status is failed. On partial it is usually EMPTY — an ordinary short delivery carries no error code, and only a partial that ran out of time reports one (ORDER_TIMEOUT), so do not rely on it to explain every shortfall; compare delivered_quantity against quantity instead. See the Errors guide for the full list of order error codes.
Human-readable text for error; empty whenever error is empty.
Delivered key/code strings (key items only).
Who placed the order. For an order placed through the API, the API key that placed it — id is the key’s id and email is empty — since a key belongs to the account, not to a person. For an order placed in the dashboard, the person and their address.
When the order was fully delivered. Set ONLY when status is completed; stays null on partial and failed even though those are terminal. Test status — not this field — to decide whether an order has settled.
Delivery status of the outbound order-result webhook. Present only for API-placed orders (source: "api") that have a webhook URL configured; null for dashboard orders or when no webhook is set. Lets you see whether the terminal event reached your endpoint. See the Webhooks guide.