This page documents the end-to-end flows for the two primary integration paths: collecting payments and sending payouts.
Payment Collection Flow
Use this flow to accept payments from customers via QRIS, Virtual Account, Bank Account, E-Wallet, or the hosted Checkout page.
Flow Diagram
sequenceDiagram
participant S as Your Server
participant Z as Payment Gateway
participant P as Payment Channel
participant C as Customer
S->>Z: 1. Create payment request
Note right of S: POST /api/create/qris<br/>POST /api/create/va<br/>POST /api/create/bank<br/>POST /api/create/ewallet<br/>POST /api/checkout
Z-->>S: Payment details (QR, VA number, URL)
S->>C: 2. Show payment info
Note right of S: QR code, VA number,<br/>redirect URL, etc.
C->>P: 3. Customer pays
P->>Z: Payment notification
Z->>S: 4. Webhook: payment.v2.completed
opt Verify manually
S->>Z: 5. POST /api/check/transaction
Z-->>S: Transaction status
end
Step by Step
1. Create a payment request
Choose the endpoint based on the payment method:
| Method | Endpoint | Response contains |
|---|---|---|
| QRIS | POST /api/create/qris |
QR code URL + content |
| Virtual Account | POST /api/create/va |
VA number |
| Bank Account | POST /api/create/bank |
Account number |
| E-Wallet | POST /api/create/ewallet |
Redirect URL |
| Hosted Checkout | POST /api/checkout |
Checkout page URL |
See Generate Direct Payment or Checkout for request/response details.
2. Present the payment to the customer
- QRIS: Display the QR code image from
data.qr_urlor encodedata.qr_content - VA / Bank Account: Show the account number and amount for the customer to transfer
- E-Wallet: Redirect the customer to
data.redirect_url - Checkout: Redirect to
checkout_url— the gateway handles the payment UI
3. Customer completes payment
The customer pays through their banking app, e-wallet, or by scanning the QR code. All payments have an expiry time returned in data.expired_at.
4. Receive the webhook
The gateway sends a payment.v2.completed webhook to your registered endpoint when payment succeeds:
{
"event": "payment.v2.completed",
"timestamp": "2025-01-15T14:35:00+07:00",
"data": {
"transaction_id": "...",
"merchant_transaction_id": "ORDER-001",
"amount": "50000.00",
"status": "success"
}
}
No webhook is sent when a payment expires. Use the status check below to detect expiry.
5. (Optional) Poll for status
If your webhook endpoint is unavailable or you need to verify manually:
POST /api/check/transaction
{ "merchant_transaction_id": "ORDER-001" }
See Check Transaction Status for details.
Payout (Disbursement) Flow
Use this flow to send money to a bank account (e.g., withdrawal, refund, commission payment).
Flow Diagram
sequenceDiagram
participant S as Your Server
participant Z as Payment Gateway
participant B as Recipient Bank
S->>Z: 1. Inquiry — validate & reserve funds
Note right of S: POST /api/inquiry<br/>⏱ Valid for 30 minutes
Z-->>S: inquiry_id, account_name, fee
S->>Z: 2. Transfer — execute payout
Note right of S: POST /api/transfer<br/>{ "inquiry_id": "..." }
Z->>B: Process transfer
Z->>S: 3. Webhook callback
Note right of Z: disbursement.v2.completed (success)<br/>disbursement.v2.fail (failure)<br/>disbursement.v2.expired (expired)
opt Verify manually
S->>Z: 4. POST /api/check/inquiry
Z-->>S: Inquiry status
end
Step by Step
1. Create an inquiry
The inquiry step validates the destination bank account and reserves funds from your balance.
POST /api/inquiry
{
"merchant_transaction_id": "PAYOUT-001",
"bank_code": "014",
"account_number": "1234567890",
"amount": 100000
}
Response includes inquiry_id, account_name (the validated account holder), and fee.
2. Execute the transfer
Use the inquiry_id from step 1:
POST /api/transfer
{
"inquiry_id": "01jj1g751vqw68ng5546xnda5c"
}
3. Receive the webhook
The gateway sends one of three webhook events:
| Event | Meaning |
|---|---|
disbursement.v2.completed |
Funds successfully transferred to the recipient |
disbursement.v2.fail |
Transfer failed (e.g., bank rejected the transaction) |
disbursement.v2.expired |
Transfer expired before completion |
Each event fires exclusively — you will receive exactly one of these three events per payout.
4. (Optional) Poll for status
POST /api/check/inquiry
{ "merchant_transaction_id": "PAYOUT-001" }
Possible status values: pending, valid (approved, awaiting transfer), processing, success, fail.
See Check Inquiry Status for details.
Checking Your Balance
Before initiating payouts, you can check your available balance:
GET /api/balance
Returns balance (settled), reserved_funds (reserved by pending inquiries), and outstanding_funds (unsettled).
See Check Balance for details.