Payout API std1
Three calls: apply for a payout, query a payout, query your balance; when a payout has a result we call you back (see Callbacks). All are POST forms and every response is a flat JSON object.
Common rules
- Requests:
POSTwithContent-Type: application/x-www-form-urlencoded; charset=UTF-8. Parameters go in the body only; a query string on the URL is ignored. - Parameter names may contain only letters, digits and underscores; a parameter sent twice is rejected as a parameter error.
- The request body must not exceed 65536 bytes.
- Responses: HTTP 200,
application/json; charset=UTF-8, a flat JSON object whose values are all strings (amounts too); fields without a value are left out. - HTTP other than 200, a body that is not JSON, or a signature that does not verify: treat all of them as “result unknown”, see Error codes.
msgis Chinese text for people; your program should look only atcode.- There is no timestamp or nonce: duplicates are prevented by “one merchant order number is processed once”.
- All three calls check your payout IP allow-list; an empty list rejects everything.
Apply for a payout
| Item | Value |
|---|---|
| Method | POST |
| URL | https://api.xx2system.xyz/std1/payout/apply |
| Request body | application/x-www-form-urlencoded; charset=UTF-8 |
| Body limit | 65536 bytes |
| Rate limit | 20 per second |
| IP allow-list | checked against your payout IP list; an empty list rejects everything |
| Response | application/json; charset=UTF-8 |
Request parameters
| Parameter | Required | Rule | Description |
|---|---|---|---|
mchId | yes | format [A-Za-z0-9_-]{1,32} | Merchant ID |
mchOrderNo | yes | format [A-Za-z0-9_-]{1,64} | Your order number, unique per merchant; resend with it when the result is unknown (see “Sending the same order number again”) |
amount | yes | format [1-9][0-9]{0,11} | Payout amount, integer in the currency's minor unit; for a two-decimal currency 10000 means 100.00 |
currency | no | three uppercase letters; only the platform currency (CNY) is accepted; omitted means that currency | Currency |
accountName | yes | 1–64 characters;no leading or trailing whitespace;no control characters;no invisible characters such as zero-width or bidi controls | Payee name |
accountNo | yes | format [\x21-\x7E]{5,255} | Payee account: bank card, wallet account and so on; 5–255 visible ASCII characters (letters, digits, symbols), kept exactly as sent |
bankName | yes | 1–64 characters;no leading or trailing whitespace | Bank name (matched by name; there is no bank code) |
bankBranch | no | at most 128 characters | Branch |
bankProvince | no | at most 32 characters | Province of the bank |
bankCity | no | at most 32 characters | City of the bank |
notifyUrl | no | at most 256 characters;starts with http:// / https:// | Result callback URL; without it there is no callback and you query instead |
remark | no | at most 128 characters | Your own note; returned in queries and callbacks, never sent upstream |
productId | no | format [A-Za-z0-9_-]{1,32} | For the official product ID code, please contact customer service; leave it out to use your default payout product. A product not opened for you or switched off gets MERCHANT_DISABLED |
sign | yes | format [0-9A-Fa-f]{64} | Signature, see Signatures |
productIdpicks which of your payout products this payout uses, and the fee follows that product; we choose the channel within it. Leave it out to use your default payout product; existing integrations need no change.- You may add parameters of your own (names must not clash with the ones above); they are signed and ignored after verification.
- There is no bank code: the bank is matched by name only.
Response
| Parameter | Present when | Description |
|---|---|---|
code | always(SUCCESS) | Result code, see Error codes |
mchId | always | Merchant ID |
mchOrderNo | always | Your order number |
payoutNo | always | Platform payout number |
amount | always | Payout amount (minor units) |
fee | always | Fee (minor units), fixed when accepted |
currency | always | Currency |
createTime | always | Accepted at, Beijing time |
sign | always | Signature |
msg | in failure responses | Failure reason (Chinese, for people) |
code=SUCCESSmeans accepted and funds frozen, not paid yet. The final result comes from the callback or a query.- The accepted response has no status field.
- With payout confirmation on: we call your confirmation URL while accepting this payout request, and accept it only if the success value comes back; otherwise you get
ORDER_CONFIRM_FAILED. Save the order before calling the payout API, so it can be found when the confirmation URL is asked.
Sending the same order number again
| This order number | This time's parameters | You get |
|---|---|---|
| accepted | exactly the same as the first time | the first accepted response, byte for byte; nothing is paid twice |
| rejected | exactly the same as the first time | the same rejection as the first time |
| accepted or rejected | anything different | ORDER_NO_CONFLICT: nothing was done, the original is unaffected |
| no record | — | handled as a new request |
- “Exactly the same” means every non-empty parameter except
signhas the same value (an empty string counts as not sent). Sendingcurrencythe first time and leaving it out the second time counts as different. - When the result is unknown, resend only with the same order number and the same parameters. Resubmitting under a new number is the only way to pay twice.
- The same card and amount under a new order number is a new payout, and we execute it.
Example
Example key (fake):0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef;Example merchant ID:DEMO0001
POST https://api.xx2system.xyz/std1/payout/apply
String to sign
accountName=张三&accountNo=6222021234567890123&amount=10000&bankName=中国工商银行&mchId=DEMO0001&mchOrderNo=ORDER-20260917-0001
sign
4d368047ec349d118d7865c7bcba91f1f152c72b41bba9f389be963630a22064
Request body
accountName=%E5%BC%A0%E4%B8%89&accountNo=6222021234567890123&amount=10000&bankName=%E4%B8%AD%E5%9B%BD%E5%B7%A5%E5%95%86%E9%93%B6%E8%A1%8C&mchId=DEMO0001&mchOrderNo=ORDER-20260917-0001&sign=4d368047ec349d118d7865c7bcba91f1f152c72b41bba9f389be963630a22064
Response(Accepted: funds frozen, not paid yet)
{"code":"SUCCESS","mchId":"DEMO0001","mchOrderNo":"ORDER-20260917-0001","payoutNo":"P20260917120000000001","amount":"10000","fee":"200","currency":"CNY","createTime":"2026-09-17 12:00:00","sign":"13dc9a6b36d02a8dc8fe08117a4b85cdf9e69d3bc50cc7c5010df98263d809e0"}
Response(Rejected (class B))
{"code":"INSUFFICIENT_BALANCE","msg":"可用余额不足","mchId":"DEMO0001","mchOrderNo":"ORDER-20260917-0001","sign":"9213d0f28d29dd694bf15c5797c985a3926a059157dfefaa81f71aae57c52331"}Query a payout
| Item | Value |
|---|---|
| Method | POST |
| URL | https://api.xx2system.xyz/std1/payout/query |
| Request body | application/x-www-form-urlencoded; charset=UTF-8 |
| Body limit | 65536 bytes |
| Rate limit | 50 per second |
| IP allow-list | checked against your payout IP list; an empty list rejects everything |
| Response | application/json; charset=UTF-8 |
Request parameters
| Parameter | Required | Rule | Description |
|---|---|---|---|
mchId | yes | format [A-Za-z0-9_-]{1,32} | Merchant ID |
mchOrderNo | one of two | format [A-Za-z0-9_-]{1,64} | Your order number, unique per merchant; resend with it when the result is unknown (see “Sending the same order number again”) |
payoutNo | one of two | format [A-Za-z0-9]{1,32} | Platform payout number (from the accepted response) |
sign | yes | format [0-9A-Fa-f]{64} | Signature, see Signatures |
Give at least one of mchOrderNo and payoutNo; if you give both they must belong to the same payout, otherwise you get ORDER_NOT_FOUND.
Response
| Parameter | Present when | Description |
|---|---|---|
code | always(SUCCESS) | Result code, see Error codes |
mchId | always | Merchant ID |
mchOrderNo | always | Your order number |
payoutNo | always | Platform payout number |
amount | always | Payout amount (minor units) |
fee | always | Fee (minor units), fixed when accepted |
currency | always | Currency |
status | always | Payout status, see Status below |
createTime | always | Accepted at, Beijing time |
finishTime | when status is FAILED / REVERSED / SUCCESS | When it entered the current status |
failMsg | when status is FAILED | Cancellation reason |
remark | always | Your note from the application |
sign | always | Signature |
msg | in failure responses | Failure reason (Chinese, for people) |
- Querying a rejected order returns the original rejection code.
ORDER_NOT_FOUNDdoes not prove the order was never created: the application may still be on its way.- No payee details and no channel information are returned.
Status
| Status | Meaning |
|---|---|
PROCESSING | Processing: accepted, funds frozen, no final result yet. May last hours or days; nothing is paid twice |
SUCCESS | Paid |
FAILED | Cancelled; funds returned to the available balance |
REVERSED | Returned after payment (reversal); funds returned |
- You can only see two paths:
PROCESSING → SUCCESS → REVERSEDandPROCESSING → FAILED.REVERSED(reversal) is not sent as a callback; you see it only by querying. PROCESSINGmay last hours or days (when an upstream result must be checked by hand). Funds stay frozen and nothing is paid twice; do not resubmit under a new order number; contact the operator with thepayoutNo.
Example
Example key (fake):0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef;Example merchant ID:DEMO0001
POST https://api.xx2system.xyz/std1/payout/query
String to sign
mchId=DEMO0001&mchOrderNo=ORDER-20260917-0001
sign
20f17f6d87cf293d6ced8c01c4c40d887d7846161e306d7610828fe333c83b25
Request body
mchId=DEMO0001&mchOrderNo=ORDER-20260917-0001&sign=20f17f6d87cf293d6ced8c01c4c40d887d7846161e306d7610828fe333c83b25
Response(Paid)
{"code":"SUCCESS","mchId":"DEMO0001","mchOrderNo":"ORDER-20260917-0001","payoutNo":"P20260917120000000001","amount":"10000","fee":"200","currency":"CNY","status":"SUCCESS","createTime":"2026-09-17 12:00:00","finishTime":"2026-09-17 12:05:30","sign":"6d415f531376788d1e915e70deeffb44e96f669aba651f32e33933255f650fa2"}Query your balance
| Item | Value |
|---|---|
| Method | POST |
| URL | https://api.xx2system.xyz/std1/balance/query |
| Request body | application/x-www-form-urlencoded; charset=UTF-8 |
| Body limit | 65536 bytes |
| Rate limit | 10 per second |
| IP allow-list | checked against your payout IP list; an empty list rejects everything |
| Response | application/json; charset=UTF-8 |
Request parameters
| Parameter | Required | Rule | Description |
|---|---|---|---|
mchId | yes | format [A-Za-z0-9_-]{1,32} | Merchant ID |
currency | no | three uppercase letters; only the platform currency (CNY) is accepted; omitted means that currency | Currency |
sign | yes | format [0-9A-Fa-f]{64} | Signature, see Signatures |
Response
| Parameter | Present when | Description |
|---|---|---|
code | always(SUCCESS) | Result code, see Error codes |
mchId | always | Merchant ID |
currency | always | Currency |
balance | always | Total balance (minor units), including frozen funds |
frozenAmount | always | Frozen (minor units): payouts in flight and settlement requests |
availableAmount | always | Available (minor units) = balance − frozenAmount |
sign | always | Signature |
msg | in failure responses | Failure reason (Chinese, for people) |
availableAmount = balance − frozenAmount. Merchants allowed a negative balance may see negative values.
Example
Example key (fake):0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef;Example merchant ID:DEMO0001
POST https://api.xx2system.xyz/std1/balance/query
String to sign
mchId=DEMO0001
sign
a896e78745bd80092e80a28976a4f758ca0a713d74228db79806337828fd9695
Request body
mchId=DEMO0001&sign=a896e78745bd80092e80a28976a4f758ca0a713d74228db79806337828fd9695
Response(Balance)
{"code":"SUCCESS","mchId":"DEMO0001","currency":"CNY","balance":"500000","frozenAmount":"10200","availableAmount":"489800","sign":"0b6b91b47831daa89b4c350a6eb38b755d998df8fc168e503b68bacfa5b634fd"}