Checkout Sessions
A Checkout Session is the standard integration path: you create one server-side, then send the customer to the hosted Cashier at the returned url. The result reaches you by signed webhook.
Create a session
POST /api/v1/checkout_sessions
Authorization: Bearer sk_test_...
Idempotency-Key: your-deposit-id
Content-Type: application/json
{
"amount": "500.00",
"asset_code": "USDT.TRC20",
"customer": { "external_ref": "12345", "email": "[email protected]", "country": "MY" },
"success_url": "https://your-app.example/deposits/success",
"cancel_url": "https://your-app.example/deposits/cancel",
"metadata": { "account_ref": "MT5-882130", "crm_request_id": "your-deposit-id" }
}201 Created
{
"id": "cs_01J9ZW3XQ4R8",
"object": "checkout_session",
"status": "open",
"amount": "500.00",
"asset_code": "USDT.TRC20",
"country": "MY",
"customer": "cust_01J9ZR2KD7VE",
"url": "https://payxiro.com/c/cs_01J9ZW3XQ4R8",
"payment": null,
"expires_at": "2026-07-05T10:41:22Z",
"metadata": { "account_ref": "MT5-882130", "crm_request_id": "your-deposit-id" },
"created_at": "2026-07-05T09:41:22Z"
}Redirect the customer to url. Once they commit, a Payment (pay_...) is created and linked on the session, and the outcome arrives by webhook.
Request fields
The body's top-level additionalProperties is false — send only these keys.
| Field | Notes |
|---|---|
| amount | Decimal string ("500.00"). Omit for an open-amount session (see below). |
| asset_code | Required. Registry code, e.g. USDT.TRC20 or MYR. |
| customer | external_ref (required), plus optional email, phone, country, kyc_status, custom_fields. Upserts on external_ref. |
| success_url / cancel_url | Must match the Platform's allowed redirect patterns (configured in the Portal). |
| metadata | Free-form key/values echoed back on the Payment and in webhooks — put your lookup keys here. |
| context | Informational risk context: kyc_status, customer_ip, customer_since. |
Redirect-URL rules
success_url and cancel_url must fall within the Platform's allowed redirect patterns (set in the Merchant Portal). A URL outside them is rejected, with param naming the offending field. These redirects are a UX signal only — the trusted signal for crediting is always the webhook.
amount must fit the asset's display decimals: "500.001" is rejected for a 2-decimal asset.
Open-amount deposits
Omit amount and send "open_amount": true instead to create a session with no fixed amount — the Cashier shows "send any amount" and the Payment settles at whatever arrives. asset_code stays required; amount and open_amount are mutually exclusive. The resulting Payment returns "amount": null until (and after) settlement, with the settled figure in received_amount. Open-amount routes only to Provider Accounts that declare the open_amount capability.
POST /api/v1/checkout_sessions
Idempotency-Key: your-deposit-id
{
"open_amount": true,
"asset_code": "USDT.TRC20",
"customer": { "external_ref": "12345", "country": "MY" },
"success_url": "https://your-app.example/deposits/success",
"cancel_url": "https://your-app.example/deposits/cancel"
}Retrieve a session
GET /api/v1/checkout_sessions/{id}
Authorization: Bearer sk_test_...- Returns the session with its current
status(open→completed|expired|cancelled) and the linkedpaymentonce one exists.
Next: choose an integration mode.