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

request
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" }
}
response
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.

FieldNotes
amountDecimal string ("500.00"). Omit for an open-amount session (see below).
asset_codeRequired. Registry code, e.g. USDT.TRC20 or MYR.
customerexternal_ref (required), plus optional email, phone, country, kyc_status, custom_fields. Upserts on external_ref.
success_url / cancel_urlMust match the Platform's allowed redirect patterns (configured in the Portal).
metadataFree-form key/values echoed back on the Payment and in webhooks — put your lookup keys here.
contextInformational 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.

open-amount request
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

request
GET /api/v1/checkout_sessions/{id}
Authorization: Bearer sk_test_...
  • Returns the session with its current status (opencompleted | expired | cancelled) and the linked payment once one exists.

Next: choose an integration mode.

View this page as markdown·Sourced from the PayXiro engineering docs — the contract wins on any technical claim.