Installment Payments

Topics covered on this page

Installment payments allow customers to split one large payment into several smaller payments over a fixed period. Omise offers a new installment payment flow and a set of APIs that allow you to offer your customers this convenient payment method.

For the legacy integration with installment payments using the redirect payment flow, see the Redirect Integration.

How to enable

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

To enable Installment Payments, send an email requesting this feature to support@omise.co. You will need to review and accept the new terms and conditions.

Supported cards

Credit CardSource typeInstallment Term Lengths (months)Minimum Monthly Amount (THB)
Krungsriinstallment_wlb_bay3, 4, 6, 9, 10500
Bangkok Bankinstallment_wlb_bbl3, 4, 5, 6, 7, 8, 9, 10500
Krungsri First Choiceinstallment_wlb_first_choice3, 4, 6, 9, 10, 12, 18, 24, 36300
Kasikorn Bankinstallment_wlb_kbank3, 4, 6, 10No Minimum Amount
Krungthai Card (KTC)installment_wlb_ktc3, 4, 5, 6, 7, 8, 9, 10
Siam Commercial Bankinstallment_wlb_scb3, 4, 6, 9, 10500
TMBThanachart Bankinstallment_wlb_ttb3, 4, 6, 10500
United Overseas Bank (UOB)installment_wlb_uob3, 4, 6, 10500

Supported Loan Cards

Card Source type Installment Term Lengths (months) Minimum Monthly Amount (THB)
Krungsri First Choice installment_wlb_first_choice 3, 4, 6, 9, 10, 12, 18, 24, 36 300

If the merchant enables Krungsri or Krungsri First Choice installment payments, Omise issues a 1-baht authorization charge for those cards during token creation. Omise voids the charge immediately afterward.

You can find the list of supported installment terms for each card type in the Capability API.

Payment flow

When customers choose to pay using installment payments, you (the merchant) display a checkout page that shows the relevant installment details for the customer to select.

Once the customer submits their card details and confirms the payment, Omise charges the card the same way as a normal credit card payment. Your current card processing settings therefore also apply to every charge, and Omise redirects the customer to the issuer to authenticate through 3DS. Upon completion, Omise redirects the customer back to your website.

The following screenshots demonstrate this payment flow. At checkout, the customer selects the installment payment method.

installment 1

installment 2

After the customer submits the credit card they want to pay with, Omise redirects them to the external webpage, where they might occasionally need to authenticate. After confirmation, Omise redirects the customer to your website through the specified return URI.

Setting who pays installment interest

Either you (the merchant) or the customer pays the interest for installment payments. We use the term zero-interest installments to describe the case where you pay the interest instead of the customer.

Default setting

Use the Dashboard to set the default party that pays installment interest. You can override this setting per charge.

Setting Zero Interest Installments

Per charge setting

Override the default setting by passing the boolean parameter zero_interest_installments at both source creation and charge creation. When you set it to true, you (the merchant) pay the interest. When you set it to false, the customer pays. When you omit it, the default account value applies. The values you pass at source creation and charge creation must match.

If you charge a source directly, pass this parameter at charge creation.

Implementation

To create a charge using Installment Payments, make the following API requests.

  1. Create a new token using Omise.js or one of the mobile SDKs (iOS and Android).
  2. Create a new payment source (type: installment_wlb_bay, installment_wlb_bbl, installment_wlb_first_choice, installment_wlb_kbank, installment_wlb_ktc, installment_wlb_scb, installment_wlb_ttb, or installment_wlb_uob) using Omise.js or one of the mobile SDKs (iOS and Android).
  3. Create a new charge using the token ID and source ID you created in Steps 1 and 2.
  4. After you receive the charge completion webhook event, retrieve the charge to verify its status (optional, but recommended).

Use your public key to create the token and the Installment Payments source on the client (a customer's browser or mobile phone). Use your secret key to create the Installment Payments charge on the server.

If you must create and charge a source on the server side, you can do both in a single API request using your secret key.

Creating a card token

Omise.js is a client-side JavaScript library that provides a form with validation, so you can collect card information easily. It sends sensitive card data to Omise's secure vault server and generates a token.

When the customer confirms that they want to pay with a card, create a new token and specify the card details in a card object. You can use a token only once.

The following examples demonstrate how to create a new card token for ฿4,000. Replace the omise_public_key and $OMISE_PUBLIC_KEY variables with the test public key from your Dashboard.

With Omise.js, you supply the type parameter as the first argument to the createToken method.

Omise.setPublicKey(omise_public_key);

Omise.createToken('card', {
  "name": "Somchai Prasert",
  "number": "4242424242424242",
  "expiration_month": "10",
  "expiration_year": "2022",
  "city": "Bangkok",
  "postal_code": "10320",
  "security_code": "123"
}, function(statusCode, response) {
  console.log(response)
});

For testing, you can send the same request using curl.

curl https://vault.omise.co/tokens \
  -X POST \
  -u $OMISE_PUBLIC_KEY: \
  -d "card[name]=Somchai Prasert" \
  -d "card[city]=Bangkok" \
  -d "card[postal_code]=10320" \
  -d "card[number]=4242424242424242" \
  -d "card[security_code]=123" \
  -d "card[expiration_month]=12" \
  -d "card[expiration_year]=2024"
{
  "object": "token",
  "id": "tokn_test_6275ran0cxjao4505d1",
  "livemode": false,
  "location": "https://vault.omise.co/tokens/tokn_test_6275ran0cxjao4505d1",
  "used": false,
  "charge_status": "unknown",
  "card": {
    "object": "card",
    "id": "card_test_6275ramxwea3rk2uduo",
    "livemode": false,
    "location": null,
    "deleted": false,
    "street1": null,
    "street2": null,
    "city": "Bangkok",
    "state": null,
    "phone_number": null,
    "postal_code": "10320",
    "country": "us",
    "financing": "credit",
    "bank": "JPMORGAN CHASE BANK N.A.",
    "brand": "Visa",
    "fingerprint": "b3ejUqhKT6DjGjtnathYRJk8oifeVAFXPhgtoQMhZIs=",
    "first_digits": null,
    "last_digits": "4242",
    "name": "Somchai Prasert",
    "expiration_month": 12,
    "expiration_year": 2024,
    "security_code_check": true,
    "tokenization_method": null,
    "created_at": "2024-12-26T03:16:37Z"
  },
  "created_at": "2024-12-26T03:16:37Z"
}

The id attribute is the token identifier, which begins with tokn.

Creating a source

When the customer confirms that they want to pay with this payment method, create a new source and specify the amount, currency, installment_term, and type.

Parameter Type Description
amount integer (required) See Limits
currency string (required) THB
installment_term integer (required) Valid installment term length in months
type string (required) Valid installment source type
zero_interest_installments string (optional, defaults to account setting) Whether the customer or the merchant absorbs interest. true when the merchant absorbs interest

The following examples demonstrate how to create a new Installment Payments source for ฿4,000. Replace the omise_public_key and $OMISE_PUBLIC_KEY variables with the test public key from your Dashboard.

With Omise.js, you supply the type parameter as the first argument to the createSource method.

Omise.setPublicKey(omise_public_key);

Omise.createSource('installment_wlb_ktc', {
  "amount": 400000,
  "currency": "THB",
  "installment_term": 4
}, function(statusCode, response) {
  console.log(response)
});

For testing, you can send the same request using curl.

curl https://api.omise.co/sources \
  -u $OMISE_PUBLIC_KEY: \
  -d "amount=400000" \
  -d "currency=THB" \
  -d "type=installment_wlb_ktc" \
  -d "installment_term=4"
{
  "object": "source",
  "id": "src_test_6275raqws8zz5bm5oba",
  "livemode": false,
  "location": "/sources/src_test_6275raqws8zz5bm5oba",
  "amount": 400000,
  "barcode": null,
  "bank": null,
  "created_at": "2024-12-26T03:16:38Z",
  "currency": "THB",
  "email": null,
  "flow": "redirect",
  "installment_term": 4,
  "ip": "35.198.236.178",
  "absorption_type": "customer",
  "name": null,
  "mobile_number": null,
  "phone_number": null,
  "platform_type": null,
  "scannable_code": null,
  "billing": null,
  "shipping": null,
  "items": [],
  "references": null,
  "provider_references": null,
  "store_id": null,
  "store_name": null,
  "terminal_id": null,
  "type": "installment_wlb_ktc",
  "zero_interest_installments": false,
  "charge_status": "unknown",
  "receipt_amount": null,
  "discounts": [],
  "promotion_code": null
}

The id attribute is the source identifier, which begins with src.

Creating a charge

Create a charge and specify the parameters return_uri, source, card, amount, and currency.

  • return_uri specifies the location on your website to which the customer returns after completing the payment authorization step.
  • source specifies the source identifier.
  • card specifies the token identifier.
  • The amount and currency must match those of the source.

The following example demonstrates how to create a new charge using curl.

  • Replace $OMISE_SECRET_KEY with the test secret key from your Dashboard.
  • Replace $SOURCE_ID with the id of the source.
  • Replace $TOKEN_ID with the id of the card token.

For installments, you can also pass the following parameter:

  • zero_interest_installments: The value must match the value in the source.
curl https://api.omise.co/charges \
  -u $OMISE_SECRET_KEY: \
  -d "source=$SOURCE_ID" \
  -d "amount=400000" \
  -d "currency=THB" \
  -d "card=$TOKEN_ID" \
  -d "return_uri=https://example.com/orders/345678/complete"
{
  "object": "charge",
  "id": "chrg_test_6275raual3km80ul0d3",
  "location": "/charges/chrg_test_6275raual3km80ul0d3",
  "amount": 400000,
  "acquirer_reference_number": null,
  "net": 384378,
  "fee": 14600,
  "fee_vat": 1022,
  "interest": 0,
  "interest_vat": 0,
  "funding_amount": 400000,
  "refunded_amount": 0,
  "transaction_fees": {
    "fee_flat": "0.0",
    "fee_rate": "3.65",
    "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_6275raual3km80ul0d3/refunds",
    "order": "chronological",
    "from": "1970-01-01T00:00:00Z",
    "to": "2024-12-26T03:16:38Z"
  },
  "link": null,
  "description": null,
  "metadata": {},
  "card": {
    "object": "card",
    "id": "card_test_6275ra9jn0agjscj9q1",
    "livemode": false,
    "location": null,
    "deleted": false,
    "street1": null,
    "street2": null,
    "city": "Bangkok",
    "state": null,
    "phone_number": null,
    "postal_code": "10320",
    "country": "us",
    "financing": "credit",
    "bank": "JPMORGAN CHASE BANK N.A.",
    "brand": "Visa",
    "fingerprint": "b3ejUqhKT6DjGjtnathYRJk8oifeVAFXPhgtoQMhZIs=",
    "first_digits": null,
    "last_digits": "4242",
    "name": "Somchai Prasert",
    "expiration_month": 9,
    "expiration_year": 2025,
    "security_code_check": true,
    "tokenization_method": null,
    "created_at": "2024-12-26T03:16:35Z"
  },
  "source": {
    "object": "source",
    "id": "src_test_6275r9v0js90wdo7saw",
    "livemode": false,
    "location": "/sources/src_test_6275r9v0js90wdo7saw",
    "amount": 400000,
    "barcode": null,
    "bank": null,
    "created_at": "2024-12-26T03:16:33Z",
    "currency": "THB",
    "email": null,
    "flow": "redirect",
    "installment_term": 4,
    "ip": "35.198.236.178",
    "absorption_type": "customer",
    "name": null,
    "mobile_number": null,
    "phone_number": null,
    "platform_type": null,
    "scannable_code": null,
    "billing": null,
    "shipping": null,
    "items": [],
    "references": null,
    "provider_references": null,
    "store_id": null,
    "store_name": null,
    "terminal_id": null,
    "type": "installment_wlb_ktc",
    "zero_interest_installments": false,
    "charge_status": "pending",
    "receipt_amount": null,
    "discounts": [],
    "promotion_code": null
  },
  "schedule": null,
  "linked_account": null,
  "customer": null,
  "dispute": null,
  "transaction": null,
  "failure_code": null,
  "failure_message": null,
  "merchant_advice": null,
  "status": "pending",
  "authorize_uri": "https://pay.omise.co/payments/pay2_test_6275rauc8sa7s5tl12s/authorize?acs=false",
  "return_uri": "https://example.com/orders/345678/complete",
  "created_at": "2024-12-26T03:16:38Z",
  "paid_at": null,
  "authorized_at": null,
  "expires_at": "2025-01-02T03:16:38Z",
  "expired_at": null,
  "reversed_at": null,
  "multi_capture": false,
  "zero_interest_installments": false,
  "branch": null,
  "terminal": null,
  "device": null,
  "authorized": false,
  "capturable": false,
  "capture": true,
  "disputable": false,
  "livemode": false,
  "refundable": false,
  "partially_refundable": false,
  "reversed": false,
  "reversible": false,
  "voided": false,
  "paid": false,
  "expired": false,
  "can_perform_void": false,
  "approval_code": null
}

Creating a source and charge

Alternatively, you can create and charge a source in a single API request.

curl https://api.omise.co/charges \
  -u $OMISE_SECRET_KEY: \
  -d "amount=400000" \
  -d "currency=THB" \
  -d "return_uri=http://example.com/orders/345678/complete" \
  -d "card=$TOKEN_ID_CHARGE_SOURCE" \
  -d "source[type]=installment_wlb_ktc" \
  -d "source[installment_term]=4"

Creating a source and charge where the customer pays interest

Override the default setting for who pays installment interest by passing the zero_interest_installments parameter. See setting who pays installment interest for more details.

curl https://api.omise.co/charges \
  -u $OMISE_SECRET_KEY: \
  -d "amount=400000" \
  -d "currency=THB" \
  -d "return_uri=http://example.com/orders/345678/complete" \
  -d "zero_interest_installments=false" \
  -d "card=$TOKEN_ID_CHARGE" \
  -d "source[type]=installment_wlb_ktc" \
  -d "source[installment_term]=4"

Completing the charge

You have created a new charge with its status set to pending. The other possible values for charge status are successful, failed, and expired.

The following sections detail how to authorize a charge, receive its completion webhook event, and update its status.

sequenceDiagram participant customer participant omise.js participant merchant participant api.omise.co customer->>omise.js: Send payment details for purchase omise.js->>api.omise.co: Request source using payment details api.omise.co-->>omise.js: Return source omise.js->>merchant: Return source to merchant merchant->>api.omise.co: Request charge using source and purchase details api.omise.co-xmerchant: Send "charge.create" webhook api.omise.co-->>merchant: Return charge merchant->>customer: Redirect to "authorize_uri" for pending charge customer->>api.omise.co: Provide charge authorization details at "authorize_uri" api.omise.co-->>customer: Redirect to "return_uri" api.omise.co-xmerchant: Send "charge.complete" webhook merchant-xcustomer: Send charge result (e.g., via email)

Authorizing the charge

Redirect the customer to the location specified in authorize_uri so they can authorize the charge.

In test mode, you can simulate this authorization phase using our test cards.

After the customer completes the authorization phase, Omise redirects them to the location specified in return_uri.

Receiving the charge completion event

The best way to receive notification of a charge's completion is through webhook events.

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

Checking the charge status

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

If the value of status is successful, you have received the payment.

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

The possible failure codes are as follows.

Failure Code Description
insufficient_balance The account has insufficient funds, or the payment method has reached its limit.
payment_cancelled The payer canceled the payment.
timeout The payer did not take action before the charge expired.
failed_processing A general payment processing failure occurred.

Voids and refunds

See the Refunds API documentation for information on how to refund an installment payment charge.

Installment payment charges do not support partial refunds. Omise supports only full refunds.

Credit Card Refundable Period
Krungsri 30 days
Bangkok Bank 1 year
Krungsri First Choice 30 days
Kasikorn Bank 120 days
Krungthai Card (KTC) 180 days
Siam Commercial Bank 180 days
TMBThanachart Bank 1 year
United Overseas Bank (UOB) 1 year

Limits

  • Minimum: 200000 (฿2,000.00)
  • Maximum: 15000000 (฿150,000.00)

Most credit cards have their own monthly minimum, so the effective minimum charge amount may be higher depending on the credit card and installment term length you choose. Kasikorn Bank and Krungthai Card (KTC) have no monthly minimum, so only the general minimum above applies to them.

For example, a ฿3,300 charge paid over a 10-month installment term results in a monthly charge of approximately ฿330. The monthly charge falls below the ฿500 minimum for Bangkok Bank credit cards, so Bangkok Bank credit cards cannot process the charge. Kasikorn Bank and KTC credit cards have no monthly minimum, so they can process it.

How to check the public key and secret key

For information on how to obtain and check the public and secret keys, see How to access Omise API keys.

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