Online Direct Debit NEW

Topics covered on this page

Enable secure and seamless purchases directly from your customers' bank accounts using Direct Debit. Customers can link their bank account to your website or application for faster checkout, eliminating the need to enter payment details on future purchases.

How to enable

  • Supported Countries: Thailand
  • Minimum API version: 2017-11-02

To enable Online Direct Debit, send an email requesting this feature to support@opn.ooo. You will need to review and accept new terms and conditions.

Supported banks

Bank Linked account type
Bank of Ayudhya direct_debit_bay
Kasikorn Bank direct_debit_kbank
Krungthai Bank direct_debit_ktb
Siam Commercial Bank direct_debit_scb

Transaction limits

Country Currencies Min. amount Max. amount
Thailand THB 2000 (THB 20) 15000000 (THB 150,000)

Direct Debit charges cannot be refunded.

Payment flow

First, customers need to link their bank account to your platform securely. The steps are as follows:

Bank Account Registration

  1. The customer chooses the bank to link their bank account.

  2. The customer gets redirected to their bank's website or application to authenticate.

  3. The customer selects the bank account they want to link to your platform.

  4. The bank account details are displayed for confirmation.

  5. The customer provides consent.

  6. The customer is redirected to your website with their bank account successfully linked.

Later, customers wishing to make payments can follow these steps:

Bank Account Payment

  1. The customer selects the Direct Debit payment method.

  2. The customer selects the bank from which they would like to pay.

  3. The customer selects the bank account linked to your platform.

  4. The customer sees your payment confirmation page.

Customers only need to link their bank account to your platform once. Afterward, they won't need to authorize future transactions with that linked account.

Implementation

Use the following API requests to link a customer's bank account to your website or application.

  1. Create a linked account.

  2. Redirect the customer to the specified registration_uri.

  3. Wait for the linked account completion webhook event. You may also retrieve it manually to independently verify its status.

  4. Create a customer and attach the newly successful linked account to it (alternatively, you can also attach the linked account to an existing customer).

Next, create a charge using the customer ID and linked account ID you previously made.

Creating a linked account

When the customer confirms that they wish to link their bank account, create a new linked account specifying the type and return_uri.

Parameter Type Description
type string (required) Linked account type (direct_debit_bay, direct_debit_kbank, direct_debit_ktb, or direct_debit_scb).
return_uri string (required) Location on your website to which the customer should be redirected after completing the registration.
citizen_id string (optional) Customer's citizen ID. If supplied, banks will perform validation before the registration process. For direct_debit_ktb, this field is required if you would like to register the customer using the KTB NEXT app.

The following examples demonstrate the creation of a new linked account for direct_debit_kbank. Replace the $OMISE_SECRET_KEY variable with the test secret key found on your dashboard.

curl https://api.omise.co/linked_accounts \
  -u $OMISE_SECRET_KEY: \
  -d "type=direct_debit_kbank" \
  -d "return_uri=https://example.com/accounts/345678/complete"
{
  "object": "linked_account",
  "id": "lnac_test_5zr9wnoskjk6g0vpjd3",
  "livemode": false,
  "location": "/linked_accounts/lnac_test_5zr9wnoskjk6g0vpjd3",
  "registration_uri": "http://test.omise.co/register?ref=lnac_test_5zr9wnoskjk6g0vpjd3",
  "return_uri": "https://example.com/accounts/345678/complete",
  "type": "direct_debit_kbank",
  "status": "pending",
  "last_digits": null,
  "metadata": {},
  "failure_code": null,
  "failure_message": null,
  "registered_at": null,
  "expires_at": "2024-05-16T10:38:20Z",
  "created_at": "2024-05-15T10:38:20Z"
}

The id attribute is the linked account ID (begins with lnac).

Completing the registration

You have now created a new linked account with its status set to pending. Other possible values for the linked account status are successful, failed, expired, and deleted.

Redirect the customer to the location specified in registration_uri so they can complete the registration.

You can simulate this registration phase in test mode by visiting registration_uri to manually mark the linked account as successful or failed.

After the customer has completed the registration phase, they will be redirected to the location specified in return_uri.

sequenceDiagram participant Customer participant Merchant participant API as api.omise.co Customer ->> Merchant : Request bank account linking Merchant ->> API : Request linked account API -x Merchant: Send "linked_account.create" webhook API -->> Merchant : Return linked account Merchant ->> Customer : Redirect to "registration_uri" Customer ->> API : Perform registration at "registration_uri" API -->> Customer : Redirect to "return_uri" API -x Merchant : Send "linked_account.complete" webhook Merchant -x Customer : Send linked account result (e.g. via email)

Receiving the linked account completion event

The best way to be notified when a linked account is completed is by using webhook events.

Set up a location on the merchant server to receive webhook events and add this location as a webhook endpoint on the dashboard.

Checking the linked account status

After receiving this event, retrieve the linked account using its id and confirm that its status matches the status of the linked account contained in the event.

If the value of status is successful, the customer's bank account has been successfully linked.

If the value of status is failed, check the failure_code and failure_message in the linked account object for an explanation.

Possible failure codes are as follows.

Failure Code Description
failed_processing General linked account processing failure.
invalid_account The customer's account information is invalid or does not exist in the bank system.
registration_rejected The bank rejected the registration.
rate_limit_exceeded There are too many requests for a given period. Please try again.

Creating a customer

After receiving a successful linked account, you need to attach it to a customer before using it to create a charge. This will allow for better management and tracking between customers and their linked accounts.

Create a new customer or update the existing one specifying the linked_account using the desired linked account ID.

One customer can have multiple linked accounts, but a linked account can only be attached to one customer.

The following examples demonstrate creating a new customer. Replace the $OMISE_SECRET_KEY variable with the test secret key found on your dashboard.

curl https://api.omise.co/customers \
  -u $OMISE_SECRET_KEY: \
  -d "linked_account=$LINKED_ACCOUNT_ID"
{
  "object": "customer",
  "id": "cust_test_5zr9wnsj8za8bn31rur",
  "livemode": false,
  "location": "/customers/cust_test_5zr9wnsj8za8bn31rur",
  "deleted": false,
  "metadata": {},
  "cards": {
    "object": "list",
    "data": [],
    "limit": 20,
    "offset": 0,
    "total": 0,
    "location": "/customers/cust_test_5zr9wnsj8za8bn31rur/cards",
    "order": "chronological",
    "from": "1970-01-01T00:00:00Z",
    "to": "2024-05-15T10:38:20Z"
  },
  "default_card": null,
  "linked_accounts": {
    "object": "list",
    "data": [
      {
        "object": "linked_account",
        "id": "lnac_test_5zr9527qwb44ad4s9lw",
        "livemode": false,
        "location": "/linked_accounts/lnac_test_5zr9527qwb44ad4s9lw",
        "registration_uri": "http://test.omise.co/register?ref=lnac_test_5zr9527qwb44ad4s9lw",
        "return_uri": "https://omise.co",
        "type": "direct_debit_kbank",
        "status": "successful",
        "last_digits": "7890",
        "metadata": {},
        "failure_code": null,
        "failure_message": null,
        "registered_at": "2024-05-15T09:20:00Z",
        "expires_at": "2024-05-16T09:19:56Z",
        "created_at": "2024-05-15T09:19:56Z"
      }
    ],
    "limit": 20,
    "offset": 0,
    "total": 1,
    "location": "/customers/cust_test_5zr9wnsj8za8bn31rur/linked_accounts",
    "order": "chronological",
    "from": "1970-01-01T00:00:00Z",
    "to": "2024-05-15T10:38:20Z"
  },
  "description": null,
  "email": null,
  "created_at": "2024-05-15T10:38:20Z"
}

The id attribute is the customer ID (begins with cust).

Creating a charge

Create a charge specifying the parameters amount, currency, customer, and linked_account.

Parameter Type Description
amount integer (required) Amount in subunits (see transaction limits)
currency string (required) Currency as three-letter ISO 4217 code (THB)
customer string (required) Customer ID with a linked account from the bank account registration
linked_account string (required) Linked account ID from the bank account registration

The following examples demonstrate how to create a new charge. Replace the $OMISE_SECRET_KEY variable with the test secret key found on your dashboard.

curl https://api.omise.co/charges \
  -u $OMISE_SECRET_KEY: \
  -d "amount=5000" \
  -d "currency=THB" \
  -d "customer=$CUSTOMER_ID" \
  -d "linked_account=$LINKED_ACCOUNT_ID"
{
  "object": "charge",
  "id": "chrg_test_5zr9wnvxw05szpqkh9k",
  "location": "/charges/chrg_test_5zr9wnvxw05szpqkh9k",
  "amount": 5000,
  "acquirer_reference_number": null,
  "net": 4973,
  "fee": 25,
  "fee_vat": 2,
  "interest": 0,
  "interest_vat": 0,
  "funding_amount": 5000,
  "refunded_amount": 0,
  "transaction_fees": {
    "fee_flat": "0.0",
    "fee_rate": "0.5",
    "vat_rate": "7.0"
  },
  "platform_fee": {
    "fixed": null,
    "amount": null,
    "percentage": null
  },
  "currency": "THB",
  "funding_currency": "THB",
  "ip": null,
  "refunds": {
    "object": "list",
    "data": [],
    "limit": 20,
    "offset": 0,
    "total": 0,
    "location": "/charges/chrg_test_5zr9wnvxw05szpqkh9k/refunds",
    "order": "chronological",
    "from": "1970-01-01T00:00:00Z",
    "to": "2024-05-15T10:38:22Z"
  },
  "link": null,
  "description": null,
  "metadata": {},
  "card": null,
  "source": null,
  "schedule": null,
  "linked_account": {
    "object": "linked_account",
    "id": "lnac_test_5zr9527qwb44ad4s9lw",
    "livemode": false,
    "location": "/linked_accounts/lnac_test_5zr9527qwb44ad4s9lw",
    "registration_uri": "http://test.omise.co/register?ref=lnac_test_5zr9527qwb44ad4s9lw",
    "return_uri": "https://omise.co",
    "type": "direct_debit_kbank",
    "status": "successful",
    "last_digits": "7890",
    "metadata": {},
    "failure_code": null,
    "failure_message": null,
    "registered_at": "2024-05-15T09:20:00Z",
    "expires_at": "2024-05-16T09:19:56Z",
    "created_at": "2024-05-15T09:19:56Z"
  },
  "customer": "cust_test_5zr9nrqgambvlg9bn5y",
  "dispute": null,
  "transaction": "trxn_test_5zr9wo1aw1wrn49d346",
  "failure_code": null,
  "failure_message": null,
  "status": "successful",
  "authorize_uri": null,
  "return_uri": null,
  "created_at": "2024-05-15T10:38:21Z",
  "paid_at": "2024-05-15T10:38:21Z",
  "expires_at": "2024-05-22T10:38:21Z",
  "expired_at": null,
  "reversed_at": null,
  "zero_interest_installments": false,
  "branch": null,
  "terminal": null,
  "device": null,
  "authorized": true,
  "capturable": false,
  "capture": true,
  "disputable": false,
  "livemode": false,
  "refundable": false,
  "partially_refundable": false,
  "reversed": false,
  "reversible": false,
  "voided": false,
  "paid": true,
  "expired": false,
  "can_perform_void": false,
  "approval_code": null
}

Completing the charge

If the payment succeeds, the charge status will be successful upon creation. Other possible values for charge status are failed and pending.

In the event of a pending charge status due to bank processing delays, rest assured that the system is designed to automatically update it to the correct status shortly. No action is needed from your side or the customer. We recommend waiting for the charge.complete webhook for the finalized charge status.

sequenceDiagram participant Customer participant Merchant participant API as api.omise.co Customer ->> Merchant : Request charge Merchant ->> API : Create charge using linked account API -x Merchant: Send "charge.create" webhook API -->> Merchant : Return charge Merchant ->> Customer : Return result alt If charge is pending API -x Merchant : Send "charge.complete" webhook Merchant ->> Customer : Return result end

Receiving the charge completion event

The best way to be notified about the completion of a charge is using webhook events.

Set up a location on the merchant server to receive webhook events, and add this location as a webhook endpoint on the dashboard.

Checking the charge status

After receiving this event, retrieve the charge using its id and confirm that its status matches the status of the charge contained in the event.

If the value of status is successful, you got paid.

If the value of status is failed, check the failure_code and failure_message in the charge object for an explanation.

Possible failure codes are as follows.

Failure Code Description
failed_processing General payment processing failure.
invalid_account Valid account for payment method not found.
insufficient_fund Insufficient funds in the account or the payment method has reached its limit.
rate_limit_exceeded There are too many requests for a given period. Please try again.

Creating a recurring charge

Most direct debit use cases involve recurring payments, typically requiring setting up a schedule to charge a bank account automatically at specified intervals. You can manage this schedule either by yourself, where you send charge creation requests at selected times, or by leveraging our Schedule API for automated handling.

Follow this guide for examples of creating a charge schedule. Here's an example of how to create a recurring direct debit charge on the first day of every month:

curl https://api.omise.co/schedules \
  -u $OMISE_SECRET_KEY: \
  -d "every=1" \
  -d "period=month" \
  -d "on[days_of_month][]=1" \
  -d "start_date=2025-01-01" \
  -d "end_date=2025-12-31" \
  -d "charge[amount]=5000" \
  -d "charge[currency]=THB" \
  -d "charge[customer]=$CUSTOMER_ID" \
  -d "charge[linked_account]=$LINKED_ACCOUNT_ID"
{
    "object": "schedule",
    "id": "schd_test_60rjgvu1gnr8loh44l0",
    "deleted": false,
    "livemode": false,
    "location": "/schedules/schd_test_60rjgvu1gnr8loh44l0",
    "every": 1,
    "occurrences": {
        "object": "list",
        "data": [],
        "limit": 20,
        "offset": 0,
        "total": 0,
        "location": "/schedules/schd_test_60rjgvu1gnr8loh44l0/occurrences",
        "order": "chronological",
        "from": "1970-01-01T00:00:00Z",
        "to": "2024-08-16T03:54:32Z"
    },
    "on": {
        "days_of_month": [
            1
        ]
    },
    "in_words": "Every 1 month(s) on the 1st",
    "period": "month",
    "status": "running",
    "active": true,
    "state": "Active",
    "charge": {
        "object": "scheduled_charge",
        "id": "rchg_test_60rjgvu0wxzapqjgvop",
        "livemode": false,
        "currency": "THB",
        "amount": 5000,
        "default_card": false,
        "card": null,
        "customer": "cust_test_60rjevagkj6dqq7zqz4",
        "linked_account": "lnac_test_60rjesjp1hjn0hux6re",
        "description": null,
        "metadata": {},
        "created_at": "2024-08-16T03:54:31Z"
    },
    "next_occurrences_on": [
        "2025-01-01",
        "2025-02-01",
        "2025-03-01",
        "2025-04-01",
        "2025-05-01",
        "2025-06-01",
        "2025-07-01",
        "2025-08-01",
        "2025-09-01",
        "2025-10-01",
        "2025-11-01",
        "2025-12-01"
    ],
    "ended_at": null,
    "start_on": "2025-01-01",
    "end_on": "2025-12-31",
    "created_at": "2024-08-16T03:54:31Z",
    "deleted_by": null
}

Removing a linked account

When the customer wants to remove their bank account from your platform, you may do so by removing the linked account.

After the linked account is removed, it will have a deleted status and no longer be usable for future charges.

Note: Deleting a customer will not remove the attached linked accounts.

For Krungthai Bank, after removing the linked account from your platform, the customer needs to contact their bank to disconnect the bank account completely.

curl https://api.omise.co/linked_accounts/$LINKED_ACCOUNT_ID \
  -X DELETE \
  -u $OMISE_SECRET_KEY:
{
    "object": "linked_account",
    "id": "lnac_test_5zrb4qbkn11ogwc221x",
    "livemode": false,
    "location": "/linked_accounts/lnac_test_5zrb4qbkn11ogwc221x",
    "registration_uri": "http://test.omise.co/register?ref=lnac_test_5zrb4qbkn11ogwc221x",
    "return_uri": "https://omise.co",
    "type": "direct_debit_kbank",
    "status": "deleted",
    "last_digits": "7890",
    "metadata": {},
    "failure_code": null,
    "failure_message": null,
    "registered_at": "2024-05-15T12:43:37Z",
    "expires_at": "2024-05-16T12:43:32Z",
    "created_at": "2024-05-15T12:43:32Z"
}

How to check the public key and secret key

For information on how to obtain and check the public and secret keys, please refer to this document.

Omise uses cookies to improve your overall site experience and collect information on your visits and browsing behavior. By continuing to browse our website, you agree to our Privacy Policy. Learn more