Reference
Error codes
Every error_code the Open Payment API returns and what to do about it.
Errors carry the real HTTP status and a stable error_code:
json
{ "trace_id": "1a2b3c4d5e6f7a8b", "status_code": 422, "message": "The amount exceeds the app's payment limit.", "error_code": "LIMIT_EXCEEDED" }Request and signature
error_code |
HTTP | Meaning | What to do |
|---|---|---|---|
INVALID_REQUEST |
400 | A field is missing or invalid; message names it. Also a missing/invalid Idempotency-Key or a body over 64 KB |
Fix the request |
SIGNATURE_INVALID |
401 | Missing headers, unknown/revoked/expired key, wrong signature, timestamp outside ±5 min, or nonce reused | See common mistakes |
REPLAY_PROTECTION_UNAVAILABLE |
503 | Temporary issue checking the nonce | Retry with a new nonce |
IDEMPOTENCY_KEY_REUSED |
409 | Same Idempotency-Key, different body |
Use a new key for a different operation |
IDEMPOTENCY_IN_PROGRESS |
409 | The first request with this key is still running | Retry after a short wait |
TOO_MANY_REQUESTS |
429 | Rate limit | Wait Retry-After seconds |
INTERNAL_ERROR |
500 | Unexpected error | Retry with backoff; contact support with trace_id |
App and account
error_code |
HTTP | Meaning | What to do |
|---|---|---|---|
APP_UNAVAILABLE |
403 | App suspended/offline, developer suspended, or a production order for an unpublished app | Check the app status in the console |
PAYMENT_NOT_ENABLED |
403 | Payments not enabled or disabled | Apply in the console / contact support |
PAYOUT_NOT_ALLOWED |
403 | Payouts not in your terms | Apply again with payouts |
DEVELOPER_WALLET_UNAVAILABLE |
403 | Your wallet is frozen or missing | Contact support |
SANDBOX_USER_ONLY |
403 | Sandbox order for someone who is not a test user | Add them as a test user, or use production |
Orders
error_code |
HTTP | Meaning | What to do |
|---|---|---|---|
INVALID_AMOUNT |
422 | Not positive, more than 2 decimals, or not more than the fee | Fix the amount |
CURRENCY_NOT_SUPPORTED |
422 | Currency other than USDT |
Send USDT |
LIMIT_EXCEEDED |
422 | Over the single, daily or monthly limit | Lower the amount, try tomorrow, or ask for higher limits |
ORDER_ALREADY_EXISTS |
409 | out_order_no / out_refund_no already used in this environment |
Look the order up instead of creating it |
ORDER_NOT_FOUND |
404 | No such order for this app in this environment | Check the ID and that you use the right key |
INVALID_STATE |
409 | E.g. closing a paid payment | Refund instead |
USER_NOT_AUTHORIZED |
422 | The sub never signed in to your apps, revoked access, or the account is inactive |
Ask the user to sign in with HTP again |
SELF_PAYMENT_FORBIDDEN |
422 | You tried to pay or charge your own developer account | Use another account / a test user |
REFUND_NOT_ALLOWED |
409 | The payment is not PAID |
Only refund paid payments |
REFUND_AMOUNT_EXCEEDED |
422 | More than amount − refunded_amount |
Lower the refund |
INSUFFICIENT_BALANCE |
422 | Your wallet cannot cover the refund or payout | Top up your wallet |
Errors the user sees in the cashier
You never receive these, but users may tell you about them:
| Code | Meaning for the user |
|---|---|
CHECKOUT_EXPIRED |
The payment expired or you closed it — create a new one |
CHECKOUT_ALREADY_PAID |
Already paid — check your callback / order status |
CHECKOUT_PAYER_MISMATCH |
The payment was created for another user (payer_sub) |
INSUFFICIENT_WALLET_BALANCE |
The user needs to top up |
WALLET_UNAVAILABLE |
The user's wallet is frozen |
LIMIT_EXCEEDED |
Your limit was reached between create and confirm |
INCORRECT_PIN / TOO_MANY_PIN_ATTEMPTS |
Wrong PIN; locked for 1 minute after 4 tries |