Deposit Flow
✅ Recommended : use Create Payment — FLEX (Hosted Payment Page) — one API call that automatically uses every payment channel we have, returning a hosted
payment_urlthat handles the entire customer flow (instructions, QR code or destination bank account, exact transfer amount, countdown, slip submission, and live status).
This document explains the end-to-end deposit workflow when integrating with the payment gateway using the FLEX endpoint.
Overview
The deposit flow describes the complete process — from when a customer initiates a deposit on the merchant's website, through to the final credit confirmation. With FLEX, the merchant makes one API call and redirects the customer to the hosted payment page; that page walks the customer through the whole payment, and the merchant is notified via webhook when the payment is confirmed.
Deposit Workflow Steps
Step 1: Customer Initiates Deposit Request
The deposit process begins when a customer on the merchant's website decides to make a deposit:
- Customer navigates to the deposit page on the merchant's website
- Customer enters the desired deposit amount
- Customer submits the deposit request
Step 2: Merchant Backend Creates a FLEX Order
Upon receiving the customer's deposit request, the merchant's backend system must:
Prepare the payment request payload including:
- Merchant credentials (
merchant_id,token) - Current timestamp (
time) - Unique merchant order ID (
merchant_order_id) - Deposit amount (
amount) - Webhook notification URL (
notify_url) - (optional)
redirect_url— where to send the customer back after payment - (optional)
payment_theme— visual theme for the hosted page
- Merchant credentials (
Generate the HMAC-SHA256 signature using the merchant's secret key
Send a POST request to the API endpoint:
/payment-flex/create
Example API Request:
{
"merchant_id": "AA12345678",
"token": "testtokentesttokentesttokentesttokentesttoken",
"time": 1656272222,
"merchant_order_id": "ORDER0123456789789445566",
"amount": "1000.00",
"notify_url": "https://merchant.com/callback/payment",
"redirect_url": "https://merchant.com/return",
"payment_theme": "halo"
}
Step 3: The Payment Gateway Returns a Hosted Payment URL
The payment gateway processes the request and:
- Validates the merchant credentials and signature
- Generates a unique platform order ID
- Picks the best available payment channel for the order
- Returns a hosted
payment_urlto the merchant
Example API Response:
{
"success": 200,
"data": {
"platform_order_id": "THBP202605061004030AAAA001",
"payment_method": "FLEX",
"payment_url": "https://payment.example.com/THBP202605061004030AAAA001/<hash>"
}
}
Important Response Fields:
platform_order_id: the gateway's unique order identifier — persist it for reconciliationpayment_url: The hosted payment page — send the customer here
Pending-order guard (
409) : only one open FLEX order is allowed per customer account at a time. If the customer already has an open order, the API returns409withdata.pending_order_id— reuse/await that order, let the customer cancel it on the payment page, or cancel it from your backend via Cancel Payment Order, before creating a new one.
Step 4: Merchant Opens the Payment URL for the Customer
The merchant simply sends the customer to payment_url — there is nothing else to render:
- Redirect the customer's browser to
payment_url, or - Embed it as an iframe inside your own page
Step 5: The Hosted Page Handles the Entire Customer Flow
The hosted payment page walks the customer through everything:
- Clear payment instructions
- The QR code or the destination bank account (whichever channel was selected)
- The exact amount to transfer (
transfer_amount, with any decimal variance) - A live countdown to the expiry deadline
- Slip submission, if required
- Real-time payment status
The customer pays from their banking app and (where applicable) submits the slip — all on the hosted page. You do not need to build any of this yourself.
Step 6: The Payment Gateway Detects and Verifies Payment
Once the customer completes the transfer:
- The gateway's system detects the incoming transaction
- The system validates the amount and matches it to the open order
- Payment status is updated to paid
Step 7: The Payment Gateway Sends Webhook Notification
After successful payment verification, the payment gateway sends a webhook notification to the merchant:
- POST request sent to the
notify_urlprovided in the original request - Webhook payload contains payment confirmation details (
mode: PAYMENT,status: PAID) - The payment gateway retries until it receives
HTTP 200, so your handler must be idempotent
For detailed webhook specifications, see Payment Callback documentation.
Step 8: Merchant Credits Customer Account
Upon receiving the webhook notification, the merchant's system should:
Validate the webhook:
- Verify the signature
- Confirm the
merchant_order_idmatches the original order - Check the order hasn't been processed already (prevent duplicate crediting)
Update order status: mark the order as paid; record the
platform_order_idCredit the customer: add the deposit amount to the customer's balance
Send confirmation response: return
HTTP 200 OKto acknowledge the webhook
After payment, the hosted page redirects the customer back to your redirect_url (if provided).
Alternative Flow: Webhook Not Received
If the webhook notification is not received (network issues, server downtime, etc.), there are two alternative verification paths:
Option 1: Query Payment Status
The merchant can actively query the payment status:
- Send a request to
/payment/querywith themerchant_order_idorplatform_order_id - Receive the current payment status
- Process accordingly
For detailed specifications, see Query Payment Order documentation.
Option 2: Customer Submits Payment Slip
On the hosted FLEX page the customer can upload a slip directly. If you need to submit a slip server-to-server, use the Slip Upload API:
- Include the payment slip image and order reference
- The payment gateway verifies the slip against transaction records and confirms
For detailed specifications, see Slip Upload documentation.
Important Considerations
Payment Timing Critical
Decimal Variance Matching: the hosted page shows the customer an exact
transfer_amount(e.g. 1000.03 instead of 1000.00), locked to that order and time window for accurate matching.Consequences of Late Payment: if a customer transfers after the expiry time, the system may have reassigned that exact amount to another order. The payment might be credited to the wrong order, and the payment gateway cannot reverse such misallocated payments. The hosted page's countdown is there to prevent this.
One Transfer Only: the customer must transfer once, the exact amount, before expiry.
Idempotency Critical
Because the payment gateway retries the webhook until it gets HTTP 200, your handler will receive
the same platform_order_id more than once. Always make crediting idempotent — credit a given
order exactly once, no matter how many callbacks arrive.
Error Handling
Common Scenarios
Order Expired: customer didn't pay in time. Action: customer creates a new deposit request (the
409pending guard is released once the previous order is closed/cancelled).Pending Order (
409): the customer already has an open FLEX order. Action: reusedata.pending_order_id, or cancel it (on the page or via the cancel API) before retrying — do not retry-loop.Customer Cancelled: the customer pressed Cancel on the hosted page. A
CANCELLEDcallback fires. A cancel is not always final — a laterPAIDcallback may still arrive for the same order (treatPAIDas authoritative); otherwise create a new order on retry.Webhook Delivery Failure: payment succeeded but the merchant wasn't notified. Action: use the query API or slip upload above. Prevention: implement a robust, idempotent webhook endpoint and a fallback poll.
Best Practices for Merchants
Order Handling:
- Persist
platform_order_idfrom the create response for reconciliation - Handle the
409pending-order response by reusingdata.pending_order_id
- Persist
Hosted Page:
- Just redirect (or iframe) the customer to
payment_url— don't extract the QR / bank account and render it in your own UI - Provide a
redirect_urlso the customer returns to your site after paying
- Just redirect (or iframe) the customer to
Webhook Implementation:
- Implement idempotent webhook handling (prevent duplicate credits)
- Return
HTTP 200quickly; process asynchronously if needed - Verify the webhook signature and log all receipts for audit
Error Recovery:
- Implement payment-query polling as a backup to webhooks (e.g. for orders pending > 1h)
- Store all API responses for troubleshooting
Customer Communication:
- Send email/SMS confirmation upon successful deposit
- Provide a customer-support channel for payment issues
Sequence Diagram
Customer Merchant Website Merchant Backend Payment API Payment Page
| | | | |
|--[Enter Amount]---->| | | |
| |----[Create Deposit]----->| | |
| | |--[POST /payment-flex]-->| |
| | |<--[payment_url]---------| |
| |<---[payment_url]---------| | |
|--[Open payment_url]-|--------------------------|-------------------------|------------------->|
|<--[Instructions + QR or bank account + countdown]------------------------|--------------------|
|--[Transfer & submit slip on the page]------------------------------------|------------------->|
| | | [Verify Payment] |
| | |<--[Webhook Callback]---| |
| | [Credit Account] | |
| | |---[HTTP 200 OK]-------->| |
|<--[Redirect to redirect_url]------------------------------------------------------------------|
Related Documentation
- Create Payment — FLEX - API specification for the FLEX endpoint
- Embed Payment Page (iframe) - Embedding the hosted page in your site
- Payment Callback - Webhook notification format and handling
- Query Payment Order - Alternative payment status verification
- Slip Upload - Manual payment verification via slip submission
- Authentication - API authentication and signature generation