SunPay Merchant API
Doc version v3 · RSA2 signing · JSON over HTTPS · amounts in integer minor units
This is the authoritative reference for the SunPay merchant API. Recommended reading order: Onboarding → Signing & Auth → Collection / Payout.
Conventions
- Protocol: HTTPS + JSON (
Content-Type: application/json; charset=utf-8), UTF-8. - Base URL:
https://{api-domain}/openapi/v1(sandbox and production use different domains; see your onboarding email). - Amounts: always integers in minor units, never decimals. PHP uses centavo, THB uses satang (both 1/100): send
10000for100.00 PHP,25075for250.75 THB. Seeminor_unit. - Currency:
currencyis ISO 4217, three uppercase letters. Required on create requests; optional on balance queries (defaults toPHP); not sent on order queries — the response returns the order's own currency. The currencies you can use are those enabled for your products; an unknown or not-enabled currency on create returns1001and never falls through to another currency. - Time:
timestampis Unix seconds (UTC). - Order numbers:
mch_order_nomust be ≤ 64 chars; we recommend letters, digits, underscore and hyphen only.
Response envelope
Every endpoint returns the same wrapper; code="0" means success:
json
{ "code": "0", "msg": "OK", "data": { } }Idempotency
- Create: for the same
merchant_no + mch_order_nowith identical key parameters (amount / currency / product / payee), the original order is returned — never duplicated; mismatched parameters return2001. - Retries are immune to later config changes: even if the product / currency / channel is disabled afterwards, retrying an existing order with identical parameters still returns the original order — safe to resend after a network timeout.
- Callbacks: the same order may be notified more than once; dedupe by
platform_order_no+ callback type (terminal-status callbacks and payout reversal callbacks are distinct types, see Payout) and just replysuccessif that type was already processed.
Security notes
- Keep your private key server-side only: never in frontends/JS, logs, or repositories.
- If you suspect key compromise, register a new public key under a new
key_versionimmediately and disable the old version. - Always verify callback signatures before processing, and reconcile the callback amount against your local order before crediting.
- Reconcile proactively via the query endpoints rather than relying on callbacks alone.