Partner API overview
The Partner API lets your servers create pay-ins (collect money) and payouts (send money), check your balance, withdraw funds and verify transfer slips.
https://api.example.com/v1What you can do
Section titled “What you can do”| Task | Endpoint | Page |
|---|---|---|
| Collect money from a payer | /v1/payins | Pay-ins |
| Send money to a payer | /v1/payouts | Payouts |
| Manage your end users’ bank accounts | /v1/payers, /v1/banks | Payers |
| Read your account, balance and totals | /v1/account, /v1/reports | Balance and reports |
| Withdraw your balance to your own account | /v1/withdrawals | Withdrawals |
| Verify a transfer slip | /v1/slips/verify | Slip verification |
| Get notified when a status changes | (we call your URL) | Webhooks |
Environments and keys
Section titled “Environments and keys”All keys use the same base URL. The type of API key decides how requests are treated.
| Key | Format | Use |
|---|---|---|
| Live key | pk_live_ + 24 characters | Production |
| Test key | pk_test_... | Integration testing. Works only while your account is in test mode. Issued by support |
- Partners with an older key (32 hex characters) keep using it; signing works exactly the same way.
- With a test key only
POST /v1/slips/verifyreturns simulated results (see Slip verification). Every other endpoint behaves normally, so pay-ins and payouts you create are real. Test with small amounts and your own accounts. - How to get your key and secret: Quick start.
Conventions
Section titled “Conventions”- JSON, UTF-8 in both directions. Send
Content-Type: application/jsonwhen there is a body. - camelCase field names, for example
payerId,webhookUrl,createdAt. - Amounts are decimal strings such as
"150.00": 2 decimals (USDTuses 6). Send amounts as strings too, never as numbers. - Currencies are upper case:
THB,USD,USDT,LAK. - Timestamps are ISO-8601 in UTC, for example
2026-01-01T00:00:00.000Z. Report dates areYYYY-MM-DDin Thailand time (UTC+7). - IDs carry a type prefix followed by 32 lowercase hex characters. Store them as opaque strings.
| Prefix | Type |
|---|---|
pin_ | pay-in |
pout_ | payout |
payer_ | payer |
wd_ | withdrawal |
evt_ | webhook event |
- Fields without a value are
null, never an empty string. - Unknown body fields and query parameters are rejected with
400 parameter_unknown. Send only the documented fields.
Response envelope
Section titled “Response envelope”Success:
{ "data": { "object": "payin", "id": "pin_3f2b1c0d9e8f4a7b8c6d5e4f3a2b1c0d", "...": "..." }, "requestId": "req_Z3k9QmP2xR7tLw4NbV8cYh1s"}Error:
{ "error": { "type": "invalid_request_error", "code": "payer_not_found", "message": "No such payer.", "param": "payerId" }, "requestId": "req_Z3k9QmP2xR7tLw4NbV8cYh1s"}- Every response has an
X-Request-Idheader equal torequestId. Log it, and quote it whenever you contact support. - Branch on
error.code;error.messageis for humans and may change. See Errors for every code. - Every object has an
objectfield naming its type, such as"payin","payout"or"payer". - A success response may also contain
warnings, notices that do not change the result (for examplepayer_name_differs). See Errors.
Pagination
Section titled “Pagination”List endpoints (GET /v1/payins, GET /v1/payouts, GET /v1/payers, GET /v1/payers/{id}/payments) accept:
| Parameter | Value |
|---|---|
limit | 1-100, default 20 |
cursor | nextCursor from the previous page |
{ "data": [ { "object": "payin", "...": "..." } ], "pagination": { "limit": 20, "hasMore": true, "nextCursor": "eyJvIjoyMH0" }, "requestId": "req_..."}- Results are newest first.
- While
hasMoreistrue, repeat the same query withcursor=<nextCursor>. - Cursors are opaque. Do not build or edit them (an invalid one returns
400 invalid_cursor).
Access to data
Section titled “Access to data”You only see your own account’s data. An ID from another account, or a malformed ID, always returns 404 resource_not_found.
Next steps
Section titled “Next steps”- Authentication and request signing
- Quick start
- API reference with every endpoint