Withdrawal

Pay out to a bank account, PromptPay or a crypto wallet, and post to your ledger only when the terminal webhook arrives.

How it fits together

  1. 1

    Decide on Withdraw verify

    With it on, WITHDRAWAL_VERIFY reaches your backend before the withdrawal exists. Reply 2xx within 10 seconds to approve; any other answer rejects it.

  2. 2

    Create the withdrawal

    Call createRequest/fiat for baht or createRequest/crypto for USDT. The response returns id with withdrawal_status PENDING, and the amount is already reserved.

  3. 3

    Follow the record

    APPROVED and INPROGRESS send no webhook. Read them with GET /v1/withdrawal/info by id or order_id, or page through GET /v1/withdrawal/list.

  4. 4

    Post on the terminal event

    Branch on outcome.result rather than the event name, and post summary.withdrawer_received.

Before you start

Choosing the destination

receiver_bank takes "PromptPay" or a bank code from the Bank List. For PromptPay, put a mobile number, national ID, tax ID or e-wallet ID in withdrawal_address.

Open the Bank List

Event names can mislead

Status FAILED sends WITHDRAWAL_COMPLETED_PARTIALLY, because the customer already received part of the money. WITHDRAWAL_REJECT has no -ED on the end.

Refund the right amount

Refund the customer summary.withdrawer_pending_refund. outcome.refunded_amount is the merchant refund with fees included, so it is always larger.

A bounced withdrawal stays silent

FREEZED means the money neither reached the customer nor came back. No webhook announces it, so run a job that checks withdrawals still open.

Changing the webhook URL pauses withdrawals

With Automatic Approve Withdrawal on, changing the Webhook URL or switching it off blocks new withdrawals for 24 hours.

P2P withdrawals are PromptPay only

The same endpoint can be funded by depositors one leg at a time. Every settled leg sends WITHDRAWAL_PARTIALLY_FUNDED, which must never be posted to your ledger.

Read the P2P withdrawal guide