Create a payout intent
Create an idempotent Payout and read its single closed public status.
Create one Payout to a bank account. The response exposes one stable public status.
Merchant API creation starts execution without a separate Merchant approval command.
Endpoint
POST /payout_intentscurl -s -X POST "$API_BASE/payout_intents" \
-u "$API_PUBLIC_KEY:$API_SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"amount": "50000",
"currency": "MYR",
"country": "MY",
"merchant_reference": "payout_98765",
"recipient": {
"type": "bank_account",
"account_number": "1234567890",
"bank_code": "MBBEMYKL",
"holder_name": "Alice Tan"
}
}'The API validates the request and resolves Operational Configuration before dispatch. After durable
insert and acknowledged Workflow dispatch, it returns 201 with the latest Payout projection. An uncertain dispatched create remains
processing; it never invites a second Payout.
{
"object": "payout_intent",
"id": "word_01HZX...",
"amount": "50000",
"currency": "MYR",
"country": "MY",
"environment": "test",
"merchant_reference": "payout_98765",
"status": "processing",
"reserved_amount": "0",
"completed_amount": "0",
"returned_amount": "0",
"next_action": null,
"failure_code": null,
"failure_message": null,
"recipient": {
"type": "bank_account",
"account_last4": "7890",
"bank_code": "MBBEMYKL",
"holder_name": "Alice Tan"
},
"created_at": "2026-05-09T12:00:00.000Z",
"updated_at": "2026-05-09T12:00:00.000Z"
}status is one of processing, requires_action, requires_approval, succeeded, failed,
cancelled, or expired. approval_status is present only as pending while operational approval
is pending. Resolve an operational approval hold through an authorised Operator. Internal execution and Provider states are not public fields.
Replay and status
merchant_reference is a unique business reference. Reusing it returns 409 duplicate_merchant_reference.
Idempotency-Key is required. Reusing the same key with the same complete request replays the
stored response; changing any field returns 409 idempotency_conflict.
GET /payout_intents/:id is side-effect-free and never initiates Provider work. Consume webhooks or
poll this projection for later truth.
Recipient bank codes
For Thailand, recipient.bank_code uses a canonical code:
BAAC, BAY, BBL, CIMB, CLICX, EXIM, GHB, GSB, ISLAMIC, KBANK,
KKP, KTB, LHBANK, SCB, SCBT, SME, TCR, TISCO, TTB, or UOB.
Use promptpay for a PromptPay destination and put the recipient identifier in account_number.
A recognised bank code does not guarantee an eligible route. Do not send Provider-local codes
such as kkb. account_number and holder_name are required; holder_name_th supplies the Thai
name when required by the configured route. For other countries, use the bank code agreed for
the configured country and route.
Status events
Payout webhooks expose data.status with the same public values as GET. The
payout_intent.returned event reports returned funds; its resource status is failed.
It does not introduce a separate returned public status. Merchant approval commands are not
available through this API; an operational approval hold must be resolved by an authorised Operator.
If Workflow dispatch cannot be acknowledged, creation returns 503. Retry with the same
Idempotency-Key and the same body. Init reuses the stored Payout and dispatch identity; it does
not create another Payout. A 503 is not proof that the Provider did not receive a request.