Skip to content

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: OnboardingSigning & AuthCollection / 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 10000 for 100.00 PHP, 25075 for 250.75 THB. See minor_unit.
  • Currency: currency is ISO 4217, three uppercase letters. Required on create requests; optional on balance queries (defaults to PHP); 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 returns 1001 and never falls through to another currency.
  • Time: timestamp is Unix seconds (UTC).
  • Order numbers: mch_order_no must 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": { } }

See Statuses & Error Codes.

Idempotency

  • Create: for the same merchant_no + mch_order_no with identical key parameters (amount / currency / product / payee), the original order is returned — never duplicated; mismatched parameters return 2001.
  • 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 reply success if 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_version immediately 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.