Skip to main content

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​

FeaturePurposeBenefit
Enrollment authorizationCustomer 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 chargesCreate charges linked to an accepted enrollment.Simplifies billing automation and removes friction from subscription services.
Enrollment lifecycle managementQuery and cancel enrollments through the User Enrollment API.Gives merchants operational control over the bank account links of their customers.
Payment notificationsSends asynchronous updates whenever an enrollment or payment status changes.Ensures real-time updates for reconciliation and order fulfillment.

How it works​

  1. Bank account enrollment - The merchant creates the enrollment with the bank selected by the customer and redirects the customer to the bank registration page.
  2. Payment request - Once the enrollment is accepted, the merchant charges the linked bank account whenever a payment is due.
  3. Payment confirmation - EBANX sends payment status notifications to the merchant.
Transaction limits
  • 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.

Bankbank value
Bank of Ayudhya (Krungsri)bay
Kasikorn Bankkbank
Krungthai Bankktb
Siam Commercial Bankscb

Requirements​

  • API authentication - All API requests must be authenticated using JWS (JSON Web Signature). The legacy integration_key is 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.

  1. 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 sandbox
    https://sandbox.ebanxpay.com/ws/userenrollment
  2. Define enrollment parameters
    ​

    To start the direct debit process, create the enrollment using the /ws/userenrollment endpoint. 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​

    ParameterRequirementDescription
    integration_keyRequiredYour EBANX integration key.
    operationRequiredMust be enrollment.
    payment_type_codeRequiredMust be online-direct-debit.

    Enrollment parameters​

    ParameterRequirementDescription
    enrollment.countryRequiredSet to th for Thailand.
    enrollment.merchant_enrollment_codeRequiredUnique identifier for the enrollment. Required in every charge and to cancel the enrollment.
    enrollment.nameRequiredFull name of the payer.
    enrollment.emailConditionalCustomer email. Required when enrollment.phone_number is not sent.
    enrollment.phone_numberConditionalCustomer phone number. Required when enrollment.email is not sent.
    enrollment.back_urls.successRequiredURL to redirect the customer to after a completed registration.
    enrollment.back_urls.failureRequiredURL to redirect the customer to when the registration is not completed.
    enrollment.online_direct_debit.bankRequiredBank selected by the customer: bay, kbank, ktb, or scb.
  3. Enrollment request
    ​

    Enroll the customer bank account using the /ws/userenrollment endpoint.

    Sample request

    Shell
    curl -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"
    }
    }
    }'
  4. 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_url returned 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 payments

    Save the merchant_enrollment_code. It is required in every payment request and to cancel the enrollment.

  5. Confirm the enrollment
    ​

    As soon as the customer completes the registration with their bank, the enrollment status changes from pending to accepted, 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}}'
    Important

    The 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.

  6. Query enrollment status
    ​

    Before requesting any payment, call the /ws/userenrollments/query endpoint using the merchant_enrollment_code to get the latest status of the enrollment.


    Sample request

    Shell
    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

    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 accepted can be used to create payments.

  7. Define payment parameters
    ​

    After the enrollment is accepted, create payments through /ws/direct. The payment follows the usual standards of /ws/direct requests, with the addition of the enrollment reference.

    ParameterRequirementDescription
    integration_keyRequiredYour EBANX integration key.
    operationRequiredSet to request.
    payment.nameRequiredFull name of the payer.
    payment.emailRequiredCustomer email.
    payment.countryRequiredSet to th for Thailand.
    payment.payment_type_codeRequiredSet to online-direct-debit.
    payment.merchant_payment_codeRequiredUnique code for the payment.
    payment.currency_codeRequiredSet to THB.
    payment.amount_totalRequiredPayment amount, between 20.00 and 150,000.00.
    payment.merchant_enrollment_codeRequiredUnique identifier associated with the accepted enrollment.
  8. Create payment request
    ​

    Sample request

    Shell
    curl -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}}"
    }
    }'
    Important

    The merchant_enrollment_code associated with the enrollment is required for every charge, and the enrollment must be accepted.

    Billing engine

    EBANX does not offer a recurring billing engine. Merchants are required to maintain their own charge schedules.

  9. 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"
    }
  10. 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).

  11. Congratulations!
    ​

    You have successfully integrated Online Direct Debit.

    For more information, refer to the
    Direct 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

Shell
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

JSON
{
"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:

ParameterRequirementDescription
integration_keyRequiredYour unique and secret integration key.
operationRequiredMust be cancel.
payment_type_codeRequiredMust be online-direct-debit.
enrollment.countryRequiredMust be th.
enrollment.merchant_enrollment_codeRequiredThe unique enrollment identifier.

Sample request

Shell
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.

JSON
{
"status": "SUCCESS",
"enrollment": {
"status": "revoked"
}
}
Important
  • 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.

Still need help?

Help Image

We hope this article was helpful. If you still have questions, you can explore the following options: