Checkout sessions
POST /api/v1/checkout/initialize creates the session a buyer pays against. It is the only call most integrations make.
Request body
{
"amount": "1200.00",
"order_id": "ORD-1042",
"customer_name": "Rumana Akter",
"customer_contact": "01711111111",
"success_url": "https://yourshop.example/orders/ORD-1042/thanks",
"cancel_url": "https://yourshop.example/orders/ORD-1042",
"webhook_url": "https://yourshop.example/webhooks/kronx"
}| Field | Type | Required | Rules |
|---|---|---|---|
amount | string or number | Yes | At most two decimal places, greater than 0 and at most 10,000,000. Normalised to a fixed two-decimal string and handed to Postgres as text, so no floating-point rounding happens anywhere. |
order_id | string | Yes | 1 to 128 characters, matching [A-Za-z0-9._:-]+. This is the idempotency key. |
customer_name | string | No | Up to 128 characters. |
customer_contact | string | No | Up to 64 characters. |
success_url | string | No | Where the buyer’s browser is sent after a verified payment. See the URL rules below. |
cancel_url | string | No | Where the buyer is sent if they back out. |
webhook_url | string | No | Where the signed callback is POSTed. Fetched by the server, so the address rules are stricter. |
Response
{
"success": true,
"checkout_url": "https://pay.your-kronx-domain/pay/3f8c2a10-5b7e-4d21-9c6f-8e1a2b3c4d5e",
"payment_id": "kpay_5f1c8a2d4b3e4f7a9c1d2e3f4a5b6c7d",
"trid": "kpay_5f1c8a2d4b3e4f7a9c1d2e3f4a5b6c7d",
"expires_at": "2026-02-28T10:51:00.000Z"
}| Field | Meaning |
|---|---|
checkout_url | The hosted page to send the buyer to. |
payment_id | The session’s external id, formatted kpay_ followed by 32 hex characters. Store it against your order. |
trid | The same value as payment_id. It is named trid in every webhook body, so both names are returned here to save you a mapping. |
expires_at | ISO 8601 timestamp. After this moment the session stops accepting a claim. |
trid is never the bKash TrxID.It is ToruPay’s own session id. The provider TrxID is what the buyer types in and what the SMS carries; it is matched internally and is not what a callback quotes back to you.Idempotency
Sessions are keyed on the pair of your account and order_id. Calling initialize again with an order_id that already has an open session returns that session unchanged, with the same payment_id and expires_at. Retry a timed-out request freely.
Expiry
A session lives for 30 minutes by default. The hosted page counts down to expires_at and refuses to submit after it. A claim attempted after expiry returns 410 SESSION_EXPIRED.
URL rules
- All three URLs must be
https:and at most 2048 characters, with no embedded credentials in the formhttps://user:pass@host. - If your account has an allowed-host list configured, the
webhook_urlhostname must match an entry exactly. - A
webhook_urlis re-resolved immediately before every delivery and refused if it points at loopback, RFC 1918, link-local, carrier-grade NAT, multicast or other reserved addresses, or if the hostname is written as a raw or hex-encoded integer. - A rejected URL fails the initialize call with
400and the specific reason inerror.
Other outcomes
503while checkout is in maintenance.429when your account or the platform has hit its daily transaction limit.
Exact strings are on the errors page.