NAV undefined
bash php javascript java go

Introduction

Welcome! Here at Xendit, our mission is to provide payments infrastructure that helps you succeed. We help with both the money in (accepting payments) and money out (disbursing payments). Use cases range from platform business to eCommerce, SaaS, and everything else in between.

The Xendit API is organized around REST. Our API has predictable, resource-oriented URLs, and uses HTTP response codes to indicate API errors. We use built-in HTTP features and HTTP verbs, which are understood by off-the-shelf HTTP clients. JSON is returned by all API responses, including errors.

Learn our APIs with Postman

To make it easier to get familiar with our APIs, we've published a Postman Collection so that you can see examples of all of Xendit APIs in one place. See our Postman Guide to get started!

Authentication

To successfully authenticate with Xendit's APIs, you must authenticate your secret API key using Basic Auth. You can obtain your API keys in Dashboard. For example if your API key is

xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==

Select Basic Auth authentication. Input secret API key in username and leave the password empty

Basic Auth format
{{username}}:{{password}}

Following the format (with colon)
xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==:

Encode Basic Auth format above into Base64 format

eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==

Include Base64 encoded value in HTTP(s) header

Authorization: Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==

Xendit API is organized around REST to make it cleaner and easier to understand. All our API responses return JSON. To let you explore our APIs, make sure that you have registered an account. You can obtain and manage your API keys in API Keys Settings. We provide you API keys for both the test and live environments.

To authenticate your account, you have to include your secret API key in the request which can be accessed in Xendit Dashboard. Here are the steps to authenticate your account:

  1. Generate secret API key
  2. Obtain your secret API key from Dashboard
  3. Select Basic Access Authentication or BASIC AUTH authentication
  4. BASIC AUTH format will be {{username}}:{{password}}
  5. Input Secret API key as username and leave the password empty. Make sure to include : at the end
  6. Encode the value above into Base64 format
  7. Include the base64 encoded into Authorization header

All the API requests should be made over HTTPS instead of HTTP (all calls made over plain HTTP will fail). All requests made in the test environment will never hit the banking networks and will not cost you anything. Your API keys should be kept private so do not share your secret API keys. Learn more about API key here

Libraries / SDKs

Xendit has official libraries for different programming languages and mobile platforms. We are continuously developing more libraries and plugins. If you have implemented your own library or an example that you would like to share, send us a link to your code and we'll be happy to add it to the list!

Node.js

Install via npm

npm install xendit-node

See the source on Github

Node.js library is a server-side library that helps you to integrate Xendit easily using Node.js.

List of Supported Products

  1. Credit/debit cards
  2. eWallets
  3. Cardless Credit
  4. Bank Transfer via Virtual Accounts
  5. Retail Outlets
  6. Invoices
  7. Recurring Payments
  8. Payouts
  9. Disbursements
  10. Batch Disbursements

Installation

You can install our Node.js library using npm npm install xendit-node or check out the source on Github

PHP

Download PHP package here

https://packagist.org/packages/xendit/xendit-php

PHP library is a client that is created on top of PHP so it is easier for you to integrate with us to accept payments via our supported payment channels.

You can visit our PHP library in Packagist

There are two versions of Xendit PHP libraries that we support:

List of Supported Products - Xendit PHP v2

  1. Credit/debit cards
  2. eWallets
  3. Cardless Credit
  4. Bank Transfer via Virtual Accounts
  5. Retail Outlets
  6. Invoices
  7. Recurring Payments
  8. Payouts
  9. Disbursements
  10. Batch Disbursements

List of Supported Products - Xendit PHP v1

  1. Credit/debit cards
  2. Bank Transfer via Virtual Accounts
  3. Invoices
  4. Disbursements

Installation and Upgrade Guide

Check out our Github source to learn on how to install or upgrade Xendit PHP library

Java

Install Xendit in your Java code

Maven

<dependency>
  <groupId>com.xendit</groupId>
  <artifactId>xendit-java-lib</artifactId>
  <version>1.0.0</version>
  <type>pom</type>
</dependency>

Gradle

compile 'com.xendit:xendit-java-lib:1.0.0'

Import Xendit Library

import com.xendit.Xendit; 
import com.xendit.exception.XenditException; 
import com.xendit.model.AvailableBank; 
import com.xendit.model.VirtualAccount;

Java library is a server-side library that helps you to integrate Xendit easily using Java.

List of Supported Products

  1. Credit/debit cards
  2. eWallets
  3. Cardless Credit
  4. Bank Transfer via Virtual Accounts
  5. Retail Outlets
  6. Invoices
  7. Recurring Payments
  8. Payouts
  9. Disbursements
  10. Batch Disbursements

Installation

Xendit Java library (Gradle and Maven) installation is easy and simple. For more detail about the steps, refer to the right section

  1. Add Xendit dependency in your Java code
  2. Import Xendit library
  3. Obtain your API keys in Dashboard to start using Xendit Java library APIs.

You can also learn more on our Github source for complete installation guide

Go

See the source on Github

Go library is a server-side library that helps you to integrate Xendit easily using Go programming language.

List of Supported Products

  1. Credit/debit cards
  2. eWallets
  3. Cardless Credit
  4. Bank Transfer via Virtual Accounts
  5. Retail Outlets
  6. Invoices
  7. Recurring Payments
  8. Payouts
  9. Disbursements
  10. Batch Disbursements

Installation

You can install our Go library by checking out our source on Github for complete installation guide

Python

Install via pip

pip install xendit-python

See the source on Github

Python library is a server-side library that helps you to integrate Xendit easily using Python.

List of Supported Products

  1. Credit/debit cards
  2. eWallets
  3. Cardless Credit
  4. QR Codes
  5. Direct Debit
  6. Bank Transfer via Virtual Accounts
  7. Retail Outlets
  8. Invoices
  9. Recurring Payments
  10. Payouts
  11. Disbursements
  12. Batch Disbursements

Installation

You can install our Python library using pip pip install xendit-python or check out the source on Github

Android

Download Xendit Android SDK

https://github.com/xendit/xendit-sdk-android

Android SDK helps you to process digital payments using Xendit with features as follow:

  1. Tokenize credit/debit cards with single-use token
  2. Tokenize credit/debit cards with multiple-use token
  3. Authenticate credit/debit card transactions

iOS

Download Xendit iOS SDK

https://github.com/xendit/xendit-sdk-ios

iOS SDK helps you to process digital payments using Xendit with features as follow:

  1. Tokenize credit/debit cards with single-use token
  2. Tokenize credit/debit cards with multiple-use token
  3. Authenticate credit/debit card transactions

Versioning

Description

Versioning Example

curl https://api.xendit.co/ewallets -X POST \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
   -H X-API-VERSION='2020-02-01' \
   -d external_id='ovo-ewallet' \
   -d amount=1000 \
   -d phone='08123123123'\
   -d ewallet_type='OVO'

Our API is backwards-incompatible, and every changes to the API, we release new version in dated versions. The current version is 2020-02-01. To set the API version on a specific request, send a x-api-version header.

Errors

Your Xendit integration might have to deal with errors at some point when making API requests to Xendit. These errors fall into a few major categories:

The right approach and idempotency semantics to use for handling errors depend on the type of error being handled.

HTTP Status Code

Xendit uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a charge failed, etc). Codes in the 5xx range indicate an error with Xendit's servers (these are rare).

Status Code Description
200 - OK Everything worked as expected
400 - Bad Request The request was unacceptable, often due to missing a required parameter
401 - Unauthorized No valid API key provided
403 - Forbidden The API key doesn't have permissions to perform the request
404 - Not Found The requested resources doesn't exist
500 - Server Errors Something went wrong on Xendit's end (These are rare)

Error Code

Below are some of most common errors across all our endpoints. Specific errors are located under each endpoint.

Error Code Description
API_VALIDATION_ERROR Invalid request errors arise when your request has invalid parameters
INVALID_API_KEY No valid API key provided
REQUEST_FORBIDDEN_ERROR
The API key doesn't have permissions to perform the request
SERVER_ERROR API errors cover any other type of problem (e.g. a temporary problem with Xendit's servers), and are extremely uncommon

Error Handling

Safely retry requests with idempotency

A key part of web API design is the idea of idempotency, defined as being able to apply the same operation multiple times without changing the result beyond the first try. Because a certain amount of intermittent failure is to be expected, clients need a way of reconciling failed requests with a server, and idempotency provides a mechanism for that.

The Xendit API guarantees the idempotency of GET requests, so it's always safe to retry them. Including an idempotency key makes POST and PATCH request idempotent, which prompts the API to do the bookkeeping required to prevent duplicate operations. For example, if a request to create disbursements does not respond due to network connection error, you can retry the request with the same idempotency key to guarantee that no more than one disbursement is created.

Idempotency keys are sent in the x-idempotency-key header, and you should use them for all POST requests to Xendit's API whenever supported. A few common strategies for generating idempotency keys are:

A response that's being replayed from the server because it had already executed previously can be identified by the error code DUPLICATE_TRANSACTION_ERROR

Content errors

Content errros are the result of the contents of an API request being invalid and return a 4xx error code. Integrations should correct the original request and try again. Depending of the type of user error, it may be possible to handle the problem programmatically.

For a POST operation using an idempotency key, as long as an API method began execution, Xendit's API servers will cache the results of the request regardless of what they were. A request that returns a 400 will send back the same 400 if followed by a new request with the same idempotency key. A fresh idempotency key should be generated when modifying the original request to get a successful result. The safest strategy where 4xx errors are concerned is to always generate a new idempotency key.

Network errors

Network errors are the result of connectivity problems between client and server and tend to manifest as low-level errors like socket or timeout exceptions.

This class of errors is where the value of idempotency keys and request retries is most obvious. When intermittent problems occur, clients are usually left in a state where they don't know whether or not the server received the request. To get a definitive answer, they should retry such requests with the same idempotency keys and the same parameters until they're able to receive a result from the server. Sending the same idempotency with different parameters will produce an error indicating that the new request didn't match the original.

Server errors

Server errors are the result of a server-side problem and return a 5xx error code. These errors are the most difficult to handle, so we try to ensure that they happen as infrequently as possible.

As with the errors, retrying them with the same idempotency key will usually produce the same result. The request can be retried with a new idempotency key, but we'd advice against it because it's possible for the original one to have produced side effects.

The result of a 500 request should be treated as indeterminate. The exact nature of any retroactive changes in the system depend heavily on the type of request. For example, if creating a disbursement returns a 500 error but we detect that the information has gone out to a payment network, we'll try to roll it forward and send callback after it has been completed. If not, we'll try to roll it back. However, ideal results under these circumstances are not guaranteed, and requests resulting in a 500 error may proeduce user-visible side effects.

Integration that want to maximize robustness must configure callback handlers that are capable of receiving events that have never been seen in an API response.

Callback

Xendit uses callback to notify your application any time an event happens on your account. Set up callback for events that Xendit doesn't already notify you of, like when a disbursement has been completed, a Virtual Account has been created and paid, or your invoice has expired.

Setup

You need to provide an endpoint in your system to receive callback from us. The callback notification will be sent over POST request to your callback URL that you have set. Setup your callback URL in Callback settings. You can use a tool like ngrok to make your endpoint available for receiving callback during testing.

Delivery Attempts and Retries

Understand how to view delivery attempts and retry logic when callback events aren't acknowledged

View events

When viewing information about a specific event through the Dashboard's Callback tab, you can check how many times Xendit attempted to send an event to the endpoint. This shows the latest response from your endpoint, a list of all attempted callback, and the respective HTTP status codes Xendit received.

Retry logic

Xendit attempts to deliver your callback three times and will stop retrying until we have received response from your server or there is still no response yet.

Receive callback statistics via email

You can also receive summary of your callback statistics (number of success and failed callback) via email every 6 hours. You can enable this feature in Email Recipient settings

Event Handling

Handling callback events correctly is crucial to making sure your integration's business logic works as expected

Acknowledge events immediately

If your callback script performs complex logic, or makes network calls, it's possible that the script would time out before Xendit sees its complete execution. Ideally, your callback handler code (acknowledging receipt of an event by returning a 2xx status code) is separate of any other logic you do for that event.

Handle duplicate events

Callback endpoints might occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing idempotent. One way of doing this is logging the events you've processed, and then not processing already-logged events.

Order of events

Xendit does not guarantee delivery of events in the order in which they are generated. Your endpoint should not expect delivery of these events in this order and should handle this accordingly. You can also use the API to fetch any missing objects.

Security

Keeping your endpoints secure is critical to protecting your customers' information. Xendit provides several ways for you to verify events are coming from Xendit in a secure manner.

Receive events with an HTTPS server

If you use an HTTPS URL for your callback endpoint, Xendit will validate that the connection to your server is secure before sending your callback data. For this to work, your server must be correctly configured to support HTTPS with a valid server certificate.

Verify events are sent from Xendit

Xendit can optionally sign the callback events it sends to your endpoints. We do so by including a token in each event's x-callback-token header. This allows you to verify that the events were sent by Xendit, not by a third party.

Header Parameter Description
x-callback-token
string Your Xendit unique callback token to verify the origin of the callback

Before you can verify tokens, you need to retrieve your callback token from Dashboard's Callback settings. Each secret is unique to each environments.

Balances

Get Balance

Endpoint: Get Balance

GET https://api.xendit.co/balance?account_type={account_type}

Balance is like your wallet since it will tell you how much money is available to you on Xendit. You can retrieve it to see the current balance on your Xendit cash account. Your balance is debited on any money out transaction, e.g. when performing disbursements or Xendit fees are charged. Your balance is credited when money comes into your account, e.g. invoices are paid or you deposit funds.

Request Parameters

Example Get Balance Request

curl https://api.xendit.co/balance -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php

  use Xendit\Xendit;
  require 'vendor/autoload.php';

  Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');

  $getBalance = \Xendit\Balance::getBalance('CASH');
  var_dump($getBalance);

?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });

const { Balance } = x;
const balanceSpecificOptions = {};
const b = new Balance(balanceSpecificOptions);

const resp = await b.getBalance()
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
  Balance balance = Balance.get();
} catch (XenditException e) {
  e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="

data := balance.GetParams{
  AccountType: "CASH",
}

resp, err := balance.Get(&data)
if err != nil {
  log.Fatal(err)
}

fmt.Printf("balance: %+v\n", resp)

Get Balance allows you to retrieve the balance of your cash and pending balance. Some use cases include: deciding when you may need to withdraw funds, and determining if you have funds to disburse

Header Parameter Type Description
for-user-id
optional
string The sub-account user-id that you want to make this transaction for.

This header is only used if you have access to xenPlatform. See xenPlatform for more information

Query Parameter Type Description
account_type
optional
default: CASH
string The selected balance type

available values: CASH, HOLDING, TAX

Response Parameters

Example Get Balance Response

{
  "balance": 1241231
}
Parameter Description
balance The balance remaining in your cash account

Payment Channels

Get Payment Channels

Endpoint: Get Payment Channels API

GET https://api.xendit.co/payment_channels

Example Get Payment Channels

curl https://api.xendit.co/payment_channels -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:

Request Parameters

Returns an array of payment channel objects. Use this to identify which payment channels have been enabled for your business.

Header Parameter Type Description
for-user-id
optional
string The Sub-account user-id that you want to make this transaction for

This header is only used if you have access to xenPlatform. See xenPlatform for more information.

Response Parameters

Example Get Payment Channels Response

[
  {
    "business_id": "xxxxxxxx",
    "is_livemode": true, 
    "channel_code": "BRI",
    "name": "BRI Virtual account",
    "currency": "IDR",
    "channel_category": "VIRTUAL_ACCOUNT",
    "is_enabled": false
  },
  {
    "business_id": "xxxxxxxx",
    "is_livemode": true, 
    "channel_code": "MASTERCARD",    
    "name": "Mastercard credit and debit cards",
    "currency": "IDR",
    "channel_category": "CREDIT_CARD",
    "is_enabled": true     
  },
  {
    "business_id": "xxxxxxxx",
    "is_livemode": true, 
    "channel_code": "MASTERCARD",    
    "name": "Mastercard credit and debit cards",
    "currency": "USD",
    "channel_category": "CREDIT_CARD",
    "is_enabled": true     
  }
  ...
]
Parameter Type Description
business_id
required
string Your business ID
is_livemode
required
boolean true When making the request with your live API key. false when making the request with your test API key
channel_code
required
string Payment channel code
name
required
string Payment channel name
currency
required
string Processing currency of the payment channel. Based on ISO 4217 currency code.
channel_category
required
string Payment channel category.
Available values: VIRTUAL_ACCOUNT, RETAIL_OUTLET, EWALLET,CREDIT_CARD
is_enabled
required
boolean When true, an API request can be successfully made for the business with the payment channel. When false, the API request will fail. You should activate the payment channel in the dashboard settings to make it successfully

Credit Cards

Create Token

Javascript Function: createToken

Xendit.card.createToken(tokenData, function (err, data) {
    if (err) {
        //Define error handling
    }

    if (data.status === 'VERIFIED') {
        // Handle success
    } else if (data.status === 'IN_REVIEW') {
        // Handle authentication (3DS)
    } else if (data.status === 'FAILED') {
        // Handle failure
    }
});

Tokenization is the process where card details (account number and expiration date) are securely collected on the client-side, so that sensitive card data is never passed through your systems. Tokens are then used to Charge Cards.

Example tokenData object

{        
    "amount": "10000",        
    "card_number": "4000000000000002",        
    "card_exp_month": "12",        
    "card_exp_year": "2017",        
    "card_cvn": "123",
    "is_multiple_use": false,
    "should_authenticate": true
}

Example Tokenization Response

{
    "id": "586f0ba2ab70de5d2b409e0d",
    "authentication_id": "598c3e5a8c62078a5108f661",
    "masked_card_number": "400000XXXXXX0002",
    "status": "IN_REVIEW",
    "payer_authentication_url": "https://api.xendit.co/credit_card_tokens/586f0ba2ab70de5d2b409e0d/authentication_redirect?api_key=xnd_public_development_key"
}

Tokens can be created for single or multiple use. If you plan to save a card for future use, set is_multiple_use to true.

See our Tokenization Sample for an example implementation.

Single Use Tokens

For single-use tokens, authentication is performed by default, and so the amount field is also required. If optional authentication is enabled on your account, it can be bypassed by setting should_authenticate to false.

Multiple Use Tokens

When tokenizing a card for multi-use, the amount field is optional. If you want to use Authentication for a multi-use token, the amount field must be specified during Authentication. See Create Authentication for more details.

Request Parameters (Money-in write permission)

Header Parameter Type Description
for-user-id
optional
string The sub-account user-id that you want to make this transaction for.

This header is only used if you have access to xenPlatform. See xenPlatform for more information

Body Parameter Type Description
amount
optional
string The charge amount. Only required for single use tokens with bundled authentication.
card_number
required
string Card number
card_exp_month
required
string Card expiration month
card_exp_year
required
string Card expiration year
card_cvn
optional
string Card CVN/CVV code
Optional but highly recommended. Required for cards issued in Europe.
is_multiple_use
optional
default: false
boolean Whether or not to save token for multiple use
should_authenticate
optional
default: true
boolean Whether or not to bundle authentication with tokenization.
By default, authentication is required for all transactions. You can request to enable optional authentication via your Xendit Dashboard.
xenditResponseHandler
required
function The response handler function is called after tokenization is attempted, to receive errors and tokenization response

Response Parameters

Parameter Type Description
id
required
string The token ID. This will be used later to Charge the funds from the credit card
authentication_id
optional
string Returned only if authentication was bundled with tokenization. Xendit.js bundles authentication with single-use token creation by default, but not for multiple-use token creation.
masked_card_number
required
string The first 6 digits and last 4 digits of the tokenized card.
status
required
string Tokenization status. See Tokenization Statuses
payer_authentication_url
optional
string Returned only if authentication is bundled with tokenization, and the status returned is IN_REVIEW. This field contains the URL to the page for users to authenticate themselves using 3DS. See Tokenization Statuses.
failure_reason
optional
string If the tokenization status is FAILED, this describes the reason for failure. See Tokenization Failure Reasons.

Statuses

Status Description
IN_REVIEW Returned only if authentication is bundled with tokenization, and therefore the customer must authenticate their identity. Xendit provides a URL which you should navigate your users to for easily performing 3DS.
VERIFIED This means that a token was successfully created. If authentication was bundled with tokenization, it also means that the user has successfully authenticated their identity via 3DS. It is now safe to send the token to your backend for charging.
FAILED Returned only if authentication is bundled with tokenization, and authentication has failed. Will always return AUTHENTICATION_FAILED as the failure reason.
The token will still be created and authentication can be attempted again using the created token.

Failure Reasons

Failure Reason Description
AUTHENTICATION_FAILED This status means the customer tried to authenticate using 3DS but did not successfully complete the authentication.

Error Codes

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
INVALID_JSON_FORMAT
400
The request body is not valid JSON.
ACCOUNT_NUMBER_INVALID_ERROR
400
Credit card number is invalid.
VALIDATION_ERROR
400
Data was passed in an incorrect format.
BRAND_NOT_SUPPORTED_ERROR
400
Card brand is not supported. Ask user to try a Visa/Mastercard.
CREDIT_CARD_DATA_ERROR
400
Invalid data was sent to the credit card processor.
AUTHENTICATION_REQUIRED_ERROR
400
A valid authentication_id was not included in the request, and your account is not configured for optional authentication. Include a valid authentication_id or contact us if you would like to enable optional authentication.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
VERIFICATION_TIMEOUT_ERROR
408
The credit card network timed out when trying to tokenize the card.
TEMPORARY_SERVICE_ERROR
503
There was a problem with the credit card network, which prevents tokenization.
CONNECTION_ERROR
Error connecting to our server. Try again and if the error persists, try with another device/network.
TOKENIZATION_ERROR
General error. Try again or try with a different card.

Create Authentication

Javascript Function: createAuthentication

Xendit.card.createAuthentication(authenticationData, function (err, data) {
    if (err) {
        //Define error handling
    }

    if (data.status === 'VERIFIED') {
        // Handle success
    } else if (data.status === 'IN_REVIEW') {
        // Handle authentication (3DS)
    } else if (data.status === 'FAILED') {
        // Handle failure
    }
});

To authenticate a token, use the Xendit.card.createAuthentication function in Xendit.js. This function accepts an authenticationData object and returns an authentication_id which can be used to authenticate a charge. For more details on creating a charge, see Create Charge.

See our Authentication Sample for an example implementation.

Example authenticationData object

{        
    "amount": "10000",        
    "token_id": "58e2096018b815f555c8a524"
}

Example Authentication Response

{
    "id": "58e2097218b815f555c8a526",
    "status": "VERIFIED"
}

Request Parameters

Header Parameter Type Description
for-user-id
optional
string The sub-account user-id that you want to make this transaction for.

This header is only used if you have access to xenPlatform. See xenPlatform for more information

Body Parameter Type Description
amount
required
string Authentication amount
token_id
required
string Token to authenticate
xenditResponseHandler
required
function Response handler, called after authentication attempt to handle errors and response.

Response Parameters

Parameter Type Description
id
required
string Authentication ID returned by Xendit, used when creating a Charge. If authentication status is FAILED, this id will still be returned but authentication will need to be performed again.
status
required
string Authentication status. See Tokenization Statuses
payer_authentication_url
optional
string If status is IN_REVIEW, this contains the URL for authenticating users with 3DS
failure_reason
optional
string If status is FAILED, this describes the failure. See Tokenization Failure Reasons.

Failure Reasons

Failure Reason Description
AUTHENTICATION_FAILED The customer tried to authenticate using 3DS but did not successfully complete the authentication.

Create Authorization

Definition: Create authorization

POST https://api.xendit.co/credit_card_charges

Example Create Authorization Request

curl -X POST \
  https://api.xendit.co/credit_card_charges \
  -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
  -H 'content-type: application/json' \
  -d '{
      "token_id" : "598d5d0e51e0870d44c61534",
      "external_id": "postman-charge-1502436817",
      "amount": 140000,
      "authentication_id":"598d5d0f51e0870d44c61535",
      "card_cvn":"123",
      "capture":false
    }'
<?php
  require 'vendor/autoload.php';

  $options['secret_api_key'] = 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==';

  $xenditPHPClient = new XenditClient\XenditPHPClient($options);

  $external_id = 'sample-external-id-1475459775872';
  $token_id = 'sample-token-id-1475459775872';
  $amount = 140000;
  $authentication_id = '58e2097218b815f555c8a526';
  $capture = false;

  $response = $xenditPHPClient->captureCreditCardPayment($external_id, $token_id, $amount);
  print_r($response);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });

const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);

const resp = await card.createAuthorization({
  externalID: 'sample-external-id-1475459775872',
  tokenID: 'sample-token-id-1475459775872',
  amount: 140000,
  authID: '58e2097218b815f555c8a526',
})
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
  CreditCardCharge creditCardCharge = CreditCard.createAuthorization(
  "token_id", // tokenId
  "postman-charge-1502436793", // externalId
  140000, // amount
  "auth_id", // authenticationId
  "123", // Card CVN
  false // capture
  );
} catch (XenditException e) {
  e.printStackTrace();
}

Example Create Authorization Response

{
    "created": "2020-01-11T07:33:14.442Z",
    "status": "AUTHORIZED",
    "business_id": "5850e55d8d9791bd40096364",
    "authorized_amount": 140000,
    "external_id": "postman-charge-1502436793",
    "merchant_id": "xendit",
    "merchant_reference_code": "598d5d0d51e0870d44c61533",
    "card_type": "CREDIT",
    "masked_card_number": "400000XXXXXX0002",
    "charge_type": "SINGLE_USE_TOKEN",
    "card_brand": "VISA",
    "bank_reconciliation_id": "5132390610356134503009",
    "eci": "05",
    "id": "598d5dba51e0870d44c61539"
}

You can do authorization using create charge endpoint. Just capture field as false, and you will receive an authorized charge response.

Example Zero Amount Authorization Request

curl -X POST \
  https://api.xendit.co/credit_card_charges \
  -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
  -H 'content-type: application/json' \
  -d '{
      "token_id" : "598d5d0e51e0870d44c61534",
      "external_id": "postman-charge-1502436817",
      "amount": 0,
      "authentication_id":"598d5d0f51e0870d44c61535",
      "card_cvn":"123"
    }'
<?php
  require 'vendor/autoload.php';

  $options['secret_api_key'] = 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==';

  $xenditPHPClient = new XenditClient\XenditPHPClient($options);

  $external_id = 'sample-external-id-1475459775872';
  $token_id = 'sample-token-id-1475459775872';
  $amount = 0;
  $authentication_id = '58e2097218b815f555c8a526';

  $response = $xenditPHPClient->captureCreditCardPayment($external_id, $token_id, $amount);
  print_r($response);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });

const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);

const resp = await card.createAuthorization({
  externalID: 'sample-external-id-1475459775872',
  tokenID: 'sample-token-id-1475459775872',
  amount: 0,
  authID: '58e2097218b815f555c8a526',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
  CreditCardCharge creditCardCharge = CreditCard.createAuthorization(
  "token_id", // tokenId
  "test_id", // externalId
  0, // amount
  "auth_id", // authenticationId
  "123", // Card CVN
  false // capture
  );
} catch (XenditException e) {
  e.printStackTrace();
}

Example Zero Amount Authorization Response

{
    "created": "2020-01-11T07:33:14.442Z",
    "status": "AUTHORIZED",
    "business_id": "5850e55d8d9791bd40096364",
    "authorized_amount": 0,
    "external_id": "postman-charge-1502436793",
    "merchant_id": "xendit",
    "merchant_reference_code": "598d5d0d51e0870d44c61533",
    "card_type": "CREDIT",
    "masked_card_number": "400000XXXXXX0002",
    "charge_type": "SINGLE_USE_TOKEN",
    "card_brand": "VISA",
    "bank_reconciliation_id": "5132390610356134503009",
    "eci": "05",
    "id": "598d5dba51e0870d44c61539"
}

Zero Amount Authorization

You can also do zero amount authorization amount using create charge endpoint. Just put 0 for amount field, and you will receive and authorized charge response.

To be able to do zero amount authorization, your account must have card processor that has zero amount authorization compatibility.
Please contact us to set up zero amount compatible card processor for your account. You can always use development environment to try zero amount authorization feature.

Reverse Authorization

Definition: Reversing Authorized Charge

POST https://api.xendit.co/credit_card_charges/:charge_id/auth_reversal

Example Reverse Authorization

curl -X POST \
  https://api.xendit.co/credit_card_charges/:charge_id/auth_reversal \
  -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
  -d '{
    "external_id": "reverse-authorization-1502436817",
    }'
<?php

    use Xendit\Xendit;
    require 'vendor/autoload.php';

    Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');

    $id = '5ecc82736275b80019591c91';
    $params = ['external_id' => 'reverse-authorization-1502436817'];

    $reverseAuth = \Xendit\Cards::reverseAuthorization(
        $id,
        $params
    );
    var_dump($reverseAuth);

?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });

const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);

const resp = await card.reverseAuthorization({
  externalID: 'reverse-authorization-1502436817',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
  CreditCardReverseAuth creditCardReverseAuth = CreditCard.reverseAuthorization(
    "1234567", //chargeId
    "reverse-authorization-1502436817" //externalId
  );
} catch (XenditException e) {
  e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="

reverseAuthorizationData := card.ReverseAuthorizationParams{
  ChargeID:   "123",
  ExternalID: "reverse-authorization-1502436817",
}

reverseAuthorizationResp, err := card.ReverseAuthorization(&reverseAuthorizationData)
if err != nil {
  log.Fatal(err)
}

fmt.Printf("reversed authorization: %+v\n", reverseAuthorizationResp)

Example of request body

{        
    "external_id": "reverse-authorization-1502436817",
}

Example of Reverse Authorization Response

{
    "status": "SUCCEEDED",
    "currency": "IDR",
    "credit_card_charge_id": "5ecc82640d679500199621ad",
    "business_id": "5dd7928f4e6d9a2ec299ea43",
    "external_id": "reverse-authorization-1502436817",
    "amount": 5000,
    "created": "2020-05-26T02:44:03.458Z",
    "id": "5ecc82736275b80019591c91"
}

This API provides reversing charge when the charge has AUTHORIZED status and hasn't yet captured.

Request Parameters

Header Parameter Type Description
for-user-id
optional
string The sub-account user-id that you want to make this transaction for.

This header is only used if you have access to xenPlatform. See xenPlatform for more information

Body Parameter Type Description
external_id
required
string Reverse authorization reference to help you track your request

Response Parameters

Parameter Type Description
status
required
string Status of the reverse authorization. See Reverse Authorization Statuses.
currency
required
string Currency of the charge that requested to be reversed.
credit_card_charge_id
required
string The ID of the charge that requested to be reversed.
business_id
required
string The ID of your business in Xendit.
external_id
required
string Unique Identifier for your Reversed Charge reference
amount
required
number The amount that requested to be reversed for this charge.
created
required
string An ISO timestamp that tracks when the reverse authorization was made.
id
required
string ID of the charge transaction in Xendit system that requested to be reversed.
failure_reason
optional
string If status is FAILED, this describes the failure. See Reverse Authorization Failure Reasons.

Statuses

Recommendation Description
SUCCEEDED
Reverse Authorization request is success
FAILED
Reverse Authorization is failed with detailed failure reason

Failure Reasons

Failure Reason Description
REVERSE_AUTHORIZATION_REJECTED_BY_BANK The authorization that you requested to be reversed is rejected by the bank. There's possibility that the authorization is no longer valid and the authorized amount is already reversed back automatically to the card holder's credit balance.
PROCESSOR_ERROR The reverse authorization failed because there's an integration issue between card processor and the bank. Contact us if you encounter this issue.

Error Codes

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
CHARGE_ALREADY_REVERSED_ERROR
400
Charge already reversed, therefore cannot be reversed
CHARGE_ALREADY_CAPTURED_ERROR
400
Charge already captured, therefore cannot be reversed
CHARGE_FAILED_ERROR
400
Charge is failed, therefore cannot be reversed
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
CREDIT_CARD_CHARGE_NOT_FOUND_ERROR
404
credit_card_charge_id not found for this transaction. Please try with another valid charge ID
INVALID_AMOUNT_FOR_REVERSE_AUTHORIZATION_ERROR
400
Invalid charge amount to be reversed. Please make sure that the authorized amount that you requested to be reversed is no 0.

Create Charge

Definition: Create Charge

POST https://api.xendit.co/credit_card_charges

Example Charge Request

curl -X POST \
  https://api.xendit.co/credit_card_charges \
  -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
  -H 'content-type: application/json' \
  -d '{
      "token_id" : "598d5d0e51e0870d44c61534",
      "external_id": "postman-charge-1502436817",
      "amount": 900000,
      "authentication_id": "598d5d0f51e0870d44c61535",
      "card_cvn": "123",
      "descriptor": "My new store"
      "currency": "IDR",
      "mid_label": "IDR_MID",
      "billing_details": {
        "given_names": "John",
        "middle_name": "Doe",
        "surname": "John Doe",
        "email": "johndoe@xendit.co",
        "mobile_number": "+62899336634448",
        "phone_number": "+629934448",
        "address": {
          "street_line_1": "Panglima Polim IV",
          "street_line_2": "Ruko Grand Panglima Polim, Blok E",
          "suburb": "Kebayoran",
          "city": "Jakarta Selatan",
          "province": "DKI Jakarta",
          "zip_code": "993448",
          "country": "Indonesia"
        }
      },
      "promotion": {
          "reference_id": "BCA_10",
          "original_amount": 1000000
      },
      "installment": {
          "count": 3,
            "interval": "month"
      }
    }'
<?php

  use Xendit\Xendit;
  require 'vendor/autoload.php';

  Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');

  $params = [
      'token_id' => '5e2e8231d97c174c58bcf644',
      'external_id' => 'card_' . time(),
      'authentication_id' => '5e2e8658bae82e4d54d764c0',
      'amount' => 15000,
      'card_cvn' => '123',
      'capture' => false
  ];

  $createCharge = \Xendit\Cards::create($params);
  var_dump($createCharge);

?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });

const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);

const resp = await card.createCharge({
  externalID: 'sample-external-id-1475459775872',
  tokenID: 'sample-token-id-1475459775872',
  amount: 900000,
  authID: '58e2097218b815f555c8a526',
  cardCvn: "123",
  descriptor: "My new store",
  currency: "IDR",
  midLabel: "IDR_MID",
  billing_details: {
      given_names: "John",
      middle_name: "Doe",
      surname: "John Doe",
      email: "johndoe@xendit.co",
      mobile_number: "+62899336634448",
      phone_number: "+629934448",
      address: {
          street_line_1: "Panglima Polim IV",
          street_line_2: "Ruko Grand Panglima Polim, Blok E",
          suburb: "Kebayoran",
          city: "Jakarta Selatan",
          province: "DKI Jakarta",
          zip_code: "993448",
          country: "Indonesia"
      }
  },
  promotion: {
      referenceId: "BCA_10",
      originalAmount: 1000000
  },
  installment: {
      count: 3,
      interval: "month"
  }
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
  CreditCardCharge creditCardCharge = CreditCard.createCharge(
    "token_id", //tokenId
    "postman-authorize-1502437417", //externalId
    90000, //amount
    "auth_id", //authenticationId
    "123", //Card CVN
    "XENDIT*MYBUSINESS-MY NEW STORE" //Descriptor
  );
} catch (XenditException e) {
  e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="

createChargeData := card.CreateChargeParams{
  TokenID:          "example-token-id",
  AuthenticationID: "example-authentication-id",
  ExternalID:       "postman-charge-1502436793",
  Amount:           900000,
  Capture:          new(bool),
}

chargeResp, err := card.CreateCharge(&createChargeData)
if err != nil {
  log.Fatal(err)
}

fmt.Printf("created charge: %+v\n", chargeResp)

Once you have a token, that token can be used to charge a card.

Request Parameters

Header Parameter Type Description
for-user-id
optional
string The sub-account user-id that you want to make this transaction for.

This header is only used if you have access to xenPlatform. See xenPlatform for more information


Body Parameter Type Description
token_id
required
string The token ID used to charge the card.
external_id
required
string A unique identifier of your choice. Max 64 characters.
amount
required
number Amount that expected to be charged.
authentication_id
optional
string Authentication ID for authenticating charge. Optional only if charge was already authenticated with a single-use token, or if optional authentication is enabled for your account.
card_cvn
optional
string 3 or 4 digit CVN (CVC) code. Optional but highly recommended. Required for cards issued in Europe.
capture
optional

default: true
boolean Whether or not to capture immediately. Set to false to issue an authorization (hold funds) only, to be captured later with the capture endpoint.
Note: Authorizations expire in 7 days.
descriptor
optional
string Specific descriptor to define merchant's identity.
Note:
For aggregator merchant, it will always return XENDIT*[MERCHANT_NAME]-DESCRIPTOR
For switcher merchant, it will always return [MERCHANT_NAME]-DESCRIPTOR
currency
optional

default: IDR
string Currency which you want to process the transaction in. Use a three-letter ISO currency code. If left blank, it will default to IDR
mid_label
optional
string Specific string value which labels any of your Merchant IDs (MID) set up with Xendit. This can be configured in the list of MIDs on your Dashboard settings. (If this is not included in a request, and you have more than 1 MID in your list, the transaction will proceed using your prioritized MID (first MID on your list)).
Note:
Only available in the response for switcher merchant
billing_details
optional
object Billing details of the cardholder. If entered, should correspond with billing details registered by cardholder with their issuer. Required for a card to be verified by the Address Verification System (AVS) - only for USA / Canadian / Great Britain cards.
billing details child parameters
Key Value
given_names string Given name (also known as first name)
middle_name
optional
string Middle name
surname
optional
string Surname (also known as last name)
email
optional
string Email
mobile_number
optional
string Mobile phone number
phone_number
optional
string Other phone number (e.g. landline)
address
required
object Address Object
address details child parameters
Key Value
country
required
string 2-letter ISO 3166-2 country code for the customer's country of residence
street_line1
optional
string Building name and apartment unit number
street_line2
optional
string Building street address
city
optional
string City, village or town as appropriate
province
optional
string Geographic area, province, or region, if applicable
state
optional
string Formal state designation within country, if applicable. If the user is USA citizen, make sure to use state code (e.g put CA instead of California)
postal_code
optional
string Postal, zip or rural delivery code, if applicable
description
optional
string Freetext to describe type of address eg. home, provincial, work, etc.
promotion
optional
object If you are want to apply a Promotion to a charge, you must input these parameters.
promotion details child parameters
Key Value
reference_id
optional
stringUnique reference, such as an ID or name, you wish to assign to the created Promotion
original_amount
optional
numberThe amount of the original transaction (before the Promotion discount).
installment
optional
object These parameters are required to mark a transaction as an installment.
installment details child parameters
count
optional
numberTogether with the "interval" parameter, this defines your installment tenor. If you want the installment tenor to be 3 months, then the value of "count" should be 3.
interval
optional
string Together with the "count" parameter, this defines your installment tenor. If you want the installment tenor to be 3 months, then the value of "interval" should be "month"

Example Charge Response

{
    "created": "2020-01-11T07:33:14.442Z",
    "status": "CAPTURED",
    "business_id": "5850e55d8d9791bd40096364",
    "authorized_amount": 900000,
    "external_id": "postman-charge-1502436793",
    "merchant_id": "xendit",
    "merchant_reference_code": "598d5d0d51e0870d44c61533",
    "card_type": "CREDIT",
    "masked_card_number": "400000XXXXXX0002",
    "charge_type": "SINGLE_USE_TOKEN",
    "card_brand": "VISA",
    "bank_reconciliation_id": "5132390610356134503009",
    "eci": "05",
    "capture_amount": 900000,
    "descriptor": "XENDIT*MYBUSINESS-MY NEW STORE",
    "id": "598d5dba51e0870d44c61539",
    "mid_label": "IDR_MID",
    "promotion": {
        "reference_id": "BCA_10",
        "original_amount": "1000000"
    },
    "installment": {
        "count": 3,
        "interval": "month"
    }
}

Example Authorization Response

{
    "created": "2020-01-11T07:43:39.563Z",
    "status": "AUTHORIZED",
    "business_id": "5850e55d8d9791bd40096364",
    "authorized_amount": 90000,
    "external_id": "postman-authorize-1502437417",
    "merchant_id": "xendit",
    "merchant_reference_code": "598d5ffb51e0870d44c6153a",
    "card_type": "CREDIT",
    "masked_card_number": "400000XXXXXX0002",
    "charge_type": "SINGLE_USE_TOKEN",
    "card_brand": "VISA",
    "bank_reconciliation_id": "5132390610356134503009",
    "eci": "05",
    "descriptor": "XENDIT*MYBUSINESS-MY NEW STORE",
    "id": "598d602b51e0870d44c6153d",
    "mid_label": "IDR_MID",
    "promotion": {
        "reference_id": "BCA_10",
        "original_amount": "100000"
    },
    "installment": {
        "count": 3,
        "interval": "month"
    }
}

Charge Response



Parameter Type Description
created
required
string An ISO timestamp that tracks when the charge was made.The token ID used to charge the card. The timezone will be default
Timezone: GMT+0
charge_type
required
string Types of charges. See Charge types.
business_id
required
string The ID of your business in Xendit.
authorized_amount
required
number The amount that've been authorized for this charge.
external_id
required
string A unique identifier of your choice.
card_type
required
string Type of card (CREDIT or DEBIT).
merchant_id
required
string Your merchant ID used for processing credit cards with the bank.
masked_card_number
required
string Masked card number. The first 6 digits are the BIN (Bank Identification Number).
charge_type
required
string Types of charges. See Charge types.
card_brand
required
string Card scheme (VISA, MASTERCARD, JCB, ...).
bank_reconciliation_id
required
string ID of the transaction that can be reconciled with the bank.
eci
optional
string Status of 3DS authentication. See ECI codes.
capture_amount
optional
number Amount captured for this charge. Can be up to authorized_amount.
failure_reason
optional
string If status is FAILED, this describes the failure. See Charge Failure Reasons.
approval_code
optional
string Series of number (usually 6 digits) which is a code that indicate your authorization is approved by acquiring bank.
merchant_reference_code
required
string An ID used to reconcile transactions with the bank.
descriptor
optional
string Description which already inputted by merchant when creating a charge.
Note:
For aggregator merchant, it will always return XENDIT*[MERCHANT_NAME]-DESCRIPTOR
For switcher merchant, it will always return [MERCHANT_NAME]-DESCRIPTOR
currency
optional

default: IDR
string Currency which you want to process the transaction in. Use a three-letter ISO currency code. If left blank, it will default to IDR
mid_label
optional
string Specific string value which labels any of your Merchant IDs (MID) set up with Xendit. This can be configured in the list of MIDs on your Dashboard settings. (If this is not included in a request, and you have more than 1 MID in your list, the transaction will proceed using your prioritized MID (first MID on your list)).
Note:
Only available in the response for switcher merchant
id
required
string ID of the charge transaction in Xendit system.
promotion
optional
object Detail of promotion that used for this transaction.
promotion details child parameters
Key Value
reference_id
optional
stringUnique reference, such as an ID or name, you wish to assign to the created Promotion
original_amount
optional
numberThe amount of the original transaction (before the Promotion discount).
installment
optional
object These parameters will be returned to mark a transaction as an installment.
installment details child parameters
count
optional
numberTogether with the "interval" parameter, this defines your installment tenor count.
interval
optional
string Together with the "count" parameter, this defines your installment tenor interval."

Statuses

Status Description
CAPTURED Charge is successfully captured and the funds will be settled according to the settlement schedule.
AUTHORIZED Charge is successfully authorized.
REVERSED Charge is successfully reversed.
FAILED Charge failed. See Charge Failure Reasons

Failure Reasons

Failure Reason Description
EXPIRED_CARD The card you are trying to capture is expired. Ask your customer for a different card
CARD_DECLINED The card you are trying to capture has been declined by the bank. Ask your customer for a different card
INSUFFICIENT_BALANCE The card you are trying to capture does not have enough balance to complete the capture
STOLEN_CARD The card you are trying to capture has been marked as stolen. Ask your customer for a different card
INACTIVE_CARD The card you are trying to capture is inactive. Ask your customer for a different card
INVALID_CVN The cvn that being submitted is not correct.
PROCESSOR_ERROR The charge failed because there's an integration issue between card processor and the bank. Contact us if you encounter this issue.
BIN_BLOCK The cards' BIN has been blocked by request from the Bank.

Error Codes

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
INVALID_JSON_FORMAT
400
The request body is not valid JSON.
TOKEN_ALREADY_USED_ERROR
400
The single-use token ID has already been used in a charge.
AUTHENTICATION_ALREADY_USED_ERROR
400
The authentication ID has already been used in a charge.
INVALID_TOKEN_ID_ERROR
400
The token ID format is invalid.
INVALID_CVN_LENGTH_ERROR
400
The length of CVN is invalid. For AMEX card, CVN length must be 4 digit and for the others card type it must be 3.
AUTHENTICATION_ID_MISSING_ERROR
400
Authentication ID is required for this charge.
AMOUNT_GREATER_THAN_AUTHENTICATED_ERROR
400
Charge amount was greater than what was authenticated.
INVALID_AUTHENTICATION_ID_ERROR
400
The authentication ID format is invalid.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
TOKEN_NOT_FOUND_ERROR
404
The token ID was not found in the system.
AUTHENTICATION_NOT_FOUND_ERROR
404
Authenticated token with given authentication ID is not found.
MID_NOT_FOUND_ERROR
404
The MID specified in "mid_label" cannot be found. Check if you have registered this MID, or if you entered the MID label incorrectly
INVALID_PROMOTION_DETAILS
400
The promotion detail which inputted in this request is invalid. Please change the input or check if you have available promotion in your system or not.
CARDHOLDER_NAME_REQUIRED
400
Please send cardholder name fields in the billing_details object in your request body.
INSTALLMENT_BELOW_MINIMUM_AMOUNT
400
Amount is below the minimum allowed for installments.
BRI, BNI: Rp 500.000
INSTALLMENT_UNAVAILABLE
404
Possible error messages:
  • Installments are not available for cards from this bank. Please try with a card from another bank.
  • The requested installment interval is currently not supported. Please try an installment transaction with another interval.

  • AMOUNT_BELOW_MINIMUM_LIMIT
    400
    The amoubnt which inputted in this request is below your minimum limit. Please send another request with amount equal to or greater than the minimum limit. Default minimum limit based on currency:
  • IDR: 5000.
  • PHP: 20.

  • AMOUNT_ABOVE_MAXIMUM_LIMIT
    400
    The amoubnt which inputted in this request is above your maximum limit. Please send another request with amount equal to or lower than the maximum limit. Default maximum limit based on currency:
  • IDR: 200000000.
  • PHP: 700000.

  • Charge Types

    Status Description
    SINGLE_USE_TOKEN Charge created with single-use token
    MULTIPLE_USE_TOKEN Charge created with multiple-use token
    RECURRING Charge a recurring charge in a subscription

    ECI Codes

    ECI Description
    0 Unable to Authenticate (MasterCard)
    1 Authentication attempted (MasterCard)
    2 Successful authentication (MasterCard)
    5 Successful authentication (Visa, AMEX, JCB)
    6 Authentication attempted (Visa, AMEX, JCB)
    7 Unable to Authenticate (Visa, AMEX, JCB)

    Capture Charge

    Definition: Capture Charge

    POST https://api.xendit.co/credit_card_charges/:credit_card_charge_id/capture

    Example Capture Charge Request

    curl https://api.xendit.co/credit_card_charges/5877255293ff67900c6aa64e/capture \
        -X POST \
        -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
        -d amount=15000
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '598942c4bb91a4ec309e9a37';
      $params = ['amount' => 10000];
    
      $captureCharge = \Xendit\Cards::capture($id, $params);
      var_dump($captureCharge);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Card } = x;
    const cardSpecificOptions = {};
    const card = new Card(cardSpecificOptions);
    
    const resp = await card.captureCharge({
      chargeID: id,
      amount: 10000,
    });
    console.log(resp)
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      CreditCardCharge creditCardCharge = CreditCard.captureCharge(
        "12345678", //chargeId
        10000 //amount
      );
    } catch (XenditException e) {
      e.printStackTrace();
    }
    captureChargeData := card.CaptureChargeParams{
        ChargeID: "598942c4bb91a4ec309e9a37",
        Amount:   9900,
    }
    
    chargeResp, err := card.CaptureCharge(&captureChargeData)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("captured charge: %+v\n", chargeResp)

    Example Capture Charge Response

    {
      "created": "2020-01-08T04:49:08.815Z",
      "status": "CAPTURED",
      "business_id": "5848fdf860053555135587e7",
      "authorized_amount": 10000,
      "external_id": "test-pre-auth",
      "merchant_id": "xendit",
      "merchant_reference_code": "598942aabb91a4ec309e9a35",
      "card_type": "CREDIT",
      "masked_card_number": "400000XXXXXX0002",
      "charge_type": "SINGLE_USE_TOKEN",
      "card_brand": "VISA",
      "bank_reconciliation_id": "5132390610356134503009",
      "capture_amount": 9900,
      "descriptor": "My new store",
      "id": "598942c4bb91a4ec309e9a37"
    }

    Capturing a charge only needed if you do pre-authorization by specifying capture to false in create charge request. You can capture a charge with amount different than authorized amount as long as it's less than authorized amount. Response for this endpoint is the same as create charge response

    Request Parameters

    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Query Parameter Type Description
    credit_card_charge_id
    required
    string Charge ID of authorization
    Body Parameter Type Description
    amount
    required
    string Amount to be captured. Can be up to amount of authorization but not more

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not valid JSON.
    AMOUNT_GREATER_THAN_AUTHORIZED_ERROR
    400
    Capture amount is larger than authorized amount
    INVALID_CHARGE_STATUS_ERROR
    400
    Charge status is not AUTHORIZED
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    CREDIT_CARD_CHARGE_NOT_FOUND_ERROR
    404
    credit_card_charge_id not found
    AUTHORIZATION_EXPIRED
    400
    It is likely that the authorization has been reversed because it expired. Please create another authorization or charge.

    Get Charge

    Definition: Get Charge

    GET https://api.xendit.co/credit_card_charges/:credit_card_charge_id

    Example Get Charge Request

    curl https://api.xendit.co/credit_card_charges/5877255293ff67900c6aa64e \
        -X GET \
        -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '598942c4bb91a4ec309e9a37';
      $getCharge = \Xendit\Cards::retrieve($id);
      var_dump($getCharge);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Card } = x;
    const cardSpecificOptions = {};
    const card = new Card(cardSpecificOptions);
    
    const resp = await card.getCharge({ chargeID: '5877255293ff67900c6aa64e' });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      CreditCardCharge creditCardCharge = CreditCard.getCharge("5877255293ff67900c6aa64e");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    getChargeData := card.GetChargeParams{
      ChargeID: "598942c4bb91a4ec309e9a37",
    }
    
    chargeResp, err := card.GetCharge(&getChargeData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("retrieved charge: %+v\n", chargeResp)

    Example Get Charge Response

    {
      "created": "2020-01-08T04:49:08.815Z",
      "status": "CAPTURED",
      "business_id": "5848fdf860053555135587e7",
      "authorized_amount": 10000,
      "external_id": "test-pre-auth",
      "merchant_id": "xendit",
      "merchant_reference_code": "598942aabb91a4ec309e9a35",
      "card_type": "CREDIT",
      "masked_card_number": "400000XXXXXX0002",
      "charge_type": "SINGLE_USE_TOKEN",
      "card_brand": "VISA",
      "bank_reconciliation_id": "5132390610356134503009",
      "capture_amount": 9900,
      "descriptor": "My new store",
      "id": "598942c4bb91a4ec309e9a37"
    }

    This is endpoint to get a charge object. You need to specify the charge_id. Response for this endpoint is the same as create charge response

    Request Parameters

    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Query Parameter Type Description
    credit_card_charge_id
    required
    string Charge ID of the payment that have been authorized

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    CREDIT_CARD_CHARGE_NOT_FOUND_ERROR
    404
    credit_card_charge_id not found

    Create Refund

    Definition: Create Refund

    POST https://api.xendit.co/credit_card_charges/:credit_card_charge_id/refunds

    Example Refund Request

    curl https://api.xendit.co/credit_card_charges/5877255293ff67900c6aa64e/refunds \
        -X POST \
        -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
        -H "X-IDEMPOTENCY-KEY: unique-id-12345" \
        -H "x-api-version: 2019-05-01" \
        -d "amount": 15000
        -d "external_id": unique-external-id
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $params = [
          'external_id' => 'postman-charge-1502436793',
          'amount' => 15000,
          'X-IDEMPOTENCY-KEY' => 'unique-id'
      ];
    
      $refund = \Xendit\Cards::createRefund($id, $params);
      var_dump($refund);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Card } = x;
    const cardSpecificOptions = {};
    const card = new Card(cardSpecificOptions);
    
    const resp = await card.createRefund({
      chargeID: '5877255293ff67900c6aa64e',
      amount: 15000,
      externalID: 'unique-external-id',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      CreditCardRefund creditCardRefund = CreditCard.createRefund(
        "1234567", //id
        15000, //amount
        "unique-external-id" //externalId
      );
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    createRefundData := card.CreateRefundParams{
      IdempotencyKey: "unique-idempotency-key",
      ChargeID:       "58f984f09d1b74bc08506c34",
      Amount:         15000,
      ExternalID:     "unique-external-id",
    }
    
    refundResp, err := card.CreateRefund(&createRefundData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("refunded charge: %+v\n", refundResp)

    Example Refund Response

    {
      "updated": "2020-01-21T04:05:09.755Z",
      "created": "2020-01-21T04:05:04.936Z",
      "credit_card_charge_id": "58f89041780d51ed097896c5",
      "user_id": "57c5aa7a36e3b6a709b6e148",
      "amount": 15000,
      "external_id": "unique-external-id",
      "status": "REQUESTED",
      "fee_refund_amount": 150,
      "id": "58f984f09d1b74bc08506c34"
    }

    The Refund API accepts two parameters, amount and external_id. The charge ID, which is returned after a successful charge, must be used in request URL per the definition. Several partial refund calls can be made, so long as the total amount refunded is not greater than the total charge amount.

    Note: Idempotency can be achieved by sending a header with the key X-IDEMPOTENCY-KEY.

    Request Parameters

    Header Parameter Type Description
    X-IDEMPOTENCY-KEY
    optional
    string A unique key to prevent processing duplicate requests. Must be unique across test & live mode.
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    x-api-version
    required
    string Value of this must be "2019-05-01".
    Body Parameter Type Description
    amount
    required
    string The amount to be refunded.
    external_id
    required
    string A unique identifier of your choice. Max 64 characters.

    Response Parameters

    Parameter Type Description
    updated
    required
    string ISO timestamp that tracks when the last time refund was updated.
    created
    required
    string ISO timestamp that tracks when the refund was made
    Timezone: GMT+0
    .
    credit_card_charge_id
    required
    string charge ID, a unique identifier for each charge.
    user_id
    required
    string ID of your business in Xendit's system.
    amount
    required
    number Refund amount.
    external_id
    required
    string Unique identifier for refund request, provided by you.
    status
    required
    string Status of the refund. See Refund Statuses
    failure_reason
    optional
    string Reason provided if refund request fails. See Refund Failure Reasons
    fee_refund_amount
    required
    number Amount of Xendit's fee refunded (proportional to the refund amount).
    id
    required
    string Unique ID referencing the refund request.

    Statuses

    Status Description
    REQUESTED Refund request succeeded
    FAILED Refund failed

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not valid JSON.
    REFUND_AMOUNT_EXCEEDED_ERROR
    400
    Refunded amount would exceed total charge
    DUPLICATE_REFUND_ERROR
    400
    external_id has already been used
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    CREDIT_CARD_CHARGE_NOT_FOUND_ERROR
    404
    credit_card_charge_id not found

    Failure Reason

    Failure Reason Description
    INSUFFICIENT_BALANCE Your Xendit balance has insufficient funds to create a refund
    REFUND_FAILED The refund request has been rejected by the processor. Please try again or contact us at help@xendit.co
    REFUND_PERIOD_EXPIRED Refund period expired. The period where this charge can be refunded has expired. You can try refunding the charge by making a disbursement

    Get Charge Option

    When accepting credit card payments from your customers, you may wish to give them additional payment options. These can include:

    These options must be selected by a customer before you create a Charge. For example, you would check if a card is eligible for a Promotion, and discount the Charge amount if so, before you initiate payment you would check if a card can be used for installments, and return the option to the customer, to let them choose if they want to do so

    Our GET Charge Option API endpoint helps you with this. Send a request to this endpoint with info entered by your customer (such as card Bank Identification Number (BIN), promo code) and Xendit checks to see what Charge Options are available. The response will contain all options available for that card. You can select an option and create a Charge with the details from that option.

    Definition: Get Charge Option

    GET https//api.xendit.co/credit_card_charges/option

    Example Get Charge Option Using First 6 Digits of Card

    curl -X POST \
      https://api.xendit.co/promotions
      -u xnd_public_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
      -H 'content-type: application/json' \
      -d {
          "bin": "552002",
          "amount": 1000000,
          "currency": "IDR”
        }

    Example Get Charge Option Using Token ID

    curl -X POST \
      https://api.xendit.co/promotions
      -u xnd_public_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
      -H 'content-type: application/json' \
      -d {
          "token_id": "598d5d0e51e0870d44c61534",
          "amount": 1000000,
          "currency": "IDR”
        }

    Example Get Charge Option Response

    {
        "business_id": "5ea2a0cdb62b6a00108ed248",
        "bin": "552002",
        "promotions":[{
            "reference_id": "some_promo_1",
            "discount_percent": "25",
            "original_amount": 1000000,
            "final_amount": 750000,
            "currency": "IDR"
        }],
        "installments" : [{
            "count": 3,
            "interval": "month",
            "acquirer": "BRI",
            "currency": "IDR",
            "minimum_amount": 500000
        },{
            "count": 6,
            "interval": "month",
            "acquirer": "BRI",
            "currency": "IDR",
            "minimum_amount": 500000
        },{
            "count": 12,
            "interval": "month",
            "acquirer": "BRI",
            "currency": "IDR",
            "minimum_amount": 500000
        }]
    }

    Get Charge Option Request

    Query Parameter Type Description
    bin
    required but optional if token_id exists
    string The BIN (first 6 digits of a card) entered by the cardholder, which you want to check if it is associated with any Charge Option.
    amount
    required
    number The amount of the original transaction.
    currency
    optional
    string The currency which payment will be made in. For banks with branches in more than one country, a Promotion will only apply to cards based on the currency. e.g. if currency is IDR and channel_code is DBS, then the Promotion will apply only to BINs issued by DBS Indonesia.
    promo_code
    optional
    string Promo code which can be used by an end user to activate the promo. Include this if you want your Promotion be activated by your user entering a promo code is entered.
    Charactersa-z, A-Z, 0-9; accepted symbols - _ \
    token_id
    optional
    string Token ID of a card, obtained during tokenization with Xendit. We will look up the token to associate it with a BIN and get the available options.

    Get Charge Option Response

    Parameter Type Description
    business_id
    required
    string The ID of your business in Xendit.
    bin
    required
    string The BIN (first 6 digits of a card) entered by the cardholder, which you sent in the Get Charge Option request.
    promotions
    optional
    array Array containing details of all promotions applicable to the card.
    promotion details child parameters
    Key Value
    reference_id
    optional
    string Unique reference, such as an ID or name which you assigned to the promo and you've inputted in the promo creation request.
    Charactersa-z, A-Z, 0-9; accepted symbols - _ \
    original_amount
    required
    number The amount of the original transaction (before the Promotion discount).
    discount_amount
    optional
    number Amount of discount applicable for a specific Promotion (includes decimal).
    MaximumNone
    Minimum0
    discount_percent
    optional
    number Percentage discount applicable for a specific Promotion (includes decimal).
    Maximum100
    Minimum0
    final_amount
    required
    number The final amount, after the Promotion discount has been applied. You should use this sum to charge the card.
    currency
    required
    string The currency which payment will be made in.
    installments
    optional
    object Define the available installment option.
    installments details child parameters
    Key Value
    count
    required
    numberTogether with the "interval" parameter, this defines your installment tenor count.
    interval
    required
    string Together with the "count" parameter, this defines your installment tenor period.
    acquirer
    required
    stringThe bank corresponding to the card BIN, which offers the installments.
    currency
    required
    string The currency which payment will be made in.
    minimum_amount
    required
    numberThe minimum amount necessary for a card Charge to be paid via installments. A Charge with amount below this minimum cannot be paid via installments.

    May differ across banks, and may not always apply.

    Create Promotion

    A great way to attract more customers is to offer discounts based on the type of card that they use. Issuing banks often collaborate with merchants to provide discounts to users if they choose to use their cards. An important feature in the payment flow is the ability to check if the card number entered by a user is issued by a specific bank.

    Xendit's Promotion APIs fully support such promotions. They allow you to create a Promotion and select a range of credit card Bank Identification Numbers (BINs) to whitelist (BINs are the first 6 digits of a card, e.g. 480012). During the card payment process, send us a request to GET a Promotion Calculation. If an applicable Promotion for the type of card exists, Xendit automatically applies the promotion discount rate and returns you the information so you can charge the discounted amount.

    Definition: Create Promotion

    POST https://api.xendit.co/promotions

    Example Create Promotion Request

    curl -X POST \
      https://api.xendit.co/promotions
      -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
      -H 'content-type: application/json' \
      -d {
          "reference_id": "BRI_20_JAN",
          "description": "20% discount applied for all BRI cards",
          "bin_list": [
              "400000",
              "460000"
          ],
          "discount_percent": 20,
          "channel_code": "BRI",
          "currency": "IDR"
        }

    Example Create Promotion Response

    {
        "id": "36ab1517-208a-4f22-b155-96fb101cb378",
        "business_id": "5e61664b3dba955c203d232e",
        "reference_id": "BRI_20_JAN",
        "description": "20% discount applied for all BRI cards",
        "start_time": "2020-01-01 00:00:00.000Z",
        "end_time": "2020-01-01 00:00:00.000Z",
        "status": "ACTIVE",
        "bin_list": [
          "400000",
          "460000"
        ],
        "discount_percent": 20,
        "channel_code": "BRI",
        "currency": "IDR"
    }

    Request Parameters

    Body Parameter Type Description
    reference_id
    required
    string Unique reference, such as an ID or name, you wish to assign to the created Promotion.
    Charactersa-z, A-Z, 0-9; accepted symbols - _ \
    description
    required
    text The description of the Promotion. This will later be returned in the Get Promotions Calculation response, and you can expose it to the user on your user interface.
    promo_code
    optional
    string Promo code which can be used by an end user to activate the promo.
    Include this if you want your Promotion to be activated by the end user entering a code. A Promotion can be created with both the promo_code and bin_list or channel_code, if you want only certain cards to be able to use the promo code.
    Charactersa-z, A-Z, 0-9; accepted symbols - _
    bin_list
    optional
    array of strings The list of BINs whitelisted for a specific Promotion.
    Example: [ "400000", "460000" ]
    channel_code
    optional
    string The bank whitelisted for a specific Promotion.
    When a specific bank is chosen, any BIN which Xendit associates with that bank will be eligible for the Promotion.
    discount_percent
    optional
    number Percentage discount applicable for a specific Promotion. e.g. you want the Promotion to be a 20% discount.
    Either discount_percent or discount_amount is required.
    CharactersNumbers (includes decimals)
    Maximum 100
    Minimum0
    discount_amount
    optional
    number Amount of discount applicable for a specific Promotion. e.g. you want the Promotion to be a 50000 IDR discount.
    Either discount_percent or discount_amount is required.
    CharactersNumbers (includes decimals)
    Maximum none
    Minimum0
    currency
    required
    default: IDR
    string Currency which you want to process the transaction in. Use a three-letter ISO currency code. For banks with branches in more than one country, a Promotion will only apply to cards based on the currency.
    e.g. if currency is IDR and channel_code is DBS, then the Promotion will apply only to BINs issued by DBS Indonesia.
    start_time
    required
    ISO All created Promotions will start immediately by default.
    If you want a Promotion to start later, use this field to enter the start date of the promotion.
    Promo end date must be a date in the future.
    end_time
    required
    ISO Date which the Promotion will end.
    Promo end date must be a date in the future.

    Response Parameters

    Promotion Object

    Parameter Type Description
    id string Unique ID of the created Promotion (generated by Xendit).
    business_id string ID of your account with Xendit, used to identify you as a unique merchant.
    status string Status of the Promotion. Can be:
    ACTIVE: the Promotion is active
    INACTIVE: the Promotion is inactive.
    reference_id string Unique reference, such as an ID or name, you wish to assign to the created Promotion.
    Charactersa-z, A-Z, 0-9; accepted symbols - _ \
    description text The description of the Promotion. You can expose this to the user on your user interface to give them details about the Promotion.
    promo_code string Promo code which can be used by an end user to activate the promo. Include this if you want your Promotion to be activated by the end user entering a code. A Promotion can be created with both the promo_code and bin_list or channel_code, if you want only certain cards to be able to use the promo code..
    Charactersa-z, A-Z, 0-9; accepted symbols - _
    bin_list array of strings The list of BINs whitelisted for a specific Promotion.
    channel_code string The bank whitelisted for a specific Promotion. When a specific bank is chosen, any BIN which Xendit associates with that bank will be eligible for the Promotion. The channel code must match the channel codes here precisely.
    discount_percent number Percentage discount applicable for a specific Promotion.
    CharactersNumbers (includes decimals)
    Maximum 100
    Minimum0
    discount_amount number Amount of discount applicable for a specific Promotion.
    CharactersNumbers (includes decimals)
    Maximum none
    Minimum0
    currency
    default: IDR
    string Currency which you want to process the transaction in. Use a three-letter ISO currency code. For banks with branches in more than one country, a Promotion will only apply to cards based on the currency.
    e.g. if currency is IDR and channel_code is DBS, then the Promotion will apply only to BINs issued by DBS Indonesia.
    start_time ISO All created Promotions will start immediately by default.
    If you want a Promotion to start later, use this field to enter the start date of the promotion.
    Promo end date must be a date in the future.
    end_time ISO Date which the Promotion will end.
    Promo end date must be a date in the future.

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not valid JSON.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have the necessary permissions to perform the request. Please assign proper permissions for the key, or use a different key.
    REFERENCE_IN_USE
    409
    This Promotion name has been used for a previous or existing Promotion. Please use a different name.
    PROMO_CODE_IN_USE
    409
    This Promotion code has been used for a previous or existing Promotion. Please use a different code

    Get Promotions

    Use this API endpoint to obtain details of a created Promotion. Useful to get a quick snapshot of your available Promotions. If more than one Promotion matches a field you have entered, an array of all the relevant Promotions will be returned.

    Definition: Get Promotions

    GET https://api.xendit.co/promotions

    Example Get Promotions Request

    curl -X GET \
      https://api.xendit.co/promotions
      -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
      -H 'content-type: application/json' \
      -d {
          "reference_id": "BRI_20_JAN"
         }

    Example Get Promotions Response

    {
        "id": "36ab1517-208a-4f22-b155-96fb101cb378",
        "business_id": "5e61664b3dba955c203d232e",
        "reference_id": "BRI_20_JAN",
        "description": "20% discount applied for all BRI cards",
        "start_time": "2020-01-01 00:00:00.000Z",
        "end_time": "2020-01-01 00:00:00.000Z",
        "status": "ACTIVE",
        "bin_list": [
            "400000",
            "460000"
        ],
        "discount_percent": 20,
        "channel_code": "BRI",
        "currency": "IDR"
    }

    Request Parameters

    Query Parameter Type Description
    reference_id
    optional
    string Enter the specific reference_id of a single Promotion.
    status
    required
    enum Status of the Promotion.
    ACTIVE or INACTIVE.
    bin
    optional
    string A specific BIN.

    Example: 460000
    channel_code
    optional
    string The bank whitelisted for a specific Promotion.
    currency
    optional
    default: IDR
    string Currency which you want to process the transaction in. Use a three-letter ISO currency code.
    currently, only IDR is accepted.

    Response Parameters

    The array returns details of available Promotions depending on what fields you included in your query, in the Promotion Object format. For example, if you entered the bin_list value as [ "400000" ], an array of all available Promotions which include that BIN value will be returned.

    If no promotions match the query, an empty array will be returned.

    Get Promotions Calculation

    This endpoint is used to calculate how much discount should be applied to an amount being charged. It accepts a BIN or a promo_code, as well as the original charge amount. If the BIN or promo_code matches an available Promotion, Xendit will apply the discount to the original amount and return the discounted amount in the response.

    Definition: Get Promotions Calculation

    GET https://api.xendit.co/promotions/calculate

    Example Get Promotions Calculation Request using Bin

    curl -X GET \
      https://api.xendit.co/promotions/calculate
      -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
      -H 'content-type: application/json' \
      -d  {
            "amount": 1000000,
            "bin": "460000"
          }

    Example Get Promotions Calculation Request using Token ID

    curl -X GET \
      https://api.xendit.co/promotions/calculate
      -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
      -H 'content-type: application/json' \
      -d  {
            "amount": 1000000,
            "token_id": "598d5d0e51e0870d44c61534"
          }

    Example Get Promotions Calculation Response

    {
        "original_amount": 1000000,
        "discount_percent": 20,
        "reference_id": "BRI_20_JAN",
        "final_amount": 800000,
        "currency": "IDR",
        "description": "20% discount applied for all BRI cards"
    }

    Get Promotions Calculation Request

    Query Parameter Type Description
    amount
    required
    number The amount of the original transaction (before the Promotion discount).
    bin
    optional
    string The BIN entered by the cardholder, which you want to check if it is associated with any active Promotion.
    promo_code
    optional
    string The promo_code entered by the cardholder, which you want to check if it is associated with any active Promotion.
    currency
    optional
    default: IDR
    string Currency which you want to process the transaction in. Use a three-letter ISO currency code.
    token_id
    optional
    string Token ID of a card, obtained during tokenization with Xendit. We will look up the token to associate it with a BIN and get the available options.

    Get Promotions Calculation Response

    Parameter Type Description
    reference_id
    required
    string Unique reference which you assigned to the created Promotion.
    original_amount
    required
    number The amount of the original transaction (before the Promotion discount).
    discount_percent
    optional
    number Percentage discount applicable for a specific Promotion.
    Returned if the Promotion was created using discount_percent.
    discount_amount
    optional
    number Amount of discount applicable for a specific Promotion.

    Returned if the Promotion was created using discount_amount.
    final_amount
    required
    number The final amount, after the Promotion discount has been applied. You should use this sum to charge the card.
    description
    required
    text The description of the Promotion. Returned in the Get Promotions Calculation response so you can expose it on your user interface.

    eWallets

    eWallet payment channel allows you to receive payments directly from top ewallets provider in Indonesia, such as OVO, DANA, and LinkAja.

    Create Payment

    Endpoint: Create Ewallet Payment

    POST https://api.xendit.co/ewallets

    Version

    You are currently viewing API version 2020-02-01. Click here to view older versions.

    Version Changelog
    2020-02-01 (Latest) Implemented the asynchronous flow for OVO payment callbacks.
    2019-02-04 Returns a response immediately without any callbacks returned.

    OVO

    Request Parameters

    Example: Create Ewallet Payment Request

    curl https://api.xendit.co/ewallets -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -H "x-api-version: 2020-02-01" \
       -d external_id='ovo-ewallet' \
       -d amount=1000 \
       -d phone='08123123123'\
       -d ewallet_type='OVO'
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $ovoParams = [
        'external_id' => 'ovo-ewallet',
        'amount' => 1000,
        'phone' => '08123123123',
        'ewallet_type' => 'OVO'
      ];
    
      $createOvo = \Xendit\EWallets::create($ovoParams);
      var_dump($createOvo);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { EWallet } = x;
    const ewalletSpecificOptions = {};
    const ew = new EWallet(ewalletSpecificOptions);
    
    const resp = await ew.createPayment({
      externalID: 'ovo-ewallet',
      amount: 1000,
      phone: '08123123123',
      ewalletType: EWallet.Type.OVO,
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      EWalletPayment ewal = EWalletPayment.createOvoPayment(
        "ovo-ewallet", //externalId
        1000,        //amount
        "08123123123"  //phone
      );
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    data := ewallet.CreatePaymentParams{
      ExternalID:  "ovo-ewallet",
      Amount:      1000,
      Phone:       "08123123123",
      EWalletType: xendit.EWalletTypeOVO,
      CallbackURL: "mystore.com/callback",
      RedirectURL: "mystore.com/redirect",
    }
    
    resp, err := ewallet.CreatePayment(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created payment: %+v\n", resp)
    Header Parameter Type Description
    X-API-VERSION
    optional
    string API version in date semantic (e.g. 2020-02-01). Attach this parameter when calling a specific API version. List of API versions can be found here.
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information
    Body Parameter Type Description
    external_id
    required
    string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID.
    Note: The only allowed punctuation is -.
    Note: Maximum length allowed is 50 characters.
    Note: It has to be unique per payment request.
    amount
    required
    number Amount end-customer will pay.
    Note: minimum amount is 1 IDR and maximum is 10,000,000 IDR
    phone
    required
    string Phone number of end-customer (e.g. 08123123123)
    Note: End-customer must have an active ewallet account registered to Indonesian phone number prior to payment request.
    Note: Phone number format should always be "088889998888" (not using "+62").
    ewallet_type
    required
    string ewallet_type must be in capital letters - 'OVO'

    Response Parameters

    Example: Create Ewallet Payment API Success Response

    {
      "business_id": "585te55dst9791ing4009123",
      "external_id": "ovo-ewallet",
      "amount": 1000,
      "phone": "08123123123",
      "ewallet_type": "OVO",
      "status": "PENDING",
      "created": "2020-02-20T00:00:00.000Z",
    }
    Parameter Type Description
    business_id
    required
    string Unique identifier for the merchant
    external_id
    required
    string Unique identifier for the payment request of a merchant
    amount
    required
    number Amount requested
    phone
    required
    string Phone number of the end user
    ewallet_type
    required
    string Type of eWallet. Value: OVO
    status
    required
    string Status of payment. Value: PENDING
    created
    required
    string Timestamp ISO 8601 when the payment was requested (in UTC)

    Error Codes

    Example: Create Ewallet Payment API Error Response

    {
        "error_code": "DUPLICATE_PAYMENT_REQUEST_ERROR",
        "message": "There is already a payment request with external_id: ovo-ewallet"
    }
    Error Code Description
    API_VALIDATION_ERROR
    422
    There is invalid input in one of the required request fields.
    EWALLET_TYPE_NOT_SUPPORTED
    422
    Your requested ewallet_type is not supported yet
    DUPLICATE_PAYMENT_REQUEST_ERROR
    400
    The payment with the same external_id has already been made before.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    DANA

    Request Parameters

    Example: Create Ewallet Payment Request

    curl https://api.xendit.co/ewallets -X POST \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
      -d external_id = 'dana-ewallet' \
      -d amount = 1001 \
      -d expiration_date = '2020-02-20T00:00:00.000Z' \
      -d callback_url = 'https://my-shop.com/callbacks' \
      -d redirect_url = 'https://my-shop.com/home' \
      -d ewallet_type = 'DANA'
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $danaParams = [
        'external_id' => 'dana-ewallet',
        'amount' => 1000,
        'phone' => '081298498259',
        'expiration_date' => '2020-02-20T00:00:00.000Z',
        'callback_url' => 'https://my-shop.com/callbacks',
        'redirect_url' => 'https://my-shop.com/home',
        'ewallet_type' => 'DANA'
      ];
    
      $createDana = \Xendit\EWallets::create($danaParams);
      var_dump($createDana);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { EWallet } = x;
    const ewalletSpecificOptions = {};
    const ew = new EWallet(ewalletSpecificOptions);
    
    const resp = await ew.createPayment({
      externalID: 'dana-ewallet',
      amount: 1001,
      expirationDate: new Date(2020, 1, 20),
      callbackURL: 'https://my-shop.com/callbacks',
      redirectURL: 'https://my-shop.com/home',
      ewalletType: EWallet.Type.DANA,
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      EWalletPayment ewal = EWalletPayment.createDanaPayment(
        "dana-ewallet", //externalId
        1000, //amount
        "08123123123", //phone
        "24-08-2019", //expirationDate
        "callback_url", //callbackUrl
        "redirect_url" //redirectUrl
      );    
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    data := ewallet.CreatePaymentParams{
      ExternalID:  "dana-ewallet",
      Amount:      20000,
      Phone:       "08123123123",
      EWalletType: xendit.EWalletTypeDANA,
      CallbackURL: "mystore.com/callback",
      RedirectURL: "mystore.com/redirect",
    }
    
    resp, err := ewallet.CreatePayment(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created payment: %+v\n", resp)
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    external_id
    required
    string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 1000 characters.
    amount
    required
    number Amount end-customer will pay.
    Note: minimum amount is 1 IDR and maximum is 10,000,000 IDR
    expiration_date
    optional
    string End-customer cannot complete the payment past the expiration date
    Timezone: UTC unless specified (e.g. 2020-03-20T04:54:10+07:00)
    Expiry: Default expiry is 24 hours unless specified.
    callback_url
    required
    string The URL to receive the callback after payment made by end-customer
    redirect_url
    required
    string The URL to redirect to after payment made by end-customer
    ewallet_type
    required
    string ewallet_type must be in capital letters - 'DANA'

    Response Parameters

    Example: Create Ewallet Payment API Success Response

    {
      "external_id": "dana-ewallet",
      "checkout_url": "https://dana.id/m/portal/cashier/checkout?id=5d34079d51a9ed12c78a78d3",
      "amount": 1000,
      "ewallet_type": "DANA"
    }
    Parameter Type Description
    external_id
    required
    string Unique identifier for the payment request of a merchant
    checkout_url
    required
    string URL generated by DANA for end user to authorize and complete payment
    amount
    required
    number Amount requested
    ewallet_type
    required
    string Type of eWallet. Value: DANA

    Error Codes

    Example: Create Ewallet Payment API Error Response

    {
      "error_code": "DUPLICATE_ERROR",
      "message": "Transaction with this external_id is already exist"
    }
    Error Code Description
    API_VALIDATION_ERROR
    422
    There is invalid input in one of the required request fields.
    EWALLET_TYPE_NOT_SUPPORTED
    422
    Your requested ewallet_type is not supported yet
    DUPLICATE_ERROR
    400
    The payment with the same external_id has already been made before.
    CHECKOUT_ERROR
    400
    There was an external error from DANA. Please try again in a few minutes or contact our customer success team.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    LINKAJA

    Request Parameters

    Example: Create Ewallet Payment Request

    curl https://api.xendit.co/ewallets -X POST \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
      --header 'content-type: application/json' \
      --data '{
        "external_id": "linkaja-ewallet",
        "phone": "081245671234",
        "amount": 300000,
        "items": [
          {
            "id": "123123",
            "name": "Phone Case",
            "price": 100000,
            "quantity": 1
          },
          {
            "id": "345678",
            "name": "Powerbank",
            "price": 200000,
            "quantity": 1
          }
        ],
        "callback_url": "https://yourwebsite.com/callback",
        "redirect_url": "https://yourwebsite.com/order/123",
        "ewallet_type": "LINKAJA"
    }'
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $linkajaParams = [
        'external_id' => 'linkaja-ewallet',
        'amount' => 300000,
        'phone' => '081298498259',
        'items' => [
          [
            'id' => '123123',
            'name' => 'Phone Case',
            'price' => 100000,
            'quantity' => 1
          ],
          [
            'id' => '345678',
            'name' => 'Powerbank',
            'price' => 200000,
            'quantity' => 1
          ]
        ],
        'callback_url' => 'https =>//yourwebsite.com/callback',
        'redirect_url' => 'https =>//yourwebsite.com/order/123',
        'ewallet_type' => 'LINKAJA'
      ];
    
      $createLinkaja = \Xendit\EWallets::create($linkajaParams);
      var_dump($createLinkaja);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { EWallet } = x;
    const ewalletSpecificOptions = {};
    const ew = new EWallet(ewalletSpecificOptions);
    
    const item = {
      id: "345678",
      name: "Powerbank",
      price: 200000,
      quantity: 1
    };
    const resp = await ew.createPayment({
      externalID: 'linkaja-ewallet',
      amount: 300000,
      items: [item, item],
      callbackURL: 'https://my-shop.com/callbacks',
      redirectURL: 'https://my-shop.com/home',
      ewalletType: EWallet.Type.LINKAJA
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      //items
      EWalletLinkajaItem items[] = new EWalletLinkajaItem[1];
      items[0] =
      EWalletLinkajaItem.builder()
          .id("123")
          .name("Phone Case")
          .price(200000)
          .quantity(1)
          .build();
    
      EWalletPayment ewal = EWalletPayment.createLinkajaPayment(
        "linkaja-ewallet", //externalId
        1000, //amount
        "08123123123", //phone
        items, //EWwalletLinkajaitem[]
        "callback_url", //callbackUrl
        "redirect_url" //redirectUrl
      );  
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    item1 := ewallet.Item {
      ID: "123123",
      Name: "Phone Case",
      Price: 100000,
      Quantity: 1,
    }
    
    item2 := ewallet.Item {
      ID: "345678",
      Name: "Powerbank",
      Price: 200000,
      Quantity: 1,
    }
    
    var items []ewallet.Item
    items = append(items, item1)
    items = append(items, item2)
    
    data := ewallet.CreatePaymentParams{
      ExternalID:  "linkaja-ewallet",
      Amount:      300000,
      Phone:       "08123123123",
      EWalletType: xendit.EWalletTypeLINKAJA,
      CallbackURL: "mystore.com/callback",
      RedirectURL: "mystore.com/redirect",
      Items: items,
    }
    
    resp, err := ewallet.CreatePayment(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created payment: %+v\n", resp)
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    external_id
    required
    string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 1000 characters.
    phone
    required
    string Phone number of end-customer (e.g. 08123123123)
    Note: End-customer must have an active ewallet account registered to Indonesian phone number prior to payment request.
    amount
    required
    number Amount end-customer will pay.
    Note: minimum amount is 100 IDR and maximum is 10,000,000 IDR
    items
    required
    array of item object List of items / products.
    item object
    required
    item object Details of an item, it should contains: id [string], name [string], price [number], quantity [number]
    callback_url
    required
    string The URL to receive the callback after payment made by end-customer
    redirect_url
    required
    string The URL to redirect to after payment made by end-customer
    ewallet_type
    required
    string ewallet_type must be in capital letters - 'LINKAJA'

    Response Parameters

    Example: Create Ewallet Payment API Success Response

    {
      "checkout_url": "https://ewallet-linkaja-dev.xendit.co/checkouts/b0c464ab-dcdc-4426-9255-759a9450c9d2",
      "transaction_date": "2019-10-25T08:42:54.308Z",
      "amount": 300000,
      "external_id": "linkaja-ewallet",
      "ewallet_type": "LINKAJA"
    }
    Parameter Type Description
    checkout_url
    required
    string URL generated by LINKAJA for end user to authorize and complete payment
    Expiry: Default expiry is 5 mins.
    transaction_date
    required
    string Timestamp ISO 8601 when the payment was requested (in UTC)
    amount
    required
    number Amount requested
    external_id
    required
    string Unique identifier for the payment request of a merchant
    ewallet_type
    required
    string Type of eWallet. Value: LINKAJA

    Error Codes

    Example: Create Ewallet Payment API Error Response

    {
        "error_code": "DUPLICATE_PAYMENT_ERROR",
        "message": "Checkout URL with the same external_id has been created before."
    }
    Error Code Description
    API_VALIDATION_ERROR
    400
    There is invalid input in one of the required request fields.
    GENERATE_CHECKOUT_TOKEN_ERROR
    422
    An error occured when generating the checkout_url.
    EWALLET_TYPE_NOT_SUPPORTED
    422
    Your requested ewallet_type is not supported yet
    DUPLICATE_PAYMENT_ERROR
    400
    The payment with the same external_id has already been made before.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Get Payment Status

    Endpoint: Get Ewallet Payment Status

    GET https://api.xendit.co/ewallets?external_id={external_id}&ewallet_type={ewallet_type}

    This endpoint is used to get payment status of an single payment. You need to specify the external_id and ewallet_type.

    Request Parameters

    Example: Check Ewallet Payment Status Request

    OVO, DANA, LINKAJA

    curl 'https://api.xendit.co/ewallets?external_id=ovo-ewallet&ewallet_type=OVO' \
       -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $external_id = 'ovo-payment';
      $ewallet_type = 'OVO';
      $getPayments = \Xendit\EWallets::getPaymentStatus($external_id, $ewallet_type);
      var_dump($getPayments);
    
    ?>
    Parameter Type Description
    external_id
    required
    string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 1000 characters.
    ewallet_type
    required
    string ewallet_type must be in capital letters
    Supported ewallet types: 'OVO', 'DANA', 'LINKAJA'
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { EWallet } = x;
    const ewalletSpecificOptions = {};
    const ew = new EWallet(ewalletSpecificOptions);
    
    const resp = await ew.getPayment({
      externalID: 'ovo-ewallet',
      ewalletType: EWallet.Type.OVO,
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      EWalletPayment payment = EWalletPayment.getPaymentStatus("ovo-ewallet", EWalletPayment.EWalletType.OVO);    
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    data := ewallet.GetPaymentStatusParams{
      ExternalID:  "ovo-payment",
      EWalletType: xendit.EWalletTypeDANA,
    }
    
    resp, err := ewallet.GetPaymentStatus(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("retrieved payment: %+v\n", resp)

    Example: Check Ewallet Payment Status Success Responses

    OVO Responses

    OVO

    {
      "amount": "10000",
      "business_id": "5850eteStin791bd40096364",
      "ewallet_type": "OVO",
      "external_id": "ovo-payment",
      "status": "COMPLETED",
      "transaction_date": "2020-01-14T11:48:47.903Z"
    }
    Status Description
    COMPLETED Payment transaction for specified external_id is successfully
    PENDING Payment transaction for specified external_id is awaiting approval by OVO user
    FAILED Payment transaction for specified external_id has failed and is not completed (e.g. user did not complete the payment process or payment session timed out)

    DANA Responses

    DANA

    {
      "amount": "10000",
      "business_id": "5850eteStin791bd40096364",
      "checkout_url": "https://example.com/checkout",
      "external_id": "dana-payment-23",
      "expiration_date": "2020-03-20T04:54:10+07:00",
      "status": "PAID"
    }
    Status Description
    PAID Payment transaction for specified external_id is successfully
    PENDING Payment transaction for specified external_id is awaiting approval by DANA user
    FAILED Payment creation for specified external_id failed with DANA
    EXPIRED Payment transaction URL for specified external_id has expired (e.g. user did not access payment link or complete the payment process)

    LinkAja Responses

    LINKAJA - COMPLETED or FAILED

    {
      "amount": 10000,
      "business_id": "5850eteStin791bd40096364",
      "external_id": "linkaja-payment-23",
      "payment_timestamp": "2020-01-14T11:48:47.903Z",
      "status": "COMPLETED"
    }

    LINKAJA - PENDING or EXPIRED

    {
      "amount": 10000,
      "business_id": "5850eteStin791bd40096364",
      "checkout_url": "https://example.com/checkout",
      "expired_at": "2020-01-14T11:48:47.903Z",
      "external_id": "linkaja-payment-23",
      "status": "PENDING"
    }
    Status Description
    COMPLETED Payment transaction specified external_id is successfully
    PENDING Payment transaction for specified external_id is awaiting approval by LinkAja user
    FAILED Payment creation for specified external_id failed with LinkAja
    EXPIRED Payment transaction URL for specified external_id has expired (e.g. user did not access payment link or complete the payment process)

    Error Codes

    Example: Check Ewallet Payment Status Error Response

    {
      "error_code": "PAYMENT_NOT_FOUND_ERROR",
      "message": "Payment not found",
    }
    Error Code Description
    PAYMENT_NOT_FOUND_ERROR
    404
    Payment not found
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Payment Status Callback

    You need to provide an endpoint in your system to receive payment callback notification from our system. You will receive the callback when end-customer completed the payment for OVO, DANA, or LINKAJA. The payment callback notification will be sent as POST request to the "callback_url" that you have set in the dashboard. Note: Please give this notification a response back with status 200 so we know that our notification is received.

    Version

    You are currently viewing API version 2020-02-01. Click here to view older versions.

    Version Changelog
    2020-02-01 (Latest) Implemented the asynchronous flow for OVO payment callbacks.
    2019-02-04 Returns a response immediately without any callbacks returned.

    Example Payment Status Callback

    OVO

    Callback Payload

    Example: Success Payment Callback Payload

    {
      "event": "ewallet.payment",
      "id": "6bb25ae6-cf57-437a-9b36-7ad2ee17b727",
      "external_id": "ECLrAZPq8F6",
      "business_id": "5850eteStin791bd40096364",
      "phone": "081234567890",
      "ewallet_type": "OVO",
      "amount": 20000,
      "created": "2019-11-01T12:34:56.007Z",
      "status": "COMPLETED"
    }
    Parameter Type Description
    event required string Available value: "ewallet.payment"
    id required string Unique identifier generated for the payment (payment_id)
    external_id required string Unique identifier for the payment request of a merchant
    business_id required string Unique identifier for the merchant
    phone required string Phone number of the end user
    ewallet_type required string Type of eWallet. Value: OVO
    amount required number Amount paid
    status required string Status of payment.
    Possible values: FAILED, COMPLETED
    failure_code optional string If the payment FAILED, we include a failure code for more details on the failure.
    Possible values: See Error Code column in this table
    created optional string If the payment is COMPLETED, we include the timestamp ISO 8601 when the payment was made (in UTC)

    Failure Codes

    Example: Failed Payment Callback Payload

    {
      "event": "ewallet.payment",
      "id": "6bb25ae6-cf57-437a-9b36-7ad2ee17b727",
      "external_id": "ECLrAZPq8F6",
      "business_id": "5850eteStin791bd40096364",
      "phone": "081234567890",
      "ewallet_type": "OVO",
      "amount": 20000,
      "failure_code": "USER_DECLINED_THE_TRANSACTION",
      "status": "FAILED"
    }
    Failure Code Failure Message
    USER_DID_NOT_AUTHORIZE_THE_PAYMENT
    User did not authorize the payment request within time limit
    USER_DECLINED_THE_TRANSACTION
    User declined the payment request
    PHONE_NUMBER_NOT_REGISTERED
    Phone number the user tried to pay is not registered
    EWALLET_APP_UNREACHABLE
    The ewallet provider/server can't reach the user ewallet app/phone. Common cases are the ewallet app is uninstalled
    OVO_TIMEOUT_ERROR
    There was a connection timeout from the OVO app to the OVO server
    CREDENTIALS_ERROR
    The merchant is not registered in e-wallet provider system
    ACCOUNT_AUTHENTICATION_ERROR
    User authentication has failed
    ACCOUNT_BLOCKED_ERROR
    Unable to process the transaction because the user account is blocked
    SENDING_TRANSACTION_ERROR
    Error while sending transaction notification to OVO
    EXTERNAL_ERROR
    There is an error on the e-wallet provider side

    DANA

    Example: Success Payment Callback Payload

    {
      "external_id": "dana-ewallet",
      "amount": 1001,
      "business_id": "5850eteStin791bd40096364",
      "payment_status": "PAID",
      "transaction_date": "2020-03-20T04:54:10+07:00",
      "ewallet_type":"DANA",
      "callback_authentication_token": "sample-token-id=="
    }
    Parameter Type Description
    external_id string Your transaction identifier that you specified in on the Generate Checkout URL request.
    amount number The amount of transaction
    business_id string Your business_id that registered on our system.
    payment_status string The status of payment.
    Notes: The statuses are: EXPIRED and PAID.
    transaction_date string The time that of payment was made
    ewallet_type string The type of ewallet that you specified when creating the payment request.
    Supported ewallet types: OVO, DANA, LINKAJA
    callback_authentication_token string Your Callback Verfication API Key that you can found on your Xendit Dashboard. You need to verify if this had the same value.

    LINKAJA

    Example: Success Payment Callback Payload

    {
      "external_id": "linkaja-ewallet",
      "amount": 300000,
      "items": [
        {
          "id": "123123",
          "name": "Phone Case",
          "price": 100000,
          "quantity": 1
        },
        {
          "id": "345678",
          "name": "Powerbank",
          "price": 200000,
          "quantity": 1
        }
      ],
      "status": "SUCCESS_COMPLETED",
      "ewallet_type": "LINKAJA",
      "callback_authentication_token": "sample-token-id=="
    }
    Parameter Type Description
    external_id string Your transaction identifier that you specified in on the Generate Checkout URL request.
    amount number The amount of transaction
    items array of item object List of items / products.
    item object item object Details of an item, it should contains: id [string], name [string], price [number], quantity [number]
    status string The status of payment.
    Notes: The statuses are: FAILED and SUCCESS_COMPLETED
    ewallet_type string The type of ewallet that you specified when creating the payment request.
    Supported ewallet types: OVO, DANA, LINKAJA
    callback_authentication_token string Your Callback Verfication API Key that you can found on your Xendit Dashboard. You need to verify if this had the same value.

    Cardless Credit

    Cardless credit payment channel allows you to receive payments upfront from the credit provider. End users get the option to split their payments into installments.

    Create Payment / Generate Checkout URL

    Endpoint: Generate Checkout URL

    POST https://api.xendit.co/cardless-credit

    Request Parameters

    Example: Generate Checkout URL

    curl https://api.xendit.co/cardless-credit -X POST \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
      --header 'content-type: application/json' \
      --data '{
        "cardless_credit_type": "KREDIVO",
        "external_id": "test-cardless-credit-01",
        "amount": 800000,
        "payment_type": "3_months",
        "items": [
          {
            "id": "123123",
            "name": "Phone Case",
            "price": 200000,
            "type": "Smartphone",
            "url": "http://example.com/phone/phone_case",
            "quantity": 2
          },
          {
            "id": "234567",
            "name": "Bluetooth Headset",
            "price": 400000,
            "type": "Audio",
            "url": "http://example.com/phone/bluetooth_headset",
            "quantity": 1
          }
        ],
        "customer_details": {
          "first_name": "customer first name",
          "last_name": "customer last name",
          "email": "customer@yourwebsite.com",
          "phone": "081513114262"
        },
        "shipping_address": {
          "first_name": "first name",
          "last_name": "last name",
          "address": "Jalan Teknologi No. 12",
          "city": "Jakarta",
          "postal_code": "12345",
          "phone": "081513114262",
          "country_code": "IDN"
        },
        "redirect_url": "https://example.com",
        "callback_url": "http://example.com/callback-cardless-credit"
      }'
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $params = [
        'cardless_credit_type' => 'KREDIVO',
        'external_id' => 'test-cardless-credit-01',
        'amount' => 800000,
        'payment_type' => '3_months',
        'items' => [
          [
            'id' => '123123',
            'name' => 'Phone Case',
            'price' => 200000,
            'type' => 'Smartphone',
            'url' => 'http=>//example.com/phone/phone_case',
            'quantity' => 2
          ],
          [
            'id' => '234567',
            'name' => 'Bluetooth Headset',
            'price' => 400000,
            'type' => 'Audio',
            'url' => 'http=>//example.com/phone/bluetooth_headset',
            'quantity' => 1
          ]
        ],
        'customer_details' => [
          'first_name' => 'customer first name',
          'last_name' => 'customer last name',
          'email' => 'customer@yourwebsite.com',
          'phone' => '081513114262'
        ],
        'shipping_address' => [
          'first_name' => 'first name',
          'last_name' => 'last name',
          'address' => 'Jalan Teknologi No. 12',
          'city' => 'Jakarta',
          'postal_code' => '12345',
          'phone' => '081513114262',
          'country_code' => 'IDN'
        ],
        'redirect_url' => 'https://example.com',
        'callback_url' => 'http://example.com/callback-cardless-credit'
      ];
    
      $createPayment = \Xendit\CardlessCredit::create($params);
      var_dump($createPayment);
    
    ?>
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      //items
      CardlessCreditItem items[] = new CardlessCreditItem[1];
      items[0] =
        CardlessCreditItem.builder()
            .id("123")
            .name("Phone Case")
            .price(200000)
            .type("Smartphone")
            .url("https://www.example.org")
            .quantity(1)
            .build();
    
      //address
      CardlessCreditShippingAddress address =
          CardlessCreditShippingAddress.builder()
              .firstName("Lorem")
              .lastName("Ipsum")
              .address("Jalan teknologi")
              .city("Jakarta")
              .postalCode("12345")
              .countryCode("IDN")
              .phone("08129748247684")
              .build();
    
      //Customer
      CardlessCreditCustomer customer =
          CardlessCreditCustomer.builder()
              .firstName("Lorem")
              .lastName("Ipsum")
              .email("email@example.com")
              .phone("08129748247684")
              .build();
    
      CardlessCredit cardlessCredit = CardlessCredit.create(
        "KREDIVO",
        "external_id",
        200000,
        CardlessCredit.PaymentType.THREE_MONTHS.getVal(),
        items,
        customer,
        address,
        "www.example.com",
        "www.example.com"
      );
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    createPaymentData := cardlesscredit.CreatePaymentParams{
      CardlessCreditType: xendit.CardlessCreditTypeEnumKREDIVO,
      ExternalID:         "test-cardless-credit-01",
      Amount:             200000,
      PaymentType:        xendit.PaymentTypeEnum3Months,
      Items: []cardlesscredit.Item{
        {
          ID:       "123",
          Name:     "Laptop Asus Ila",
          Price:    200000,
          Type:     "Laptop",
          URL:      "http://asus-ila.com",
          Quantity: 1,
        },
      },
      CustomerDetails: cardlesscredit.CustomerDetails{
        FirstName: "Michael",
        LastName:  "Belajarrock",
        Email:     "michaelbelajarrock@mail.com",
        Phone:     "08123123123",
      },
      ShippingAddress: cardlesscredit.ShippingAddress{
        FirstName:   "Michael",
        LastName:    "Belajarjazz",
        Address:     "Jalan Teknologi No. 12",
        City:        "Jakarta",
        PostalCode:  "40000",
        Phone:       "08123123123",
        CountryCode: "IDN",
      },
      RedirectURL: "https://sandbox.kredivo.com/kredivo/v2/signin?tk=fKhTeBntLW3Zyu23+GQ6s+RQaMMRtQ6YdZA1bnbTszt9WXcph/B4+j8nuPlV599Rfkv85FAYuE21Suajpm45tEMZqjZIdqnSgIPlt7T5gJk=",
      CallbackURL: "https://google.com",
    }
    
    resp, err := cardlesscredit.CreatePayment(&createPaymentData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created payment: %+v\n", resp)

    Example: Generate Checkout URL Success Response

    {
      "redirect_url": "https://sandbox.kredivo.com/kredivo/v2/signin?tk=fKhTeBntLW3Zyu23+GQ6s+RQaMMRtQ6YdZA1bnbTszt9WXcph/B4+j8nuPlV599Rfkv85FAYuE21Suajpm45tEMZqjZIdqnSgIPlt7T5gJk=",
      "transaction_id": "66403e84-c8da-4af4-8d30-d17e95522f43",
      "order_id": "123456-test-cardless-credit-01",
      "external_id": "test-cardless-credit-01",
      "cardless_credit_type": "KREDIVO"
    }
    Parameter Type Description
    cardless_credit_type
    required
    string The type of cardless-credit to be paid. Must be in capital letters.
    Supported Cardless Credit types: KREDIVO
    external_id
    required
    string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 1000 characters.
    amount
    required
    number Amount end customer will pay.
    Note: minimum amount is 1 IDR
    payment_type
    required
    string The type of installment, you can choose between: "30_days", "3_months", "6_months" and "12_months".
    items
    required
    array of item object List of items / products.
    item object
    required
    item object Details of an item, it should contains: id [string], name [string], price [number], type [string], url [string], quantity [number]
    customer_details
    required
    object Details of the customer, it should contains: first_name [string], last_name [string], email [string], phone [string]
    shipping_address
    required
    object Details of the shipping address, it should contains: first_name [string], last_name [string], address [string], city [string], postal_code [string], phone [string], country_code [string]
    redirect_url
    required
    string After end-customer complete the checkout they will be redirected to the url that you specify in this field. You can put your transaction details page or your home page.
    callback_url
    required
    string We will send callback to this address when the customer completes the payment proccess.

    Error Codes

    Example: Generate Checkout URL error response

    {
      "error_code": "API_VALIDATION_ERROR",
      "message": "[fieldName] is required"
    }
    {
      "error_code": "DUPLICATE_PAYMENT_ERROR",
      "message": "Checkout URL with the same external_id has been created before."
    }
    Error Code Description
    MERCHANT_NOT_FOUND
    422
    You are not registered yet to use this payment method.
    GENERATE_CHECKOUT_URL_ERROR
    422
    Your request did not meet the requirement or there is a problem in the Kredivo / Partner server.
    DUPLICATE_PAYMENT_ERROR
    422
    Checkout URL with the same external_id has been created before.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Calculate Payment Types

    Calculate Payment Types feature helps merchants to get an accurate value of the installment offered to end customers by the cardless credit provider. Merchants can use this to calculate and display installment plans before end customer is redirected for authentication.

    Endpoint: Calculate Payment Types

    POST https://api.xendit.co/cardless-credit/payment-types

    Calculate Payment Types

    Example: Calculate Payment Types Request

    curl https://api.xendit.co/cardless-credit/payment-types -X POST \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
      --header 'content-type: application/json' \
      --data '{
        "cardless_credit_type": "KREDIVO",
        "amount": 2000000,
        "items": 
        [
          {
            "id": "123123",
            "name": "Phone Case",
            "price": 1000000,
            "type": "Smartphone",
            "url": "http://example.com/phone/phone_case",
            "quantity": 1
          }
        ]
      }'
    <?php
      $url = 'https://api.xendit.co/cardless-credit/payment-types';
      $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
      $headers = [];
      $headers[] = 'Content-Type: application/json';
      $item_1 = new stdClass();
      $item_1->id = "123123";
      $item_1->name = "Phone Case";
      $item_1->price = 200000;
      $item_1->type = "Smartphone";
      $item_1->url = "http://example.com/phone/phone_case";
      $item_1->quantity = 2;
      $data = [
          "cardless_credit_type" => "KREDIVO",
          "amount" => 800000,
          "items" => [ $item_1 ],
      ];
      $curl = curl_init();
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
      $result = curl_exec($curl);
      echo $result;
    Parameter Description
    cardless_credit_type
    required
    string The type of cardless-credit to be paid. Must be in capital letters.
    Supported Cardless Credit types: KREDIVO
    amount
    required
    number Amount end customer will pay.
    Note: minimum amount is 1 IDR
    items
    required
    array of item object List of items / products.
    items.id
    required
    string Merchant product ID of specified product in transaction
    items.name
    required
    string Name of specified product in transaction
    items.price
    required
    number Unit price of specified product in transaction
    items.type
    required
    string Category of specified product in transaction
    items.url
    required
    string Web url of specified product in transaction
    items.quantity
    required
    number Quantity of specified product in transaction

    Calculate Payment Types Response

    Example: Calculate Payment Types Response

    {
        "message": "Available payment types are listed.",
        "payments": [
            {
                "raw_monthly_installment": 187534.6668043921,
                "name": "Bayar dalam 6 bulan",
                "amount": 1000000,
                "installment_amount": 1125240,
                "raw_amount": 1000000,
                "rate": 2.95,
                "down_payment": 0,
                "monthly_installment": 187540,
                "discounted_monthly_installment": 0,
                "tenure": 6,
                "id": "6_months"
            },
            {
                "raw_monthly_installment": 1020000,
                "name": "Bayar dalam 30 hari",
                "amount": 1020000,
                "installment_amount": 1020000,
                "raw_amount": 1020000,
                "rate": 0,
                "down_payment": 0,
                "monthly_installment": 1020000,
                "discounted_monthly_installment": 0,
                "tenure": 1,
                "id": "30_days"
            },
            {
                "raw_monthly_installment": 356786.46273702476,
                "name": "Bayar dalam 3 bulan",
                "amount": 1000000,
                "installment_amount": 1070370,
                "raw_amount": 1000000,
                "rate": 2.95,
                "down_payment": 0,
                "monthly_installment": 356790,
                "discounted_monthly_installment": 0,
                "tenure": 3,
                "id": "3_months"
            }
        ]
    }
    Parameter Description
    message
    required
    string “Available payment types are listed
    payments
    required
    array List of calculated payment types
    payments.raw_monthly_installment
    required
    number Monthly installment before rounding
    payments.name
    required
    string Name of installment plan
    payments.amount
    required
    number Total payment amount before interest
    payments.installment_amount
    required
    number Total payment amount after interest
    payments.raw_amount
    required
    number Payment amount before interest before rounding
    payments.rate
    required
    number Applied interest rates
    payments.down_payment
    required
    number Amount paid upfront
    payments.monthly_installment
    required
    number Monthly installment offered by Kredivo to end user
    payments.discounted_monthly_installment
    required
    number Monthly installment offered by Kredivo to end user after discount (if any)
    payments.tenure
    required
    number Repayment term of installment in months
    payments.id
    required
    string ID of installment type

    Payment Callback Notification

    Callback Payload

    You need to provide an endpoint in your system to receive payment callback notification from our system. We will send the payment callback notification when the end-customer completes the payment on the Checkout page.

    The payment callback notification will be sent as POST request to the "callback_url" that you sepecified on the Generate Checkout URL request.

    Example: Payment Callback Notification Request

    {
      "external_id": "test-cardless-credit-01",
      "order_id": "75191237c81273jajsh7291c-test-cardless-credit-01",
      "transaction_id": "ashd7129-sh82-a9ks-js82-asj82912bajs",
      "amount": 800000,
      "transaction_status": "settlement",
      "payment_type": "3_months",
      "items": [
        {
          "id": "123123",
          "name": "Phone Case",
          "price": 200000,
          "type": "Smartphone",
          "url": "http://example.com/phone/phone_case",
          "quantity": 2
        },
        {
          "id": "234567",
          "name": "Bluetooth Headset",
          "price": 400000,
          "type": "Audio",
          "url": "http://example.com/audio/bluetooth_headset",
          "quantity": 1
        }
      ],
      "customer_details": {
          "first_name": "customer first name",
          "last_name": "customer last name",
          "email": "customer@yourwebsite.com",
          "phone": "081513114262"
        },
        "shipping_address": {
          "first_name": "first name",
          "last_name": "last name",
          "address": "Jalan Teknologi No. 12",
          "city": "Jakarta",
          "postal_code": "12345",
          "phone": "081513114262",
          "country_code": "IDN"
        },
      "cardless_credit_type": "KREDIVO",
      "callback_authentication_token": "MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n=="
    }
    Parameter Type Description
    external_id string Your transaction identifier that you specified in on the Generate Checkout URL request.
    order_id string Unique Identifier that we gave to the cardless credit payment partner.
    transaction_id string Transaction ID given by Cardless Credit partner.
    transaction_status string Transaction status, the value is:
    settlement: Transaction is successful
    pending: End-User has not completed the transaction
    deny: Transaction has been denied by our Cardless Credit Partner
    cancel: Transaction has been cancelled
    expire: End-User did not complete transaction in 24 hours, thus transaction is expired
    payment_type string the type of installment.
    amount number Amount that you specified in on the Generate Checkout URL request.
    items array of item List of items / products that you specified in on the Generate Checkout URL request.
    item object
    item detail Details of an item, it should contains: id [string], name [string], price [number], type [string], url [string], quantity [number]
    customer_details object Details of the customer, it should contains: first_name [string], last_name [string], email [string], phone [string]
    shipping_address object Details of the shipping address, it should contains: first_name [string], last_name [string], address [string], city [string], postal_code [string], phone [string], country_code [string]
    cardless_credit_type string The type of cardless-credit.
    Supported Cardless Credit types: KREDIVO
    callback_authentication_token string Your Callback Verfication API Key that you can found on your Xendit Dashboard. You need to verify if this had the same value.

    QR Codes

    QR codes payment instrument allows you to receive payments directly from end user's mobile banking app balance or eWallet balance. In Indonesia, our merchants can receive payments from any providers connected on QRIS network. (e.g. OVO, Gopay, DANA, LinkAja, BCA, CIMB, Shopeepay)

    Create QR Code

    Endpoint: Create QR Code

    POST https://api.xendit.co/qr_codes

    Request Parameters

    Example: Create QRIS QR Code

    curl https://api.xendit.co/qr_codes -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
       -d external_id='testing_id_123' \
       -d type='DYNAMIC' \
       -d callback_url='https://yourwebsite.com/callback'\
       -d amount=1500
    $ch = curl_init();
    
    curl_setopt($ch, CURLOPT_URL, 'https://api.xendit.co/qr_codes');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, "external_id=testing_id_123&type=DYNAMIC&callback_url=https://yourwebsite.com/callback&amount=1500");
    curl_setopt($ch, CURLOPT_USERPWD, 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==' . ':' . '');
    
    $headers = array();
    $headers[] = 'Content-Type: application/x-www-form-urlencoded';
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    
    $result = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'Error:' . curl_error($ch);
    }
    curl_close($ch);
    var request = require('request');
    
    var dataString = 'external_id=testing_id_123&type=DYNAMIC&callback_url=https://yourwebsite.com/callback&amount=1500';
    
    var options = {
        url: 'https://api.xendit.co/qr_codes',
        method: 'POST',
        body: dataString,
        auth: {
            'user': 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==',
            'pass': ''
        }
    };
    
    function callback(error, response, body) {
        if (!error && response.statusCode == 200) {
            console.log(body);
        }
    }
    
    request(options, callback);
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information
    Body Parameter Type Description
    external_id
    required
    string An ID of your choice. Often it is unique identifier in your system like customer ID or order ID
    Note: It has to be unique per creation request
    type
    required
    string DYNAMIC or STATIC
    Note: DYNAMIC QR code contains the payment value upon scanning and can be paid multiple times
    Note: STATIC QR code requires end user to input the payment value and can be paid multiple times
    callback_url
    required
    string The URL to receive payment notification after payment has been made by end user
    amount
    optional
    number The payment value embedded in the QR code, end user can only pay the specified amount after scanning the QR code. For STATIC QR code, amount parameter will be ignored.
    Note: Min amount is 1,500 IDR
    Note: Max amount is 2,000,000 IDR

    Response Parameters

    Example: Create QRIS QR Code API Success Response

    {
        "id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
        "external_id": "testing_id_123",
        "amount": 1500,
        "qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52  045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
        "callback_url": "https://yourwebsite.com/callback",
        "type": "DYNAMIC",
        "status": "ACTIVE",
        "created": "2020-01-08T18:18:18.661Z",
        "updated": "2020-01-08T18:18:18.661Z"
    }
    Parameter Type Description
    id
    required
    string Unique identifier for this transaction
    external_id
    required
    string Unique identifier specified by merchant for QR code creation
    amount
    required
    number Amount specified in request
    Note: Value will be NULL if QR type is STATIC
    qr_string
    required
    string QR string to be rendered for display to end users. QR string to image rendering are commonly available in software libraries (e.g Nodejs, PHP, Java)
    callback_url
    required
    string The URL provided by merchant to receive payment notification after payment has been made by end user
    type
    required
    string DYNAMIC or STATIC
    status
    required
    string ACTIVE (QR code can be paid) or INACTIVE (QR code has been paid for DYNAMIC QR)
    created
    required
    string Timestamp ISO 8601 when the QR code was created (in UTC)
    updated
    required
    string Timestamp ISO 8601 when the QR code was patched (in UTC)

    Error Codes

    Example: Create QRIS QR Code API Error Response

    {
        "error_code": "API_VALIDATION_ERROR",
        "message": "Amount must be within range [1500, 2000000]"
    }
    Error Code Description
    DUPLICATE_ERROR
    409
    The payment with the same external_id has already been made before.
    DATA_NOT_FOUND
    409
    QRIS merchant not found, please contact our customer success team for activation.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    API_VALIDATION_ERROR
    400
    There is invalid input in one of the required request fields.

    Get QR Code by External ID

    GET https://api.xendit.co/qr_codes/:external_id

    Request Parameters

    Example: Get QR Code by external_id

    curl https://api.xendit.co/qr_codes/external_id -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
    $ch = curl_init();
    
    curl_setopt($ch, CURLOPT_URL, 'https://api.xendit.co/qr_codes/external_id');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    
    curl_setopt($ch, CURLOPT_USERPWD, 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==' . ':' . '');
    
    $result = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'Error:' . curl_error($ch);
    }
    curl_close($ch);
    var request = require('request');
    
    var options = {
        url: 'https://api.xendit.co/qr_codes/external_id',
        auth: {
            'user': 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==',
            'pass': ''
        }
    };
    
    function callback(error, response, body) {
        if (!error && response.statusCode == 200) {
            console.log(body);
        }
    }
    
    request(options, callback);
    Path Parameter Type Description
    external_id
    required
    string Merchant provided unique ID used to create QR code

    Response Parameters

    Example: Get QR Code by external_id Success Response

    {
        "id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
        "external_id": "testing_id_123",
        "amount": 1500,
        "qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
        "callback_url": "https://yourwebsite.com/callback",
        "type": "DYNAMIC",
        "status": "ACTIVE",
        "created": "2020-01-08T18:18:18.661Z",
        "updated": "2020-01-08T18:18:18.661Z"
    }
    Parameter Type Description
    id
    required
    string Unique identifier for this transaction
    external_id
    required
    string Unique identifier specified by merchant for QR code creation
    amount
    required
    number Amount specified in request
    Note: Value will be NULL if QR type is STATIC
    qr_string
    required
    string QR string to be rendered for display to end users. QR string to image rendering are commonly available in software libraries (e.g Nodejs, PHP, Java)
    callback_url
    required
    string The URL provided by merchant to receive payment notification after payment has been made by end user
    type
    required
    string Type of QR code - DYNAMIC or STATIC
    status
    required
    string ACTIVE (QR code can be paid) or INACTIVE (QR code has been paid for DYNAMIC QR)
    created
    required
    string Timestamp ISO 8601 when the QR code was created (in UTC)
    updated
    required
    string Timestamp ISO 8601 when the QR code was patched (in UTC)

    Error Codes

    Example: Create QRIS QR Code API Error Response

    {
        "error_code": "DATA_NOT_FOUND",
        "message": "QR code with external_id testing_id_123 not found"
    }
    Error Code Description
    DATA_NOT_FOUND
    404
    The QR code with specified external_id does not exist.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Simulate Payment (for completion of payment in test mode)

    POST https://api.xendit.co/qr_codes/:external_id/payments/simulate

    Request Parameters (test mode)

    Example: Simulate Payment in Test Mode

    curl https://api.xendit.co/qr_codes/:external_id/payments/simulate -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
       -d amount=1500
    $ch = curl_init();
    
    curl_setopt($ch, CURLOPT_URL, 'https://api.xendit.co/qr_codes/:external_id/payments/simulate');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, "amount=1500");
    curl_setopt($ch, CURLOPT_USERPWD, 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==' . ':' . '');
    
    $headers = array();
    $headers[] = 'Content-Type: application/x-www-form-urlencoded';
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    
    $result = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'Error:' . curl_error($ch);
    }
    curl_close($ch);
    var request = require('request');
    
    var dataString = 'amount=1500';
    
    var options = {
        url: 'https://api.xendit.co/qr_codes/:external_id/payments/simulate',
        method: 'POST',
        body: dataString,
        auth: {
            'user': 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==',
            'pass': ''
        }
    };
    
    function callback(error, response, body) {
        if (!error && response.statusCode == 200) {
            console.log(body);
        }
    }
    
    request(options, callback);
    
    Path Parameter Type Description
    external_id
    required
    string Unique identifier specified by merchant for QR code creation
    Body Parameter Type Description
    amount
    optional
    number The payment value for simulation in callback to test mode endpoint
    Note: Min amount is 1,500 IDR
    Note: Max amount is 2,000,000 IDR

    Response Parameters (test mode)

    Example: Simulate Payment (test mode) Success Response

    {
      "id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
      "amount": 1500,
      "created": "2020-01-08T18:18:18.857Z",
      "qr_code": {
        "id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
        "external_id": "testing_id_123",
        "qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
        "type": "DYNAMIC"
      },
      "status": "COMPLETED"
    }
    Parameter Type Description
    id required string Unique identifier for this transaction
    amount required number Amount paid by end user
    created required string Timestamp ISO 8601 when the QR code was paid (in UTC)
    qr_code required string QR code object associated with the QR code payment
    qr.id required string Unique identifier for the QR code creation transaction
    qr.external_id required string Unique identifier specified by merchant for QR code creation
    qr.qr_string required string QR string to be rendered for display to end users. QR string to image rendering are commonly available in software libraries (e.g Nodejs, PHP, Java)
    qr.type required string Type of QR code - DYNAMIC or STATIC
    status required string Status of payment. Possible value(s): COMPLETED

    Error Codes

    Example: Create QRIS QR Code API Error Response

    {
        "error_code": "DATA_NOT_FOUND",
        "message": "QR code with external_id testing_id_123 not found"
    }
    Error Code Description
    INACTIVE_QR_CODE
    410
    Payment simulation for DYNAMIC QRIS has been completed previously. DYNAMIC QRIS is inactive.
    DATA_NOT_FOUND
    404
    The QR code with specified external_id does not exist.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    API_VALIDATION_ERROR
    400
    There is invalid input in one of the required request fields.

    Payment Status Callback

    You will need to provide an endpoint in your system to receive payment callback notification from our system. You will receive the callback when end-customer completed the QR code payment.
    Note: Please give this notification a response back with status 200 so we know that our notification is received.

    Callback Payload

    {
      "event": "qr.payment",
      "id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
      "amount": 1500,
      "created": "2020-01-08T18:18:18.857Z",
      "qr_code": {
        "id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
        "external_id": "testing_id_123",
        "qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
        "type": "DYNAMIC"
      },
      "status": "COMPLETED"
    }
    Parameter Type Description
    event required string Available value: "qr.payment"
    id required string Unique identifier for this transaction
    amount required number Amount paid by end user
    created required string Timestamp ISO 8601 when the QR code was paid (in UTC)
    qr_code required string QR code object associated with the QR code payment
    qr.id required string Unique identifier for the QR code creation transaction
    qr.external_id required string Unique identifier specified by merchant for QR code creation
    qr.qr_string required string QR string to be rendered for display to end users. QR string to image rendering are commonly available in software libraries (e.g Nodejs, PHP, Java)
    qr.type required string Type of QR code - DYNAMIC or STATIC
    status required string Status of payment. Possible value(s): COMPLETED

    Direct Debit

    Direct Debit enables merchants to pull payments directly from their end user’s account bank balance by linking their debit card or bank account access.

    For the integration guide, and list of supported channels and corresponding linking type, see our documentation.

    Create Customer

    A customer object is required in order to link a payment method for direct debit. This allows you to easily link and track payment methods and transactions.

    Endpoint: Create Customer

    POST https://api.xendit.co/customers

    Create Customer - Request

    Example Create Customer Request

    curl https://api.xendit.co/customers -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d reference_id=demo_1475801962607 \
       -d given_names="John" \
       -d mobile_number="+6287774441111" \
       -d email="customer@website.com" \
    <?php
      $url = "https://api.xendit.co/customers";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
      $data = [
        "given_names" => "John",
        "reference_id" => "demo_1475801962607",
        "mobile_number" => "+6287774441111",
        "email" => "customer@website.com"
      ];
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let url = "https://api.xendit.co/customers";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    var reqBody = JSON.stringify({
      "given_names":"John",
      "reference_id":"demo_1475801962607",
      "mobile_number":"+6287774441111",
      "email":"customer@website.com"});
    
    var requestOptions = {
      method: 'POST',
      headers: headers,
      body: reqBody,
      redirect: 'follow'
    };
    
    fetch(url, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Request Body Parameter Description
    reference_id
    required
    string Merchant-provided identifier for the customer
    mobile_number
    either mobile_number or email is required
    string Mobile number of the customer in E.164 international standard.
    Format: +(country code)(subscriber number)
    email
    either mobile_number or email is required
    string Email address of the customer
    given_names
    required
    string Primary of first name/s of the customer
    middle_name
    optional
    string Middle name of the customer
    surname
    optional
    string Surname of the customer
    description
    optional
    string Merchant-provided description for the customer object
    phone_number
    optional
    string Alternate or landline phone number in E.164 international standard.
    Format: +(country code)(subscriber number)
    nationality
    optional
    string 2-letter ISO 3166-2 country code for the customer's nationality
    addresses
    optional
    array of object Array of objects containing the specific customer's address information

    Each object may have the following properties:
    Key Value
    country
    required
    2-letter ISO 3166-2 country code for the customer's country of residence
    street_line1
    optional
    Building name and apartment unit number
    street_line2
    optional
    Building street address
    city
    optional
    City, village or town as appropriate
    province
    optional
    Geographic area, province, or region, if applicable
    state
    optional
    Formal state designation within country, if applicable
    postal_code
    optional
    Postal, zip or rural delivery code, if applicable
    date_of_birth
    optional
    string Date of birth of the customer in YYYY-MM-DD format
    metadata
    optional
    object A free-format JSON for additional information that you may use.

    Create Customer - Response

    Example Create Customer Success Response

    {
        "id": "239c16f4-866d-43e8-9341-7badafbc019f",
        "reference_id": "demo_1475801962607",
        "email": "customer@website.com",
        "mobile_number": null,
        "given_names": "John",
        "description": null,
        "middle_name": null,
        "surname": null,
        "phone_number": null,
        "nationality": null,
        "addresses": null,
        "date_of_birth": null,
        "metadata": null
    }
    Parameter Description
    id string Unique ID generated by Xendit for the particular customer
    reference_id string Identifer you provided during request
    mobile_number string Mobile number of the customer
    email string Email address of the customer
    given_names string Primary of first name/s of the customer
    middle_name string Middle name of the customer
    surname string Surname of the customer
    description string Description you provided for the customer object
    phone_number string Alternate or landline phone number
    nationality string Country code for the customer's nationality
    addresses object array Array of objects containing the specific customer's address information
    Key Value
    country
    required
    2-letter ISO 3166-2 country code for the customer's country of residence
    street_line1
    optional
    Building name and apartment unit number
    street_line2
    optional
    Building street address
    city
    optional
    City, village or town as appropriate
    province
    optional
    Geographic area, province, or region, if applicable
    state
    optional
    Formal state designation within country, if applicable
    postal_code
    optional
    Postal, zip or rural delivery code, if applicable
    date_of_birth string Date of birth of the customer in YYYY-MM-DD format
    metadata object A free-format JSON for additional information that you provded during request.

    Create Customer - Errors

    See other common errors here.

    Error Code Description
    DUPLICATE_ERROR
    409
    The provided reference_id has been used before. Please enter a unique reference_id and try again.

    Initialize Linked Account Tokenization

    Account authorizations are represented by linked account tokens. This endpoint initializes the authorization process and linked account token creation.

    Endpoint: Initialize Linked Account Tokenization

    POST https://api.xendit.co/linked_account_tokens/auth

    Initialize Linked Account Tokenization - Request

    Example Initialize Linked Account Tokenization Request

    curl https://api.xendit.co/linked_account_tokens/auth -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -H 'Content-Type: application/json' \
       --data-raw '{
        "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
        "channel_code": "DC_BRI",
        "properties": {
            "account_mobile_number": "62818555988",
            "card_last_four": "1234",
            "card_expiry": "06/24",
            "account_email": "email@email.com"
        }
    }'
    <?php
      $url = "https://api.xendit.co/linked_account_tokens/auth";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
      $data = [
        "customer_id" => "ba830b92-4177-476e-b097-2ad5ae4d3e55",
        "channel_code" => "DC_BRI",
        "properties" => [
          "account_mobile_number" => "62818555988",
          "card_last_four" => "1234",
          "card_expiry" => "06/24",
          "account_email" => "email@email.com"
        ]
      ];
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let url = "https://api.xendit.co/linked_account_tokens/auth";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    var reqBody = JSON.stringify({
      "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
      "channel_code": "DC_BRI",
      "properties": {
        "account_mobile_number": "62818555988",
        "card_last_four": "1234",
        "card_expiry": "06/24",
        "account_email": "email@email.com"
      }
    });
    
    var requestOptions = {
      method: 'POST',
      headers: headers,
      body: reqBody,
      redirect: 'follow'
    };
    
    fetch(url, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Request Body Parameter Description
    customer_id
    required
    string ID of the customer object to which the account token will be linked to
    channel_code
    required
    string Identifier for the specific channel of the account to be linked. Code must be in uppercase.

    Supported channel codes: DC_BRI, BA_BPI
    properties
    optional
    object JSON that contains information needed to proceed with authorization. Values inside properties change based on type of account:

    For Debit Card Linking (BRI):
    Key Value
    account_mobile_number
    required
    Mobile number of the customer registered to the partner channel
    card_last_four
    required
    Last four digits of the debit card
    card_expiry
    required
    Expiry month and year of the debit card (in MM/YY format)
    account_email
    required
    Email address of the customer that is registered to the partner channel
    For Online Banking Access Linking (BPI):
    Key Value
    success_redirect_url
    required
    URL where the end-customer is redirected if the authorization is successful. Linked account token ID will be included in the URL as a query parameter.
    failure_redirect_url
    optional
    URL where the end-customer is redirected if the authorization fails
    callback_url
    optional
    URL where the successful linking webhook will be sent. If none is provided, webhook will be sent to the default set during onboarding.
    metadata
    optional
    object A free-format JSON for additional information that you may use.

    Initialize Linked Account Tokenization - Response

    Example Initialize Linked Account Tokenization Success Response

    {
        "id": "lat-aa620619-124f-41db-995b-66a52abe036a",
        "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
        "channel_code": "DC_BRI",
        "authorizer_url": null,
        "status": "PENDING",
        "metadata": null
    }
    Parameter Description
    id string Unique ID generated by Xendit for the particular linked account token authorization
    customer_id string Customer object ID
    channel_code string Code identifier for the channel
    authorizer_url string URL to be rendered for end user to confirm authorization for linking via online banking access.
    For debit card linking (BRI), this will always be null; proceed to the "Validate OTP for Linked Account Token" step instead.
    status string Status of the authorization. Will always be PENDING for successful initiations.
    metadata object A free-format JSON for additional information that you provded during request.

    Initialize Linked Account Tokenization - Errors

    See other common errors here.

    Error Code Description
    CHANNEL_CODE_NOT_SUPPORTED_ERROR
    400
    Provided channel_code is not supported or has not yet activated for this account.
    CUSTOMER_NOT_FOUND_ERROR
    400
    Provided customer_id in the request does not exist or access is unauthorized
    CHANNEL_UNAVAILABLE
    503
    The target channel is currently unavailable. This is possibly due to partner channel downtime or error.

    Validate OTP for Linked Account Token

    Account linking for debit cards requires an OTP to proceed. Upon successful initialization, the bank will send an OTP to the customer's registered mobile number directly. This endpoint validates the OTP with the bank.

    Endpoint: Validate OTP for Linked Account Token

    POST https://api.xendit.co/linked_account_tokens/{linked_account_token_id}/validate_otp

    Validate OTP for Linked Account Token - Request

    Example Validate OTP for Linked Account Token Request

    curl https://api.xendit.co/linked_account_tokens/lat-aa620619-124f-41db-995b-66a52abe036a/validate_otp -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -H 'Content-Type: application/json' \
       --data-raw '{
        "otp_code":123456
    }'
    <?php
      $linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
      $url = "https://api.xendit.co/linked_account_tokens/" . $linkedAccountTokenId . "/validate_otp";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
      $data = [
        "otp_code" => "123456"
      ];
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
    let url = "https://api.xendit.co/linked_account_tokens/" + linkedAccountTokenId + "/validate_otp";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    var reqBody = JSON.stringify({
      "otp_code":"123456"
    });
    
    var requestOptions = {
      method: 'POST',
      headers: headers,
      body: reqBody,
      redirect: 'follow'
    };
    
    fetch(url, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Path Parameter Description
    linked_account_token_id
    required
    string Linked account token id received from Initialize Account Authorization. This has the lat- prefix.
    Request Body Parameter Description
    otp_code
    required
    string OTP received by the customer from the partner bank for account linking

    Validate OTP for Linked Account Token - Response

    Example Validate OTP for Linked Account Token Success Response

    {
        "id": "lat-aa620619-124f-41db-995b-66a52abe036a",
        "customer_id": "239c16f4-866d-43e8-9341-7badafbc019f",
        "channel_code": "DC_BRI",
        "status": "SUCCESS"
    }
    Parameter Description
    id string Unique ID generated by Xendit for the particular linked account token authorization
    customer_id string Customer object ID
    channel_code string Code identifier for the channel
    status string Status of the authorization - SUCCESS if the validation went through. Else, error will be thrown

    Validate OTP for Linked Account Token - Errors

    See other common errors here.

    Error Code Description
    DATA_NOT_FOUND_ERROR
    404
    Provided linked_account_token_id is not supported or has not yet activated for this account.
    INVALID_OTP_ERROR
    400
    The otp_code provided was incorrect.
    EXPIRED_OTP_ERROR
    400
    The otp_code provided has expired.
    MAX_OTP_ATTEMPTS_ERROR
    400
    Reached the channel’s allowed maximum attempts for OTP verification
    ACCOUNT_LINKING_ALREADY_COMPLETED
    409
    The request is a duplicate of an already processed linked account token that has been successfully completed.
    ACCOUNT_LINKING_ALREADY_FAILED
    409
    The request is a duplicate of an already processed linked account token that has failed.

    Retrieve Accessible Accounts by Linked Account Token

    This endpoint returns a list of bank accounts accessible by the linked account token. The response information from this endpoint is required for creation of payment method.

    Endpoint: Get Accessible Accounts by Linked Account Token

    GET https://api.xendit.co/linked_account_tokens/{linked_account_token_id}/accounts

    Retrieve Accessible Accounts by Linked Account Token - Request

    Example Get Accessible Accounts by Linked Account Token Request

    curl https://api.xendit.co/linked_account_tokens/lat-aa620619-124f-41db-995b-66a52abe036a/accounts -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: 
    <?php
      $linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
      $url = "https://api.xendit.co/linked_account_tokens/" . $linkedAccountTokenId . "/accounts";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    
    let linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
    let url = "https://api.xendit.co/linked_account_tokens/" + linkedAccountTokenId + "/validate_otp";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    var requestOptions = {
      method: 'GET',
      headers: headers,
      redirect: 'follow'
    };
    
    fetch(url, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Path Parameter Description
    linked_account_token_id
    required
    string Linked account token id received from Initialize Account Authorization. This has the lat- prefix.

    Retrieve Accessible Accounts by Linked Account Token - Response

    This endpoint returns an array of objects with the following properties:

    Example Get Accessible Accounts by Linked Account Token Success Response

    [{
        "id": "la-aa620619-124f-41db-995b-66a52abe036a",
        "channel_code": "DC_BRI",
        "type": "DEBIT_CARD",
        "properties": {
            "account_mobile_number": "62818555988",
            "card_last_four": "1234",
            "card_expiry": "06/24",
            "account_email": "email@email.com"
        }
    }]
    Parameter Description
    id string Unique identifier for the bank account. This has a prefix of la-.
    channel_code string Code identifier for the channel
    type string Type of account that has been linked.
    Expected values: DEBIT_CARD or BANK_ACCOUNT
    properties object Object containing information regarding the account. The values inside properties change based on the type of account:


    For type DEBIT_CARD (BRI):
    Key Value
    card_last_four stringLast four digits of the debit card
    card_expiry stringExpiry month and year of the debit card (in MM/YY format)
    currency stringCurrency of the account in ISO 4217
    description stringDescription of the account (provided by the bank)
    For type BANK_ACCOUNT (BPI):
    Key Value
    account_details stringMasked account details as provided by the bank. Used for displaying a portion of the account number.
    account_hash stringUnique hash for the specific account. This does not change across different authorizations or integrations.
    account_type stringType of bank account (provided by the bank)
    currency stringCurrency of the account in ISO 4217
    description stringDescription of the account (provided by the bank)

    Retrieve Accessible Accounts by Linked Account Token - Errors

    See other common errors here.

    Error Code Description
    DATA_NOT_FOUND_ERROR
    404
    Provided linked_account_token_id is not supported or has not yet activated for this account.

    Create Payment Method

    Payment methods enable you to abstract sources of funds and use them for making direct debit payments or recurring payments. Currently, only supports linked accounts.

    Endpoint: Create Payment Method

    POST https://api.xendit.co/payment_methods

    Create Payment Method - Request

    Example Create Payment Method Request

    curl https://api.xendit.co/payment_methods -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -H 'Content-Type: application/json' \
       --data-raw '{
        "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
        "type": "DEBIT_CARD",
        "properties": {
            "id": "la-aa620619-124f-41db-995b-66a52abe036a"
        }
    }'
    <?php
      $url = "https://api.xendit.co/payment_methods";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
      $data = [
        "customer_id" => "ba830b92-4177-476e-b097-2ad5ae4d3e55",
        "type" => "DEBIT_CARD",
        "properties" => [
          "id" => "la-aa620619-124f-41db-995b-66a52abe036a"
        ]
      ];
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let url = "https://api.xendit.co/payment_methods/";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    var reqBody = JSON.stringify({
      "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
      "type": "DEBIT_CARD",
      "properties": {
        "id": "la-aa620619-124f-41db-995b-66a52abe036a"
      }
    });
    
    var requestOptions = {
      method: 'POST',
      headers: headers,
      body: reqBody,
      redirect: 'follow'
    };
    
    fetch(url, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Request Body Parameter Description
    customer_id
    required
    string ID of the customer object to which the account token will be linked to
    type
    required
    string Type of payment method

    Supported values: DEBIT_CARD, BANK_ACCOUNT
    properties
    required
    object JSON that contains information that identifies the payment method:


    For Debit Card Linking (BRI) or Bank Account Access (BPI):
    Key Value
    id
    required
    ID of the account from which payments will be pulled from. You can retrieve account ID by using this API
    metadata
    optional
    object A free-format JSON for additional information that you may use.

    Create Payment Method - Response

    Example Create Payment Method Success Response

    {    
        "id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "type": "DEBIT_CARD",
        "properties": {
            "id": "la-aa620619-124f-41db-995b-66a52abe036a",
            "channel_code": "DC_BRI",
            "currency": "IDR",
            "card_last_four": "1234",
            "card_expiry": "06/24",
            "description": null,
        },
        "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
        "status": "ACTIVE",
        "created": "2020-03-19T05:34:55+0800",
        "updated": "2020-03-19T05:24:55+0800",
        "metadata": null  
    }
    Parameter Description
    id string Unique identifier for the payment method. This has a prefix of pm-.
    type string Type of account that has been linked.
    Expected values: DEBIT_CARD or BANK_ACCOUNT
    properties object Object containing information regarding the account. The values inside properties change based on the type of account:


    For type DEBIT_CARD (BRI):
    Key Value
    card_last_four stringLast four digits of the debit card
    card_expiry stringExpiry month and year of the debit card (in MM/YY format)
    currency stringCurrency of the account in ISO 4217
    description stringDescription of the account (provided by the bank)
    For type BANK_ACCOUNT (BPI):
    Key Value
    account_details stringMasked account details as provided by the bank. Used for displaying a portion of the account number.
    account_hash stringUnique hash for the specific account. This does not change across different authorizations or integrations.
    account_type stringType of bank account (provided by the bank)
    currency stringCurrency of the account in ISO 4217
    description stringDescription of the account (provided by the bank)
    customer_id string ID of the customer object in which this payment method is linked to
    status
    required
    string Status of the payment method.
    Will be equal to ACTIVE upon creation.
    created string Timestamp in ISO 8601 when the request was made
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    updated string Timestamp in ISO 8601 when transaction information was updated
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    metadata object A free-format JSON for additional information that you provded during request.

    Create Payment Method - Errors

    See other common errors here.

    Error Code Description
    LIINKED_ACCOUNT_NOT_FOUND_ERROR
    400
    Provided properties and type combination in the request does not exist or access is unauthorized
    CUSTOMER_NOT_FOUND_ERROR
    400
    Provided customer_id in the request does not exist or access is unauthorized
    DUPLICATE_ERROR
    409
    There is already an existing ACTIVE payment method that relates to the same account

    Create Recurring Payment with Direct Debit

    Endpoint: Create Recurring Payment

    POST https://api.xendit.co/recurring_payments

    Recurring payments allow you to use the auto debit feature in direct debit to pull funds from your customers bank account on a scheduled basis.

    Request Parameters

    Example: Create Recurring Request

    curl https://api.xendit.co/recurring_payments -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d external_id=recurring_31451441 \
       -d payment_method_id=pm_testing_id_123\
       -d payer_email=sample_email@xendit.co \
       -d interval=MONTH \
       -d interval_count=1 \
       -d description='Monthly room cleaning service' \
       -d total_recurrence=10\
       -d charge_immediately=true\
       -d invoice_duration=300\
       -d amount=125000
    <?php
      require 'vendor/autoload.php';
    
      $options['secret_api_key'] = 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==';
    
      $xenditPHPClient = new XenditClient\XenditPHPClient($options);
    
      $external_id = 'recurring_31451441';
      $amount = 125000;
      $payment_method_id='pm_testing_id_123';
      $payer_email = 'sample_email@xendit.co';
      $interval = 'MONTH';
      $interval_count = 1;
      $description = 'Monthly room cleaning service';
      $total_recurrence=10;
      $charge_immediately=true;
      $invoice_duration=300;
    
      $response = $xenditPHPClient->createRecurringPayment($external_id, $amount, $payer_email, $interval, $interval_count, $description);
      print_r($response);
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RecurringPayment } = x;
    const rpSpecificOptions = {};
    const rp = new RecurringPayment(rpSpecificOptions);
    
    const resp = await rp.createPayment({
      externalID: 'recurring_31451441',
      amount: 125000,
      payerEmail: 'sample_email@xendit.co',
      interval: RecurringPayment.Interval.Month,
      intervalCount: 1,
      description: 'Monthly room cleaning service',
      payment_method_id: 'pm_testing_id_123',
      total_recurrence: 10,
      charge_immediately: true,
      invoice_duration: 300
    });
    console.log(resp);
    Body Parameter Type Description
    external_id
    required
    string ID of your choice (typically the unique identifier of a recurring payment in your system)
    payment_method_id
    optional
    string Fill this with the payment method id created for the customer in create payment method
    payer_email
    required
    string Email of the end user you're charging
    description
    required
    string Description for the recurring payment and invoices
    amount
    required
    number Amount per invoice per interval.
    The minimum amount to create an invoice is 10.000 IDR. The maximum amount is 1.000.000 IDR for direct debit
    interval
    required
    string One of DAY, WEEK, MONTH. The frequency with which a recurring payment invoice should be billed.
    interval_count
    required
    number The number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months.
    invoice_duration
    required
    number Set this value to 300 for direct debit recurring to work. Duration of time that end user have in order to pay the invoice before it's expired (in Second).
    total_recurrence
    optional
    number The number of times you will charge your customer. If you input it as 3, Xendit will charge your customer 3 times. If you input total_recurrence as 3, interval_count as 1 and interval as "DAY", Xendit will charge customer 3 times in first day after you trigger create recurring api, the day after and 2 days after you trigger create recurring api.
    should_send_email
    optional
    boolean Specify should the end user get email when invoice is created, paid, or expired; or not
    default: false
    missed_payment_action
    optional
    string One of IGNORE, STOP. If there is an invoice from a recurring payment that expired, IGNORE will continue with the recurring payment as usual. STOP will stop the recurring payment.
    default: IGNORE
    start_date
    optional
    string (ISO 8601) time when the first invoice will be issued. When left blank, the invoice will be created immediately
    charge_immediately
    optional

    boolean Specify should the first invoice created immediately when creating recurring payment with a valid start_date,
    The next invoice will be created at start_date and the calculation for the following recurring invoice will be at
    interval*interval_count + start_date

    Response Parameters

    Example: Create Recurring Response

    {
        "id": "579c8d61f23fa4ca35e52da3",
        "user_id": "5781d19b2e2385880609791c",
        "external_id": "recurring_31451441",
        "status": "ACTIVE",
        "amount": 125000,
        "payer_email": "sample_email@xendit.co",
        "description": "Monthly room cleaning service",
        "interval": "MONTH",
        "interval_count": 1,
        "recurrence_progress": 1,
        "should_send_email": false,
        "missed_payment_action": "IGNORE",
        "last_created_invoice_url": "https://invoice-staging.xendit.co/web/invoices/5dddeea6bdb99f4b23e5eef7",
        "created": "2017-06-12T14:00:00.306Z",
        "updated": "2017-06-12T14:00:00.306Z",
        "start_date": "2017-07-12T14:00:00.306Z",
        "recharge": true,
        "payment_method_id": "pm_testing_id_123"
    }
    Parameter Type Description
    id string An recurring ID generated by Xendit
    user_id string Your Xendit Business ID
    external_id string The recurring ID in your server, that can be used to reconcile between you and Xendit
    status string ACTIVE the recurring payment is currently active
    STOPPED the recurring payment has been stopped
    PAUSED the recurring payment is currently paused and will not automatically creating invoices. resume to reactivate
    amount number Nominal amount of the recurring payment in IDR
    payer_email string Email of the payer, we get this information from your API call
    description string Description for the recurring payment and invoices
    should_send_email boolean A flag showing should payer get email when invoice is created, paid, or expired; or not
    interval string One of DAY, WEEK, MONTH. The frequency with which a recurring payment invoice should be billed.
    interval_count number The number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months.
    recurrence_progress number The current cycle of recurring payment. If your end customer is on the 4th cycle of the recurring, you will get 4 from recurrence_progress response
    last_created_invoice_url string url leading to the last invoice create by this recurring payment
    invoice_duration number Ensure that this value is 300duration of time that end user have in order to pay the invoice before it's expired (in Second).
    created string (ISO 8601) An ISO timestamp that tracks when the recurring payment was created. Timezone is UTC+0
    updated string (ISO 8601) An ISO timestamp that tracks when the recurring payment was updated. Timezone is UTC+0
    charge_immediately
    optional

    boolean A flag showing should the first invoice created immediately when creating recurring payment with a valid start_date
    recharge boolean This parameter will be true for direct debit payments.
    payment_method_id string the payment_method_id assigned to this recurring payment

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation The errors field contains details about which fields are violating validation
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format
    INVALID_PAYMENT_METHOD_ID_ERROR
    400
    Payment method id is invalid
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Other Recurring Operations

    For post recurring payment creation operations like get, edit, pause, resume, stop - refer to recurring payments

    Create Direct Debit Payment

    Create a debit to pull funds from the end customer's account using an active payment method

    Endpoint: Create Direct Debit Payment

    POST https://api.xendit.co/direct_debits

    Create Payment - Request

    Example Create Payment Request

    curl https://api.xendit.co/direct_debits -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -H 'Content-Type: application/json' \
       -H 'Idempotency-key: Test_Idempotent_Key'\
       --data-raw '{
        "reference_id": "customer_test_reference_id",
        "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "currency": "IDR",
        "amount": 1500,
        "enable_otp": true,
        "callback_url": "https://payment-callback-listener/"
    }'
    <?php
      $url = "https://api.xendit.co/direct_debits";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [
        "Content-Type" => "application/json",
        "Idempotency-key" => "Test_Idempotent_Key",
        ];
      $data = [
        "reference_id" => "customer_test_reference_id",
        "payment_method_id" => "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "currency" => "IDR",
        "amount" => 1500,
        "enable_otp" => true,
        "callback_url" => "https://payment-callback-listener/"
        ];
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let url = "https://api.xendit.co/direct_debits";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    headers.append("Idempotency-key", "Test_Idempotent_Key");
    
    var reqBody = JSON.stringify({
      "reference_id": "customer_test_reference_id",
      "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
      "currency": "IDR",
      "amount": 1500,
      "enable_otp": true,
      "callback_url": "https://payment-callback-listener/"
    });
    
    var requestOptions = {
      method: 'POST',
      headers: headers,
      body: reqBody,
      redirect: 'follow'
    };
    
    fetch(url, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Header Description
    Idempotency-key
    required
    string Provided by the merchant to prevent duplicate requests. May be equal to reference_id or any GUID.
    Note: Max 100 characters
    Request Body Parameter Description
    reference_id
    required
    string Merchant-provided identifier for this transaction
    Note: Max 255 characters
    payment_method_id
    required
    string Xendit’s identifier for specific payment method. You can create one using Create Payment Method API if you haven't already generated one. Use Get Payment Method API to retrieve the ID
    currency
    required
    string Currency of amount to debit in ISO 4217. e.g. "IDR", "PHP"
    amount
    required
    number Amount to debit from the end-customer’s account
    Note: Maximum amount that can be charged without OTP is 999,999
    callback_url
    required
    string URL where payment notification will be sent after transaction process
    Note: Max 255 characters
    enable_otp
    optional
    boolean
    true to charge end customer's account with OTP
    false to charge end customer's account without OTP
    description
    optional
    string Description for the direct debit transaction.
    basket
    optional
    array Array of objects describing the item/s purchased using direct debit
    Key Value
    reference_id
    required
    stringMerchant’s identifier for specific product (ie. SKU)
    name
    required
    stringName of product
    market
    required
    string2-letter ISO 3166-2 country code indicating target merchant’s country of operations
    type
    required
    stringType of product
    description
    optional
    stringDescription of product
    category
    optional
    stringMerchant category for item
    sub-category
    optional
    stringMerchant sub-category for item
    price
    optional
    stringPrice per unit in basket currency
    url
    optional
    stringProduct URL with product details
    metadata
    optional
    stringAdditional object that may be used for additional product attributes
    quantity
    optional
    stringNumber of units of this item in the basket
    metadata
    optional
    object Object of additional information the user may use. User defines the JSON properties and values. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long

    Create Payment - Response

    Example Create Payment Success Response

    {
        "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
        "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
        "channel_code": "DC_BRI",
        "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "currency": "IDR",
        "amount": "10000",
        "description": null,
        "status": "PENDING",
        "basket": null,
        "failure_code": null,
        "is_otp_required": true,
        "otp_mobile_number": "+6287774441111",
        "otp_expiration_timestamp": null,
        "created": "2020-03-26T05:44:26+0800",
        "updated": null,
        "metadata": null
    }
    Parameter Description
    id string Unique identifier for the transaction
    reference_id string Reference ID provided by merchant
    channel_code string Code identifier for the channel
    payment_method_id string Payment method ID of end-customer source of funds
    currency string Currency of the payment
    amount number Amount to debit from the end-customer’s account
    description string Description provided by merchant
    status string Status of the payment - "PENDING", "COMPLETED", "FAILED"
    failure_code string Reason if direct debit has failed. List of failure codes can be found here
    is_otp_required boolean The flag for merchant to know whether OTP was enabled for the particular direct debit transaction
    otp_mobile_number string Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled.
    otp_expiration_timestamp string Timestamp until when the OTP is valid. Empty string if OTP was not enabled.
    created string Timestamp in ISO 8601 when the request was made
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    updated string Timestamp in ISO 8601 when transaction information was updated
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    basket array Array of basket objects provided by merchant
    metadata object Metadata provided by merchant

    Create Payment - Errors

    Example Create Payment Error Response

    {
        "error_code" : "DUPLICATE_ERROR",
        "message" : "Idempotency key has been used before. Use a unique idempotency key and try again"
    }
    Error Code Description
    DUPLICATE_ERROR
    409
    Idempotency key has been used before. Use a unique idempotency key and try again.
    PAYMENT_METHOD_NOT_FOUND_ERROR
    400
    Provided payment_method_id is invalid, not found or access is unauthorized
    INVALID_PAYMENT_METHOD_ERROR
    503
    The payment method has expired or has been invalidated.

    Validate OTP for Direct Debit Payment

    Validate OTP provided by end customer via this endpoint to complete the transaction when OTP is enabled.

    Endpoint: Validate OTP for Direct Debit Payment

    POST https://api.xendit.co/direct_debits/:direct_debit_id/validate_otp/

    Validate Payment OTP - Request

    Example Validate Payment OTP Request

    curl https://api.xendit.co/direct_debits/ddpy-623dca10-5dad-4916-test/validate_otp/ -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       --data-raw '{
        "otp_code": "111222"
        }'
    <?php
      $direct_debit_id = "ddpy-623dca10-5dad-4916-test";
      $url = "https://api.xendit.co/direct_debits/" . $direct_debit_id . "/validate_otp";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
      $data = [
        "otp_code" => "111222"
      ];
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let direct_debit_id = "ddpy-623dca10-5dad-4916-test";
    let url = "https://api.xendit.co/direct_debits/" . $direct_debit_id . "/validate_otp";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    var reqBody = JSON.stringify({
      "otp_code":"111222"
    });
    
    var requestOptions = {
      method: 'POST',
      headers: headers,
      body: reqBody,
      redirect: 'follow'
    };
    
    fetch(url, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Path Parameter Description
    direct_debit_id
    required
    string Merchant provided identifier for specified direct debit transaction
    Request Body Parameter Description
    otp_code
    required
    string One-time-password input from end customer

    Validate Payment OTP - Response

    Will return a successful 200 HTTP response as soon as the bank has validated the OTP, otherwise an error is returned.

    Example Get Payment Status by ID Success Response

    {
        "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
        "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
        "channel_code": "BA_BPI",
        "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "currency": "PHP",
        "amount": "1000.00",
        "description": "",
        "status": "PENDING",
        "basket": [],
        "failure_code": "",
        "is_otp_required": true,
        "otp_mobile_number": "+63907XXXX123",
        "otp_expiration_timestamp": "2020-03-26T05:45:06+0800",
        "created": "2020-03-26T05:44:26+0800",
        "updated": "2020-03-26T05:44:46+0800",
        "metadata": {}
    }
    Parameter Description
    id string Unique identifier for the transaction
    reference_id string Reference ID provided by merchant
    channel_code string Code identifier for the channel
    payment_method_id string Payment method ID of end-customer source of funds
    currency string Currency of the payment
    amount number Amount to debit from the end-customer’s account
    description string Description provided by merchant
    status string Status of the payment
    failure_code string Reason if direct debit has failed
    is_otp_required boolean The flag for merchant to know whether OTP was enabled for the particular direct debit transaction
    otp_mobile_number string Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled.
    otp_expiration_timestamp string Timestamp until when the OTP is valid. Empty string if OTP was not enabled.
    created string Timestamp in ISO 8601 when the request was made
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    updated string Timestamp in ISO 8601 when transaction information was updated
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    basket array Array of basket objects provided by merchant
    metadata object Metadata provided by merchant

    Validate Payment OTP - Errors

    Example Create Payment Error Response

    {
        "error_code" : "DUPLICATE_ERROR",
        "message" : "Idempotency key has been used before. Use a unique idempotency key and try again"
    }
    Error Code Description
    DATA_NOT_FOUND_ERROR
    404
    Provided direct_debit_id does not exist or access is unauthorized
    INVALID_OTP_ERROR
    400
    OTP provided is invalid
    EXPIRED_OTP_ERROR
    400
    OTP provided has expired
    MAX_OTP_ATTEMPTS_ERROR
    400
    Payment method reached the channel’s allowed maximum attempts for OTP verification
    DIRECT_DEBIT_ALREADY_COMPLETED
    409
    The request is a duplicate of an already processed linked account token that has been successfully completed.
    DIRECT_DEBIT_ALREADY_FAILED
    409
    The request is a duplicate of an already processed linked account token that has failed.

    Get Customer by Reference ID

    Retrieves an array with a customer object that matches the provided reference_id - the identifier provided by you

    Endpoint: Get Customer by Reference ID

    GET https://api.xendit.co/customers?reference_id={reference_id}

    Get Customer by Reference ID - Request

    Example Get Customer by Reference ID Request

    curl https://api.xendit.co/customers?reference_id=demo_1475801962607 -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: 
    <?php
      $url = "https://api.xendit.co/customers";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
    
      $queryString = "?reference_id=demo_1475801962607";
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url.$queryString);
      curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let url = "https://api.xendit.co/customers";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    let queryString = "?reference_id=demo_1475801962607";
    
    var requestOptions = {
      method: 'GET',
      headers: headers,
      redirect: 'follow'
    };
    
    fetch(url + queryString, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Query String Parameter Description
    reference_id
    required
    string Merchant-provided identifier for the customer

    Get Customer by Reference ID - Response

    Example Get Customer by Reference ID Success Response

    [{
        "id": "239c16f4-866d-43e8-9341-7badafbc019f",
        "reference_id": "demo_1475801962607",
        "email": "customer@website.com",
        "mobile_number": null,
        "given_names": "John",
        "description": null,
        "middle_name": null,
        "surname": null,
        "phone_number": null,
        "nationality": null,
        "addresses": null,
        "date_of_birth": null,
        "metadata": null
    }]
    Parameter Description
    id string Unique ID generated by Xendit for the particular customer
    reference_id string Identifer you provided during request
    mobile_number string Mobile number of the customer
    email string Email address of the customer
    given_names string Primary of first name/s of the customer
    middle_name string Middle name of the customer
    surname string Surname of the customer
    description string Description you provided for the customer object
    phone_number string Alternate or landline phone number
    nationality string Country code for the customer's nationality
    addresses object array Array of objects containing the specific customer's address information
    date_of_birth string Date of birth of the customer in YYYY-MM-DD format
    metadata object A free-format JSON for additional information that you provded during request.

    Get Customer by Reference ID - Errors

    See other common errors here.

    Get Payment Methods by Customer ID

    This endpoint returns an array of payment methods that are linked to the provided customer_id

    Endpoint: Get Payment Methods by Customer ID

    GET https://api.xendit.co/payment_methods?customer_id={customer_id}

    Get Payment Methods by Customer ID - Request

    Example Get Payment Methods by Customer ID Request

    curl https://api.xendit.co/payment_methods?customer_id=ba830b92-4177-476e-b097-2ad5ae4d3e55 -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: 
    <?php
      $url = "https://api.xendit.co/payment_methods";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
    
      $queryString = "?customer_id=ba830b92-4177-476e-b097-2ad5ae4d3e55";
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url.$queryString);
      curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let url = "https://api.xendit.co/payment_methods";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    let queryString = "?customer_id=ba830b92-4177-476e-b097-2ad5ae4d3e55";
    
    var requestOptions = {
      method: 'GET',
      headers: headers,
      redirect: 'follow'
    };
    
    fetch(url + queryString, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Query String Parameter Description
    customer_id
    required
    string Customer object ID of interest

    Get Payment Methods by Customer ID - Response

    This endpoint returns an array of matching objects with the following properties:

    Example Get Payment Methods by Customer ID Success Response

    [{    
        "id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "type": "DEBIT_CARD",
        "properties": {
            "id": "la-aa620619-124f-41db-995b-66a52abe036a",
            "channel_code": "DC_BRI",
            "currency": "IDR",
            "card_last_four": "1234",
            "card_expiry": "06/24",
            "description": null,
        },
        "customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
        "status": "ACTIVE",
        "created": "2020-03-19T05:34:55+0800",
        "updated": "2020-03-19T05:24:55+0800",
        "metadata": null  
    }]
    Parameter Description
    id string Unique identifier for the payment method. This has a prefix of pm-.
    type string Type of account that has been linked.
    Expected values: DEBIT_CARD or BANK_ACCOUNT
    properties object Object containing information regarding the account. The values inside properties change based on the type of account:


    For type DEBIT_CARD (BRI):
    Key Value
    card_last_four stringLast four digits of the debit card
    card_expiry stringExpiry month and year of the debit card (in MM/YY format)
    currency stringCurrency of the account in ISO 4217
    description stringDescription of the account (provided by the bank)
    For type BANK_ACCOUNT (BPI):
    Key Value
    account_details stringMasked account details as provided by the bank. Used for displaying a portion of the account number.
    account_hash stringUnique hash for the specific account. This does not change across different authorizations or integrations.
    account_type stringType of bank account (provided by the bank)
    currency stringCurrency of the account in ISO 4217
    description stringDescription of the account (provided by the bank)
    customer_id string ID of the customer object in which this payment method is linked to
    status string Status of the payment method.
    Will be equal to ACTIVE upon creation.
    created string Timestamp in ISO 8601 when the request was made
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    updated string Timestamp in ISO 8601 when transaction information was updated
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    metadata object A free-format JSON for additional information that you provded during request.

    Get Payment Methods by Customer ID - Errors

    See other common errors here.

    Get Direct Debit Payment Status by ID

    Retrieve the details of a direct debit payment by Xendit transaction ID

    Endpoint: Get Payment Staus by ID

    POST https://api.xendit.co/direct_debits/:direct_debit_id/

    Get Payment Status by ID - Request

    Example Payment Status by ID Request

    curl https://api.xendit.co/direct_debits/ddpy-623dca10-5dad-4916-test/ -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: 
    <?php
      $direct_debit_id = "ddpy-623dca10-5dad-4916-test";
      $url = "https://api.xendit.co/direct_debits/" . $direct_debit_id . "/";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let direct_debit_id = "ddpy-623dca10-5dad-4916-test";
    let url = "https://api.xendit.co/direct_debits/" . $direct_debit_id . "/";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    var requestOptions = {
      method: 'GET',
      headers: headers,
      body: reqBody,
      redirect: 'follow'
    };
    
    fetch(url, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Path Parameter Description
    direct_debit_id
    required
    string Xendit identifier for specified direct debit transaction

    Get Payment Status by ID - Response

    Example Get Payment Status by ID Success Response

    {
        "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
        "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
        "channel_code": "DC_BRI",
        "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "currency": "IDR",
        "amount": "10000",
        "description": "",
        "status": "PENDING",
        "basket": [],
        "failure_code": "",
        "is_otp_required": true,
        "otp_mobile_number": "",
        "otp_expiration_timestamp": "",
        "created": "2020-03-26T05:44:26+0800",
        "updated": "",
        "metadata": {}
    }
    Parameter Description
    id string Unique identifier for the transaction
    reference_id string Reference ID provided by merchant
    channel_code string Code identifier for the channel
    payment_method_id string Payment method ID of end-customer source of funds
    currency string Currency of the payment
    amount number Amount to debit from the end-customer’s account
    description string Description provided by merchant
    status string Status of the payment
    failure_code string Reason if direct debit has failed
    is_otp_required boolean The flag for merchant to know whether OTP was enabled for the particular direct debit transaction
    otp_mobile_number string Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled.
    otp_expiration_timestamp string Timestamp until when the OTP is valid. Empty string if OTP was not enabled.
    created string Timestamp in ISO 8601 when the request was made
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    updated string Timestamp in ISO 8601 when transaction information was updated
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    basket array Array of basket objects provided by merchant
    metadata object Metadata provided by merchant

    Get Direct Debit Payment Status by Reference ID

    Retrieve the details of a direct debit payment by merchant provided transaction ID

    Endpoint: Get Payment Staus by Reference ID

    POST https://api.xendit.co/direct_debits?reference_id={reference_id}

    Get Payment Status by Reference ID - Request

    Example Payment Status by Reference ID Request

    curl https://api.xendit.co/direct_debits?reference_id=test_merchant_reference_id/ -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: 
    <?php
      $url = "https://api.xendit.co/direct_debits/";
      $apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
      $headers = [];
      $headers[] = "Content-Type: application/json";
    
      $queryString = "?reference_id=test_merchant_reference_id";
    
      $curl = curl_init();
    
      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url.$queryString);
      curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
      $result = curl_exec($curl);
      echo $result;
    let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
    let url = "https://api.xendit.co/direct_debits/";
    
    var headers = new Headers();
    headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
    headers.append("Content-Type", "application/json");
    
    let queryString = "?reference_id=test_merchant_reference_id";
    
    var requestOptions = {
      method: 'GET',
      headers: headers,
      redirect: 'follow'
    };
    
    fetch(url + queryString, requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
    Query String Parameter Description
    reference_id
    required
    string Merchant provided identifier for specified direct debit transaction

    Get Payment Status by ID - Response

    Example Get Payment Status by ID Success Response

    {
        "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
        "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
        "channel_code": "DC_BRI",
        "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "currency": "IDR",
        "amount": "10000",
        "description": "",
        "status": "PENDING",
        "basket": [],
        "failure_code": "",
        "is_otp_required": true,
        "otp_mobile_number": "",
        "otp_expiration_timestamp": "",
        "created": "2020-03-26T05:44:26+0800",
        "updated": "",
        "metadata": {}
    }
    Parameter Description
    id string Unique identifier for the transaction
    reference_id string Reference ID provided by merchant
    channel_code string Code identifier for the channel
    payment_method_id string Payment method ID of end-customer source of funds
    currency string Currency of the payment
    amount number Amount to debit from the end-customer’s account
    description string Description provided by merchant
    status string Status of the payment
    failure_code string Reason if direct debit has failed
    is_otp_required boolean The flag for merchant to know whether OTP was enabled for the particular direct debit transaction
    otp_mobile_number string Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled.
    otp_expiration_timestamp string Timestamp until when the OTP is valid. Empty string if OTP was not enabled.
    created string Timestamp in ISO 8601 when the request was made
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    updated string Timestamp in ISO 8601 when transaction information was updated
    Format: YYYY-MM-DDTHH:mm:ssZ
    Timezone: UTC+0
    basket array Array of basket objects provided by merchant
    metadata object Metadata provided by merchant

    Callback Notifications

    In our direct debit flow, there are up to 2 types of callbacks that could be sent. We will send callback to your system during Linked Account Tokenization and Direct Debit Payment process. Merchants need to set up URL to receive callback notifications from our system.

    Linked Account Tokenization Callback

    Payload

    Linked Account Tokenization callback is only required when integrating with online bank access flow. Merchants can skip this flow if they are only integrating for debit card flow.

    Example: Linked Account Tokenization Callback Payload

    {
        "event": "linked_account_token.successful",
        "timestamp": "2020-03-27T05:45:06+0800",
        "channel_code": "BA_BPI",
        "id": "lat-aa620619-124f-41db-995b-66a52abe036a",
        "accounts": [
            {
                "id": "l-acc-7f2bc3ad-8049-42ff-8b57-6578088e9641",
                "account_details": "XXXXXXX123",
                "account_hash": "5789fb5c4b051701928af5ac268c8178",
                "currency": "PHP",
                "account_type": "SAVINGS",
                "description": null
            }
        ]
    }
    Parameter Description
    event string Identifier of the event - "linked_account_token.successful"
    timestamp string ISO 8601 timestamp of the event. Timezone is UTC+0
    id string Unique identifier for the Linked Account Tokenization. This has a prefix of lat-.
    channel_code string Code identifier for the channel
    accounts array An array of objects containing bank account informations linked to the authorization.
    Key Value
    id string Unique identifier for bank account specific to this object. This has a prefix of la-.
    account_details string Masked account details as provided by the bank. Used for displaying a portion of the account number.
    account_hash string Unique hash for the specific account. This does not change across different authorizations or integrations, providing a consistent reference to end user bank account through rounds of renewal.
    currency string Currency of the account in ISO 4217
    account_type string Type of bank account (provided by the bank)
    description string Description of the account (provided by the bank)

    Direct Debit Payment Callback

    Payload

    Example: Payload

    {
        "event": "direct_debit.payment",
        "timestamp": "2020-03-26T05:44:26+0800",
        "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
        "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
        "channel_code": "BA_BPI",
        "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "currency": "PHP",
        "amount": "1000.00",
        "description": null,
        "status": "COMPLETED",
        "failure_code": null,
        "metadata": null
    }
    Parameter Description
    event string Identifier of the event - "direct_debit.payment"
    timestamp string ISO 8601 timestamp of the event. Timezone is UTC+0
    id string Unique identifier for the transaction
    reference_id string Reference ID provided by merchant
    channel_code string Code identifier for the channel
    payment_method_id string Payment method ID of end-customer source of funds
    currency string Currency of the payment
    amount number Amount to debited from the end-customer’s account
    description string Description provided by merchant
    status string Status of the payment - "PENDING", "COMPLETED", "FAILED"
    failure_code string Reason if direct debit has failed. List of failure codes can be found here
    metadata object Metadata provided by merchant

    Payment Status Callback - Failure Reasons

    Example: Payment Status Failure Examples

    {
        "event": "direct_debit.payment",
        "timestamp": "2020-03-26T05:44:26+0800",
        "id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
        "reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
        "channel_code": "BA_BPI",
        "payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
        "currency": "PHP",
        "amount": "1000.00",
        "description": "",
        "status": "FAILED",
        "failure_code": "INSUFFICIENT_BALANCE",
        "metadata": {}
    }
    Failure Code Description
    MAX_AMOUNT_LIMIT_ERROR End customer's daily limit has been reached, unable to process debit request. End user required to increase daily limit or retry another day
    INSUFFICIENT_BALANCE End customer has insufficient balance, unable to process debit request. End user required to top up balance
    CHANNEL_UNAVAILABLE Bank service for direct debit is currently unavailable, unable to process debit request.
    ACCOUNT_ACCESS_BLOCKED End customer bank account has been blocked, end user should contact the bank for resolution.

    Recurring Payment Callback

    Payload

    {
      "id": "5ebd6test32631dda4ef73",
      "external_id": "testing_123_123-1589472179990",
      "user_id": "5ebd26b7da0bf912db2fc716",
      "is_high": false,
      "payment_method": "DIRECT_DEBIT",
      "status": "PAID",
      "merchant_name": "Live Validation Test 2",
      "amount": 15000,
      "paid_amount": 15000,
      "paid_at": "2020-05-14T16:03:00.504Z",
      "payer_email": "test@xendit.co",
      "description": "description",
      "adjusted_received_amount": 15000,
      "fees_paid_amount": 0,
      "created": "2020-05-14T16:03:00.154Z",
      "updated": "2020-05-14T16:03:02.765Z",
      "recurring_payment_id": "5ebd6bb37d674631dda4ef72",
      "currency": "IDR",
      "payment_channel": "DC_BRI"
    }
    Parameter Type Description
    id string An invoice ID generated by Xendit
    user_id string Your Xendit Business ID
    external_id string The reference ID used to generate the recurring payment. This can be used to reconcile between you and Xendit
    is_high (DEPRECATED) boolean Should unique numbers go above or below the amount.
    merchant_name string The name of your company or website
    amount number Nominal amount for the invoice (without taxes, fees)
    status string PAID the recurring direct debit has successfully been paid or
    EXPIRED the recurring direct debit has failed
    payer_email string Email of the payer, we get this information from your API call
    description string Description for the invoice, we get this information from your API call
    fees_paid_amount number Xendit fees that was directly paid from this invoice - thanks for supporting a better world of payments :)
    adjusted_received_amount number Amount attributable to you net of our fees.
    recurring_payment_id string ID of the recurring that created this invoice
    paid_amount number Total amount paid for the invoice
    updated string (ISO 8601) An ISO timestamp that tracks when the invoice was updated. Timezone is UTC+0
    created string (ISO 8601) An ISO timestamp that tracks when the invoice was created. Timezone is UTC+0
    currency string (ISO 4217) Currency of the amount that you created.
    paid_at string (ISO 8601) Date time data when your customer pay the invoice. You will get this response when your invoice is paid
    payment_method string Payment method that is used when a customer pays the invoice. You will get this response when your invoice is paid - DIRECT_DEBIT
    payment_channel string The payment channel used when a customer pays the invoice. You will get this response when your invoice is paid
    Example : DC_BRI

    Virtual Accounts

    Virtual Accounts are virtual bank accounts that can be created and assigned to your customers and act as medium to receive payments where your customers will pay via Bank Transfer.

    Create Virtual Account

    Endpoint: Create Virtual Account

    POST https://api.xendit.co/callback_virtual_accounts

    For live environments, activate the Virtual Account Range from the dashboard by going to Dashboard > Settings > Configuration > Virtual Accounts, and clicking the "Activate!" button. The VA range will be set and activated instantly. In test environments, the test VA range is assigned right away. Read more about virtual accounts.

    Looking for your virtual accounts to be tied to a transaction rather than a user? Use our invoices API.

    Request Parameters

    Example Create Virtual Accounts Request

    curl https://api.xendit.co/callback_virtual_accounts -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d external_id=demo_virtual_account_1475459775872 \
       -d bank_code=BNI \
       -d name='Rika Sutanto'
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $params = [ 
        "external_id" => "demo-1475804036622",
        "bank_code" => "BNI",
        "name" => "Rika Sutanto"
      ];
    
      $createVA = \Xendit\VirtualAccounts::create($params);
      var_dump($createVA);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { VirtualAcc } = x;
    const vaSpecificOptions = {};
    const va = new VirtualAcc(vaSpecificOptions);
    
    const resp = await va.createFixedVA({
      externalID: 'demo_1475459775872',
      bankCode: 'BNI',
      name: 'Rika Sutanto',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Map<String, Object> params = new HashMap<>();
      params.put("external_id", "demo_virtual_account_1475459775872");
      params.put("bank_code", BankCode.BNI.getText());
      params.put("expected_amount", 100000);
      params.put("name", "Rika Sutanto");
    
      //For closed virtual account
      FixedVirtualAccount closedVirtualAccount = FixedVirtualAccount.createClosed(params);
    
      //For open virtual account
      FixedVirtualAccount openVirtualAccount = FixedVirtualAccount.createOpen(params);
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    data := virtualaccount.CreateFixedVAParams{
      ExternalID: "demo-1475804036622",
      BankCode:   "BNI",
      Name:       "Rika Sutanto",
    }
    
    resp, err := virtualaccount.CreateFixedVA(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created fixed va: %+v\n", resp)

    JSON

    {
       "external_id": "demo-1475804036622",
       "bank_code": "BNI",
       "name": "Rika Sutanto"
    }
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    external_id
    required
    string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 1000 characters. Note: External IDs cannot be changed once set

    Characters Special and alphanumeric
    Minimum length 1 character
    bank_code
    required
    string Bank code of the virtual account you want to create.
    Note: We highly recommend you redirect customers to pay into BNI Virtual Account for interbank transfers

    Available bank codes: MANDIRI, BNI, BRI, PERMATA, BCA, SAHABAT_SAMPOERNA
    name
    required
    string Name of user/virtual account, - this will be displayed in the bank's user interface, e.g. ATM confirmation screens. Note that this field can only contain letters and spaces and has no length restriction (though the banks will truncate as per their limitations)

    Characters Only alphabet
    Minimum length 1 character
    virtual_account_number
    optional
    string The virtual account number you want to assign. If you do not send one, one will be picked at random
    Note: Please do not include the merchant code (4 or 5 digit merchant prefix to the full virtual account number)

    default: random string
    suggested_amount
    optional
    integer positive The suggested amount you want to assign.
    Note: Suggested amounts is the amounts that can see as a suggestion, but user can still put any numbers (only supported for Mandiri and BRI)

    default: none
    is_closed
    optional
    boolean When set to true, the virtual account will be closed and will only accept the amount specified in expected_amount

    default: false
    expected_amount
    optional
    integer positive The specific amount that the virtual account will expect and accept if is_closed is set to true

    default: none
    expiration_date
    optional
    ISO 8601 Date The time when the virtual account will be expired

    timezone: UTC
    default: The expired date will be 31 years from VA generated
    is_single_use
    optional
    boolean When set to true, the virtual account will be inactive after it is paid

    default: false
    description
    optional
    string The virtual account description. This field is only supported for BRI

    Characters Special and alphanumeric
    Minimum length 1 character
    default: none

    Response Parameters

    Example Create Virtual Account Response

    {
      "owner_id":"57b4e5181473eeb61c11f9b9",
      "external_id":"demo-1475804036622",
      "bank_code":"BNI",
      "merchant_code":"8808",
      "name":"Rika Sutanto",
      "account_number":"8808999939380502",
      "is_closed": false,
      "id":"57f6fbf26b9f064272622aa6",
      "is_single_use": true,
      "status": "ACTIVE"
    }

    Example response with description if bank code is BRI

    {
      "owner_id": "5de8d83cafcf47000f8e76bc",
      "external_id": "1576132512",
      "bank_code": "BRI",
      "merchant_code": "26215",
      "name": "rezki",
      "account_number": "262159999857807",
      "expected_amount": 700000,
      "is_single_use": false,
      "description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
      "currency": "IDR",
      "status": "ACTIVE",
      "expiration_date": "2050-12-11T17:00:00.000Z",
      "is_closed": false,
      "id": "5df1dfa06c3736110078f9a1"
    }
    Parameter Type Description
    owner_id
    required
    string Your user ID
    external_id
    required
    string An ID of your choice which you provided upon request
    bank_code
    required
    string Bank code for the relevant bank, e.g. BNI
    merchant_code
    required
    string Prefix for the Virtual Account Number. Often this is Xendit Merchant ID or your Merchant ID on bank, e.g 01234 your_number
    name
    required
    string Name for the virtual account
    account_number
    required
    string Complete virtual account number (including merchant code as prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking.
    is_closed
    required
    boolean Value that determines whether a virtual account is closed or not
    id
    required
    string Unique ID for the virtual account that generated randomly by system. Can be used to create invoices linked to the VA.
    is_single_use
    required
    boolean When it is true, the virtual account will be inactive after it is paid
    status
    required
    string Status of virtual account that defines if it’s PENDING, INACTIVE, or ACTIVE.
  • Status is PENDING if virtual account creation request has been sent and request is being processed by the bank.
  • Status is INACTIVE either the single use virtual account has been paid or already expired.
  • If status is ACTIVE the virtual account is ready to be used by the end user.
  • suggested_amount
    optional
    string suggested amount for the virtual account
    expected_amount
    optional
    string the amount that is expected when is_closed is true
    description
    optional
    string description of the virtual account which will be displayed during payment. Only supported for BRI virtual accounts.

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    VIRTUAL_ACCOUNT_NUMBER_OUTSIDE_RANGE
    400
    The virtual account number you want is outside your range. You can check your VA range in Virtual Accounts Settings
    BANK_NOT_SUPPORTED_ERROR
    400
    The bank code is not currently supported. You can check the available bank with get virtual account banks endpoint.
    EXPIRATION_DATE_NOT_SUPPORTED_ERROR
    400
    Custom expiration date (the time when the virtual account will be expired) for the virtual account is not currently supported.
    EXPIRATION_DATE_INVALID_ERROR
    400
    Invalid custom expiration date because it's earlier than current time.
    SUGGESTED_AMOUNT_NOT_SUPPORTED_ERROR
    400
    The suggested amount for the virtual account is not currently supported.
    EXPECTED_AMOUNT_REQUIRED_ERROR
    400
    The expected_amount is required when is_closed is set to true.
    CLOSED_VA_NOT_SUPPORTED_ERROR
    400
    The closed option for this virtual account is not currently supported.
    DUPLICATE_CALLBACK_VIRTUAL_ACCOUNT_ERROR
    400
    The account number already exist
    MINIMUM_EXPECTED_AMOUNT_ERROR
    400
    The minimum expected amount is Rp.1 for BNI, BRI and MANDIRI
    MAXIMUM_EXPECTED_AMOUNT_ERROR
    400
    The maximum expected amount is Rp.50,000,000,000 for BNI, BRI and MANDIRI
    CALLBACK_VIRTUAL_ACCOUNT_NAME_NOT_ALLOWED_ERROR
    400
    The name cannot contain bank or institution name
    DESCRIPTION_NOT_SUPPORTED_ERROR
    400
    Description field is only supported for BRI
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Get Virtual Account Banks

    Endpoint: Get Virtual Account Available Banks

    GET https://api.xendit.co/available_virtual_account_banks

    Example Get Virtual Account Banks Request

    curl https://api.xendit.co/available_virtual_account_banks -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $getVABanks = \Xendit\VirtualAccounts::getVABanks();
      var_dump($getVABanks);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { VirtualAcc } = x;
    const vaSpecificOptions = {};
    const va = new VirtualAcc(vaSpecificOptions);
    
    const resp = await va.getVABanks();
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      AvailableBank[] availableBanks = FixedVirtualAccount.getAvailableBanks();
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    availableBanks, err := virtualaccount.GetAvailableBanks()
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("available va banks: %+v\n", availableBanks)

    Response Parameters

    Example Get Virtual Account Banks Response

    {
      "name": "Bank Negara Indonesia",
      "code": "BNI"
    }
    Parameter Type Description
    name
    required
    string Full name of the bank

    code
    required
    string Code of the bank, relevant during creation of virtual accounts

    Get Virtual Account

    Endpoint: Get Virtual Account

    GET https://api.xendit.co/callback_virtual_accounts/:id

    Example Get Virtual Account Request

    curl https://api.xendit.co/callback_virtual_accounts/:id -X GET \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:

    Sometime, you need to know the detail for your virtual account. This endpoint can be used to get the latest details from your virtual account

    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '59e03a976fab8b1850fdf347';
      $getVA = \Xendit\VirtualAccounts::retrieve($id);
      var_dump($getVA);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { VirtualAcc } = x;
    const vaSpecificOptions = {};
    const va = new VirtualAcc(vaSpecificOptions);
    
    const resp = await va.getFixedVA({ id: '59e03a976fab8b1850fdf347' });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      FixedVirtualAccount fpa = FixedVirtualAccount.getFixedVA("EXAMPLE_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    data := virtualaccount.GetFixedVAParams{
      ID: "59e03a976fab8b1850fdf347",
    }
    
    resp, err := virtualaccount.GetFixedVA(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("retrieved fixed va: %+v\n", resp)

    Sometime, you need to know the detail for your fixed virtual account. This endpoint can be used to get the latest details from your fixed virtual account

    Request Parameters

    Parameter Type Description
    id
    required
    string ID of the virtual account to retrieve

    Response Parameters

    Example Get Virtual Account Response

    {
        "owner_id": "58cd618ba0464eb64acdb246",
        "external_id": "va-1507867286",
        "bank_code": "BRI",
        "merchant_code": "26215",
        "name": "Steve Wozniak",
        "account_number": "262151000393993",
        "is_single_use": false,
        "status": "ACTIVE",
        "expiration_date": "2048-10-12T17:00:00.000Z",
        "is_closed": false,
        "id": "59e03a976fab8b1850fdf347"
    }
    Parameter Type Description
    owner_id
    required
    string ID of the business that own the virtual account
    external_id
    required
    string An ID of your choice which you provided upon virtual account creation
    bank_code
    required
    string Bank code of the virtual account number
    merchant_code
    required
    string 4 or 5-digit merchant prefix to the full virtual account number
    name
    required
    string Name of the virtual account
    account_number
    required
    string Account number of the virtual account
    expiration_date
    required
    string Expiration date of the virtual account
    is_closed
    required
    boolean Flag that define the virtual account is close or open
    id
    required
    string ID of the virtual account
    is_single_use
    required
    boolean Flag that define the virtual account is single use or multiple use
    status
    required
    string Status of virtual account that defines if it’s PENDING, INACTIVE, or ACTIVE.
  • Status is PENDING if virtual account creation request has been sent and request is being processed by the bank.
  • Status is INACTIVE either the single use virtual account has been paid or already expired.
  • If status is ACTIVE the virtual account is ready to be used by the end user.
  • Error Codes

    Error Code Description
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    CALLBACK_VIRTUAL_ACCOUNT_NOT_FOUND_ERROR
    404
    Could not find callback virtual account.

    Update Virtual Account

    Endpoint: Update Virtual Account (VA)

    PATCH https://api.xendit.co/callback_virtual_accounts/:id

    Virtual Account is adaptable, and can be customized to fit your needs. Therefore, we provide you this endpoint to easily update your virtual account as you like. You can update multiple use VAs as well as active single use VAs, though inactive single use VAs cannot be updated.

    Example Update Fixed Virtual Accounts Request

    curl https://api.xendit.co/callback_virtual_accounts/57f6fbf26b9f064272622aa6 -X PATCH \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d expected_amount=100000
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = 'VA-id';
      $updateParams = ["suggested_amount" => 6000];
    
      $updateVA = \Xendit\VirtualAccounts::update($id, $updateParams);
      var_dump($updateVA);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { VirtualAcc } = x;
    const vaSpecificOptions = {};
    const va = new VirtualAcc(vaSpecificOptions);
    
    const resp = await va.updateFixedVA({
      id: '57f6fbf26b9f064272622aa6',
      expectedAmt: 1000000,
    })
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Map<String, Object> params = new HashMap<>();
      params.put("is_single_use", true);
    
      FixedVirtualAccount fixedVirtualAccount = FixedVirtualAccount.update("EXAMPLE_ID", params);
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    expirationDate := time.Now().AddDate(0, 0, 1)
    
    updateFixedVAData := virtualaccount.UpdateFixedVAParams{
      ID:             "5df745b92b50911700f37e86",
      ExpirationDate: &expirationDate,
      ExpectedAmount: 6000,
    }
    
    resp, err := virtualaccount.UpdateFixedVA(&updateFixedVAData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("updated fixed va: %+v\n", resp)

    Fixed Virtual Account is adaptable, and can be customized to fit your needs. Therefore, we provide you this endpoint to easily update your fixed virtual account as you like. You can update multiple use VAs as well as active single use VAs, though inactive single use VAs cannot be updated.

    Note: Closed virtual accounts can not be changed to open virtual accounts, and vice versa.

    Request Parameters

    Example Update Virtual Accounts Request

    {
        "expiration_date": "2019-11-12T23:46:00.000Z",
        "expected_amount": 6000
    }
    Body Parameter Type Description
    suggested_amount
    optional
    integer positive suggested amount you want to assign

    expected_amount
    optional
    integer positive The amount that the virtual account will expect if is_closed is set to true
    expiration_date
    optional
    ISO 8601 Date The time when the virtual account will be expired. You can set it to be days in the past to expire virtual account immediately

    timezone: UTC
    default: The expired date will be 31 years from VA generated
    is_single_use
    optional
    boolean When set to true, the virtual account status will be inactive after it is paid

    default: false
    description
    optional
    string Virtual account description shown to end user during payment

    Characters Special and alphanumeric
    Minimum length 1 character
    default: none

    Response Parameters

    Example Update Virtual Account Response

    {
        "owner_id": "5de8d83cafcf47000f8e76bc",
        "external_id": "demo_virtual_account_1475459775872",
        "bank_code": "BNI",
        "merchant_code": "8808",
        "name": "Rika Sutanto",
        "account_number": "8808999947012640",
        "is_single_use": false,
        "expected_amount": 6000,
        "currency": "IDR",
        "status": "PENDING",
        "expiration_date": "2019-11-12T23:46:00.000Z",
        "is_closed": false,
        "id": "5df745b92b50911700f37e86"
    }
    Parameter Type Description
    owner_id
    required
    string Your user ID
    external_id
    required
    string An ID of your choice which you provided upon request
    bank_code
    required
    string Bank code for the relevant bank, e.g. BNI
    merchant_code
    required
    string The merchant code will be the prefix for the virtual account number, e.g 01234 your_number
    name
    required
    string Name for the virtual account
    account_number
    required
    string Complete virtual account number (including merchant code as prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking.
    is_closed
    required
    boolean Value that determines whether a virtual account is closed or not
    id
    required
    string Unique ID for the virtual account that generated randomly by system. Can be used to create invoices linked to the VA.
    is_single_use
    required
    boolean When it is true, the virtual account will be inactive after it is paid
    status
    required
    string Status of virtual account that defines if it’s PENDING, INACTIVE, or ACTIVE.
  • Status is PENDING if virtual account creation request has been sent and request is being processed by the bank.
  • Status is INACTIVE either the single use virtual account has been paid or already expired.
  • If status is ACTIVE the virtual account is ready to be used by the end user.
  • suggested_amount
    optional
    string suggested amount for the virtual account
    expected_amount
    optional
    string the amount that is expected when is_closed is true
    description
    optional
    string description of the virtual account which will be displayed during payment. Only supported for BRI virtual accounts.

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    VIRTUAL_ACCOUNT_NUMBER_OUTSIDE_RANGE
    400
    The virtual account number you want is outside your range. You can check your VA range in Virtual Accounts Settings
    BANK_NOT_SUPPORTED_ERROR
    400
    The bank code is not currently supported. You can check the available bank with get virtual account banks endpoint.
    SUGGESTED_AMOUNT_NOT_SUPPORTED_ERROR
    400
    The suggested amount for the virtual account is not currently supported.
    EXPECTED_AMOUNT_REQUIRED_ERROR
    400
    The expected amount is required when is_closed is set to true.
    CLOSED_VA_NOT_SUPPORTED_ERROR
    400
    The closed option for this virtual account is not currently supported.
    INACTIVE_VIRTUAL_ACCOUNT_ERROR
    400
    Account number that you want to update is inactive.
    MINIMUM_EXPECTED_AMOUNT_ERROR
    400
    The expected amount can only be more than zero
    MAXIMUM_EXPECTED_AMOUNT_ERROR
    400
    The expected amount can only be less than Rp.1000000000
    DESCRIPTION_NOT_SUPPORTED_ERROR
    400
    Description field is only supported for BRI
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Virtual Account Callback

    Endpoint: Virtual Account Callback

    POST https://yourcompany.com/virtual_account_paid_callback_url

    When someone pays into your fixed virtual account, our callback APIs will hit your URL that you already set in dashboard. Our callback API will also hit your URL upon fixed virtual account creations and updates. Please see Create Fixed Virtual Accounts for more details. For further information about callbacks please read these docs.

    This example is only used to show the body parameters that send from Xendit APIs to your callback URL and cannot be tested in here. If you want to test this callback request, use the test feature in dashboard or go to Callback settings.

    Payment Callback Payload

    Header Parameter Type Description
    x-callback-token
    required
    string Your Xendit unique callback token to verify the origin of the callback

    Example Virtual Account Payment Callback Request

    curl --include \
         --request POST \
         --header "Content-Type: application/json" \
         --header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
         --data-binary "{
        id: \"57fb4e076fa3fa296b7f5a97\",
        payment_id: \"demo-1476087608948_1476087303080\",
        callback_virtual_account_id: \"57fb4df9af86ce19778ad359\",
        owner_id: \"57b4e5181473eeb61c11f9b9\",
        external_id: \"demo-1476087608948\",
        account_number: \"8808999939380502\",
        bank_code: \"BNI\",
        amount: 99000,
        transaction_timestamp: \"2016-10-10T08:15:03.080Z\",
        merchant_code: \"8808\",
        sender_name: \"JOHN DOE\",
        updated: \"2016-10-10T08:15:03.404Z\",
        created: \"2016-10-10T08:15:03.404Z\"
    }" \
    'https://api.xendit.co/virtual_account_paid_callback_url'

    JSON

    {
        "id": "57fb4e076fa3fa296b7f5a97",
        "payment_id": "demo-1476087608948_1476087303080",
        "callback_virtual_account_id": "57fb4df9af86ce19778ad359",
        "owner_id": "57b4e5181473eeb61c11f9b9",
        "external_id": "demo-1476087608948",
        "account_number": "8808999939380502",
        "bank_code": "BNI",
        "amount": 99000,
        "transaction_timestamp": "2016-10-10T08:15:03.080Z",
        "merchant_code": "8808",
        "sender_name": "JOHN DOE",
        "updated": "2016-10-10T08:15:03.404Z",
        "created": "2016-10-10T08:15:03.404Z"
    }
    Body Parameter Type Description
    payment_id
    required
    string Our internal system’s payment ID
    callback_virtual_account_id
    required
    string The id field value from the response when the virtual account was created. See Create Virtual Accounts
    owner_id
    required
    string Your user ID
    external_id
    required
    string An ID of your choice which you provided upon virtual account creation
    account_number
    required
    string This is the virtual account number (including merchant code as prefix). This works just like a bank account and is what a user will need to enter in their internet banking/ATM to send funds.
    bank_code
    required
    string Bank code for the relevant bank, e.g. BNI
    amount
    required
    string Nominal amount to transfer
    merchant_code
    required
    string The merchant code will be the prefix for the virtual account number, e.g 01234 your_number
    id
    required
    string ID of virtual account payment
    transaction_timestamp
    required
    string Date time that the virtual account was paid
    sender_name
    string Name of the end user that paid into the virtual account. This field is only supported for Sahabat Sampoerna virtual accounts.

    Creation / Update Callback Payload

    Example Virtual Account Creation / Update Callback Request

    curl --include \
         --request POST \
         --header "Content-Type: application/json" \
         --header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
         --data-binary "{
        id: \"57fb4e076fa3fa296b7f5a97\",
        owner_id: \"5824128aa6f9f9b648be9d76\",
        external_id: \"va-1487156410\",
        merchant_code: \"88608\",
        account_number: \"886081000123456\",
        bank_code: \"MANDIRI\",
        name: \"John Doe\",
        is_closed: false,
        is_single_use: false,
        status: \"ACTIVE\",
        expiration_date: \"2048-02-15T11:01:52.722Z\",
        updated: \"2016-10-10T08:15:03.404Z\",
        created: \"2016-10-10T08:15:03.404Z\"
    }" \
    'https://api.xendit.co/virtual_account_created_callback_url'

    JSON

    {
        "id": "57fb4e076fa3fa296b7f5a97",
        "owner_id": "5824128aa6f9f9b648be9d76",
        "external_id": "va-1487156410",
        "merchant_code": "88608",
        "account_number": "886081000123456",
        "bank_code": "MANDIRI",
        "name": "John Doe",
        "is_closed": false,
        "is_single_use": false,
        "status": "ACTIVE",
        "expiration_date": "2048-02-15T11:01:52.722Z",
        "updated": "2016-10-10T08:15:03.404Z",
        "created": "2016-10-10T08:15:03.404Z"
    }
    Body Parameter Type Description
    owner_id
    required
    string Your user ID
    external_id
    required
    string An ID of your choice which you provided upon request
    bank_code
    required
    string Bank code for the relevant bank, e.g. MANDIRI
    merchant_code
    required
    string The merchant code will be the prefix for the virtual account number, e.g 01234 your_number
    name
    required
    string Name for the virtual account
    account_number
    required
    string Complete virtual account number (including merchant code as prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking.
    suggested_amount
    optional
    string suggested amount for created virtual account
    is_closed
    required
    boolean value that determines whether a virtual account is closed or not
    expected_amount
    optional
    string the amount that is expected when is_closed is true
    id
    required
    string Unique ID for the virtual account. Can be used to create invoices linked to the VA.
    is_single_use
    required
    boolean value that determines whether a virtual account will be inactive after it is paid
    status
    required
    string Status of virtual account that defines if it’s PENDING, INACTIVE, or ACTIVE.
  • Status is PENDING if virtual account creation request has been sent and request is being processed by the bank.
  • Status is INACTIVE either the single use virtual account has been paid or already expired.
  • If status is ACTIVE the virtual account is ready to be used by the end user.
  • Error Codes

    Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.

    Get Virtual Account Payment

    Endpoint: Get Virtual Account Payment

    GET https://api.xendit.co/callback_virtual_account_payments/payment_id={payment_id}

    Example Get Virtual Account Payment Request

    curl https://api.xendit.co/callback_virtual_account_payments/payment_id={payment_id} -X GET \
        -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $paymentID = '1502450097080';
      $getFVAPayment = \Xendit\VirtualAccounts::getFVAPayment($paymentID);
      var_dump($getFVAPayment);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { VirtualAcc } = x;
    const vaSpecificOptions = {};
    const va = new VirtualAcc(vaSpecificOptions);
    
    const resp = await va.getVAPayment({
      paymentID: '598d91b1191029596846047f',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      FixedVirtualAccountPayment payment = FixedVirtualAccount.getPayment("EXAMPLE_PAYMENT_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    payment, err := virtualaccount.GetPayment(&virtualaccount.GetPaymentParams{
      PaymentID: "1502450097080",
    })
    
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("retrieved va payment: %+v\n", payment)

    When you receive our callback in your URL, you can verify that the callback you receive is coming from us.

    Request Parameters

    Query Parameter Type Description
    payment_id
    required
    string ID of the payment to retrieve

    Response Parameters

    Example Get Virtual Account Payment Response

    {
        "id": "598d91b1191029596846047f",
        "payment_id": "1502450097080",
        "callback_virtual_account_id": "598d5f71bf64853820c49a18",
        "external_id": "demo-1502437214715",
        "merchant_code": "77517",
        "account_number": "1000016980",
        "bank_code": "BNI",
        "amount": 5000,
        "sender_name": "JOHN DOE",
        "transaction_timestamp": "2017-08-11T11:14:57.080Z"
    }
    Parameter Type Description
    id
    required
    string ID of the virtual account payment
    payment_id
    required
    string Our internal system’s payment ID
    callback_virtual_account_id
    required
    string ID of the virtual account payment that was paid
    external_id
    required
    string External ID on the virtual account payment
    merchant_code
    required
    string 5-digit merchant prefix to the full virtual account number
    account_number
    required
    string Account number of the virtual account
    bank_code
    required
    string Bank code of the virtual account number
    amount
    required
    integer positive Amount that was paid to this virtual account payment
    transaction_timestamp
    required
    string Date time that the virtual account was paid
    sender_name
    string Name of the end user that paid into the virtual account. This field is only supported for Sahabat Sampoerna virtual accounts.

    Error Codes

    Error Code Description
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    CALLBACK_VIRTUAL_ACCOUNT_PAYMENT_NOT_FOUND_ERROR
    404
    Could not find callback virtual account payment by payment id.

    Retail Outlets

    Create Fixed Payment Code

    Endpoint: Create Fixed Payment Code (FPC)

    POST https://api.xendit.co/fixed_payment_code

    One way for your customer to pay through Retail Outlets is by providing them Fixed Payment Code. Fixed payment code is a dedicated payment code under a name you choose, e.g. 'YourCompany - Becca Salim'. You will receive a callback each time this fixed payment code is paid.

    Request Parameters

    Example Create Fixed Payment Code Request

    curl https://api.xendit.co/fixed_payment_code -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d external_id=demo_fixed_payment_code_123 \
       -d retail_outlet_name=ALFAMART \
       -d name='Rika Sutanto' \
       -d expected_amount=10000
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $params = [
        'external_id' => '123',
        'retail_outlet_name' => 'ALFAMART',
        'name' => 'Rika Sutanto',
        'expected_amount' => 10000
      ];
    
      $createFPC = \Xendit\Retail::create($params);
      var_dump($createFPC);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RetailOutlet } = x;
    const retailOutletSpecificOptions = {};
    const ro = new RetailOutlet(retailOutletSpecificOptions);
    
    const resp = await ro.createFixedPaymentCode({
      externalID: 'demo_fixed_payment_code_123',
      retailOutletName: 'ALFAMART',
      name: 'Rika Sutanto',
      expectedAmt: 10000,
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Map<String, Object> params = new HashMap<>();
      params.put("external_id", "test");
      params.put("retail_outlet_name", "ALFAMART");
      params.put("name", "Rika Sutanto");
      params.put("expected_amount", 10000);
    
      FixedPaymentCode fpc = RetailOutlet.createFixedPaymentCode(params);
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    data := retailoutlet.CreateFixedPaymentCodeParams{
      ExternalID:       "123",
      RetailOutletName: xendit.RetailOutletNameAlfamart,
      Name:             "Rika Sutanto",
      ExpectedAmount:   10000,
    }
    
    resp, err := retailoutlet.CreateFixedPaymentCode(&data)
    if err != nil {
      log.Fatal(err.ErrorCode)
    }
    
    fmt.Printf("created retail outlet fixed payment code: %+v\n", resp)

    JSON

    {
      "external_id": "123",
      "retail_outlet_name": "ALFAMART",
      "name": "Rika Sutanto",
      "expected_amount": 10000
    }
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    external_id
    required
    string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 1000 characters.

    Characters Special and alphanumeric
    Minimum length 1 character
    retail_outlet_name
    required
    string Name of the fixed payment code you want to create

    Available Retail Outlest: ALFAMART and INDOMARET
    name
    required
    string Name of user - this might be used by the Retail Outlets cashier to validate the end user

    Characters Only alphanumeric
    Minimum length 1 character
    expected_amount
    required
    integer positive The amount that is expected to be paid by end customer
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Alfamart
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Indomaret
  • payment_code
    optional
    string The fixed payment code that you want to assign, e.g 12345. If you do not send one, one will be picked at random

    default: random string
    expiration_date
    optional
    ISO 8601 Date The time when the fixed payment code will be expired

    timezone: UTC
    default: The expired date will be 31 years from payment code generated
    is_single_use
    optional
    boolean When set to true, the fixed payment code will be inactive after it is paid

    default: false

    Response Parameters

    Example Create Fixed Payment Code Response

    {
        "owner_id": "5b614aa8e79f9214007244d4",
        "external_id": "123",
        "retail_outlet_name": "ALFAMART",
        "prefix": "TEST",
        "name": "Rika Sutanto",
        "payment_code": "TEST123456",
        "type": "USER",
        "expected_amount": 10000,
        "is_single_use": true,
        "expiration_date": "2049-07-31T17:00:00.000Z",
        "id": "5b61881e6cc2770f00117f73"
    }
    Parameter Type Description
    owner_id
    required
    string Your user ID
    external_id
    required
    string An ID of your choice which you provided upon request
    retail_outlet_name
    required
    string Name of the Retail Outlets, e.g. ALFAMART or INDOMARET
    prefix
    required
    string 3-6 characters that differentiate your fixed payment code from the others
    name
    required
    string Name for the fixed payment code
    payment_code
    required
    string Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. You can append payment_code into the barcode page URL (barcode page currently only supports Alfamart):
    TEST: https://retail-outlet-barcode-dev.xendit.co/alfamart/:payment_code
    LIVE: https://retail-outlet-barcode.xendit.co/alfamart/:payment_code
    expected_amount
    required
    integer positive The amount that is expected to be paid by end customer
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Alfamart
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Indomaret
  • is_single_use
    required
    boolean Value that determines whether a fixed payment code will be inactive after it is paid or not
    expiration_date
    required
    ISO 8601 Date The time when the fixed payment code will be expired
    id
    required
    string Unique ID for the fixed payment code that generated randomly by sistem.

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    PAYMENT_CODE_OUTSIDE_RANGE
    400
    The fixed payment code you want is outside your range. Can resolve by check the dashboard to see the range Retail Outlets Settings
    RETAIL_OUTLET_NOT_SUPPORTED_ERROR
    400
    The Retail Outlets is not currently supported.
    DUPLICATE_PAYMENT_CODE_ERROR
    400
    The payment code that you want to create is already exist
    EXPIRATION_DATE_INVALID_ERROR
    400
    Invalid custom expiration date because it's earlier than current time.
    MINIMUM_EXPECTED_AMOUNT_ERROR
    400
    The expected amount can only be more than or equal Rp 10,0000
    MAXIMUM_EXPECTED_AMOUNT_ERROR
    400
    The expected amount can only be less than or equal Rp 5,000,000
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Update Fixed Payment Code

    Endpoint: Update Fixed Payment Code (FPC)

    PATCH https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id}

    Fixed Payment Code is so adaptable, and it's all based on your needs. Therefore, we provide you this endpoint to easily update your fixed payment code as you like.

    Request Parameters

    Example Update Fixed Payment Code Request

    curl https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id} -X PATCH \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d expected_amount=20000
       -d name='Joe Contini'
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '5b61881e6cc2770f00117f73';
      $updateParams = ['expected_amount' => 20000];
    
      $updateFPC = \Xendit\Retail::update($id, $updateParams);
      var_dump($updateFPC);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RetailOutlet } = x;
    const retailOutletSpecificOptions = {};
    const ro = new RetailOutlet(retailOutletSpecificOptions);
    
    const resp = await ro.updateFixedPaymentCode({
      id: '5b61881e6cc2770f00117f73',
      name: 'Joe Contini',
      expectedAmt: 20000,
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Map<String, Object> params = new HashMap<>();
      params.put("name", "Lorem Ipsum");
    
      FixedPaymentCode fpc = RetailOutlet.updateFixedPaymentCode("EXAMPLE_ID", params);
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    expirationDate := time.Now().AddDate(0, 0, 1)
    
    updateFixedPaymentCodeData := retailoutlet.UpdateFixedPaymentCodeParams{
      FixedPaymentCodeID: "5b61881e6cc2770f00117f73",
      Name:               "Joe Contini",
      ExpectedAmount:     20000,
      ExpirationDate:     &expirationDate,
    }
    
    resp, err := retailoutlet.UpdateFixedPaymentCode(&updateFixedPaymentCodeData)
    if err != nil {
      log.Fatal(err.ErrorCode)
    }
    fmt.Printf("updated retail outlet fixed payment code: %+v\n", resp)

    JSON

    {
      "expected_amount": 20000,
      "name": "Joe Contini"
    }
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    name
    optional
    string Name for the fixed payment code

    Characters Only alphanumeric
    Minimum length 1 character
    expected_amount
    optional
    integer positive The amount that is expected to be paid by end customer
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Alfamart
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Indomaret
  • expiration_date
    optional
    ISO 8601 Date The time when the fixed payment code will be expired. You can set it to be days in the past to expire fixed payment code immediately

    timezone: UTC
    default: The expired date will be 31 years from payment code generated

    Response Parameters

    Example Update Fixed Payment Code Response

    {
        "owner_id": "5b614aa8e79f9214007244d4",
        "external_id": "123",
        "retail_outlet_name": "ALFAMART",
        "prefix": "TEST",
        "name": "Joe Contini",
        "payment_code": "TEST123456",
        "type": "USER",
        "expected_amount": 20000,
        "is_single_use": true,
        "expiration_date": "2049-07-31T17:00:00.000Z",
        "id": "5b61881e6cc2770f00117f73"
    }
    Parameter Type Description
    owner_id
    required
    string Your user ID
    external_id
    required
    string An ID of your choice which you provided upon request
    retail_outlet_name
    required
    string Name of the Retail Outlets, e.g. ALFAMART or INDOMARET
    prefix
    required
    string 3-6 characters that differentiate your fixed payment code from the others
    name
    required
    string Name for the fixed payment code
    payment_code
    required
    string Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. You can append payment_code into the barcode page URL (barcode page currently only supports Alfamart):
    TEST: https://retail-outlet-barcode-dev.xendit.co/alfamart/:payment_code
    LIVE: https://retail-outlet-barcode.xendit.co/alfamart/:payment_code
    expected_amount
    required
    integer positive The amount that is expected to be paid by end customer
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Alfamart
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Indomaret
  • is_single_use
    required
    boolean Value that determines whether a fixed payment code will be inactive after it is paid or not
    expiration_date
    required
    ISO 8601 Date The time when the fixed payment code will be expired
    id
    required
    string Unique ID for the fixed payment code that generated randomly by sistem.

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    PAYMENT_CODE_OUTSIDE_RANGE
    400
    The fixed payment code you want is outside your range. Can resolve by check the dashboard to see the range Retail Outlets Settings
    INACTIVE_FIXED_PAYMENT_CODE_ERROR
    400
    Account number that you want to update is inactive.
    MINIMUM_EXPECTED_AMOUNT_ERROR
    400
    The expected amount can only be more than or equal Rp 10,000
    MAXIMUM_EXPECTED_AMOUNT_ERROR
    400
    The expected amount can only be less than or equal Rp 5,000,000
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Get Fixed Payment Code

    Endpoint: Get Fixed Payment Code

    GET https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id}

    Example Get Fixed Payment Code Request

    curl https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id} -X GET \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '5b61881e6cc2770f00117f73';
    
      $getFPC = \Xendit\Retail::retrieve($id);
      var_dump($getFPC);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RetailOutlet } = x;
    const retailOutletSpecificOptions = {};
    const ro = new RetailOutlet(retailOutletSpecificOptions);
    
    const resp = await ro.getFixedPaymentCode({
      id: '5b61881e6cc2770f00117f73',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      FixedPaymentCode fpc = RetailOutlet.getFixedPaymentCode("EXAMPLE_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    getFixedPaymentCodeData := retailoutlet.GetFixedPaymentCodeParams{
      FixedPaymentCodeID: "5b61881e6cc2770f00117f73",
    }
    
    resp, err := retailoutlet.GetFixedPaymentCode(&getFixedPaymentCodeData)
    if err != nil {
      log.Fatal(err.ErrorCode)
    }
    
    fmt.Printf("retrieved retail outlet fixed payment code: %+v\n", resp)

    Sometimes, you need to know the detail for your fixed payment code. This endpoint can be used to get the latest details from your fixed payment code

    Request Parameters

    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    fixed_payment_code_id
    required
    string ID of the fixed payment code to retrieve

    Response Parameters

    Example Get Fixed Payment Code Response

    {
        "owner_id": "5b614aa8e79f9214007244d4",
        "external_id": "123",
        "retail_outlet_name": "INDOMARET",
        "prefix": "TEST",
        "name": "Joe Contini",
        "payment_code": "TEST123456",
        "type": "USER",
        "expected_amount": 20000,
        "is_single_use": true,
        "expiration_date": "2049-07-31T17:00:00.000Z",
        "id": "5b61881e6cc2770f00117f73"
    }
    Parameter Type Description
    owner_id
    required
    string Your user ID
    external_id
    required
    string An ID of your choice which you provided upon request
    retail_outlet_name
    required
    string Name of the Retail Outlets, e.g. ALFAMART or INDOMARET
    prefix
    required
    string 3-6 characters that differentiate your fixed payment code from the others
    name
    required
    string Name for the fixed payment code
    payment_code
    required
    string Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. You can append payment_code into the barcode page URL (barcode page currently only supports Alfamart):
    TEST: https://retail-outlet-barcode-dev.xendit.co/alfamart/:payment_code
    LIVE: https://retail-outlet-barcode.xendit.co/alfamart/:payment_code
    expected_amount
    required
    integer positive The amount that is expected to be paid by end customer
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Alfamart
  • the minimum is Rp 10,000 and the maximum is Rp 5,000,000 for Indomaret
  • is_single_use
    required
    boolean Value that determines whether a fixed payment code will be inactive after it is paid or not
    expiration_date
    required
    ISO 8601 Date The time when the fixed payment code will be expired
    id
    required
    string Unique ID for the fixed payment code that generated randomly by sistem.

    Error Codes

    Error Code Description
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    FIXED_PAYMENT_CODE_NOT_FOUND_ERROR
    404
    Could not find fixed payment code.

    Fixed Payment Code Callback

    Endpoint: Fixed Payment Code Callback

    POST https://yourcompany.com/fixed_payment_code_paid_callback_url

    When someone pays into your fixed payment code, our callback APIs will hit your URL that you already set in dashboard.

    This example is only used to show the body parameters that send from Xendit APIs to your callback URL and cannot be tested in here. If you want to test this callback request, use the test feature in dashboard and go to Callbacks settings.

    Callback Payload

    Header Parameter Type Description
    x-callback-token
    required
    string Your Xendit unique callback token to verify the origin of the callback

    Example Fixed Payment Code Payment Callback Request

    curl --include \
         --request POST \
         --header "Content-Type: application/json" \
         --header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
         --data-binary "{
        fixed_payment_code_payment_id: \"5b61ffc470f7f3470165e7b3\",
        owner_id: \"5b614aa8e79f9214007244d4\",
        fixed_payment_code_id: \"5b61f49e6cc2770f00117f82\",
        payment_id:\"1533149124896\",
        external_id: \"123\",
        payment_code: \"TEST123456\",
        prefix: \"TEST\",
        retail_outlet_name: 'INDOMARET',
        amount: 20000,
        name: 'Joe Contini',
        transaction_timestamp: \"2018-07-31T08:15:03.080Z\",
        updated: \"2016-10-10T08:15:03.404Z\",
        created: \"2016-10-10T08:15:03.404Z\"
    }" \
    'https://api.xendit.co/fixed_payment_code_paid_callback_url'

    JSON

    {
      "fixed_payment_code_payment_id": "5b61ffc470f7f3470165e7b3",
      "owner_id": "5b614aa8e79f9214007244d4",
      "fixed_payment_code_id": "5b61f49e6cc2770f00117f82",
      "payment_id":"1533149124896",
      "external_id": "123",
      "payment_code": "TEST123456",
      "prefix": "TEST",
      "retail_outlet_name": "INDOMARET",
      "amount": 20000,
      "name": "Joe Contini",
      "transaction_timestamp": "2018-07-31T08:15:03.080Z"
    }
    Body Parameter Type Description
    fixed_payment_code_payment_id
    required
    string Unique ID for the fixed payment code payment
    owner_id
    required
    string Your user ID
    fixed_payment_code_id
    required
    string Unique ID for the fixed payment code
    payment_id
    required
    string Our internal system’s payment ID that can be used as payment reference
    external_id
    required
    string An ID of your choice which you provided upon fixed payment code creation
    payment_code
    required
    string Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. You can append payment_code into the barcode page URL (barcode page currently only supports Alfamart):
    TEST: https://retail-outlet-barcode-dev.xendit.co/alfamart/:payment_code
    LIVE: https://retail-outlet-barcode.xendit.co/alfamart/:payment_code
    prefix
    required
    string 3-6 characters that differentiate your fixed payment code from the others
    retail_outlet_name
    required
    string Name for the relevant Retail Outlets, e.g. ALFAMART or INDOMARET
    amount
    required
    integer positive Nominal amount that is paid
    name
    required
    string Name for the fixed payment code
    transaction_timestamp
    required
    ISO 8601 Date Date time that the fixed payment code was paid

    Error Codes

    Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.

    Invoices

    Create Invoice

    Endpoint: Create Invoice

    POST https://api.xendit.co/v2/invoices

    Invoices allow you to quickly collect payments using with all of our payment methods. When payment is complete, a callback is made regardless of the payment method used.

    Learn more about invoices in our documentation

    Request Parameters

    Example Create Invoice Request

    curl https://api.xendit.co/v2/invoices -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d external_id=demo_1475801962607 \
       -d payer_email=alfina@xendit.co \
       -d description='Trip to Bali' \
       -d amount=230000
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $params = [ 
        'external_id' => 'demo_1475801962607',
        'payer_email' => 'alfina@xendit.co',
        'description' => 'Trip to Bali',
        'amount' => 50000
      ];
    
      $createInvoice = \Xendit\Invoice::create($params);
      var_dump($createInvoice);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Invoice } = x;
    const invoiceSpecificOptions = {};
    const i = new Invoice(invoiceSpecificOptions);
    
    const resp = await i.createInvoice({
      externalID: 'demo_1475801962607',
      amount: 230000,
      payerEmail: 'sample_email@xendit.co',
      description: 'Trip to Bali',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Map<String, Object> params = new HashMap<>();
      params.put("external_id", "demo_1475801962607");
      params.put("amount", 50000);
      params.put("payer_email", "customer@domain.com");
      params.put("description", "Trip to Bali");
    
      Invoice invoice = Invoice.create(params);
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    data := invoice.CreateParams{
      ExternalID:  "demo_1475801962607",
      Amount:      50000,
      PayerEmail:  "alfina@xendit.co",
      Description: "Trip to Bali",
    }
    
    resp, err := invoice.Create(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created invoice: %+v\n", resp)
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    external_id
    required
    string ID of your choice (typically the unique identifier of an invoice in your system)
    payer_email
    required
    string Email of the end user you're charging
    description
    required
    string Description of the invoice
    amount
    required
    number Amount on the invoice. The minimum amount to create an invoice is 1 IDR or PHP
    should_send_email
    optional

    default: false
    boolean Specify whether you want us to email the end customer when an invoice is created, paid, or expired
    callback_virtual_account_id
    optional
    string To allow payment via Fixed Virtual Account, pass in the id field value from the response when the fixed virtual account was created. See Create Fixed Virtual Accounts
    invoice_duration
    optional
    number Duration of time that the end customer is given to pay the invoice before expiration (in seconds, since creation)
    success_redirect_url
    optional
    string URL that the end customer will be redirected to upon successful invoice payment.
    example : https://<span></span>yourcompany.com/example_item/10/success_page
    failure_redirect_url
    optional
    string URL that end user will be redirected to upon expiration of this invoice.
    example : https://<span></span>yourcompany.com/example_item/10/failed_checkout
    payment_methods
    optional
    array of strings Choice of payment channels that is available in your account. Leave this field empty if all payment channel is expected to be available in this particular invoice, or if you want to use the defaults set in your Xendit Dashboard.
    example : <span></span>["BCA", "BRI", "MANDIRI", "BNI", <br> "PERMATA", "ALFAMART", "CREDIT_CARD", <br> "OVO"]
    mid_label
    optional
    string MID label when you have an acquiring bank, and are using credit cards.
    currency
    optional
    string Currency of the amount that you created
    example : "IDR" or "PHP"
    fixed_va
    optional

    default: false
    boolean Input this parameter as true to enable using a single, persistent VA number your end customers, determined by email address.
    reminder_time
    optional
    integer positive Reminder email will be sent reminder_time day(s) before the invoice expires. Allowed values are 1, 3, 7, 15, 30 days before invoice expires

    Response Parameters

    Example Create Invoice Response

    {
      "id": "579c8d61f23fa4ca35e52da4",
      "user_id": "5781d19b2e2385880609791c",
      "external_id": "demo_1475801962607",
      "status": "PENDING",
      "merchant_name": "Xendit",
      "merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1493610897264_473.png",
      "amount": 50000,
      "payer_email": "alfina@xendit.co",
      "description": "Trip to Bali",
      "invoice_url": "https://invoice.xendit.co/web/invoices/595b6248c763ac05592e3eb4",
      "expiry_date": "2020-08-01T11:20:01.017Z",
      "available_banks": [
       {
                "bank_code": "MANDIRI",
                "collection_type": "POOL",
                "bank_account_number": "8860810000525",
                "transfer_amount": 50000,
                "bank_branch": "Virtual Account",
                "account_holder_name": "LANSUR13",
            },
            {
                "bank_code": "BRI",
                "collection_type": "POOL",
                "bank_account_number": "2621510002426",
                "transfer_amount": 50000,
                "bank_branch": "Virtual Account",
                "account_holder_name": "LANSUR13",
            },
            {
                "bank_code": "BNI",
                "collection_type": "POOL",
                "bank_account_number": "880810000689",
                "transfer_amount": 50000,
                "bank_branch": "Virtual Account",
                "account_holder_name": "LANSUR13",
            }
      ],
      "available_retail_outlets": [
          {
              "retail_outlet_name": "ALFAMART",
              "payment_code": "ALFA123456",
              "transfer_amount": 54000
          }
      ],
      "should_exclude_credit_card": false,
      "should_send_email": false,
      "created": "2020-01-12T14:00:00.306Z",
      "updated": "2020-01-12T14:00:00.306Z",
      "mid_label": "test-mid",
      "currency": "IDR",
      "fixed_va":true
    }
    Parameter Description
    id An invoice ID generated by Xendit
    user_id Your Xendit Business ID
    external_id The invoice ID in your server, that can be used to reconcile between you and Xendit
    status PENDING the invoice has yet to be paid
    merchant_name The name of your company or website
    merchant_profile_picture_url The URL to profile picture of your company
    amount Nominal amount for the invoice
    payer_email Email of the payer, we get this information from your API call
    description Description for the invoice, we get this information from your API call
    invoice_url Public URL for this invoice, it’s there in case you want to use our UI
    expiry_date ISO date and time that the invoice expires. Default is 24 hours.
    available_banks Available payment methods through banks as per your config
    bank_code BCA / MANDIRI / BNI / BRI / PERMATA
    collection_type POOL type is nonfixed virtual account
    bank_account_number Bank account number for users to pay into
    transfer_amount (DEPRECATED) Amount the user should transfer
    bank_branch Bank account type
    account_holder_name Bank account holder name
    available_retail_outlets Available payment methods through retail outlet as per your config
    retail_outlet_name Name of the retail outlet
    payment_code Unique code that you use to pay in retail outlet
    transfer_amount (DEPRECATED) Amount the user should transfer
    transfer_amount (DEPRECATED) Amount the user should transfer
    should_exclude_credit_card A flag showing if credit card should be excluded in invoice UI or not
    should_send_email A flag showing should payer get email when invoice is created, paid, or expired; or not
    created An ISO timestamp that tracks when the invoice was created
    updated An ISO timestamp that tracks when the invoice was updated
    mid_label MID label that you have when you are using credit card payment and have acquiring bank. You will get this response when you add this parameter when create invoice through API
    currency Currency of the amount that you created. You will get this response when you add this parameter when create invoice through API
    fixed_va Input this parameter as true to enable one VA number for Your end customers.
    reminder_date
    optional
    ISO8601 An ISO timestamp that the customer will be sent an invoice reminder email (when they send reminder_time for invoice creation).
    Timezone: GMT+0

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    MINIMAL_TRANSFER_AMOUNT_ERROR
    400
    Could not create invoice because amount is below Rp10000.
    MAXIMUM_TRANSFER_AMOUNT_ERROR
    400
    Could not create invoice because amount is above Rp1000000000. If you are configured with Retail Outlets, then amount cannot be more than Rp5000000
    NO_COLLECTION_METHODS_ERROR
    400
    Your account has no payment methods configured (virtual account, credit card). Please contact support and we will set this up for you.
    UNAVAILABLE_PAYMENT_METHOD_ERROR
    400
    The payment method choices did not match with the available one on this business.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    UNIQUE_ACCOUNT_NUMBER_UNAVAILABLE_ERROR
    404
    There is no available virtual account in your non-fixed virtual account range.
    CALLBACK_VIRTUAL_ACCOUNT_NOT_FOUND_ERROR
    404
    Fixed virtual account id that you've specified not found
    AVAILABLE_PAYMENT_CODE_NOT_FOUND_ERROR
    404
    There is no available payment code in your retail outlet range.
    INVALID_REMINDER_TIME
    400
    The reminder_time value is not allowed.

    Get Invoice

    Endpoint: Get an Invoice

    GET https://api.xendit.co/v2/invoices/{invoice_id}

    Request Parameters

    Example Get Invoice Request

    curl https://api.xendit.co/v2/invoices/{invoice_id} -X GET \
        -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '579c8d61f23fa4ca35e52da4';
      $getInvoice = \Xendit\Invoice::retrieve($id);
      var_dump($getInvoice);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Invoice } = x;
    const invoiceSpecificOptions = {};
    const i = new Invoice(invoiceSpecificOptions);
    
    const resp = await i.getInvoice({
      invoiceID: '587cc7b4863f2b462beb31f6',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Invoice invoice = Invoice.getById("my_external_id");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    data := invoice.GetParams{
      ID: "579c8d61f23fa4ca35e52da4",
    }
    
    resp, err := invoice.Get(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("retrieved invoice: %+v\n", resp)
    Query Parameter Type Description
    invoice_id
    required
    string ID of the invoice to retrieve

    Response Parameters

    Example Get Invoice Response

    {
      "id": "579c8d61f23fa4ca35e52da4",
      "user_id": "5781d19b2e2385880609791c",
      "external_id": "invoice_123124123",
      "status": "PENDING",
      "merchant_name": "Xendit",
      "merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1493610897264_473.png",
      "amount": 50000,
      "payer_email": "alfina@xendit.co",
      "description": "This is a description",
      "invoice_url": "https://invoice.xendit.co/web/invoices/595b6248c763ac05592e3eb4",
      "expiry_date": "2020-01-31T11:20:01.017Z",
      "available_banks": [
        {
                "bank_code": "MANDIRI",
                "collection_type": "POOL",
                "bank_account_number": "8860810000525",
                "transfer_amount": 50000,
                "bank_branch": "Virtual Account",
                "account_holder_name": "LANSUR13",
            },
            {
                "bank_code": "BRI",
                "collection_type": "POOL",
                "bank_account_number": "2621510002426",
                "transfer_amount": 50000,
                "bank_branch": "Virtual Account",
                "account_holder_name": "LANSUR13",
            },
            {
                "bank_code": "BNI",
                "collection_type": "POOL",
                "bank_account_number": "880810000689",
                "transfer_amount": 50000,
                "bank_branch": "Virtual Account",
                "account_holder_name": "LANSUR13",
            }
      ],
      "available_retail_outlets": [
          {
              "retail_outlet_name": "ALFAMART",
              "payment_code": "ALFA123456",
              "transfer_amount": 54000
          }
      ],
      "should_exclude_credit_card": false,
      "should_send_email": false,
      "created": "2020-01-01T14:00:00.306Z",
      "updated": "2020-01-01T14:00:00.306Z",
      "mid_label": "test-mid",
      "currency": "IDR",
      "paid_at": "2020-01-02T11:00:00.306Z",
      "credit_card_charge_id": "579c8d61f23fa4ca35e52eas",
      "payment_method": "BANK_TRANSFER",
      "payment_channel": "BCA",
      "payment_destination": "10002233222294375",
      "success_redirect_url": "www.xendit.co",
      "failure_redirect_url": "www.xendit.co",
      "fixed_va":true
    }



    Parameter Description
    id An invoice ID generated by Xendit
    user_id Your Xendit Business ID
    external_id The invoice ID in your server, that can be used to reconcile between you and Xendit
    status PENDING the invoice has yet to be paid
    PAID the invoice has successfully been paid
    SETTLED the amount of paid invoice has been settled to cash balance
    EXPIRED the invoice has been expired
    merchant_name The name of your company or website
    merchant_profile_picture_url The URL to profile picture of your company
    amount Nominal amount for the invoice
    payer_email Email of the payer, we get this information from your API call
    description Description for the invoice, we get this information from your API call
    invoice_url Public URL for this invoice, it’s there in case you want to use our UI
    expiry_date ISO date and time that the invoice expires. Default is 24 hours.
    available_banks Available payment methods through banks as per your config
    bank_code BCA / MANDIRI / BNI / BRI / PERMATA
    collection_type POOL type is nonfixed virtual account
    bank_account_number Bank account number for users to pay into
    transfer_amount (DEPRECATED) Amount the user should transfer
    bank_branch Bank account type
    account_holder_name Bank account holder name
    available_retail_outlets
    Available payment methods through retail outlet as per your config
    retail_outlet_name Name of the retail outlet
    payment_code Unique code that you use to pay in retail outlet
    transfer_amount (DEPRECATED) Amount the user should transfer
    should_exclude_credit_card

    A flag showing if credit card should be excluded in invoice UI or not

    should_send_email

    A flag showing should payer get email when invoice is created, paid, or expired; or not

    updated

    An ISO timestamp that tracks when the invoice was updated

    created

    An ISO timestamp that tracks when the invoice was created

    mid_label MID label that you have when you are using credit card payment and have acquiring bank. You will get this response when you add this parameter when create invoice through API
    currency Currency of the amount that you created. You will get this response when you add this parameter when create invoice through API
    success_redirect_url URL that end user will be redirected to upon successful invoice payment. You will get this response when you add this parameter when create invoice through API
    failure_redirect_url URL that end user will be redirected to upon expiration of this invoice. You will get this response when you add this parameter when create invoice through API
    paid_at Date time data when your customer pay the invoice. You will get this response when your invoice is paid
    credit_card_charge_id Credit card charge ID when your customer pay the invoice with credit card. You will get this response when your invoice is paid with Credit Card
    payment_method Payment method that is used when a customer pays the invoice. You will get this response when your invoice is paid
    Example : <span></span>["BANK_TRANSFER", "CREDIT_CARD", "RETAIL_OUTLET", <br> "EWALLET"]
    payment_channel The payment channel used when a customer pays the invoice. You will get this response when your invoice is paid
    Example : <span></span>["BCA", "BRI", "MANDIRI", <br> "BNI", "PERMATA", "ALFAMART", <br> "OVO", "CREDIT_CARD"]
    payment_destination Virtual Account number or Retail Outlet payment code used to pay the invoice (will not be shown for cards and e-wallet payments). You will get this response when your invoice is paid
    fixed_va Input this parameter as true to enable one VA number for Your end customers.

    Error Codes

    Error Code Description
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    INVOICE_NOT_FOUND_ERROR
    404
    Could not find invoice by id.

    Expire Invoice

    Endpoint: Expire Invoice

    POST https://api.xendit.co/invoices/{invoice_id}/expire!

    You can cancel an already created invoice by expiring it immediately using this endpoint.

    Note:

    1. Expiring an invoice will close available payment methods: Pool Virtual Account, Retail Outlet, and Credit Card, but not Fixed Virtual Account.
    2. Expiring an invoice which is linked to Fixed Virtual Accounts will only unlink the Fixed Virtual Account's relation to the invoice, so further payments to this Fixed Virtual Account will be detected as Fixed Virtual Account payments instead of invoice payments. To expire Fixed Virtual Accounts, change the expiration_date using Update Fixed Virtual Account Endpoint

    Request Parameters

    Example Expire Invoice Request

    curl https://api.xendit.co/invoices/{invoice_id}/expire! -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '579c8d61f23fa4ca35e52da4';
      $expireInvoice = \Xendit\Invoice::expireInvoice($id);
      var_dump($expireInvoice);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Invoice } = x;
    const invoiceSpecificOptions = {};
    const i = new Invoice(invoiceSpecificOptions);
    
    const resp = await i.expireInvoice({
      invoiceID: '587cc7b4863f2b462beb31f6',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Invoice invoice = Invoice.expire("EXAMPLE_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    data := invoice.ExpireParams{
      ID: "579c8d61f23fa4ca35e52da4",
    }
    
    resp, err := invoice.Expire(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("expired invoice: %+v\n", resp)
    Parameter Type Description
    invoice_id
    required
    string ID of the invoice to be expired / canceled

    Response Parameters

    Example Expire Invoice Response

    {
      "id": "579c8d61f23fa4ca35e52da4",
      "user_id": "5781d19b2e2385880609791c",
      "external_id": "invoice_123124123",
      "status": "EXPIRED",
      "merchant_name": "Xendit",
      "merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1493610897264_473.png",
      "amount": 50000,
      "payer_email": "alfina@xendit.co",
      "description": "This is a description",
      "invoice_url": "https://invoice.xendit.co/web/invoices/595b6248c763ac05592e3eb4",
      "expiry_date": "2020-04-01T11:20:01.017Z",
      "available_banks": [
        {
          "bank_code": "BCA",
          "collection_type": "POOL",
          "bank_account_number": 1000008,
          "transfer_amount": 54000
        },
        {
          "bank_code": "MANDIRI",
          "collection_type": "POOL",
          "bank_account_number": 1000009,
          "transfer_amount": 54000
        }
      ],
      "available_retail_outlets": [
          {
              "retail_outlet_name": "ALFAMART",
              "payment_code": "ALFA123456",
              "transfer_amount": 54000
          }
      ],
      "should_exclude_credit_card": false,
      "should_send_email": false,
      "created": "2020-01-12T14:00:00.306Z",
      "updated": "2020-01-12T14:00:00.306Z"
    }
    Parameter Description
    id An invoice ID generated by Xendit
    user_id Your Xendit Business ID
    external_id The invoice ID in your server, that can be used to reconcile between you and Xendit
    status EXPIRED the invoice has been expired
    merchant_name The name of your company or website
    merchant_profile_picture_url The URL to profile picture of your company
    amount Nominal amount for the invoice
    payer_email Email of the payer, we get this information from your API call
    description Description for the invoice, we get this information from your API call
    invoice_url Public URL for this invoice, it’s there in case you want to use our UI
    expiry_date ISO date and time that the invoice expires. Default is 24 hours.
    available_banks Available payment methods through banks as per your config
    bank_code BCA / MANDIRI / BNI / BRI / PERMATA
    collection_type POOL type is nonfixed virtual account
    bank_account_number Bank account number for users to pay into
    transfer_amount (DEPRECATED) Amount the user should transfer
    bank_branch Bank account type
    account_holder_name Bank account holder name
    available_retail_outlets
    Available payment methods through retail outlet as per your config
    retail_outlet_name Name of the retail outlet
    payment_code Unique code that you use to pay in retail outlet
    transfer_amount (DEPRECATED) Amount the user should transfer
    should_exclude_credit_card

    A flag showing if credit card should be excluded in invoice UI or not

    should_send_email

    A flag showing should payer get email when invoice is created, paid, or expired; or not

    updated

    An ISO timestamp that tracks when the invoice was updated

    created

    An ISO timestamp that tracks when the invoice was created

    Error Codes

    Error Code Description
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    INVOICE_NOT_FOUND_ERROR
    404
    Could not find invoice by id.

    List All Invoices

    Endpoint: List Invoice

    GET https://api.xendit.co/v2/invoices

    You can list all invoices, or list the invoices for a specific updated time. The invoices are returned sorted by created date, with the most recently created invoices appearing first.

    Request Parameters

    Example List Invoice Request

    curl https://api.xendit.co/v2/invoices?limit=3&statuses=["SETTLED","EXPIRED"]&last_invoice_id=5ca186e407f3b83e34176eac&client_types=["DASHBOARD","API_GATEWAY"]&after=2016-02-24T23:48:36.697Z&before=2020-02-24T23:48:36.697Z -X GET \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $getAllInvoice = \Xendit\Invoice::retrieveAll();
      var_dump(($getAllInvoice));
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Invoice } = x;
    const invoiceSpecificOptions = {};
    const i = new Invoice(invoiceSpecificOptions);
    
    const resp = await i.getAllInvoices({
      statuses: ["SETTLED", "EXPIRED"],
      lastInvoiceID: '5ca186e407f3b83e34176eac',
      clientTypes: ["DASHBOARD","API_GATEWAY"],
    });
    console.log(resp);
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    createdAfter, _ := time.Parse(time.RFC3339, "2016-02-24T23:48:36.697Z")
    data := invoice.GetAllParams{
      Statuses:     []string{"EXPIRED", "SETTLED"},
      Limit:        5,
      CreatedAfter: createdAfter,
    }
    
    resps, err := invoice.GetAll(&data)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("invoices: %+v\n", resps)

    Example List Invoice Response

    [
        {
            "id": "5c65be6880a55b02867b2b6f",
            "external_id": "627",
            "user_id": "5bbe23e1c901a730130f5b15",
            "status": "EXPIRED",
            "merchant_name": "Your Business Name",
            "merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1545257692599_408.jpg",
            "amount": 838838,
            "payer_email": "alfina@xendit.co",
            "description": "Trip to Bali",
            "expiry_date": "2020-02-24T23:48:36.697Z",
            "invoice_url": "https://invoice-staging.xendit.co/web/invoices/5c65be6880a55b02867b2b6f",
            "available_banks": [
                {
                    "bank_code": "MANDIRI",
                    "collection_type": "POOL",
                    "bank_account_number": "8860838034047",
                    "transfer_amount": 838838,
                    "bank_branch": "Virtual Account",
                    "account_holder_name": "YOUR BUSINESS NAME",
                },
                {
                    "bank_code": "BRI",
                    "collection_type": "POOL",
                    "bank_account_number": "2621545817176",
                    "transfer_amount": 838838,
                    "bank_branch": "Virtual Account",
                    "account_holder_name": "YOUR BUSINESS NAME",
                },
                {
                    "bank_code": "BNI",
                    "collection_type": "POOL",
                    "bank_account_number": "880845676187",
                    "transfer_amount": 838838,
                    "bank_branch": "Virtual Account",
                    "account_holder_name": "YOUR BUSINESS NAME",
                }
            ],
            "available_ewallets": [],
            "should_exclude_credit_card": false,
            "should_send_email": false,
            "created": "2020-01-14T23:48:56.907Z",
            "updated": "2020-01-24T23:49:03.296Z"
        },
        {
            "id": "5c6398b710a54b0c867b2b52",
            "external_id": "1242",
            "user_id": "5bbe23e1c901a730130f5b15",
            "status": "SETTLED",
            "merchant_name": "Your Business Name",
            "merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1545257692599_408.jpg",
            "amount": 67888,
            "paid_amount": 67888,
            "bank_code": "MANDIRI",
            "payer_email": "budi@xendit.co",
            "description": "Trip to Bali",
            "expiry_date": "2020-02-24T16:34:24.341Z",
            "invoice_url": "https://invoice-staging.xendit.co/web/invoices/5c6398b710a54b0c867b2b52",
            "available_banks": [
                {
                    "bank_code": "MANDIRI",
                    "collection_type": "POOL",
                    "bank_account_number": "8860838033759",
                    "transfer_amount": 67888,
                    "bank_branch": "Virtual Account",
                    "account_holder_name": "YOUR BUSINESS NAME",
                },
                {
                    "bank_code": "BRI",
                    "collection_type": "POOL",
                    "bank_account_number": "2621545816888",
                    "transfer_amount": 67888,
                    "bank_branch": "Virtual Account",
                    "account_holder_name": "YOUR BUSINESS NAME",
                },
                {
                    "bank_code": "BNI",
                    "collection_type": "POOL",
                    "bank_account_number": "880845675899",
                    "transfer_amount": 67888,
                    "bank_branch": "Virtual Account",
                    "account_holder_name": "YOUR BUSINESS NAME",
                }
            ],
            "available_ewallets": [],
            "should_exclude_credit_card": false,
            "adjusted_received_amount": 62938,
            "should_send_email": false,
            "created": "2020-01-14T16:35:03.573Z",
            "updated": "2020-01-22T04:33:14.806Z"
        }
    ]
    
    Parameter Type Description
    statuses
    optional
    array of strings Indicates the status of the invoices that will be available in the list.
    It contains PENDING, PAID, SETTLED, EXPIRED
    limit
    optional

    default: 10
    number A limit on the number of invoice objects to be returned.
    Limit can range between 1 and 100.
    created_after
    optional
    string (ISO 8601) Return invoices where the created field is greater than this value. Both created_after and created_before field should be used in the same time for the filter to take effect
    created_before
    optional
    string (ISO 8601) Return invoices where the created field is less than this value.
    Both created_after and created_before field should be used in the same time for the filter to take effect
    paid_after
    optional
    string (ISO 8601) Return invoices where the paid_at field is greater than this value.
    Both paid_after and paid_before field should be used in the same time for the filter to take effect
    paid_before
    optional
    string (ISO 8601) Return invoices where the paid_at field is less than this value.
    Both paid_after and paid_before field should be used in the same time for the filter to take effect
    expired_after
    optional
    string (ISO 8601) Return invoices where the expiry_date field is greater than this value.
    Both expired_after and expired_before field should be used in the same time for the filter to take effect
    expired_before
    optional
    string (ISO 8601) Return invoices where the expiry_date field is less than this value.
    Both expired_after and expired_before field should be used in the same time for the filter to take effect
    last_invoice_id
    optional
    string A cursor for use in pagination.
    last_invoice_id is an invoice ID that defines your starting point for the list. For instance, if you make a list request and receive 10 objects, starting with obj_bar, your subsequent call can include last_invoice_id=obj_bar in order to fetch the previous page of the list.
    client_types
    optional
    array of strings Indicates the method used to create the invoice. It contains:
    API_GATEWAY Invoice created via create invoice API
    DASHBOARD Invoice created via dashboard
    INTEGRATION Invoice created via 3rd party integration such as Shopify and Woocommerce
    ON_DEMAND Invoice created via On Demand
    RECURRING Invoice created via Recurring Payment
    payment_channels
    optional
    array of strings Indicates the channels used to pay the invoice.
    on_demand_link
    optional
    string The link for the specific on demand. If you input on_demand_link, it will return invoices that created from that specific on demand link.
    recurring_payment_id
    optional
    string The recurring payment id for specific recurring payment, it will return invoices that created from that specific recurring payment id.

    Response Parameters

    List invoice response will return array of get invoices response. Please refer get an invoice for more information.

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Invoice Callback

    Endpoint: Invoice Callback

    POST https://yourcompany.com/invoice_callback_url

    When an invoice is paid, our systems will send a callback to the URL configured in the dashboard. For further instructions about callbacks, please read the invoices documentation

    This example is only used to show the body parameters that are sent from Xendit APIs to your callback URL. If you want to test this callback request, use the test feature in dashboard and go to Settings > Developers > Callbacks.

    Callback Payload

    Example Invoice Callback Request for Payment Through Bank

    curl --include \
         --request POST \
         --header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
         --header "Content-Type: application/json" \
         --data-binary "{
          id: \"593f4ed1c3d3bb7f39733d83\",
          external_id: \"testing-invoice\",
          user_id: \"5848fdf860053555135587e7\",
          is_high: false,
          payment_method: \"BANK_TRANSFER\",
          status: \"PAID\",
          merchant_name: \"Xendit\",
          amount: 2000000,
          paid_amount: 2000000,
          bank_code: \"MANDIRI\",
          paid_at: \"2020-01-14T02:32:50.912Z\",
          payer_email: \"test@xendit.co\",
          description: \"Invoice callback test\",
          adjusted_received_amount: 1995000,
          fees_paid_amount: 5000,
          created: \"2020-01-13T02:32:49.827Z\",
          updated: \"2020-01-13T02:32:50.912Z\",
          currency: \"IDR\",
          payment_channel: \"MANDIRI\",
          payment_destination: \"8458478548758748\",
    }" \
    '{{your_company_domain}}/{{callback_url}}'

    Example Invoice Callback Request for Payment Through Retail Outlet

    curl --include \
         --request POST \
         --header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
         --header "Content-Type: application/json" \
         --data-binary "{
          id: \"593f4ed1c3d3bb7f39733d83\",
          external_id: \"testing-invoice\",
          user_id: \"5848fdf860053555135587e7\",
          is_high: false,
          payment_method: \"RETAIL_OUTLET\",
          status: \"PAID\",
          merchant_name: \"Xendit\",
          amount: 2000000,
          paid_amount: 2000000,
          paid_at: \"2020-01-14T02:32:50.912Z\",
          payer_email: \"test@xendit.co\",
          description: \"Invoice callback test\",
          adjusted_received_amount: 1995000,
          fees_paid_amount: 5000,
          created: \"2020-01-13T02:32:49.827Z\",
          updated: \"2020-01-13T02:32:50.912Z\",
          currency: \"IDR\",
          payment_channel: \"ALFAMART\",
          payment_destination: \"TEST815\",
    }" \
    '{{your_company_domain}}/{{callback_url}}'
    Parameter Description
    id An invoice ID generated by Xendit
    user_id Your Xendit Business ID
    external_id The invoice ID in your server, that can be used to reconcile between you and Xendit
    is_high (DEPRECATED) Should unique numbers go above or below the amount.
    merchant_name The name of your company or website
    amount Nominal amount for the invoice (without taxes, fees)
    status PAID the invoice has successfully been paid
    EXPIRED the invoice has expired. Expired invoice callbacks are not enabled by default - if you want to enable it for your business, you can do so in your Xendit Dashboard
    payer_email Email of the payer, we get this information from your API call
    description Description for the invoice, we get this information from your API call
    fees_paid_amount Xendit fees that was directly paid from this invoice - thanks for supporting a better world of payments :)
    adjusted_received_amount Amount attributable to you net of our fees.
    bank_code
    only if payment_method is POOL
    Code of the bank used to received the money only if payment method is POOL
    e.g. MANDIRI
    retail_outlet_name
    only if payment_method is RETAIL_OUTLET
    Code of the retail outlet used to received the money only if payment method is RETAIL_OUTLET
    e.g. ALFAMART
    ewallet_type
    only if payment_method is EWALLET
    Code of the e-wallet used to received the money only if payment method is EWALLET
    e.g. OVO
    on_demand_link
    only for invoices from ondemand
    Link of the ondemand that created this invoice
    recurring_payment_id
    only for invoices from recurring
    ID of the recurring that created this invoice
    paid_amount Total amount paid for the invoice
    updated An ISO timestamp that tracks when the invoice was updated
    created An ISO timestamp that tracks when the invoice was created
    mid_label MID label that you have when you are using credit card payment and have acquiring bank. You will get this response when you add this parameter when create invoice through API
    currency Currency of the amount that you created. You will get this response when you add this parameter when create invoice through API
    success_redirect_url URL that end user will be redirected to upon successful invoice payment. You will get this response when you add this parameter when create invoice through API
    failure_redirect_url URL that end user will be redirected to upon expiration of this invoice. You will get this response when you add this parameter when create invoice through API
    paid_at Date time data when your customer pay the invoice. You will get this response when your invoice is paid
    credit_card_charge_id Credit card charge ID when your customer pay the invoice with credit card. You will get this response when your invoice is paid with Credit Card
    payment_method Payment method that is used when a customer pays the invoice. You will get this response when your invoice is paid
    Example : ["BANK_TRANSFER", "CREDIT_CARD", "RETAIL_OUTLET", "EWALLET"]
    payment_channel The payment channel used when a customer pays the invoice. You will get this response when your invoice is paid
    Example : ["BCA", "BRI", "MANDIRI", "BNI", "PERMATA", "ALFAMART", "OVO", "CREDIT_CARD"]
    payment_destination Virtual Account number or Retail Outlet payment code used to pay the invoice (will not be shown for cards and e-wallet payments). You will get this response when your invoice is paid

    Callback Errors

    Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.

    Recurring Payments

    Create a Recurring Payment

    Endpoint: Create Recurring Payment

    POST https://api.xendit.co/recurring_payments

    Recurring payments allow you to automatically bill your customers using our system.

    Request Parameters

    Example: Create Recurring Request

    curl https://api.xendit.co/recurring_payments -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d external_id=recurring_31451441 \
       -d payer_email=sample_email@xendit.co \
       -d interval=MONTH \
       -d interval_count=1 \
       -d description='Monthly room cleaning service' \
       -d amount=125000
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $params = [
        'external_id' => 'recurring_31451441',
        'payer_email' => 'sample_email@xendit.co',
        'description' => 'Monthly room cleaning service',
        'amount' => 125000,
        'interval' => 'MONTH',
        'interval_count' => 1
      ];
    
      $createRecurring = \Xendit\Recurring::create($params);
      var_dump($createRecurring);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RecurringPayment } = x;
    const rpSpecificOptions = {};
    const rp = new RecurringPayment(rpSpecificOptions);
    
    const resp = await rp.createPayment({
      externalID: 'recurring_31451441',
      amount: 125000,
      payerEmail: 'sample_email@xendit.co',
      interval: RecurringPayment.Interval.Month,
      intervalCount: 1,
      description: 'Monthly room cleaning service',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Map<String , Object> params = new HashMap<>();
      params.put("external_id", "recurring_31451441");
      params.put("payer_email", "sample_email@xendit.co");
      params.put("interval", "MONTH");
      params.put("interval_count", 1);
      params.put("description", "Monthly room cleaning service");
      params.put("amount", 125000);
    
      RecurringPayment recurringPayment = RecurringPayment.create(params);
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    createData := recurringpayment.CreateParams{
      ExternalID:    "recurring_31451441",
      Amount:        125000,
      PayerEmail:    "sample_email@xendit.co",
      Description:   "Monthly room cleaning service",
      Interval:      xendit.RecurringPaymentIntervalDay,
      IntervalCount: 1,
    }
    
    resp, err := recurringpayment.Create(&createData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created recurring payment: %+v\n", resp)
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    external_id
    required
    string ID of your choice (typically the unique identifier of a recurring payment in your system)
    payer_email
    required
    string Email of the end user you're charging
    description
    required
    string Description for the recurring payment and invoices
    amount
    required
    number Amount per invoice per interval.
    The minimum amount to create an invoice is 1 IDR. The maximum amount is 1.000.000.000 IDR
    interval
    required
    string One of DAY, WEEK, MONTH. The frequency with which a recurring payment invoice should be billed.
    interval_count
    required
    number The number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months.
    total_recurrence
    optional
    number The number of times you will charge your customer. If you input it as 3, Xendit will charge your customer 3 times. If you input total_recurrence as 3, interval_count as 1 and interval as "DAY", Xendit will charge customer 3 times in first day after you trigger create recurring api, the day after and 2 days after you trigger create recurring api.
    invoice_duration
    optional
    number duration of time that end user have in order to pay the invoice before it's expired (in Second). If it's not filled, invoice_duration will follow your business default invoice duration.

    invoice_duration should and will always be less than the interval-interval_count combination.
    should_send_email
    optional

    default: false
    boolean Specify should the end user get email when invoice is created, paid, or expired; or not
    missed_payment_action
    optional

    default: IGNORE
    string One of IGNORE, STOP. If there is an invoice from a recurring payment that expired, IGNORE will continue with the recurring payment as usual. STOP will stop the recurring payment.
    credit_card_token
    optional
    string Token ID for credit card autocharge. If it's empty then the autocharge is disabled. This token must be multiple use (is_multiple_use is true). please refer create cards token on how to create multi-use token. The token will still be there even if it's failed to charge.
    start_date
    optional
    string (ISO 8601) time when the first invoice will be issued. When left blank, the invoice will be created immediately
    success_redirect_url
    optional
    string url that end user will be redirected to upon successful payment to invoice created by this recurring payment.
    example : https://<span></span>yourcompany.com/example_item/10/success_page
    failure_redirect_url
    optional
    string url that end user will be redirected to upon expireation of invoice created by this recurring payment.
    example : https://<span></span>yourcompany.com/example_item/10/failed_checkout
    recharge
    optional
    default: true
    boolean Input this parameter as true when you want to enable auto-charged and capture card information through XenInvoice.
    charge_immediately
    optional

    boolean Specify should the first invoice created immediately when creating recurring payment with a valid start_date,
    The next invoice will be created at start_date and the calculation for the following recurring invoice will be at
    interval*interval_count + start_date
    payment_method_id
    optional
    string Fill this with the payment method id created for the customer
    currency
    optional

    string Currency of the amount that you created
    example : "IDR"

    Response Parameters

    Example: Create Recurring Response

    {
        "id": "579c8d61f23fa4ca35e52da3",
        "user_id": "5781d19b2e2385880609791c",
        "external_id": "recurring_31451441",
        "status": "ACTIVE",
        "amount": 125000,
        "payer_email": "sample_email@xendit.co",
        "description": "Monthly room cleaning service",
        "interval": "MONTH",
        "interval_count": 1,
        "recurrence_progress": 1,
        "should_send_email": false,
        "missed_payment_action": "IGNORE",
        "last_created_invoice_url": "https://invoice-staging.xendit.co/web/invoices/5dddeea6bdb99f4b23e5eef7",
        "created": "2017-06-12T14:00:00.306Z",
        "updated": "2017-06-12T14:00:00.306Z",
        "start_date": "2017-07-12T14:00:00.306Z",
        "recharge": true
    }
    Parameter Type Description
    id An recurring ID generated by Xendit
    user_id Your Xendit Business ID
    external_id The recurring ID in your server, that can be used to reconcile between you and Xendit
    status ACTIVE the recurring payment is currently active
    STOPPED the recurring payment has been stopped
    PAUSED the recurring payment is currently paused and will not automatically creating invoices. resume to reactivate
    amount Nominal amount of the recurring payment in IDR
    payer_email Email of the payer, we get this information from your API call
    description Description for the recurring payment and invoices
    should_send_email A flag showing should payer get email when invoice is created, paid, or expired; or not
    interval One of DAY, WEEK, MONTH. The frequency with which a recurring payment invoice should be billed.
    interval_count The number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months.
    total_recurrence The number of times you will charge your customer. If you input it as 3, Xendit will charge your customer 3 times. If you input total_recurrence as 3, interval_count as 1 and interval as "DAY", Xendit will charge customer 3 times in first day after you trigger create recurring api, the day after and 2 days after you trigger create recurring api.
    recurrence_progress The current cycle of recurring payment. If your end customer is on the 4th cycle of the recurring, you will get 4 from recurrence_progress response
    last_created_invoice_url url leading to the last invoice create by this recurring payment
    credit_card_token Token ID for credit card autocharge. If it's empty then the autocharge is disabled. This token must be multiple use (is_multiple_use is true). please refer create cards token on how to create multi-use token. The token will still be there even if it's failed to charge.
    success_redirect_url
    optional
    string url that end user will be redirected to upon successful payment to invoice created by this recurring payment.
    example : https://<span></span>yourcompany.com/example_item/10/success_page
    failure_redirect_url
    optional
    string url that end user will be redirected to upon expireation of invoice created by this recurring payment.
    example : https://<span></span>yourcompany.com/example_item/10/failed_checkout
    invoice_duration
    optional
    number duration of time that end user have in order to pay the invoice before it's expired (in Second).

    invoice_duration should and will always be less than the interval-interval_count combination.
    created An ISO timestamp that tracks when the recurring payment was created
    updated An ISO timestamp that tracks when the recurring payment was updated
    charge_immediately
    optional

    boolean A flag showing should the first invoice created immediately when creating recurring payment with a valid start_date
    recharge When this parameter is true, it means you want to enable auto-charged and capture card information through XenInvoice.
    payment_method_id the payment_method_id assigned to this recurring payment
    currency
    optional

    string Currency of the amount that you created

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    INVALID_CREDIT_CARD_TOKEN_ERROR
    400
    Credit Card token is invalid.
    INVALID_PAYMENT_METHOD_ID_ERROR
    400
    Payment method id is invalid.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    UNSUPPORTED_CURRENCY
    400
    The currency is not configured yet in the settings, please contact us.

    Get a Recurring Payment

    Endpoint: Get a Recurring Payment

    GET https://api.xendit.co/recurring_payments/{id}

    Request Parameters

    Example Get Recurring Payment Request

    curl https://api.xendit.co/recurring_payments/{id} \
      -X GET \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '579c8d61f23fa4ca35e52da3';
    
      $getRecurring = \Xendit\Recurring::retrieve($id);
      var_dump($getRecurring);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RecurringPayment } = x;
    const rpSpecificOptions = {};
    const rp = new RecurringPayment(rpSpecificOptions);
    
    const resp = await rp.getPayment({ id: '579c8d61f23fa4ca35e52da3' });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      RecurringPayment recurringPayment = RecurringPayment.get("EXAMPLE_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    getData := recurringpayment.GetParams{
      ID: "579c8d61f23fa4ca35e52da3",
    }
    
    resp, err := recurringpayment.Get(&getData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("retrieved recurring payment: %+v\n", resp)
    Path Parameter Type Description
    id
    required
    string ID of the recurring payment to retrieve

    Response Parameters

    Example Get Recurring Payment Response

    {
        "id": "579c8d61f23fa4ca35e52da3",
        "user_id": "5781d19b2e2385880609791c",
        "external_id": "recurring_31451441",
        "status": "ACTIVE",
        "amount": 125000,
        "payer_email": "sample_email@xendit.co",
        "description": "Monthly room cleaning service",
        "interval": "MONTH",
        "interval_count": 1,
        "recurrence_progress": 1,
        "should_send_email": true,
        "missed_payment_action": "IGNORE",
        "last_created_invoice_url": "https://invoice-staging.xendit.co/web/invoices/5dddeea6bdb99f4b23e5eef7",
        "created": "2017-06-12T14:00:00.306Z",
        "updated": "2018-06-12T14:00:00.306Z",
        "start_date": "2017-07-12T14:00:00.306Z",
        "recharge":true
    }
    Parameter Type Description
    id An recurring ID generated by Xendit
    user_id Your Xendit Business ID
    external_id The recurring ID in your server, that can be used to reconcile between you and Xendit
    status ACTIVE the recurring payment is currently active
    STOPPED the recurring payment has been stopped
    PAUSED the recurring payment is currently paused and will not automatically creating invoices. resume to reactivate
    amount Nominal amount of the recurring payment
    payer_email Email of the payer, we get this information from your API call
    description Description for the recurring payment and invoices
    should_send_email A flag showing should payer get email when invoice is created, paid, or expired; or not
    interval One of DAY, WEEK, MONTH. The frequency with which a recurring payment invoice should be billed.
    interval_count number The number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months.
    total_recurrence The number of times you will charge your customer. If you input it as 3, Xendit will charge your customer 3 times. If you input total_recurrence as 3, interval_count as 1 and interval as "DAY", Xendit will charge customer 3 times in first day after you trigger create recurring api, the day after and 2 days after you trigger create recurring api.
    recurrence_progress The current cycle of recurring payment. If your end customer is on the 4th cycle of the recurring, you will get 4 from recurrence_progress response
    last_created_invoice_url url leading to the last invoice create by this recurring payment
    credit_card_token Token ID for credit card autocharge. If it's empty then the autocharge is disabled. This token must be multiple use (is_multiple_use is true). please refer invoice callback on how to create multi-use token. The token will still be there even if it's failed to charge.
    success_redirect_url
    optional
    string url that end user will be redirected to upon successful payment to invoice created by this recurring payment.
    example : https://<span></span>yourcompany.com/example_item/10/success_page
    failure_redirect_url
    optional
    string url that end user will be redirected to upon expireation of invoice created by this recurring payment.
    example : https://<span></span>yourcompany.com/example_item/10/failed_checkout
    invoice_duration
    optional
    number duration of time that end user have in order to pay the invoice before it's expired (in Second).
    created An ISO timestamp that tracks when the recurring payment was created
    updated An ISO timestamp that tracks when the recurring payment was updated
    charge_immediately
    optional

    boolean A flag showing should the first invoice created immediately when creating recurring payment with a valid start_date
    recharge When this parameter is true, it means you want to enable auto-charged and capture card information through XenInvoice.

    Error Codes

    Error Code Description
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    NOT_FOUND_ERROR
    404
    Could not find recurring by id.

    Edit Recurring Payment

    Endpoint: Edit Recurring Payment

    PATCH https://api.xendit.co/recurring_payments/{id}

    Request Parameters

    Example: Edit Recurring Payment Request

    curl https://api.xendit.co/recurring_payments/579c8d61f23fa4ca35e52da3 \
       -X PATCH \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d amount=80000 \
       -d interval=WEEK \
       -d interval_count=2 \
       -d should_send_email=true \
       -d missed_payment_action=STOP \
       -d credit_card_token=522f0ba2ab70de5d2b409eee \
    
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '579c8d61f23fa4ca35e52da3';
      $params = ['amount' => 80000];
    
      $editRecurring = \Xendit\Recurring::update($id, $params);
      var_dump($editRecurring);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RecurringPayment } = x;
    const rpSpecificOptions = {};
    const rp = new RecurringPayment(rpSpecificOptions);
    
    const resp = await rp.editPayment({
      id: '579c8d61f23fa4ca35e52da3',
      amount: 80000,
      interval: RecurringPayment.Interval.Week,
      intervalCount: 2,
      shouldSendEmail: true,
      missedPaymentAction: RecurringPayment.Action.Stop,
      creditCardToken: '522f0ba2ab70de5d2b409eee',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Map<String, Object> params = new HashMap<>();
      params.put("amount", 80000);
      params.put("interval", "WEEK");
    
      RecurringPayment recurringPayment = RecurringPayment.edit("EXAMPLE_ID", params);
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    editData := recurringpayment.EditParams{
      ID:            "579c8d61f23fa4ca35e52da3",
      Amount:        80000,
      Interval:      xendit.RecurringPaymentIntervalWeek,
      IntervalCount: 2,
    }
    
    resp, err := recurringpayment.Edit(&editData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("edited recurring payment: %+v\n", resp)
    Path Parameter Type Description
    id
    required
    string id of recurring you want to update
    Body Parameter Type Description
    amount
    optional
    number Edit amount per invoice per interval.
    The minimum amount to create an invoice is 10.000 IDR. The maximum amount is 1.000.000.000 IDR<
    credit_card_token
    optional
    string Multi use token ID for credit card autocharge. If it's empty then the autocharge is disabled. The token will still be there even if it's failed to charge
    interval
    optional
    string Edit the frequency with which a recurring payment invoice should be billed. One of DAY, WEEK, MONTH.
    interval_count
    optional
    number Edit the number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months.
    should_send_email
    optional
    boolean Edit whether the end user get email when invoice is created, paid, or expired; or not
    invoice_duration
    optional
    number duration of time that end user have in order to pay the invoice before it's expired (in Second). If it's not filled, invoice_duration will follow your business default invoice duration.

    invoice_duration should and will always be less than the interval-interval_count combination.
    missed_payment_action
    optional
    string Edit action if there is an invoice from a recurring payment that expired, IGNORE will continue with the recurring payment as usual. STOP will stop the recurring payment.
    payment_method_id
    optional
    string Fill this with the payment method id created for the customer
    customer_id
    optional

    string fill this with customer id that you want to assign the recurring payment to

    Response Parameters

    Example: Edit Recurring Payment Response

    {
        "id": "579c8d61f23fa4ca35e52da3",
        "user_id": "5781d19b2e2385880609791c",
        "external_id": "recurring_31451441",
        "status": "ACTIVE",
        "amount": 80000,
        "payer_email": "sample_email@xendit.co",
        "description": "Monthly room cleaning service",
        "interval": "WEEK",
        "interval_count": 2,
        "recurrence_progress": 1,
        "should_send_email": true,
        "recharge": true,
        "missed_payment_action": "STOP",
        "created": "2017-06-12T14:00:00.306Z",
        "updated": "2017-06-12T14:00:00.306Z",
        "start_date": "2017-06-19T14:00:00.306Z"
    }

    All response parameters will be the same as get recurring

    Error Codes

    Error Code Description
    NOT_FOUND_ERROR
    404
    Could not find recurring by id.
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    INVALID_CREDIT_CARD_TOKEN_ERROR
    400
    Credit card token is invalid.
    INVALID_PAYMENT_METHOD_ID_ERROR
    400
    Payment method id is invalid.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Stop Recurring Payment

    Endpoint: Stop Recurring

    POST https://api.xendit.co/recurring_payments/{id}/stop!

    Request Parameters

    Example: Stop Recurring Payment Request

    curl https://api.xendit.co/recurring_payments/{id}/stop! -X POST \
        -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '579c8d61f23fa4ca35e52da3';
    
      $stopRecurring = \Xendit\Recurring::stop($id);
      var_dump($stopRecurring);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RecurringPayment } = x;
    const rpSpecificOptions = {};
    const rp = new RecurringPayment(rpSpecificOptions);
    
    const resp = await rp.stopPayment({ id: '579c8d61f23fa4ca35e52da3' });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      RecurringPayment recurringPayment = RecurringPayment.stop("EXAMPLE_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    stopData := recurringpayment.StopParams{
      ID: "579c8d61f23fa4ca35e52da3",
    }
    
    resp, err := recurringpayment.Stop(&stopData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("stopped recurring payment: %+v\n", resp)
    Path Parameter Type Description
    id
    required
    string ID of the recurring payment to stop

    Response Parameters

    Example: Stop Recurring Payment Response

    {
        "id": "579c8d61f23fa4ca35e52da3",
        "user_id": "5781d19b2e2385880609791c",
        "external_id": "recurring_31451441",
        "status": "STOPPED",
        "amount": 125000,
        "payer_email": "sample_email@xendit.co",
        "description": "Monthly room cleaning service",
        "interval": "MONTH",
        "interval_count": 1,
        "recurrence_progress": 1,
        "should_send_email": true,
        "missed_payment_action": "IGNORE",
        "recharge": true,
        "created": "2017-06-12T14:00:00.306Z",
        "updated": "2018-06-12T14:00:00.306Z",
        "start_date": "2017-07-12T14:00:00.306Z"
    }

    All response parameters will be the same as get recurring

    Error Codes

    Error Code Description
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    NOT_FOUND_ERROR
    404
    Could not find recurring by id.

    Pause Recurring Payment

    Endpoint: Pause Recurring Payment

    POST https://api.xendit.co/recurring_payments/{id}/pause!

    Request Parameters

    Example Pause Recurring Payment Request

    curl https://api.xendit.co/recurring_payments/{id}/pause!
      -X POST \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '579c8d61f23fa4ca35e52da3';
    
      $pauseRecurring = \Xendit\Recurring::pause($id);
      var_dump($pauseRecurring);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RecurringPayment } = x;
    const rpSpecificOptions = {};
    const rp = new RecurringPayment(rpSpecificOptions);
    
    const resp = await rp.pausePayment({ id: '579c8d61f23fa4ca35e52da3' });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      RecurringPayment recurringPayment = RecurringPayment.pause("EXAMPLE_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    pauseData := recurringpayment.PauseParams{
      ID: "579c8d61f23fa4ca35e52da3",
    }
    
    resp, err := recurringpayment.Pause(&pauseData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("paused recurring payment: %+v\n", resp)
    Path Parameter Type Description
    id
    required
    string ID of the recurring payment to pause

    Response Parameters

    Example Pause Recurring Response

    {
        "id": "579c8d61f23fa4ca35e52da3",
        "user_id": "5781d19b2e2385880609791c",
        "external_id": "recurring_31451441",
        "status": "PAUSED",
        "amount": 125000,
        "payer_email": "sample_email@xendit.co",
        "description": "Monthly room cleaning service",
        "interval": "MONTH",
        "interval_count": 1,
        "recurrence_progress": 1,
        "should_send_email": true,
        "recharge": true,
        "missed_payment_action": "IGNORE",
        "created": "2017-06-12T14:00:00.306Z",
        "updated": "2018-06-12T14:00:00.306Z",
        "start_date": "2017-07-12T14:00:00.306Z"
    }

    All response parameters will be the same as get recurring

    Error Codes

    Error Code Description
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    NOT_FOUND_ERROR
    404
    Could not find recurring by id.

    Resume Recurring Payment

    Endpoint: Resume Recurring

    POST https://api.xendit.co/recurring_payments/{id}/resume!

    Request Parameters

    Example Resume Recurring Request

    curl https://api.xendit.co/recurring_payments/{id}/resume!
      -X POST \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '579c8d61f23fa4ca35e52da3';
    
      $resumeRecurring = \Xendit\Recurring::resume($id);
      var_dump($resumeRecurring);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { RecurringPayment } = x;
    const rpSpecificOptions = {};
    const rp = new RecurringPayment(rpSpecificOptions);
    
    const resp = await rp.resumePayment({ id: '579c8d61f23fa4ca35e52da3' });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      RecurringPayment recurringPayment = RecurringPayment.resume("579c8d61f23fa4ca35e52da3");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    resumeData := recurringpayment.ResumeParams{
      ID: "579c8d61f23fa4ca35e52da3",
    }
    
    resp, err := recurringpayment.Resume(&resumeData)
    if err != nil {
      log.Fatal(err)
    }
    fmt.Printf("resumed recurring payment: %+v\n", resp)
    Path Parameter Type Description
    id
    required
    string ID of the recurring payment to resume

    Response Parameters

    Example Resume Recurring Response

    {
        "id": "579c8d61f23fa4ca35e52da3",
        "user_id": "5781d19b2e2385880609791c",
        "external_id": "recurring_31451441",
        "status": "ACTIVE",
        "amount": 125000,
        "payer_email": "sample_email@xendit.co",
        "description": "Monthly room cleaning service",
        "interval": "MONTH",
        "interval_count": 1,
        "recurrence_progress": 1,
        "should_send_email": true,
        "missed_payment_action": "IGNORE",
        "recharge": true,
        "created": "2017-06-12T14:00:00.306Z",
        "updated": "2018-06-12T14:00:00.306Z",
        "start_date": "2017-07-12T14:00:00.306Z"
    }

    All response parameters will be the same as get recurring

    Error Codes

    Error Code Description
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    NOT_FOUND_ERROR
    404
    Could not find recurring by id.

    Recurring Callback

    Xendit will notify you of all Recurring Payment Invoice activity via the usual invoice callback. Please visit invoice callback to get more information about setting up your callback URL and getting invoice callbacks.

    Additional parameters from invoice callback if you are using recurring payments:

    Parameter Type Description
    recurring_payment_id string ID of the recurring payment for this invoice

    Get List of Payments

    Getting list of the payments can be done by searching invoices with certain recurring_payment_id and it can be done using List all invoices.

    Additional parameters from listing all invoice if you are using recurring payments:

    Request Parameters

    Parameter Type Description
    recurring_payment_id string ID of the recurring payment for this invoice

    Payouts

    Easily send funds to customers with our payouts UI, allowing them to choose their payout destination.

    Create Payout

    Endpoint: Create Payouts

    POST https://api.xendit.co/payouts

    Request Parameters

    Example Create Payout Request

    curl https://api.xendit.co/payouts -X POST \
    -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
    -d external_id=demo_2392329329 \
    -d amount=23000 \
    -d email=demo@xendit.co
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $params = [
        'external_id' => 'demo_2392329329',
        'amount' => 23000
      ];
    
      $createPayout = \Xendit\Payouts::create($params);
      var_dump($createPayout);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Payout } = x;
    const payoutSpecificOptions = {};
    const p = new Payout(payoutSpecificOptions);
    
    const resp = await p.createPayout({
      externalID: 'demo_2392329329',
      amount: 23000,
      email: 'demo@xendit.co'
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Map<String, Object> params = new HashMap<>();
      params.put("external_id", "demo_2392329329");
      params.put("amount", 23000);
      params.put("email", "demo@xendit.co");
    
      Payout payout = Payout.createPayout(params);
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    createData := payout.CreateParams{
      ExternalID: "demo_2392329329",
      Amount:     23000,
      Email: "test@email.com",
    }
    
    resp, err := payout.Create(&createData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created payout: %+v\n", resp)
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    external_id
    required
    string ID of your choice (typically the unique identifier of a payout in your system).

    Maximum: 200 characters
    amount
    required
    integer positive Amount to be paid out. The maximum amount depends on your balance.
    email
    required
    string An email address of the end user you're sending payout to.

    Response Parameters

    Example Create Payout Response

    {
      "id": "67f1b30c-0262-4955-8777-95aa0478c2fc",
      "external_id": "demo_2392329329",
      "amount": 23000,
      "merchant_name": "First Business",
      "status": "PENDING",
      "expiration_timestamp": "2019-12-10T06:13:21.637Z",
      "created": "2019-12-09T06:13:20.363Z",
      "payout_url": "https://payout.xendit.co/web/67f1b30c-0262-4955-8777-95aa0478c2fc"
    }
    Parameter Type Description
    id
    required
    string A payout ID generated by Xendit
    external_id
    required
    string The payout ID in your server, that can be used to reconcile between you and Xendit.

    Maximum: 200 characters
    amount
    required
    integer positive Amount to be paid out. The maximum amount depends on your balance.
    merchant_name
    optional
    string The name of your company or website.
    status
    required
    string PENDING The payout has successfully been created and is awaiting the end user’s response
    VOIDED The payout has been voided. This issue is raised because the payout has been expired or manually voided by hitting the void endpoint.
    COMPLETED The payout has completed.
    FAILED The payout has failed. The list of failures are described in the failure_reason field.
    expiration_timestamp
    optional
    ISO8601 An ISO timestamp that the payout expires. Default is 24 hours after creation.

    Timezone: GMT+0
    created
    optional
    ISO8601 An ISO timestamp that tracks when the payout was created.

    Timezone: GMT+0
    payout_url
    optional
    string Public URL for this payout, in case you want to use our UI.
    email
    optional
    string An email address of the end user you're sending payout to.
    bank_code
    optional
    string Bank code for the relevant bank, learn more here
    account_holder_name
    optional
    string Bank account holder name.
    account_number
    optional
    string Bank account number.
    disbursement_id
    optional
    string ID of the disbursement. You can find out here
    failure_reason
    optional
    string If the status is FAILED, this describes the failure.
    claimed_timestamp
    optional
    ISO8601 An ISO timestamp that tracks when the payout was claimed.

    Timezone: GMT+0
    completed_timestamp
    optional
    ISO8601 An ISO timestamp that tracks when the payout was completed.

    Timezone: GMT+0
    failed_timestamp
    optional
    ISO8601 An ISO timestamp that tracks when the payout was failed.

    Timezone: GMT+0
    payment_id
    optional
    string Our internal system’s payment ID that can be used as payment reference.

    Error Codes

    Error Code Description
    INSUFFICIENT_BALANCE
    400
    The balance in your account is insufficient to make the payout in the desired amount.
    DUPLICATE_PAYOUT_ERROR
    400
    The payout with the same external_id has already been made before.
    UNAUTHORIZED_MERCHANT_ERROR
    403
    This merchant is not authorized to perform this request.

    Get Payout

    Endpoint: Get a Payout

    GET https://api.xendit.co/payouts/:id

    Request Parameters

    Example Get Payout Request

    curl https://api.xendit.co/payouts/:id -X GET \
        -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '00754a09-ad00-4475-b874-1dd97f83fc24';
    
      $getPayout = \Xendit\Payouts::retrieve($id);
      var_dump($getPayout);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Payout } = x;
    const payoutSpecificOptions = {};
    const p = new Payout(payoutSpecificOptions);
    
    const resp = await p.getPayout({
        id: '67f1b30c-0262-4955-8777-95aa0478c2fc',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Payout payout = Payout.getPayout("my_test_id");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    resp, err := payout.Get(&payout.GetParams{
      ID: "00754a09-ad00-4475-b874-1dd97f83fc24",
    })
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("retrieved payout: %+v\n", resp)
    Parameter Type Description
    id
    required
    string ID of the payout to retrieve

    Response Parameters

    Example Get Payout Response

    {
      "id": "00754a09-ad00-4475-b874-1dd97f83fc24",
      "external_id": "ext-121313",
      "amount": 20000,
      "merchant_name": "First Business",
      "status": "PENDING",
      "expiration_timestamp": "2019-12-10T06:45:30.041Z",
      "created": "2019-12-09T06:45:28.628Z",
      "payout_url": "https://payout.xendit.co/web/00754a09-ad00-4475-b874-1dd97f83fc24"
    }
    Parameter Type Description
    id
    required
    string A payout ID generated by Xendit
    external_id
    required
    string The payout ID in your server, that can be used to reconcile between you and Xendit.

    Maximum: 200 characters
    amount
    required
    integer positive Amount to be paid out. The maximum amount depends on your balance.
    merchant_name
    optional
    string The name of your company or website.
    status
    required
    string PENDING The payout has successfully been created and is awaiting the end user’s response
    VOIDED The payout has been voided. This issue is raised because the payout has been expired or manually voided by hitting the void endpoint.
    COMPLETED The payout has completed.
    FAILED The payout has failed. The list of failures are described in the failure_reason field.
    expiration_timestamp
    optional
    ISO8601 An ISO timestamp that the payout expires. Default is 24 hours after creation.

    Timezone: GMT+0
    created
    optional
    ISO8601 An ISO timestamp that tracks when the payout was created.

    Timezone: GMT+0
    payout_url
    optional
    string Public URL for this payout, in case you want to use our UI.
    email
    optional
    string An email address of the end user you're sending payout to.
    bank_code
    optional
    string Bank code for the relevant bank, learn more here
    account_holder_name
    optional
    string Bank account holder name.
    account_number
    optional
    string Bank account number.
    disbursement_id
    optional
    string ID of the disbursement. You can find out here
    failure_reason
    optional
    string If the status is FAILED, this describes the failure.
    claimed_timestamp
    optional
    ISO8601 An ISO timestamp that tracks when the payout was claimed.

    Timezone: GMT+0
    completed_timestamp
    optional
    ISO8601 An ISO timestamp that tracks when the payout was completed.

    Timezone: GMT+0
    failed_timestamp
    optional
    ISO8601 An ISO timestamp that tracks when the payout was failed.

    Timezone: GMT+0
    payment_id
    optional
    string Our internal system’s payment ID that can be used as payment reference.
    </tr>

    Error Codes

    Error Code Description
    PAYOUT_NOT_FOUND_ERROR
    404
    The payout was not found in the system.
    UNAUTHORIZED_MERCHANT_ERROR
    403
    This merchant is not authorized to perform this request.

    Void a Payout

    Endpoint: Void a Payout

    POST https://api.xendit.co/payouts/:id/void

    You can cancel a pending payout by voiding it using this endpoint.

    Request Parameters

    Example Void Payout Request

    curl https://api.xendit.co/payouts/:id/void -X POST \
        -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '00754a09-ad00-4475-b874-1dd97f83fc24';
    
      $voidPayout = \Xendit\Payouts::void($id);
      var_dump($voidPayout);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Payout } = x;
    const payoutSpecificOptions = {};
    const p = new Payout(payoutSpecificOptions);
    
    const resp = await p.voidPayout({
        id: '67f1b30c-0262-4955-8777-95aa0478c2fc',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Payout payout = Payout.voidPayout("EXAMPLE_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    resp, err := payout.Void(&payout.VoidParams{
      ID: "00754a09-ad00-4475-b874-1dd97f83fc24",
    })
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("voided payout: %+v\n", resp)
    Parameter Type Description
    id
    required
    string ID of the payout to retrieve

    Void Payout Response

    Example Void Payout Response

    {
      "id": "00754a09-ad00-4475-b874-1dd97f83fc24",
      "external_id": "ext-121312",
      "amount": 20000,
      "merchant_name": "First Business",
      "status": "VOIDED",
      "expiration_timestamp": "2019-12-10T06:45:30.041Z",
      "created": "2019-12-09T06:45:28.628Z"
    }
    Parameter Type Description
    id
    required
    string A payout ID generated by Xendit
    external_id
    required
    string The payout ID in your server, that can be used to reconcile between you and Xendit.

    Maximum: 200 characters
    amount
    required
    integer positive Amount to be paid out. The maximum amount depends on your balance.
    merchant_name
    optional
    string The name of your company or website.
    status
    required
    string PENDING The payout has successfully been created and is awaiting the end user’s response
    VOIDED The payout has been voided. This issue is raised because the payout has been expired or manually voided by hitting the void endpoint.
    COMPLETED The payout has completed.
    FAILED The payout has failed. The list of failures are described in the failure_reason field.
    expiration_timestamp
    optional
    ISO8601 An ISO timestamp that the payout expires. Default is 24 hours after creation.

    Timezone: GMT+0
    created
    optional
    ISO8601 An ISO timestamp that tracks when the payout was created.

    Timezone: GMT+0
    payout_url
    optional
    string Public URL for this payout, in case you want to use our UI.
    email
    optional
    string An email address of the end user you're sending payout to.
    bank_code
    optional
    string Bank code for the relevant bank, learn more here
    account_holder_name
    optional
    string Bank account holder name.
    account_number
    optional
    string Bank account number.
    disbursement_id
    optional
    string ID of the disbursement. You can find out here
    failure_reason
    optional
    string If the status is FAILED, this describes the failure.
    claimed_timestamp
    optional
    ISO8601 An ISO timestamp that tracks when the payout was claimed.

    Timezone: GMT+0
    completed_timestamp
    optional
    ISO8601 An ISO timestamp that tracks when the payout was completed.

    Timezone: GMT+0
    failed_timestamp
    optional
    ISO8601 An ISO timestamp that tracks when the payout was failed.

    Timezone: GMT+0
    payment_id
    optional
    string Our internal system’s payment ID that can be used as payment reference.

    Void Payout Failure Reason

    Error Code Description
    PAYOUT_NOT_FOUND_ERROR
    404
    The payout was not found in the system.
    UNAUTHORIZED_MERCHANT_ERROR
    403
    This merchant is not authorized to perform this request.

    Disbursements

    Disbursements allow you to instruct Xendit to instantly send money to any bank account across Indonesia on your behalf.

    Create Disbursement

    Endpoint: Create Disbursement

    POST https://api.xendit.co/disbursements

    Request Parameters

    Example Create Disbursement Request

    curl https://api.xendit.co/disbursements -X POST \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
      -d external_id=demo_1475459775872 \
      -d amount=17000 \
      -d bank_code=BCA \
      -d account_holder_name='Bob Jones' \
      -d account_number=1231241231 \
      -d description='Reimbursement for shoes'
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $params = [
        'external_id' => '12345',
        'amount' => 1000,
        'bank_code' => 'BCA',
        'account_holder_name' => 'RAIDY WIJAYA',
        'account_number' => '1234567890',
        'description' => 'Disbursement from Example',
        'X-IDEMPOTENCY-KEY' => 'unique-id'
      ];
    
      $createDisbursements = \Xendit\Disbursements::create($params);
      var_dump($createDisbursements);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Disbursement } = x;
    const disbursementSpecificOptions = {};
    const d = new Disbursement(disbursementSpecificOptions);
    
    const resp = await d.create({
      externalID: 'demo_1475459775872',
      amount: 17000,
      bankCode: 'BCA',
      accountHolderName: 'Bob Jones',
      accountNumber: '123124231',
      description: 'Reimbursement for shoes',
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Map<String, Object> params = new HashMap<>();
      params.put("external_id", "demo_1475459775872");
      params.put("bank_code", "BCA");
      params.put("account_holder_name", "Bob Jones");
      params.put("account_number", "123124231");
      params.put("description", "Reimbursement for shoes");
      params.put("amount", "17000");
    
      Disbursement disbursement = Disbursement.create(params);
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    createData := disbursement.CreateParams{
      IdempotencyKey:    "disbursement" + time.Now().String(),
      ExternalID:        "12345",
      BankCode:          "BCA",
      AccountHolderName: "RAIDY WIJAYA",
      AccountNumber:     "1234567890",
      Description:       "Disbursement from Go",
      Amount:            1000,
    }
    
    resp, err := disbursement.Create(&createData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created disbursement: %+v\n", resp)
    Header Parameter Type Description
    X-IDEMPOTENCY-KEY
    optional
    string A unique key to prevent processing duplicate requests. Can be your external_id or any GUID. Must be unique across development & production environments.

    Characters Special and alphanumeric
    Maximum length No maximum characters
    Minimum length 1 character
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    external_id
    required
    string ID of the disbursement in your system, used to reconcile disbursements after they have been completed.

    Characters Special and alphanumeric
    Maximum length 1000 maximum characters
    Minimum length 1 character
    bank_code
    required
    string Code of the destination bank

    The bank code must match the bank codes here precisely
    account_holder_name
    required
    string Name of account holder as per the bank's or e-wallet's records. Used for verification and error/customer support scenarios.

    Characters Special and alphanumeric
    Maximum length No maximum characters
    Minimum length 1 character
    account_number
    required
    string Destination bank account number. If disbursing to an e-wallet, phone number registered with the e-wallet account.

    Characters Numeric and hyphens
    BCA required length 10 characters
    Other banks maximum length No maximum characters
    Other banks minimum length 1 character
    E-wallets Phone number registered with the e-wallet (Example: 0812XXXXXX)

    *** We support disbursements to virtual accounts of major banks (BRI, BNI, Mandiri, CIMB Niaga, Permata, BTN, and NOBU Bank).
    *** We support disbursements to major e-wallets (GoPay, OVO, and Mandiri e-cash).

    description
    required
    string Description to send with the disbursement

    Characters Special and alphanumeric
    Maximum length No maximum characters
    Minimum length 1 character
    amount
    required
    number Amount to disburse

    Characters Numerical integers, no decimals
    Maximum limit (BCA, Mandiri, BNI, BNI Syariah, BRI, Permata) No limit***
    Minimum limit (BCA, Mandiri, BNI, BNI Syariah, BRI, Permata) No limit
    Maximum limit (Other bank) Rp 50.000.000
    Minimum limit (Other bank) Rp 10.000

    *** While there is theoretically no maximum transfer limit for transfers to these banks, please note that we may have to report all transaction amounts above Rp 100.000.000 to the financial authorities in Indonesia along with supporting documentation regarding the underlying transactions.

    email_to
    optional
    string[] Email addresses that get notified of disbursement details after the disbursement is completed.
    Maximum 3 email addresses accepted.
    email_cc
    optional
    string[] Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
    Maximum 3 email addresses accepted.
    Only allowed if email_to provided.
    email_bcc
    optional
    string[] Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
    Maximum 3 email addresses accepted.
    Only allowed if email_to provided.

    Response Parameters

    Example Create Disbursement Response

    {
      "user_id": "5785e6334d7b410667d355c4",
      "external_id": "12345",
      "amount": 1000,
      "bank_code": "BCA",
      "account_holder_name": "RAIDY WIJAYA",
      "disbursement_description": "Refunds for shoes",
      "status": "PENDING",
      "id": "57f1ce05bb1a631a65eee662",
      "email_to": ["test+to1@xendit.co","test+to2@xendit.co"],
      "email_cc": ["test+bcc@xendit.co"],
      "email_bcc": ["test+bcc@xendit.co"]
    }
    Parameter Type Description
    user_id
    required
    string Your Xendit Business ID
    external_id
    required
    string Custom ID of your choice to identify the transaction. Our customers often use a phone number, email address, or transaction/order ID
    amount
    required
    number Amount to disburse
    bank_code
    required
    string Bank code of destination bank or e-wallet. See bank codes
    account_holder_name
    required
    string Name of account holder as per the bank's or e-wallet’s records. Used for verification and error/customer support scenarios
    disbursement_description
    required
    This is the description you give us :)
    status
    required
    string
    PENDING Transfer is initiated but not yet completed by bank.
    id
    required
    string Unique disbursement ID
    email_to
    optional
    string[] Email addresses that get notified of disbursement details after the disbursement is completed.
    This response parameter is only returned if this field is filled.
    email_cc
    optional
    string[] Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
    This response parameter is only returned if this field is filled.
    email_bcc
    optional
    string[] Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
    This response parameter is only returned if this field is filled.

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs are failing validation. The errors field contains details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    DISBURSEMENT_DESCRIPTION_NOT_FOUND_ERROR
    400
    Disbursement description is not set in Settings > Sending Money > Disbursements. Add a default description before retrying.
    DIRECT_DISBURSEMENT_BALANCE_INSUFFICIENT_ERROR
    400
    Not enough balance to disburse. Add more balance before retrying.
    DUPLICATE_TRANSACTION_ERROR
    400
    Idempotency key has been used before. Use a unique idempotency key and try again.
    BANK_CODE_NOT_SUPPORTED_ERROR
    400
    Destination bank code is not supported.
    RECIPIENT_ACCOUNT_NUMBER_ERROR
    400
    For transfers to BCA, account_number input needs to be 10 digits. Check the account number length before retrying.
    RECIPIENT_AMOUNT_ERROR
    400
    The transfer amount requested is lower than the prescribed minimum for the chosen destination bank. Amend the transfer amount before retrying.
    MAXIMUM_TRANSFER_LIMIT_ERROR
    400
    The transfer amount requested is higher than the prescribed maximum for the chosen destination bank. Amend the transfer amount before retrying.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    SERVER_ERROR
    500
    Error connecting to our server. Please use Get disbursement by external_id API to check whether the disbursement has already been created. If you receive DIRECT_DISBURSEMENT_NOT_FOUND_ERROR, the disbursement has not been created; please retry the disbursement request in 1-2 hours.

    Get Disbursement by ID

    Endpoint: Get Disbursement by id

    GET https://api.xendit.co/disbursements/{disbursement_id}

    This endpoint queries the current status of a disbursement. This is often used for checking the status of a transaction.

    Request Parameters

    Example Get Disbursement Request

    curl https://api.xendit.co/disbursements/57c9010f5ef9e7077bcb96b6 -X GET \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $id = '57c9010f5ef9e7077bcb96b6';
      $getDisbursements = \Xendit\Disbursements::retrieve($id);
      var_dump($getDisbursements);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Disbursement } = x;
    const disbursementSpecificOptions = {};
    const d = new Disbursement(disbursementSpecificOptions);
    
    const resp = await d.getByID({ disbursementID: '587cc7ea77535fb94bb4e8eb' });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Disbursement disbursement = Disbursement.getById("EXAMPLE_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    getByIDData := disbursement.GetByIDParams{
      DisbursementID: "57c9010f5ef9e7077bcb96b6",
    }
    
    resp, err := disbursement.GetByID(&getByIDData)
    if err != nil {
      log.Fatal(err.ErrorCode, err.Message, err.GetStatus())
    }
    
    fmt.Printf("retrieved disbursement: %+v\n", resp)
    Parameter Type Description
    disbursement_id
    required
    string ID of the disbursement to retrieve
    The disbursement_id must match the unique disbursement ID provided in our success response at disbursement creation precisely

    Response Parameters

    Example Get Disbursement Response

    {
      "user_id": "5785e6334d7b410667d355c4",
      "external_id": "disbursement_12345",
      "amount": 500000,
      "bank_code": "BCA",
      "account_holder_name": "Rizky",
      "disbursement_description": "Custom description",
      "status": "PENDING",
      "id": "57c9010f5ef9e7077bcb96b6",
      "email_to": ["test+to1@xendit.co","test+to2@xendit.co"],
      "email_cc": ["test+bcc@xendit.co"],
      "email_bcc": ["test+bcc@xendit.co"]
    }
    Parameter Description
    user_id Your Xendit Business ID
    external_id Custom ID set at disbursement creation. Our customers often use a phone number, email address, or transaction/order ID
    amount Amount to disburse
    bank_code Destination bank code. See bank codes
    account_holder_name Bank account name as per the bank's records. Used for verification and error/customer support scenarios
    disbursement_description This is the description you give us :)
    status PENDING Transfer is initiated.
    COMPLETED Bank has confirmed transmission of funds.
    FAILED Bank rejected disbursement. We will not retry.
    id Unique disbursement ID
    email_to Email addresses that get notified of disbursement details after the disbursement is completed.
    This response parameter is only returned if this field is filled.
    email_cc Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
    This response parameter is only returned if this field is filled.
    email_bcc Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
    This response parameter is only returned if this field is filled.

    Error Codes

    Error Code Description
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    DIRECT_DISBURSEMENT_NOT_FOUND_ERROR
    404
    Could not find direct disbursement.

    Get Disbursements by External ID

    Endpoint: Get Disbursements by External ID

    GET https://api.xendit.co/disbursements?external_id={external_id}

    This endpoint queries the current status of all disbursements with requested external_id. This is often used to check the status of a transaction with external_id.

    Request Parameters

    Example Get Disbursement Request

    curl https://api.xendit.co/disbursements?external_id=72655 -X GET \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $external_id = 'disbursements-ext-id';
      $getDisbursementsByExt = \Xendit\Disbursements::retrieveExternal($external_id);
      var_dump($getDisbursementsByExt);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Disbursement } = x;
    const disbursementSpecificOptions = {};
    const d = new Disbursement(disbursementSpecificOptions);
    
    const resp = await d.getByExtID({ externalID: 'disbursement_12345' });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      Disbursement[] disbursement = Disbursement.getByExternalId("EXAMPLE_ID");
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    getByExternalIDData := disbursement.GetByExternalIDParams{
      ExternalID: "disbursement_12345",
    }
    
    resps, err := disbursement.GetByExternalID(&getByExternalIDData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("retrieved disbursements: %+v\n", resps)
    Query Parameter Type Description
    external_id
    required
    string Custom ID of the disbursement set by the customer at disbursement creation
    The external_id must match the external_id used at disbursement creation precisely

    Response Parameters

    Example Get Disbursement Response

    [{
      "user_id": "5785e6334d7b410667d355c4",
      "external_id": "disbursement_12345",
      "amount": 500000,
      "bank_code": "BCA",
      "account_holder_name": "Rizky",
      "disbursement_description": "Custom description",
      "status": "PENDING",
      "id": "57c9010f5ef9e7077bcb96b6"
    },{
      "user_id": "5785e6334d7b410667d355c4",
      "external_id": "disbursement_12345",
      "amount": 450000,
      "bank_code": "BNI",
      "account_holder_name": "Jajang",
      "disbursement_description": "Custom description",
      "status": "COMPLETED",
      "id": "5a963089fd5fe5b6508f0b7b",
      "email_to": ["test+to1@xendit.co","test+to2@xendit.co"],
      "email_cc": ["test+bcc@xendit.co"],
      "email_bcc": ["test+bcc@xendit.co"]
    }]
    Parameter Description
    user_id Your Xendit Business ID
    external_id Custom ID set at disbursement creation. Our customers often use a phone number, email address, or transaction/order ID
    amount Amount to disburse
    bank_code Destination bank code. See bank codes
    account_holder_name Bank account name as per the bank's records. Used for verification and error/customer support scenarios
    disbursement_description This is the description you give us :)
    status PENDING Transfer is initiated.
    COMPLETED Bank has confirmed transmission of funds.
    FAILED Bank rejected disbursement. We will not retry.
    id Unique disbursement ID
    email_to Email addresses that get notified of disbursement details after the disbursement is completed.
    This response parameter is only returned if this field is filled.
    email_cc Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
    This response parameter is only returned if this field is filled.
    email_bcc Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
    This response parameter is only returned if this field is filled.

    Error Codes

    Error Code Description
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
    DIRECT_DISBURSEMENT_NOT_FOUND_ERROR
    404
    Could not find direct disbursement.

    Disbursement Callback

    Endpoint: Disbursement Callback

    POST https://yourcompany.com/disbursement_callback_url

    When a disbursement transaction is successful, our callback APIs will hit your URL that you already set in dashboard. For further information about callbacks please read these docs.

    This example is only used to show the body parameters that send from Xendit APIs to your callback URL. If you want to test this callback request, use the test feature in dashboard and go to Settings -> Configuration -> Disbursement.

    Request Parameters

    Example Disbursement Callback Request

    curl --include \
         --request POST \
         --header "Content-Type: application/json" \
         --header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n====" \
         --data-binary "{
        \"id\": \"57e214ba82b034c325e84d6e\",
        \"user_id\": \"57c5aa7a36e3b6a709b6e148\",
        \"external_id\": \"disbursement_123124123\",
        \"amount\": 150000,
        \"bank_code\": \"BCA\",
        \"account_holder_name\": \"XENDIT\",
        \"disbursement_description\": \"Xendit disbursement\",
        \"failure_code\": \"INVALID_DESTINATION\",
        \"is_instant\": false,
        \"status\": \"FAILED\",
        \"updated\": \"2016-10-10T08:15:03.404Z\",
        \"created\": \"2016-10-10T08:15:03.404Z\",
        \"email_to\": [\"test+to1@xendit.co\", \"test+to2@xendit.co\"],
        \"email_cc\": [\"test+cc@xendit.co\"],
        \"email_bcc\": [\"test+bcc@xendit.co\"]
    }" \
    'https://yourcompany.com/disbursement_callback_url'
    Parameter Description
    is_instant Indicates whether the disbursement is being disbursed instantly
    user_id Your Xendit Business ID
    external_id Custom ID set at disbursement creation. Our customers often use a phone number, email address, or transaction/order ID
    amount Amount to disburse
    bank_code Destination bank code. See bank codes
    account_holder_name Bank account name as per the bank's records. Used for verification and error/customer support scenarios
    disbursement_description This is the description you give us :)
    status COMPLETED Bank has confirmed transmission of funds.
    FAILED Disbursement failed because of failure code
    failure_code (optional) INSUFFICIENT_BALANCE The balance in your account is insufficient to make the disbursement in the desired amount
    UNKNOWN_BANK_NETWORK_ERROR The bank networks have returned an unknown error to us. We are unable to predict whether the disbursement will succeed should you retry the same disbursement request.
    TEMPORARY_BANK_NETWORK_ERROR The bank networks are experiencing a temporary error. Please retry the disbursement in 1-3 hours
    INVALID_DESTINATION The banks have reported that the destination account is unregistered or blocked. If unsure about this, please retry again or contact the destination bank directly regarding the status of the destination account
    SWITCHING_NETWORK_ERROR At least one of the switching networks is encountering an issue. Please retry the disbursement in 1-3 hours
    REJECTED_BY_BANK The bank has rejected this transaction for unclear reasons. We are unable to predict whether the disbursement will succeed should you retry the same disbursement request.
    TRANSFER_ERROR We’ve encountered a fatal error while processing this disbursement. Certain API fields in your request may be invalid. Please contact our customer support team for more information
    TEMPORARY_TRANSFER_ERROR We’ve encountered a temporary issue while processing this disbursement. Please retry the disbursement in 1-2 hours

    For detailed information regarding the different error codes above, please see Common Errors in Disbursements.
    id Unique disbursement ID
    email_to Email addresses that get notified of disbursement details after the disbursement is completed.
    This callback parameter is only returned if this field is filled.
    email_cc Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed.
    This callback parameter is only returned if this field is filled.
    email_bcc Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed.
    This callback parameter is only returned if this field is filled.

    Error Codes

    Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.

    Get Available Banks

    Endpoint: Get Available Disbursement Banks

    GET https://api.xendit.co/available_disbursements_banks

    Example Get Available Disbursement Banks Request

    curl https://api.xendit.co/available_disbursements_banks -X GET \
        -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $getDisbursementsBanks = \Xendit\Disbursements::getAvailableBanks();
      var_dump($getDisbursementsBanks);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Disbursement } = x;
    const disbursementSpecificOptions = {};
    const d = new Disbursement(disbursementSpecificOptions);
    
    const resp = await d.getBanks();
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      AvailableBank[] banks = Disbursement.getAvailableBanks();        
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    availableBanks, err := disbursement.GetAvailableBanks()
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("available disbursement banks: %+v\n", availableBanks)

    This API endpoint will provide you the current list of banks we support for disbursements. We support transfers to 140+ banks in Indonesia, including some BPDs and BPRs, and virtual accounts of major banks (BRI, BNI, Mandiri, CIMB Niaga, Permata, BTN, and NOBU Bank). We also support disbursements to major e-wallets (GoPay, OVO, and Mandiri e-cash). If you would like us to support payment to a specific destination, please contact us at support@xendit.co.

    Response Parameters

    Get Available Disbursement Banks Response

    [
      {
        "name": "Bank Mandiri",
        "code": "MANDIRI",
        "can_disburse": true,
        "can_name_validate": true
      },
      {
        "name": "Bank Rakyat Indonesia (BRI)",
        "code": "BRI",
        "can_disburse": true,
        "can_name_validate": true
      },
      {
        "name": "Bank Central Asia (BCA)",
        "code": "BCA",
        "can_disburse": true,
        "can_name_validate": true
      }
    ]
    Parameter Description
    name Full name of the bank or e-wallet
    code Code of the bank or e-wallet you would like to disburse to

    Batch Disbursement

    Batch disbursements (beta) are a set of instructions containing multiple commands to disburse funds to any banks in Indonesia.

    Note: Idempotency can be achieved by sending a header with the key X-IDEMPOTENCY-KEY.

    Create Batch Disbursement

    With this API endpoint you can create multiple disbursements at the same time.

    Endpoint: Create Batch Disbursement

    POST https://api.xendit.co/batch_disbursements

    Request Parameters (Money-out write permission)

    Example Create Batch Disbursement Request

    curl https://api.xendit.co/batch_disbursements -X POST \
      -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
      -H "Content-Type: application/json" \
      -d '{
        "reference": "demo_123",
        "disbursements": [
          {
            "external_id": "demo_123_1",
            "bank_code": "BCA",
            "bank_account_name": "Stanley Nguyen",
            "bank_account_number": "12345678",
            "description": "Reimbursement for pair of shoes (1)",
            "amount": 20000
          }
        ]
      }'
    <?php
    
      use Xendit\Xendit;
      require 'vendor/autoload.php';
    
      Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
    
      $batch_params = [
        'reference' => 'qwerty1234',
        'disbursements' => [
          [
            'amount' => 20000,
            'bank_code' => 'BCA',
            'bank_account_name' => 'Fadlan',
            'bank_account_number' => '1234567890',
            'description' => 'Batch Disbursement',
            'external_id' => 'disbursement-1'
          ],
          [
            'amount' => 10000,
            'bank_code' => 'MANDIRI',
            'bank_account_name' => 'Lutfi',
            'bank_account_number' => '1234567891',
            'description' => 'Batch Disbursement with email notifications',
            'external_id' => 'disbursement-2',
            'email_to' => ['test+to@xendit.co'],
            'email_cc' => ['test+cc@xendit.co'],
            'email_bcc' => ['test+bcc1@xendit.co', 'test+bcc2@xendit.co']
          ]
        ]
      ];
    
      $createBatchDisbursements = \Xendit\Disbursements::createBatch($batch_params);
      var_dump($createBatchDisbursements);
    
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Disbursement } = x;
    const disbursementSpecificOptions = {};
    const d = new Disbursement(disbursementSpecificOptions);
    
    const resp = await d.createBatch({
      reference: 'demo_123',
      disbursements: [
        {
          externalID: 'demo_123_1',
          bankCode: 'BCA',
          accountHolderName: 'Stanley Nguyen',
          accountNumber: '12345678',
          description: 'Reimbursement for pair of shoes (1)',
          amount: 20000,
        }
      ]
    });
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      String emailTo[] = new String[1];
      emailTo[0] = "test@email.com";
    
      String emailCC[] = new String[1];
      emailCC[0] = "test@email.com";
    
      String emailBcc[] = new String[1];
      emailBcc[0] = "test@email.com";
    
      BatchDisbursementItem items[] = new BatchDisbursementItem[1];
    
      BatchDisbursementItem item =
            BatchDisbursementItem.builder()
                .amount(10000)
                .bankCode("ABC")
                .bankAccountName("Lorem Ipsum")
                .bankAccountNumber("1234567890")
                .description("Lorem ipsum dolor sit amet")
                .externalId("test_id")
                .emailTo(emailTo)
                .emailCC(emailCC)
                .emailBcc(emailBcc)
                .build();
    
      items[0] = item;
    
      BatchDisbursement.create(
        "reference", //reference
        items //BatchDisbursementItem []
      );
    
    } catch (XenditException e) {
      e.printStackTrace();
    }
    xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
    
    createBatchData := disbursement.CreateBatchParams{
      Reference: "batch_disbursement" + time.Now().String(),
      Disbursements: []disbursement.DisbursementItem{
        {
          Amount:            200000,
          BankCode:          "BNI",
          BankAccountName:   "Michael Jackson",
          BankAccountNumber: "1234567890",
          Description:       "Batch disbursement from Go",
        },
        {
          Amount:            100000,
          BankCode:          "BRI",
          BankAccountName:   "Michael Jackson",
          BankAccountNumber: "1234567890",
          Description:       "Batch disbursement from Go 2",
        },
      },
    }
    
    batchDisbursementResp, err := disbursement.CreateBatch(&createBatchData)
    if err != nil {
      log.Fatal(err)
    }
    
    fmt.Printf("created batch disbursement: %+v\n", batchDisbursementResp)
    Header Parameter Type Description
    X-IDEMPOTENCY-KEY
    optional
    string A unique key to prevent processing duplicate requests. Can be your external_id or any GUID. Must be unique across development & production environments.
    for-user-id
    optional
    string The sub-account user-id that you want to make this transaction for.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Body Parameter Type Description
    reference
    required
    string ID of the batch disbursement in your system, used to reconcile disbursements after they have been completed
    disbursements
    required
    Disbursement Item[] List of disbursements in the batch

    Disbursement Item

    Parameter Type Description
    amount
    required
    number Amount to disburse
    bank_code
    required
    string Code of the receiving bank
    bank_account_name
    required
    string Receiving bank account holder name
    bank_account_number
    required
    string Receiving bank account number
    description
    required
    string Description to accompany the disbursement
    external_id
    optional
    string ID of disbursement in your system
    email_to
    optional
    string[] Email addresses that get notified of disbursement details after the disbursement is completed
    email_cc
    optional
    string[] Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed
    email_bcc
    optional
    string[] Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed

    Response Parameters

    Example Create Batch Disbursement Response

    {
      "created": "2017-03-30T06:12:47.212Z",
      "reference": "qwerty1234",
      "total_uploaded_amount": 30000,
      "total_uploaded_count": 2,
      "status": "NEEDS_APPROVAL",
      "id": "58dca1dffee4228917d37336"
    }
    Parameter Type Description
    created
    required
    string Timestamp of batch disbursement creation in ISO format
    reference
    required
    string ID of the batch disbursement in your system, used to reconcile disbursements after they have been completed
    total_uploaded_count
    required
    number The count of all disbursements in the batch
    total_uploaded_amount
    required
    number Total amount of all disbursements in the batch
    status
    required
    string NEEDS_APPROVAL Batch disbursement is created but needs to be approved to be processed further
    id
    required
    string Unique ID of batch disbursement in our system

    Error Codes

    Error Code Description
    API_VALIDATION_ERROR
    400
    Inputs has failed in validation. The errors field in the response will contain details about which fields are violating validation.
    INVALID_JSON_FORMAT
    400
    The request body is not a valid JSON format.
    DUPLICATE_TRANSACTION_ERROR
    400
    Request failed because idempotency key has been seen before.
    INVALID_API_KEY
    401
    Wrong API key is being used.
    BATCH_DISBURSEMENT_MAXIMUM_ROWS_LIMIT_EXCEEDED_ERROR
    400
    Request failed because the disbursements contain more than 1000 items.
    REQUEST_FORBIDDEN_ERROR
    403
    API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

    Batch Disbursement Callback

    Endpoint: Disbursement Callback

    POST https://yourcompany.com/disbursement_callback_url

    After creating a batch disbursement via API, to receive a callback, you must log into your Dashboard and do the following steps:

    When all disbursements in a batch disbursement has been processed, our system will hit the callback URL that you have already set. We will also give you callback if a batch disbursement has been deleted in the dashboard. Please contact our technical support to set your callback URL.

    Callback Payload

    Parameter Description
    created Timestamp of batch disbursement creation in ISO format
    updated Timestamp of the latest batch disbursement status change in ISO format
    reference ID of the batch disbursement in your system, used to reconcile disbursements after they have been completed
    total_uploaded_count The count of all disbursements in the batch that you requested
    total_uploaded_amount Total amount of all disbursements in the batch that you requested
    approved_at Timestamp of batch disbursement approved in ISO format
    approver_id User ID of the person who approves the batch disbursement
    status COMPLETED All disbursements are successfully paid
    CHECK Some disbursements are successfully paid
    DELETED Batch disbursement has been deleted
    FAILED All disbursements are not successfully paid
    id Unique ID of batch disbursement in our system
    user_id Your Xendit Business ID
    total_error_count The count of all disbursements in the batch that are not successfully paid
    total_error_amount Total amount of all disbursements in the batch that are not successfully paid
    total_disbursed_count The count of all disbursements in the batch that are succesfully paid
    total_disbursed_amount Total amount of all disbursements in the batch that are succesfully paid
    disbursements Details of each disbursement in the batch, explained below

    Disbursement

    Parameter Description
    created Timestamp of batch disbursement item creation in ISO format
    updated Timestamp of latest batch disbursement status update in ISO format
    external_id ID of disbursement from your system
    amount Amount to disburse
    bank_code Receiving bank code. See bank codes
    bank_account_number Receiving bank account number
    bank_account_name Receiving bank account holder name
    description Description to accompany the disbursement
    email_to Email addresses that get notified of disbursement details after the disbursement is completed
    email_cc Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed
    email_bcc Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed
    status COMPLETED Disbursement is successfully paid
    FAILED Disbursement is not successfully paid
    bank_reference Transaction reference number from the bank
    valid_name Valid receiving account holder name according to receiving bank
    failure_code The error code associated with the failure of disbursement
    failure_message The error message associated with the failure of disbursement
    id Unique ID of the batch disbursement item in our system

    Callback Errors

    Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.

    Get Available Banks

    Endpoint: Get Available Disbursement Banks

    GET https://api.xendit.co/available_disbursements_banks

    Example Get Available Disbursement Banks Request

    curl https://api.xendit.co/available_disbursements_banks -X GET \
        -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
    <?php
      require 'vendor/autoload.php';
    
      $options['secret_api_key'] = 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==';
    
      $xenditPHPClient = new XenditClient\XenditPHPClient($options);
    
      $response = $xenditPHPClient->getAvailableDisbursementBanks();
      print_r($response);
    ?>
    const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
    
    const { Disbursement } = x;
    const disbursementSpecificOptions = {};
    const d = new Disbursement(disbursementSpecificOptions);
    
    const resp = await d.getBanks();
    console.log(resp);
    Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
    try {
      AvailableBank[] banks = BatchDisbursement.getAvailableBanks();
    } catch (XenditException e) {
      e.printStackTrace();
    }

    This API endpoint will provide you the current list of banks we support for disbursements. The current list of supported banks is >140 just for Indonesia, including some BPDs and BPRs.

    Response Parameters

    Get Available Disbursement Banks Response

    [
      {
        "name": "Bank Central Asia (BCA)",
        "code": "BCA"
      },
      {
        "name": "Bank Mandiri",
        "code": "MANDIRI"
      },
      {
        "name": "Bank Rakyat Indonesia (BRI)",
        "code": "BRI"
      }
    ]
    Parameter Description
    name Full name of the bank
    code Code of the bank, relevant during creation of virtual accounts

    xenPlatform

    Description

    xenPlatform is Xendit's solution for platform businesses that work with third-party partners. Platform businesses face complex payments challenges that range from partner onboarding, to moving funds, to payouts and billing.

    With xenPlatform, you can onboard and create accounts for your partners, transact on behalf of them, split payments, monitor their transactions, and directly bill them.

    Overview

    Once xenPlatform has been activated for your account, you may use the Account API to create sub accounts that are linked to your master account.

    Thereafter simply include a for-user-id header in any standard Xendit API call to create a transaction for those accounts.

    These accounts and their transactions will appear in the xenPlatform tab of your Xendit dashboard.

    Create Account

    The Create Account API allows your xenPlatform enabled account to create sub-accounts that are linked to your account. The response includes the corresponding user_id value that you should store in order to make transactions for that sub-account in the future.

    There are two types of accounts that can be created: MANAGED, OWNED.

    For MANAGED accounts: When a successful POST request is made to the Create Account API with a valid email in the account_email field, a sub-account is immediately created and a sub-account invitation email is sent to that email for further registration. Via the sub-account invitation email, your third-party partners can complete registration in order to get access to their own Xendit dashboard.

    For OWNED accounts: Owned accounts do not get access to their own Xendit Dashboards. When a successful POST request is made to the Create Account API with a valid email in the account_email field, a sub-account is immediately created. No invitation email is sent to that email for further registration. The business_name parameter is mandatory for OWNED accounts.

    Endpoint: Create Account

    POST https://api.xendit.co/accounts

    Request Parameters

    Example: Create Account

    curl https://api.xendit.co/accounts -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d account_email=angie@pinkpanther.com \
       -d type=OWNED \
       -d business_profile[business_name]="Angie's lemonade stand" \
      <?php
          $url = 'https://api.xendit.co/accounts';
          $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
          $headers = [];
          $headers[] = 'Content-Type: application/json';
          $data = [
              'account_email' => 'angie@pinkpanther.com',
              'type' => 'OWNED',
              'business_profile' => [
                'business_name' => 'Angie\'s lemonade stand'
              ]
          ];
    
          $curl = curl_init();
    
          $payload = json_encode($data);
          curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
          curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
          curl_setopt($curl, CURLOPT_URL, $url);
          curl_setopt($curl, CURLOPT_POST, true);
          curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
          curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
          $result = curl_exec($curl);
          echo $result;
    Body Parameter Type Description
    account_email
    required
    string Email identifier for your account

    Minimum length 1 character
    Maximum length No maximum characters
    type
    required
    string Type of account you are creating

    Available values: MANAGED, OWNED
    business_profile
    required for OWNED, else optional
    object Business information about the account being created
    business_name
    required for OWNED, else optional
    string Name of the business

    Response Parameters

    Example: Create Account Response

    {
        "created": "2019-01-01T08:51:44.484Z",
        "status": "SUCCESSFUL",
        "account_email": "angie@pinkpanther.com",
        "user_id": "57fb4e076fb3fa296b7f5a17",
        "type": "OWNED"
    }
    Parameter Type Description
    created
    required
    string Timestamp of when the account was created

    Timezone: GMT+0
    status
    required
    string The status of account creation

    Available values: SUCCESSFUL
    account_email
    required
    string The email identifier of the account created
    user_id
    required
    string The user_id of the account created, use this to create transactions on behalf of your accounts
    type
    required
    string The type of account created

    Available values: MANAGED, OWNED

    Set Callback URLs

    The Set Callback URLs API allows you to set your sub-accounts' Callback URLs.

    Use your production key to set production URLs; use your development key to set development URLs.

    Note: Production callback URLs have to use the https protocol.

    The following can be used in the :type path parameters.

    Money-In

    1. invoice: When an Invoice is paid, our systems will send a callback to the URL
    2. fva_status: When a Fixed Virtual Account is created or updated, our systems will send a callback to the URL
    3. fva_paid: When a Fixed Virtual Account is paid, our systems will send a callback to the URL
    4. ro_fpc_paid: When a Retail Outlet Payment Code is paid, our systems will send a callback to the URL
    5. ovo_paid: When an OVO Request is paid, our systems will send a callback to the URL

    Money-Out

    1. disbursement: When a Disbursement is sent, our systems will send a callback to the URL
    2. batch_disbursement: When a Batch Disbursement is sent, our systems will send a callback to the URL

    Endpoint: Set Callback URLs

    POST https://api.xendit.co/callback_urls/:type

    Request Parameters

    Example: Set Callback URLs

    curl https://api.xendit.co/callback_urls/:type -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d url=https://www.xendit.co/callback_catcher \
      <?php
          $url = 'https://api.xendit.co/callback_urls';
          $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
          $headers = [];
          $headers[] = 'Content-Type: application/json';
          $data = [
              'url' => 'https://www.xendit.co/callback_catcher'
          ];
    
          $curl = curl_init();
    
          $payload = json_encode($data);
          curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
          curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
          curl_setopt($curl, CURLOPT_URL, $url);
          curl_setopt($curl, CURLOPT_POST, true);
          curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
          curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
          $result = curl_exec($curl);
          echo $result;
    Header Parameter Type Description
    for-user-id
    optional
    string The sub-account user-id that you want to set this Callback URL on.

    This header is only used if you have access to xenPlatform. See xenPlatform for more information

    Path Parameter Type Description
    type
    required
    string The type of Callback URL you want to set

    Available values: invoice, fva_status, fva_paid, ro_fpc_paid, ovo_paid, batch_disbursement, disbursement
    Body Parameter Type Description
    url
    required
    string URL of your server that you want to receive our Callbacks at

    Minimum length 1 character
    Maximum length No maximum characters

    Response Parameters

    Example: Set Callback URLs Response

    {
        "status": "SUCCESSFUL",
        "user_id": "5e6b30d967627b957de8c123",
        "url": "https://www.xendit.co/callback_catcher",
        "environment": "TEST",
        "callback_token": "66a6680348e1c33ed2b9053a8eb9291b9e2230ff4f4d3057c9f4ac26405d2123"
    }
    Parameter Type Description
    status
    required
    string The status of setting the Callback URL

    Available values: SUCCESSFUL
    user_id
    required
    string The user_id on which the Callback URL has been set
    url
    required
    string The Callback URL that has been set
    environment
    required
    string The environment on which the Callback URL has been set
    callback_token
    required
    string The unique Callback token that is attached to each sub-account. Use this to validate that a Callback is sent from Xendit's servers.

    Transfers

    The Transfers API allows you to transfer balances: i) from your sub-accounts to your master account and vice versa, ii) between your sub-accounts. Use this to manage, or split payments between your platform and your sub accounts within the Xendit ecosystem.

    Visit your xenPlatform dashboard in order to view the user_id of your account and sub-accounts.

    Endpoint: Create Transfer

    POST https://api.xendit.co/transfers

    Example: Create Transfer

    curl https://api.xendit.co/accounts -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d reference=transfer001 \
       -d amount=10000 \
       -d source_user_id=54afeb170a2b18519b1b8768 \
       -d destination_user_id=5cafeb170a2b1851246b8768 \
      <?php
          $url = 'https://api.xendit.co/transfers';
          $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
          $headers = [];
          $headers[] = 'Content-Type: application/json';
          $data = [
              'reference' => 'transfer001',
              'amount' => 10000,
              'source_user_id' => '54afeb170a2b18519b1b8768',
              'destination_user_id' => '5cafeb170a2b1851246b8768'
          ];
    
          $curl = curl_init();
    
          $payload = json_encode($data);
          curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
          curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
          curl_setopt($curl, CURLOPT_URL, $url);
          curl_setopt($curl, CURLOPT_POST, true);
          curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
          curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
          $result = curl_exec($curl);
          echo $result;

    Request Parameters

    Body Parameter Type Description
    reference
    required
    string A unique reference for this Transfer. Use this to reconcile transactions across your master and sub-accounts
    amount
    required
    number The amount that you would like to transfer
    source_user_id
    required
    string The account balance from which you would like to send the Transfer from. This can either be your platform or sub accounts user_id
    destination_user_id
    required
    string The account balance from which you would like to send the Transfer to. This can either be your platform or sub accounts user_id

    Response Parameters

    Example: Transfers Response

    {
        "created": "2020-01-01T08:51:44.484Z",
        "transfer_id": "60b9d810-d9a3-456c-abbf-2786ec7a9651",
        "reference": "transfer001",
        "source_user_id": "54afeb170a2b18519b1b8768",
        "destination_user_id": "5cafeb170a2b1851246b8768",
        "status": "SUCCESSFUL",
        "amount": 10000
    }
    Parameter Type Description
    created
    required
    string Timestamp of when the Transfer was created

    Timezone: GMT+0
    transfer_id
    required
    string A unique reference for this Transfer set by Xendit systems
    reference
    required
    string A unique reference for this Transfer that you set when making the request
    source_user_id
    required
    string The source of the transfer. This is the user_id of either your master or sub account
    destination_user_id
    required
    string The destination of the transfer. This is the user_id of either your master or sub account
    status
    required
    string The status of the Transfer

    Available values: SUCCESSFUL
    amount
    required
    string The amount that was transferred

    Account Updated Callback

    Endpoint: Account Updated Callback

    POST https://yourcompany.com/xenplatform_callback_url

    The Account Updated callback can be used to let your system know when your sub-accounts have been successfully registered and live payments enabled.

    This example is used to show the body parameters that will be sent from Xendit APIs to your callback URL.

    You will receive callbacks from the Create Account API at 2 points during the sub-account onboarding process:

    1. when a sub-account has been registered
    2. when live payments has been enabled for your sub-account (i.e. activated)

    Please configure your callback URL in the settings page of your Xendit dashboard in order to receive these callbacks. You may also test this callbacks request in the same settings page.

    Callback Payload

    Example Account Updated Callback Request

    curl https://yourcompany.com/xenplatform_callback_url -X POST \
       -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
       -d created="2019-01-01T10:51:44.484Z" \
       -d event_type="account.registered" \
       -d data[user_id]="57fb4e076fb3fa296b7f5a17" \
       -d data[account_info][payments_enabled]=false \
      <?php
          $url = 'https://yourcompany.com/xenplatform_callback_url';
          $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
          $headers = [];
          $headers[] = 'Content-Type: application/json';
          $data = [
              'created' => '2019-01-01T10:51:44.484Z',
              'event_type' => 'account.registered',
              'data' => [
                'user_id' => '57fb4e076fb3fa296b7f5a17',
                'account_info' => [
                  'payments_enabled' => false
                ]
              ]
          ];
    
          $curl = curl_init();
    
          $payload = json_encode($data);
          curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
          curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
          curl_setopt($curl, CURLOPT_URL, $url);
          curl_setopt($curl, CURLOPT_POST, true);
          curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
          curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    
          $result = curl_exec($curl);
          echo $result;
    Body Parameter Type Description
    created
    required
    string Indicates when the callback was sent
    event_type
    required
    string The type of event callback that was sent

    Available values: account.registered, account.activated
    data
    required
    object Contains metadata for the event type
    user_id
    required
    string User ID of the sub account
    account_info
    required
    object Account info meta data

    Account Info Metadata Object Parameters

    Parameter Type Description
    payments_enabled
    required
    boolean Boolean value indicating whether payments has been enabled for the sub-account

    Test Scenarios

    This section includes test scenarios and other information to make sure your integration works as planned. Use it to trigger different flows in your integration and ensure they are handled accordingly

    Checklists

    Xendit has designed its live and test modes to function as similarly as possible. Flipping the switch is mostly a matter of swapping your API keys.

    If you are a developer, or had a developer perform an integration for you, you should also consider the following items before going live.

    Handle Edge Cases

    We have created several test cases you can use to replicate various states and responses. Beyond these options, perform your due diligence, testing your integration with:

    We also recommend you have someone else test your integration, especially if that other person is not a developer themselves.

    Review Error Handling

    Once you have gone live is an unfortunate time to discover you have not properly written your code to handle every possible error type, including those that should "never" happen. Be certain your code is defensive, handling not just the common errors, but all possibilities.

    When testing your error handling, especially watch what information is shown to your users. A card being declined (i.e., CARD_DECLINED) is a different concern than an error on your backend (e.g., an API_VALIDATION_ERROR).

    Review Your Logging

    Xendit logs every request made with you API keys. We recommend that you log all important data on your end, too, despite the apparent redundancy. Your own logs will be a life-saver if your server has a problem contacting Xendit or there's an issue with your API keys--both cases would prevent us from logging your request.

    Regularly examine your logs to ensure they're storing all the information you may need and they are not storing anything of a sensitive nature (e.g., personally identifiable information).

    Independent From Test Mode Objects

    Xendit objects created in test mode--such as charge, virtual accounts, retail outlets, etc---are not usable in live mode. This prevents your test data from being inadvertently used in your production code. When recreating necessary objects in live mode, be certain to use the same ID values (e.g. the same Virtual Account external ID) to guarantee your code will continue to work without issue

    Register Live Callback URL

    Your Xendit account can have both test and live callback URLs. If you are using callback, make sure you have defined live endpoints in your Xendit account. Then confirm that the live endpoint functions exactly the same as your test endpoint.

    While examining your callback status, also take a moment to check that your live endpoint:

    Secure Your API keys

    As a security measure, we recommend change your API keys on a regular basis, and also just before going live. This is in case they have been saved somewhere outside of your codebase during development. Make sure your workflow doesn't result in your API keys being represented or stored in multiple places--this leads to bugs--or even ending up in your version control software.

    Docs Changelog

    API Reference Changelog

    Aug 04, 2020

    Aug 3, 2020

    Jul 31, 2020

    Jul 30, 2020

    Jul 28, 2020

    Jul 27, 2020

    Jul 24, 2020

    Jul 16, 2020

    Jul 07, 2020

    Jul 07, 2020

    Jul 07, 2020

    Jul 01, 2020

    June 30, 2020

    June 25, 2020

    Jun 24, 2020

    Jun 18, 2020

    June 17, 2020

    Jun 11, 2020

    Jun 06, 2020

    May 31, 2020

    May 26, 2020

    May 22, 2020

    May 21, 2020

    May 13, 2020

    May 12, 2020

    May 06, 2020

    April 28, 2020

    April 24, 2020

    April 20, 2020

    April 16, 2020

    April 16, 2020

    April 14, 2020

    March 20,2020

    March 19, 2020

    March 11, 2020

    March 5, 2020

    March 3, 2020

    March 2, 2020

    February 28, 2020

    February 26, 2020

    February 18, 2020

    February 14, 2020

    February 12, 2020

    February 04, 2020

    January 23, 2020

    January 20, 2020

    January 16, 2020

    January 14, 2020

    January 9, 2020

    January 6, 2020

    December 15, 2019

    December 14, 2019

    December 12, 2019

    December 11, 2019

    December 9, 2019

    November 27, 2019

    November 26, 2019

    November 21, 2019

    November 7, 2019

    October 31, 2019

    October 30, 2019

    October 23, 2019