Place an order

View as Markdown
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 to `1`); **omit for service** items (always `1`). Must be within the item's min/max range. - **`merchant_order_id`** (optional) — your own idempotency/reference string, unique per account. - **`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 no `fields`. - **`price`** (optional) — the order **total** you expect to be charged. When sent, a price that no longer matches is rejected with `400 price_mismatch` (carrying `actual_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

AuthorizationBearer

Bearer authentication of the form Bearer <token>, where token is your auth token.

Request

This endpoint expects an object.
item_idintegerRequired
The numeric item id.
quantitydoubleOptional
Integer count for **key** items (default `1`); decimal amount for **top-up** items (required); omit for **service** items.
merchant_order_idstringOptional<=100 characters
Your reference id, unique per account (optional).
fieldsmap from strings to stringsOptional
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.
pricedoubleOptional>=0
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.

idstringOptionalformat: "uuid"
The order id.
itemintegerOptional
Numeric item id.
item_namestringOptional
item_product_typeenumOptional
quantitydoubleOptional
delivered_quantityintegerOptional
Units delivered so far (relevant for key items / partials).
pricedoubleOptional
Amount charged, in major currency units.
refund_amountdoubleOptional
Amount refunded for undelivered units (partial / failed).
fieldsmap from strings to stringsOptional
The submitted input fields (choice values shown as their display name).
statusenumOptional
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 with `POST /v1/orders/{id}/client-code`, after which the order returns to `processing`. 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`; `error` is 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.
errorstringOptional
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.
error_messagestringOptional
Human-readable text for `error`; empty whenever `error` is empty.
codeslist of stringsOptional
Delivered key/code strings (key items only).
merchant_order_idstringOptional
sourceenumOptional
created_byobject or nullOptional
created_atdatetimeOptional
completed_atdatetime or nullOptional
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.
webhookobject or nullOptional
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.

Errors

400
Bad Request Error
401
Unauthorized Error