Online Direct Debit
Online Direct Debit enables merchants to collect payments directly from a customer's bank account in Thailand. Customers link their bank account to the merchant platform once, and every following purchase is debited from that account without asking the customer to enter payment details or authorize the charge again.
This is a two-phase payment method: the customer first authorizes a bank account link (the enrollment), and the merchant then creates charges against that enrollment whenever a payment is due. The method is widely used in Thailand for subscription and on-demand billing, including streaming platforms, digital memberships, SaaS products, and utilities, where a card-free and frictionless checkout increases conversion and reduces churn.
This guide outlines the key concepts and implementation details required to integrate Online Direct Debit via API. It covers essential steps such as enrolling the customer bank account, creating payments linked to the enrollment, and cancelling the enrollment.
Key features
| Feature | Purpose | Benefit |
|---|---|---|
| Enrollment authorization | Customer authorizes the bank account link once, directly with their bank. | Provides secure customer consent and removes the need for authorization on every payment. |
| Merchant-initiated charges | Create charges linked to an accepted enrollment. | Simplifies billing automation and removes friction from subscription services. |
| Enrollment lifecycle management | Query and cancel enrollments through the User Enrollment API. | Gives merchants operational control over the bank account links of their customers. |
| Payment notifications | Sends asynchronous updates whenever an enrollment or payment status changes. | Ensures real-time updates for reconciliation and order fulfillment. |
How it works
- Bank account enrollment - The merchant creates the enrollment with the bank selected by the customer and redirects the customer to the bank registration page.
- Payment request - Once the enrollment is accepted, the merchant charges the linked bank account whenever a payment is due.
- Payment confirmation - EBANX sends payment status notifications to the merchant.
- Online Direct Debit is available in Thailand only, in THB.
- Minimum amount per transaction: THB 20.00
- Maximum amount per transaction: THB 150,000.00
The time it takes for a bank to accept the enrollment differs per bank, up to a maximum of 24 hours.
Supported banks
The customer selects one of the banks below at checkout, and the corresponding bank code is sent in the enrollment request.
| Bank | bank value |
|---|---|
| Bank of Ayudhya (Krungsri) | bay |
| Kasikorn Bank | kbank |
| Krungthai Bank | ktb |
| Siam Commercial Bank | scb |
Requirements
- API authentication - All API requests must be authenticated using JWS (JSON Web Signature). The legacy
integration_keyis being deprecated — if you still use it, follow the Migration Guide to transition to JWS. If you don't have credentials yet, complete the Merchant Signup Form. - Payment method enabled - Online Direct Debit must be enabled for your merchant account in Thailand before you can create enrollments. Additional provider terms and conditions apply, so contact your EBANX integration specialist to have it activated.
- Bank selection at checkout - Your checkout must let the customer select one of the four supported banks and must support redirecting the customer to the bank registration page.
Instructions
Follow the steps below.
- Select your environment
Select the appropriate environment for your integration. Use the sandbox environment for testing or the production environment for live transactions.
Select the appropriate environment for your integration. Use the sandbox environment for testing, or the production environment for live transactions. Use the URL for your HTTP requests based on your selection.
Check the method's availability for your country and tenant in Payment Methods by Country. Questions about tenant and environment? Check our API Operability and API Endpoints.
Cross-border sandboxhttps://sandbox.ebanxpay.com/ws/userenrollment - Define enrollment parameters
To start the direct debit process, create the enrollment using the
/ws/userenrollmentendpoint. This step collects the customer details and the bank selected at checkout, and returns the URL where the customer authorizes the bank account link.Customers are required to authenticate with their bank to accept the enrollment. Once the registration is complete, the bank account is linked and can be charged.
Basic parameters
Parameter Requirement Description integration_keyRequired Your EBANX integration key. operationRequired Must be enrollment.payment_type_codeRequired Must be online-direct-debit.Enrollment parameters
Parameter Requirement Description enrollment.countryRequired Set to thfor Thailand.enrollment.merchant_enrollment_codeRequired Unique identifier for the enrollment. Required in every charge and to cancel the enrollment. enrollment.nameRequired Full name of the payer. enrollment.emailConditional Customer email. Required when enrollment.phone_numberis not sent.enrollment.phone_numberConditional Customer phone number. Required when enrollment.emailis not sent.enrollment.back_urls.successRequired URL to redirect the customer to after a completed registration. enrollment.back_urls.failureRequired URL to redirect the customer to when the registration is not completed. enrollment.online_direct_debit.bankRequired Bank selected by the customer: bay,kbank,ktb, orscb. - Enrollment request
Enroll the customer bank account using the
/ws/userenrollmentendpoint.Sample request
Shellcurl -X POST \
--location 'https://sandbox.ebanxpay.com/ws/userenrollment' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"operation": "enrollment",
"payment_type_code": "online-direct-debit",
"enrollment": {
"country": "th",
"merchant_enrollment_code": "{{unique_enrollment_code}}",
"name": "John Doe",
"email": "john.doe@example.com",
"online_direct_debit": {
"bank": "kbank"
},
"back_urls": {
"success": "https://merchant.example.com/callback/success",
"failure": "https://merchant.example.com/callback/failure"
}
}
}' - Enrollment response
A successful request returns a JSON response like the one below.
JSON{
"status": "SUCCESS",
"redirect_url": "{{redirect_url}}",
"enrollment": {
"merchant_enrollment_code": "{{unique_enrollment_code}}",
"country": "th",
"name": "John Doe",
"email": "john.doe@example.com",
"back_urls": {
"success": "https://merchant.example.com/callback/success",
"failure": "https://merchant.example.com/callback/failure"
}
}
}Important notes about enrollment- Redirect the customer to the
redirect_urlreturned in the response so they can authorize the bank account link with their bank. - No amount is displayed to the customer during the bank account linking.
Subsequent paymentsSave the
merchant_enrollment_code. It is required in every payment request and to cancel the enrollment. - Redirect the customer to the
- Confirm the enrollment
As soon as the customer completes the registration with their bank, the enrollment status changes from
pendingtoaccepted, and a Status Update Notification is sent to the URL defined in your merchant configuration.Notification example:
Shell# Sent by EBANX to the merchant notification URL
curl -X POST \
--location 'https://merchant.example.com/callback' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'operation=enrollment_status_change' \
--data-urlencode 'notification_type=update' \
--data-urlencode 'merchant_enrollment_code={{unique_enrollment_code}}'ImportantThe registration outcome is not always immediate and differs per bank: Siam Commercial Bank returns a failed enrollment, while Krungthai Bank keeps the enrollment pending until the 24-hour window expires. Always rely on the notification or the query endpoint instead of assuming an immediate result.
- Query enrollment status
Before requesting any payment, call the
/ws/userenrollments/queryendpoint using themerchant_enrollment_codeto get the latest status of the enrollment.Sample request
Shellcurl -X POST \
--location 'https://sandbox.ebanxpay.com/ws/userenrollments/query' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"payment_type_code": "online-direct-debit",
"enrollment": {
"country": "th",
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
}'Sample response
JSON{
"status": "SUCCESS",
"enrollment": {
"status": "accepted"
}
}The response indicates one of the following values for the enrollment status:
accepted- Bank account successfully linked by the customer.not_accepted- The registration failed or was rejected by the bank.pending- The registration is awaiting customer action.expired- The registration was not completed within 24 hours.not_found- Enrollment not found.revoked- Enrollment cancelled.
Only enrollments with the status
acceptedcan be used to create payments. - Define payment parameters
After the enrollment is accepted, create payments through
/ws/direct. The payment follows the usual standards of/ws/directrequests, with the addition of the enrollment reference.Parameter Requirement Description integration_keyRequired Your EBANX integration key. operationRequired Set to request.payment.nameRequired Full name of the payer. payment.emailRequired Customer email. payment.countryRequired Set to thfor Thailand.payment.payment_type_codeRequired Set to online-direct-debit.payment.merchant_payment_codeRequired Unique code for the payment. payment.currency_codeRequired Set to THB.payment.amount_totalRequired Payment amount, between 20.00 and 150,000.00. payment.merchant_enrollment_codeRequired Unique identifier associated with the accepted enrollment. - Create payment request
Sample request
Shellcurl -X POST \
--location 'https://sandbox.ebanxpay.com/ws/direct' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"operation": "request",
"payment": {
"name": "John Doe",
"email": "john.doe@example.com",
"country": "th",
"payment_type_code": "online-direct-debit",
"merchant_payment_code": "{{unique_merchant_code}}",
"currency_code": "THB",
"amount_total": 99.85,
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
}'ImportantThe
merchant_enrollment_codeassociated with the enrollment is required for every charge, and the enrollment must beaccepted.Billing engineEBANX does not offer a recurring billing engine. Merchants are required to maintain their own charge schedules.
- Payment response
A successful request returns a JSON response like the one below. The Online Direct Debit payment has a pending (
PE) status until it is confirmed by the customer's bank.JSON{
"payment": {
"hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
"country": "th",
"merchant_payment_code": "{{unique_merchant_code}}",
"order_number": null,
"status": "PE",
"status_date": "{{YYYY-MM-DD HH:mm:ss}}",
"open_date": "{{YYYY-MM-DD HH:mm:ss}}",
"confirm_date": null,
"transfer_date": null,
"amount_br": "99.85",
"amount_ext": "99.85",
"amount_iof": "1",
"currency_rate": "1",
"currency_ext": "THB",
"due_date": "{{YYYY-MM-DD}}",
"instalments": "1",
"payment_type_code": "online-direct-debit",
"pre_approved": false,
"capture_available": null,
"customer": {
"name": "John Doe",
"email": "john.doe@example.com"
}
},
"status": "SUCCESS"
} - Monitor payment for status changes
Notifications
-
EBANX will send a notification whenever a payment status changes.
-
Make sure your system is set up to receive notifications from EBANX for any changes in payment status.
-
Bank processing may delay the notification, so also retrieve the payment status by polling.
Status
-
After receiving a notification that the status has changed, retrieve the payment status.
-
When a payment is confirmed, the status changes from pending (PE) to confirmed (CO). When the debit is not completed or the payment expires after 24 hours, the status changes to cancelled (CA).
-
- Congratulations!
You have successfully integrated Online Direct Debit.
For more information, refer to theDirect API reference guidechevron_right
Cancel the enrollment
Merchants can revoke an active bank account link by sending a cancel request with the merchant enrollment code.
Ensure the enrollment status is pending or accepted
You can only cancel an enrollment if its status is pending or accepted. You can check the status using the /ws/userenrollments/query endpoint referencing its merchant_enrollment_code.
Sample request
curl -X POST \
--location 'https://sandbox.ebanxpay.com/ws/userenrollments/query' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"payment_type_code": "online-direct-debit",
"enrollment": {
"country": "th",
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
}'
Sample response
{
"status": "SUCCESS",
"enrollment": {
"status": "accepted"
}
}
Cancel the enrollment
To cancel an enrollment, call the /ws/userenrollment endpoint (from your server) with the following required fields:
| Parameter | Requirement | Description |
|---|---|---|
integration_key | Required | Your unique and secret integration key. |
operation | Required | Must be cancel. |
payment_type_code | Required | Must be online-direct-debit. |
enrollment.country | Required | Must be th. |
enrollment.merchant_enrollment_code | Required | The unique enrollment identifier. |
Sample request
curl -X POST \
--location 'https://sandbox.ebanxpay.com/ws/userenrollment' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"operation": "cancel",
"payment_type_code": "online-direct-debit",
"enrollment": {
"country": "th",
"merchant_enrollment_code": "{{unique_enrollment_code}}"
}
}'
Sample response
A successful request returns a JSON response with a status of revoked.
{
"status": "SUCCESS",
"enrollment": {
"status": "revoked"
}
}
- Cancelling the enrollment removes the bank account link on your platform. For Krungthai Bank, the customer must also contact the bank to disconnect the account entirely.
- A customer can also unbind the account directly with their bank. There is no notification for this case, so it only becomes visible when a charge fails. Treat a failed charge on a previously working enrollment as a possible unbinding and ask the customer to link the account again.
Resources
Use the following resources when testing in your sandbox environment.
API Reference
Click here to access detailed API documentation to integrate efficiently.
Mock Customer Data
Click here to view mock customer data for testing and validating user flows.
Error Codes
Click here to review common error codes to troubleshoot and resolve issues quickly.
Still need help?
We hope this article was helpful. If you still have questions, you can explore the following options:
- Merchant support: Contact our support team at sales.engineering@ebanx.com for assistance.
- Not a partner yet? Please complete the Merchant Signup Form, and our commercial team will reach out to you.