Verify a payment
POST /api/v1/checkout/verify claims a session from your own backend. Use it when you already hold the TrxID: a customer sent it over chat, your support team read it from a screenshot, or you collect it in your own checkout instead of the hosted page.
Request
curl -X POST "$KRONX_BASE_URL/api/v1/checkout/verify" \
-H "x-api-key: $KRONX_API_KEY" \
-H "content-type: application/json" \
-d '{
"sessionId": "3f8c2a10-5b7e-4d21-9c6f-8e1a2b3c4d5e",
"trxId": "9ABCD123",
"provider": "bkash"
}'| Field | Rules |
|---|---|
sessionId | The session UUID from checkout_url. Anything that is not a UUID returns 404. |
trxId | Trimmed and upper-cased, then required to match [A-Z0-9]{6,20}. |
provider | Lower-cased. One of bkash, nagad, rocket, upay, cellfin. |
Success
{
"success": true,
"message": "Payment verified successfully",
"data": { "trx_id": "9ABCD123", "amount": 1200 }
}The claim runs inside a single Postgres function that checks the amount, the expiry, your account status and the attempt count together. Two requests racing the same TrxID cannot both succeed, and a TrxID already applied to another session will not match.
404 NOT_FOUND as a session that does not exist, so the endpoint cannot be used to probe for other merchants’ sessions.Outcomes
| Status | error | What happened |
|---|---|---|
| 200 | None | Claimed, or already claimed with this same TrxID. |
| 409 | ALREADY_COMPLETED | The session was already completed with a different transaction. |
| 400 | VERIFICATION_FAILED | No matching unclaimed transaction. The TrxID or the amount does not line up. |
| 429 | TOO_MANY_ATTEMPTS | Too many failed attempts against this session. It is locked. |
| 410 | SESSION_EXPIRED | Past expires_at. |
| 410 | SESSION_UNAVAILABLE | The session is cancelled or otherwise not accepting money. |
| 404 | NOT_FOUND | No such session for this account. |
| 403 | VENDOR_INACTIVE | The account is not active. |
The buyer-facing counterpart
POST /api/v1/checkout/submit takes the same three fields and returns the same outcomes, without an API key. The hosted page uses it; the session id is the authorisation. There is no ownership check because there is no authenticated account on that request.
A successful claim through either endpoint queues the callback, so you do not need to poll. See webhooks.