Browse docs
Getting started

Responses & errors

Every business response uses one envelope. A zero code means success; anything else is a failure with the reason in msg.

Response envelope

envelope
{
  "code": 0,
  "msg": "success",
  "data": {}
}
  • code = 0 means success; code != 0 means failure.
  • msg carries the reason.
  • data holds the business object on success and is usually empty or null on failure.

Responses are signed — verify the X-Sign header over the raw body before parsing. See Verify responses.

Error codes

CodeMeaningWhat to do
0Successdata holds the business object.
400Invalid request formatMalformed JSON or a missing required field. Check the field tables for the endpoint.
401UnauthorizedMissing or invalid auth headers. Start with the signature checklist.
403Forbidden / invalid signatureThe signature did not verify, or the merchant is not allowed to call this route.
422Business validation errorWell-formed request rejected by a business rule; msg explains which.
500Internal server errorRetry. Reuse the same merchant reference so a double-submit is caught as 2001 rather than creating a second order.
1003Signature verification failedRecompute sign_payload and compare byte-for-byte. See troubleshooting.
2001Duplicate ordermerchant_order_no was already used. Query the existing order instead.
2002Order not foundNo payment matches the given order_no / merchant_order_no.
2006Collection amount outside limitsThe amount is outside the minimum/maximum currently allowed for that payment method.
3003Payment method not enabledThe payment_method is not switched on for your account. Contact support.
5001Duplicate payout ordermerchant_payout_no was already used.
5002Payout order not foundNo payout matches the given payout_no / merchant_payout_no.
5004Insufficient payout balanceRun a precheck; spendable_balance is below total_debit.
5008Payout amount outside limitsThe amount is outside the minimum/maximum currently allowed for payouts with that method.
HTTP status vs. business code
The code field is the authoritative result. Transport-level codes (400, 401, 403, 500) may also surface as HTTP status codes; business codes (2xxx, 3xxx, 5xxx) arrive in a normal JSON envelope.

Amount limits

2006 (collection) and 5008 (payout) mean the amount does not satisfy the amount limits currently in effect for that payment method. They are not signature errors — X-Sign does not need investigation.

typical failure
{
  "code": 2006,
  "msg": "Payment amount does not satisfy limits",
  "data": null
}
  1. Is trans_amount.value below the current minimum for this payment method?
  2. Is it above the current maximum?

For payouts, call precheck with the amount first — it returns 5008 for the same condition without creating anything.

Conventions

TopicRule
Field namessnake_case everywhere: payment_method, merchant_order_no, trade_info.goods_name. camelCase keys are rejected.
AmountsDecimal strings, e.g. "99.99", inside a trans_amount object with currency and value. Never floats.
Currency3-letter uppercase ISO code, e.g. USD.
Country2-letter uppercase ISO code, e.g. US.
TimestampsRFC 3339 strings in response bodies (2026-06-24T10:01:23Z); Unix seconds in X-Timestamp.
Your referencesmerchant_order_no, merchant_refund_no, merchant_payout_no — unique on your side, used for idempotency.
Our referencesorder_no, refund_no, payout_no — assigned by StablePay. Query endpoints accept either yours or ours.
Passthroughmetadata is an opaque string returned unchanged in queries and notifications.
StatusesPayments and refunds: PENDING, SUCCESS, FAILED. Payouts add PROCESSING and CANCELED.