Skip to content

Payout

Controlled payout: the platform freezes your available balance first, then enters the approval/disbursement flow; large or risk-flagged orders go to manual review. The final result always comes via callback/query.

Create POST /payout/create

Business parameters (plus the common parameters):

FieldRequiredDescription
mch_order_noYesYour order number, unique within your account
product_codeYesPayout product code
amountYesAmount in the currency's minor unit
currencyYesCurrency enabled for you; not-enabled returns 1001
payee_nameYesPayee name
payee_accountYesPayee account number
bank_codeYesBank/wallet code, per currency and must match currency — see Bank Codes. Not in the table → 2006; no serving channel for that currency → 1001
attachNoPass-through data (string)

Request example:

json
{
  "merchant_no": "M100001",
  "app_id": "app_10001",
  "key_version": 1,
  "timestamp": 1769990400,
  "nonce": "c3d4e5f6a1b2c3d4",
  "sign_type": "RSA2",
  "mch_order_no": "PO20260601001",
  "product_code": "PAYOUT",
  "amount": 500000,
  "currency": "PHP",
  "payee_name": "Juan Dela Cruz",
  "payee_account": "09171234567",
  "bank_code": "PH_GXI",
  "sign": "BASE64_SIGNATURE"
}

Response data fields:

FieldDescription
platform_order_no / mch_order_noOrder numbers
amount / fee / currencyAmount / fee / currency (minor units)
statusAPPROVED (proceeding to disbursement) or FROZEN (manual review)
review_requiredWhether manual review is required (status=FROZEN when true)

Response example:

json
{
  "code": "0",
  "msg": "OK",
  "data": {
    "platform_order_no": "P20260601123456efgh",
    "mch_order_no": "PO20260601001",
    "amount": 500000,
    "fee": 6000,
    "currency": "PHP",
    "status": "APPROVED",
    "review_required": false
  }
}

Query POST /payout/query

Business parameters (plus the common parameters):

FieldRequiredDescription
mch_order_noOne of twoYour order number
platform_order_noOne of twoPlatform order number (prefer exactly one)

Request example:

json
{
  "merchant_no": "M100001",
  "app_id": "app_10001",
  "key_version": 1,
  "timestamp": 1769990800,
  "nonce": "d4e5f6a1b2c3d4e5",
  "sign_type": "RSA2",
  "platform_order_no": "P20260601123456efgh",
  "sign": "BASE64_SIGNATURE"
}

Response data fields:

FieldDescription
platform_order_no / mch_order_noOrder numbers
amount / fee / currencyAmount / fee / currency (minor units)
statusOrder status, see Statuses
finished_atTerminal time (Unix seconds; present once terminal)
reversed_atReversal time (Unix seconds; present if the order was reversed)
fail_reasonFailure reason (present on failure)

Response example:

json
{
  "code": "0",
  "msg": "OK",
  "data": {
    "platform_order_no": "P20260601123456efgh",
    "mch_order_no": "PO20260601001",
    "amount": 500000,
    "fee": 6000,
    "currency": "PHP",
    "status": "SUCCESS",
    "finished_at": 1769991200
  }
}

Async callback

When a payout order reaches a terminal state, the platform POSTs to your payout callback URL. Verification and reply rules are the same as collection callbacks (platform-key signature, platform public key by key_version, verify-then-process, reply success, increasing retries).

Callback fields:

FieldDescription
platform_order_no / mch_order_noOrder numbers
amount / fee / currencyAmount / fee / currency (minor units)
statusTerminal: SUCCESS / FAILED / REJECTED, see Statuses
fail_reasonFailure reason (present on failure/rejection)
key_versionPlatform callback key version
timestamp / nonce / sign_type / signPlatform signing fields

Callback example (success):

json
{
  "platform_order_no": "P20260601123456efgh",
  "mch_order_no": "PO20260601001",
  "amount": 500000,
  "fee": 6000,
  "currency": "PHP",
  "status": "SUCCESS",
  "key_version": 1,
  "timestamp": 1769991205,
  "nonce": "e5f6a1b2c3d4e5f6",
  "sign_type": "RSA2",
  "sign": "PLATFORM_SIGN_BASE64"
}

Callback example (failure):

json
{
  "platform_order_no": "P20260601123456efgh",
  "mch_order_no": "PO20260601001",
  "amount": 500000,
  "fee": 6000,
  "currency": "PHP",
  "status": "FAILED",
  "fail_reason": "UPSTREAM_REJECTED",
  "key_version": 1,
  "timestamp": 1769991205,
  "nonce": "e5f6a1b2c3d4e5f6",
  "sign_type": "RSA2",
  "sign": "PLATFORM_SIGN_BASE64"
}

Reply (after successful verification and processing — HTTP 200, body exactly):

text
success

Query vs callback

The callback body is a terminal snapshot (it does not carry finished_at/attach); call the query endpoint when you need the terminal time or pass-through data.

Reversal callback (payout.reversed)

Even after a payout order reaches the terminal SUCCESS state, the platform may reverse it (e.g. upstream bank bounce / funds clawed back). On reversal the platform sends an additional callback to the same payout callback URL, with the same signing and reply rules as above.

  • How to recognize it: the reversal callback carries event="payout.reversed" and does not carry a status field; normal terminal callbacks carry status and no event. Route only by the event field.
  • Order status does not change: it stays SUCCESS; the query endpoint reflects it via reversed_at. Mark the payout as reversed in your own system and handle the funds accordingly.
  • Idempotency: at most one reversal callback per order (delivery retries aside). Dedupe key = platform_order_no + callback type — do not dedupe by order number alone, or the reversal will be mistaken for an already-processed terminal callback and dropped.

Callback fields:

FieldDescription
eventAlways payout.reversed
reversed_atReversal time (Unix seconds)
platform_order_no / mch_order_noOrder numbers
amount / feeOriginal order amount / fee (minor units)
currencyCurrency
reversal_amountReversed amount (minor units)
fee_refundRefunded fee (minor units)
key_version / timestamp / nonce / sign_type / signPlatform signing fields

Callback example (reversal):

json
{
  "event": "payout.reversed",
  "reversed_at": 1770099205,
  "platform_order_no": "P20260601123456efgh",
  "mch_order_no": "PO20260601001",
  "amount": 500000,
  "fee": 6000,
  "currency": "PHP",
  "reversal_amount": 500000,
  "fee_refund": 6000,
  "key_version": 1,
  "timestamp": 1770099210,
  "nonce": "a1b2c3d4e5f6a1b2",
  "sign_type": "RSA2",
  "sign": "PLATFORM_SIGN_BASE64"
}

Reply as usual: after successful verification and processing, respond HTTP 200 with the exact plain text success.