NAV undefined
undefined
bash php java

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 fintech lending and eCommerce, 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 API, you must append a colon and Base 64 encode the API key you find in the dashboard. For example if your API key is

xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==

First, add a colon at the end

xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==:

Finally, Base64 encode the colon appended key to get

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, we provide you API keys for both the development and production environments. All requests made in the development environment will never hit the banking networks and will not cost you anything.

Before using the API, make sure that you have registered and get your account authenticated as API requests without authentication will fail. To authenticate your account, you have to include your secret API key in the request which can be accessed in Xendit Dashboard. You can manage your API keys in the Dashboard > Settings > API Keys. Your development and production keys determine your environment. Your API keys should be kept private so do not share your secret API keys.

All the API requests should be made over HTTPS instead of HTTP (all calls made over plain HTTP will fail). We also provide PHP client libraries to save you time. We’re developing more libraries and plugins in the near future and if you write your own library, we would love to hear about it. Make sure you’ve completed the authentication before using our API.

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. You can assign your money into different accounts according to your business logic (eg: cash account, tax account, escrow account) and each account has its own balance that can be accessed in the dashboard.

Get Balance Request

Example Get Balance Request

curl https://api.xendit.co/balance -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->getBalance();
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.xendit.co/balance")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

Get Balance allows you to retrieve the balance of your cash, escrow and tax account. Some use cases include: deciding when you may need to withdraw funds, determining if you have funds to disburse, and if you just like to check it’s still there :P

Currently, the API only supports querying the balance for your cash, escrow and tax account. Anything else related to the account (eg: adding new account, transferring money from accounts besides cash account, etc.) will be done at the beginning in initial configuration with our technical team.

Parameter Description
account_type
optional
default: CASH
string The selected account type (CASH, HOLDING, or TAX).

Get Balance Response

Example Get Balance Response

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

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 not required as it is instead specified during Authentication. See Create Authentication for more details.

Tokenization Request

Parameter 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/CVC code
Note: Only used for single-use tokens
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.
xenditResponseHandler
required
function The response handler function is called after tokenization is attempted, to receive errors and tokenization response

Tokenization Response

Parameter Description
id
required
string The token ID. This will be used later to Charge the funds from the credit card
authentication_id
optional
string Included if authentication was bundled for single use token.
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 If status is IN_REVIEW, this contains the URL to the page for users to authenticate themselves using 3DS
failure_reason
optional
string If status is FAILED, this describes the failure. See Tokenization Failure Reasons.

Tokenization Statuses

Status Description
IN_REVIEW The customer must authenticate their identity. Xendit provides a URL which you should navigate your users to for easily performing 3DS.
VERIFIED The customer successfully authenticated their identity. Therefore, it is safe to send the token to your backend for charging.
FAILED Tokenization can fail for many reasons. See Tokenization Failure Reasons.

Tokenization Failure Reasons

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

Tokenization Errors

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.
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"
}

Authentication Request

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

Authentication Response

Parameter Description
id
required
string Authentication ID to be used with Token ID when charging a card
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.

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);
?>

Example Create Authorization Response

{
    "created": "2017-08-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);
?>

Example Zero Amount Authorization Response

{
    "created": "2017-08-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": "postman-charge-1502436817",
    }'

Example of request body

{        
    "external_id": "postman-charge-1502436817",
}

Example of Reverse Autherization Response

{
    "created": "2018-06-21T11:37:51.436Z",
    "credit_card_charge_id": "5b2b8e024ec5ad6463cdc594",
    "external_id": "postman-charge-1502436817",
    "business_id": "5ae9216707ce36df1060c309",
    "amount": 5000,
    "status": "SUCCEEDED",
    "id": "5b2b8e0f4ec5ad6463cdc597"
}

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

Reverse Authorization Fields

Parameter Description
external_id
required
string Charge reference

Reverse Autherization Response

Parameter Description
external_id
required
string Unique Identifier for your Reversed Charge reference
business_id
required
string The ID of your business in Xendit.
merchant_id
required
string Your merchant ID used for processing credit cards with the bank
merchant _reference_code
required
string An ID used to reconcile transactions 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,...)
authorized_amount
required
number The amount that've been authorized for this charge.
status
required
string Status of the charge. See Charge Statuses.
created
required
string An ISO timestamp that tracks when the charge was made.

Stasus

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

Reverse Authorization Errors

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
CHARGE_ALREADY_CAPTURED _ERROR
400
Charge already captured
CHARGE_FAILED _ERROR
400
Charge already captured
TEMPORARY_SERVICE _ERROR
400
Charge already captured
CREDIT_CARD_CHARGE _NOT_FOUND_ERROR
404
credit_card_charge_id not found

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": 15000,
      "authentication_id":"598d5d0f51e0870d44c61535",
      "card_cvn":"123",
      "descriptor":"My new store"
    }'
<?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 = 17000;
  $authentication_id = '58e2097218b815f555c8a526';

  $response = $xenditPHPClient->captureCreditCardPayment($external_id, $token_id, $amount);
  print_r($response);
?>

Example Charge Response

{
    "created": "2017-08-11T07:33:14.442Z",
    "status": "CAPTURED",
    "business_id": "5850e55d8d9791bd40096364",
    "authorized_amount": 15000,
    "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": 15000,
    "descriptor": "My new store",
    "id": "598d5dba51e0870d44c61539"
}

Example Authorization Response

{
    "created": "2017-08-11T07:43:39.563Z",
    "status": "AUTHORIZED",
    "business_id": "5850e55d8d9791bd40096364",
    "authorized_amount": 15000,
    "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": "My new store",
    "id": "598d602b51e0870d44c6153d"
}

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

Charge Request

Parameter 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 The charge amount
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 Spesific descriptor to define merchant's identity

Charge Response

Parameter Description
created
required
string An ISO timestamp that tracks when the charge was made.
status
required
string Status of the charge. See Charge Statuses.
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.
merchant_id
required
string Your merchant ID used for processing credit cards with the bank.
merchant _reference_code
required
string An ID used to reconcile transactions with the bank.
card_type
required
string Type of card (CREDIT or DEBIT)
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,...)
bank_reconciliation_id
required
string ID of the transaction that can be reconciled with bank
eci
optional
string Status of 3DS authentication. See ECI codes.
capture_amount
optional
number The amount that've been captured for this charge. Can be up to authorized_amount.
id
required
string ID of the charge captured.
descriptor
required
string Description which already inputted by merchant when creating a charge.
failure_reason
optional
string If status is FAILED, this describes the failure. See Charge Failure Reasons.

Charge 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 sucessfully reversed.
FAILED Charge failed. See Charge Failure Reasons

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

Charge Errors

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

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
1 Incomplete authentication (MasterCard)
2 Successful authentication (MasterCard)
5 Successful authentication (Visa, AMEX, JCB, Diners Club)
6 Authentication attempted (Visa, AMEX, JCB, Diners Club)
7 Unable to Authenticate

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

Example Capture Charge Response

{
  "created": "2017-08-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

Capture Charge Request

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

Capture Charge Errors

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
CREDIT_CARD_CHARGE _NOT_FOUND_ERROR
404
credit_card_charge_id not found

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==:

Example Get Charge Response

{
  "created": "2017-08-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

Get Charge Request

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

Get Charge Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
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" \
    -d amount=15000
    -d external_id=unique-external-id
<?php
  require 'vendor/autoload.php';

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

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

  $credit_card_charge_id = '5877255293ff67900c6aa64e';
  $amount = 15000;
  $external_id = 'unique-external-id';

  $response = $xenditPHPClient->issueCreditCardRefund($credit_card_charge_id, $amount, $external_id);
  print_r($response);
?>

Example Refund Response

{
  "updated": "2017-04-21T04:05:09.755Z",
  "created": "2017-04-21T04:05:04.936Z",
  "credit_card_charge_id": "58f89041780d51ed097896c5",
  "user_id": "57c5aa7a36e3b6a709b6e148",
  "amount": 15000,
  "external_id": "unique-external-id",
  "status": "PENDING",
  "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 refund calls can be made, so long as the total amount refunded is not greater than the total charge amount. For every refund request you will receive a PENDING refund.

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

Refund Request

Header Description
X-IDEMPOTENCY-KEY
optional
string A unique key to prevent processing duplicate requests. Must be unique across development & production environments.
Parameter Description
credit_card_charge_id
required
string Charge ID of the payment that will be refunded (you can see this in credit card details in dashboard)
amount
required
string The amount to be refunded
external_id
required
string A unique identifier of your choice. Max 64 characters.

Refund Response

Parameter Description
updated
required
string An ISO timestamp that tracks when the last time refund was updated
created
required
string An ISO timestamp that tracks when the refund was made
credit_card_charge_id
required
string The charge ID, used to unique identify every charge.
user_id
required
string Your ID in xendit system
amount
required
number Amount of the refund
external_id
required
string Unique identifier that you provide in the request
status
required
string Status of the refund. See Refund Statuses
failure_reason
required
string If the status is failed, this is describe the reason. See Refund Failure Reasons
fee_refund_amount
required
number Amount of fee refunded (proportional to the refund amount)
id
required
string Unique ID referencing the refund request

Refund Statuses

Status Description
PENDING Refund still on progress.
SUCCEEDED Refund succeeded
FAILED Refund failed

Refund Errors

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
CREDIT_CARD_CHARGE _NOT_FOUND_ERROR
404
credit_card_charge_id not found

Refund Failure Reason

Failure Reason Description
INSUFFICIENT_BALANCE Insufficient balance to create refund
REFUND_FAILED Request for refund is rejected by processor

Refund Callback

Example: Refund Callback (Success)

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

Example: Refund Callback (Failed)

{
    "updated": '2017-04-21T04:05:09.755Z',
    "created": '2017-04-21T04:05:04.936Z',
    "credit_card_charge_id": '58f89041780d51ed097896c5',
    "user_id": '57c5aa7a36e3b6a709b6e148',
    "amount": 15000,
    "external_id": 'unique-external-id',
    "status": 'FAILED',
    "failure_reason": "REFUND_REJECTED",
    "fee_refund_amount": 150,
    "id": '58f984f09d1b74bc08506c34'
}

Once we finished processing the refund you will receive a callback from Xendit. Make sure you setup credit card refund callback URL Xendit Dashboard Configuration Credit Cards > Credit Card Refund Callback URLs.

Create Subscription

Definition: Create Subscription

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

Example Create Subscription Request

curl -X POST \
  https://api.xendit.co/managed_subscriptions \
  -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
  -H 'content-type: application/json' \
  -d '{
    "token_id": "59644ba513c7f01759213052",
    "authentication_id": "59644bb713c7f01759213053",
    "amount": 75000,
    "frequency": "MONTHLY",
    "start_date": "2017-07-15T10:00:00.000Z",
    "end_date": "2018-07-15T10:00:00.000Z"
}'
// BETA - Not yet added to PHP Library

When a Subscription is created, Xendit takes care of charging the credit card periodically, at an interval set in the frequency field.

Create Subscription Request

Parameter Description
token_id
required
string ID of the token that represents the credit card you wish to periodically charge
authentication_id
optional
string The id of a 3DS authentication
amount
required
number The amount to be charged periodically
frequency
required
string An enum value representing the frequency at which Xendit will charge the credit card. See frequency details
start_date
required
string The ISO date on which Xendit will charge the card for the first time for this subscription. Note: The time is not required.
end_date
required
string The ISO date on which the subscription expires, after which Xendit will no longer charge the credit card. Note: The time is not required

Example Subscription Response

{
  "token_id": "591e7edafe439c3c698bc8a9",
  "authorization_id": "5963c7b313c7f01759213033",
  "amount": 75000,
  "frequency": "MONTHLY",
  "start_date": "2017-07-10T17:00:00.000Z",
  "end_date": "2018-07-09T17:00:00.000Z",
  "status": "ACTIVE",
  "id": "5963c7b313c7f01759213034"
}

Create Subscription Response

The create Subscription response will conform to the structure outlined by the Subscription Schema

Subscription Schema

Parameter Description
id
required
string A unique identifier representing the Subscription
token_id
required
string ID of the token that represents the credit card you wish to periodically charge
authorization_id
required
string The id of the authorization performed before the subscription begins
amount
required
number The amount to be charged periodically
frequency
required
string An enum value representing the frequency at which Xendit will charge the credit card. See frequency details
start_date
required
string The ISO date on which Xendit will charge the card for the first time for this subscription
end_date
required
string The ISO date when the subscription expires, after which Xendit will no longer charge the credit card
status
required
string An enum value representing the status of the subscription. See status details
credit_card_charges
optional
arrayList of charges created for this subscription

Subscription Statuses

Status Description
ACTIVE The subscription is active and the card will be charged periodically
CANCELLED The subscription is cancelled and the credit card will no longer be charged
EXPIRED The subscription's end_date has passed. The credit card will no longer be charged
FAILED Xendit was unable to charge the credit card

Subscription Frequency

Status Description
DAILY The card will be charged every day
WEEKLY The card will be charged every 7 days
MONTHLY The card will be charged on the same day each month, rounded to the latest day of the month (e.g. May 31st, then June 30th)
YEARLY The card will be charged on the same day each year

Create Subscription Errors

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.
INVALID_START _DATE_ERROR
400
The start date is before today (GMT+7)
INVALID_END _DATE_ERROR
400
The end date is not after the start date
AMOUNT_GREATER_THAN _AUTHENTICATED_ERROR
400
The amount value exceeds the amount the user agreed on in the 3DS authentication
AUTHENTICATION_ID _MISSING_ERROR
400
The authentication_id field is missing but is required in order to create this Subscription
AUTHENTICATION_ALREADY _USED_ERROR
400
The authentication_id provided was already used
TOKEN_NOT_FOUND _ERROR
404
A valid token with the provided token id could not be found
AUTHENTICATION_NOT _FOUND_ERROR
404
A valid 3DS authentication with the provided authentication id could not be found

Subscription callback

Example: Subscription Callback (Charge Success)

{
    "id": "59f7574b3f9ebe7c62214833",
    "status": "CAPTURED",
    "business_id": "5850e55d8d9791bd40096364",
    "subscription_id": "59f755c9d4e70a7279eb95a7",
    "external_id": "59f755c9d4e70a7279eb95a8",
    "merchant_reference_code": "59f7574a3f9ebe7c62214832",
    "merchant_id": "xendit_recurring",
    "card_type": "CREDIT",
    "masked_card_number": "400000XXXXXX0002",
    "charge_type": "RECURRING",
    "card_brand": "VISA",
    "capture_amount": 10000,
    "eci": "7",
    "created": "2017-10-30T16:46:03.550Z"
}

Example: Subscription Callback (Charge Failed)

{
    "id": "59f7574b3f9ebe7c62214833",
    "status": "FAILED",
    "failure_reason": "CARD_DECLINED",
    "business_id": "5850e55d8d9791bd40096364",
    "subscription_id": "59f755c9d4e70a7279eb95a7",
    "external_id": "59f755c9d4e70a7279eb95a8",
    "merchant_reference_code": "59f7574a3f9ebe7c62214832",
    "merchant_id": "xendit_recurring",
    "card_type": "CREDIT",
    "masked_card_number": "400000XXXXXX0002",
    "charge_type": "RECURRING",
    "card_brand": "VISA",
    "capture_amount": 10000,
    "eci": "7",
    "created": "2017-10-30T16:46:03.550Z"
}

Every time a charge created at interval that you've been specified, we will notify you using a callback. You can set your callback URL in the Dashboard at Settings > Configuration > Credit Cards > Managed Subcription Callback URLs.

Parameter Description
id
required
string ID of the charge captured
status
required
string Status of the charge. See Charge Statuses
failure_reason
optional
string If status is FAILED, this describes the failure. See Charge Failure Reasons
business_id
required
string The ID of your business in Xendit
subscription_id
required
string ID of the subscription link to this charge
external_id
required
string A unique identifier for this charge.
merchant _reference_code
required
string An ID used to reconcile transactions with the bank
merchant_id
required
string Your merchant ID used for processing credit cards with the bank
card_type
required
string Type of card (CREDIT or DEBIT)
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,...)
capture_amount
required
number The charge amount
eci
optional
string Status of 3DS authentication. See ECI codes
created
required
string An ISO timestamp that tracks when the charge was made

Get Subscription

Definition: Get Subscription

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

Example Get Subscription Request

curl https://api.xendit.co/managed_subscriptions/591e7edafe439c3c698bc8a9 \
    -X GET \
    -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
// BETA - Not yet added to PHP Library

Example Subscription Response

{
  "token_id": "591e7edafe439c3c698bc8a9",
  "authorization_id": "5963c7b313c7f01759213033",
  "amount": 75000,
  "frequency": "MONTHLY",
  "start_date": "2017-07-10T17:00:00.000Z",
  "end_date": "2018-07-09T17:00:00.000Z",
  "status": "ACTIVE",
  "id": "5963c7b313c7f01759213034",
  "credit_card_charges": [
        {
            "created": "2017-09-13T12:14:04.885Z",
            "business_id": "5848fdf860053555135587e7",
            "authorized_amount": 10000,
            "external_id": "59b920d8a51f84ad216e0cf8",
            "merchant_id": "xendit_recurring",
            "merchant_reference_code": "59b9210b29cd10f53469348c",
            "card_type": "CREDIT",
            "masked_card_number": "400000XXXXXX0002",
            "charge_type": "RECURRING",
            "card_brand": "VISA",
            "status": "CAPTURED",
            "capture_amount": 10000,
            "id": "5963c7b313c7f01759213034"
        }
    ]
}

Get Subscription Request

Parameter Description
id
required
string The id of the Subscription you would like to retrieve

Get Subscription Response

The get Subscription response will conform to the structure outlined by the Subscription Schema

Get Subscription Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
MANAGED_SUBSCRIPTION _NOT_FOUND_ERROR
404
A Subscription with the given id was not found

Cancel Subscription

Definition: Cancel Subscription

POST https://api.xendit.co/managed_subscriptions/:id/cancellation

Example Cancel Subscription Request

curl https://api.xendit.co/managed_subscriptions/591e7edafe439c3c698bc8a9/cancellation \
    -X POST \
    -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
// BETA - Not yet added to PHP Library

Example Subscription Cancellation Response

{
  "token_id": "591e7edafe439c3c698bc8a9",
  "authorization_id": "5963c7b313c7f01759213033",
  "amount": 75000,
  "frequency": "MONTHLY",
  "start_date": "2017-07-10T17:00:00.000Z",
  "end_date": "2018-07-09T17:00:00.000Z",
  "status": "CANCELLED",
  "id": "5963c7b313c7f01759213034"
}

Cancel Subscription Request

Parameter Description
id
required
string The id of the Subscription you would like to cancel

Cancel Subscription Response

The cancel Subscription response will confirm to the structure outlined by the Subscription Schema

Cancel Subscription Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
ACTIVE_MANAGED _SUBSCRIPTION _NOT_FOUND_ERROR
404
An active subscription with the given id was not found

Fraud Detection

Definition: Check fraud risk

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

Example Check Fraud Risk Request

curl -X POST \
  https://api.xendit.co/fraud_detection \
  -u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
  -H 'content-type: application/json' \
  -d '{
    "billing_first_name": "Giuseppe",
    "billing_last_name": "Contini",
    "billing_street_1": "123 Elm St.",
    "billing_city": "Cambridge",
    "billing_state": "MA",
    "billing_country": "US",
    "billing_postal_code": "02139",
    "billing_email": "joe@xendit.co",
    "token_id": "5aebf2f75d20a0ba4d105185",
    "billing_customer_id": "joe_16171235678",
    "billing_phone_number": "+16171235678",
    "shipping_first_name": "Joe",
    "shipping_last_name": "Contini",
    "shipping_street_1": "Jl. Casablanca Raya 88",
    "shipping_city": "Jakarta Selatan",
    "shipping_state": "Jakarta",
    "shipping_country": "ID",
    "shipping_postal_code": "12870",
    "shipping_phone_number": "+6281213831234",
    "shipping_method": "JNE",
    "amount": 4000000,
    "items" : [
       {    
         "product_sku" : "106101100105",
         "product_code" : "Lightsaber_green_02",
         "product_name" : "Electrum Lightsaber",
         "quantity" : "1",
         "unit_price" : "4000000"
       }
    ],
    "merchant_defined_data" : {
        "mdd_1" : "Xendit",
        "mdd_100" : "Space Program"
    }
}'

Example of request body

{        
    "billing_first_name": "Giuseppe",
    "billing_last_name": "Contini",
    "billing_street_1": "123 Elm St.",
    "billing_city": "Cambridge",
    "billing_state": "MA",
    "billing_country": "US",
    "billing_postal_code": "02139",
    "billing_email": "joe@xendit.co",
    "token_id": "5aebf2f75d20a0ba4d105185",
    "billing_customer_id": "joe_16171235678",
    "billing_phone_number": "+16171235678",
    "shipping_first_name": "Joe",
    "shipping_last_name": "Contini",
    "shipping_street_1": "Jl. Casablanca Raya 88",
    "shipping_city": "Jakarta Selatan",
    "shipping_state": "Jakarta",
    "shipping_country": "ID",
    "shipping_postal_code": "12870",
    "shipping_phone_number": "+6281213831234",
    "shipping_method": "JNE",
    "amount": 4000000,
    "items" : [
       {    
         "product_sku" : "106101100105",
         "product_code" : "Lightsaber_green_02",
         "product_name" : "Electrum Lightsaber",
         "quantity" : "1",
         "unit_price" : "4000000"
       }
    ],
    "merchant_defined_data" : {
        "mdd_1" : "Xendit",
        "mdd_100" : "Space Program"
    }
}

Example of Check Fraud Risk Response

{
    "id": "586f4a15dd75f9e1722f8488",
    "risk_score": 29,
    "recommendation": "ALLOW"
}

This API provides risk score of a transaction scenario, higher risk score means higher probability that the transaction is a fraud

Fraud Fields

Parameter Description
billing_first_name
required
string Billing first name
billing_last_name
required
string Billing last name
billing_street_1
required
string Billing address
billing_city
required
string Billing city
billing_state
required
string Billing State. Required only for US/Canada.
billing_country
required
string Billing Country
billing_postal_code
required
string Billing postal code. Required only for US/Canada.
billing_email
required
string Billing email
token_id
optional
string Token ID from a card tokenization
billing_customer_id
optional
string Billing customer ID
billing_phone_number
optional
string Billing phone number
shipping_first_name
optional
string Shipping first name
shipping_last_name
optional
string Shipping last name
shipping_street_1
optional
string Shipping address
shipping_city
optional
string Shipping city
shipping_state
optional
string Shipping state. Required for U.S. and Canada
shipping_country
optional
string Shipping country
shipping_postal_code
optional
string Shipping postal code. Required only for US/Canada.
shipping_phone_number
optional
string Shipping phone number
shipping_method
optional
string Shipping method
amount
required if no items field
number Total transaction amount
items
required if no amount field
array Items in the order. See Fraud Item Fields
merchant_defined_data
optional
string Merchant defined data. See Merchant Defined Data Fields

Fraud Item Fields

Parameter Description
product_sku
required
string Product SKU
product_code
required
string Product code
product_name
required
string Product name
quantity
required
string Quantity
unit_price
required
string Unit price

Merchant Defined Data Fields

This fields allows you to store information. Please note that this field must not be used to capture personally identifying information.

Please contact us to to know more about this feature.

Parameter Description
mdd_1
optional
string merchant defined data field #1
to
mdd_100
optional
string merchant defined data field #100

Fraud Detection Response

Parameter Description
id
string Request ID
risk_score
number Fraud risk score of a transaction scenario
recommendation
string Recommended action for a transaction scenario See Recommendation

Recommendation

Recommendation Description
ALLOW
Transaction scenario is unlikely a fraud
BLOCK
Transaction is likely a fraud and should be declined

Fraud Detection Errors

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_NOT_FOUND _ERROR
404
A valid token with the provided token id could not be found
CARD_EXPIRED _ERROR
400
Token contain information of an expired card

Virtual Accounts

Get banks for virtual accounts

Endpoint: Get Available Banks for Virtual Accounts

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

Example Get Banks for Virtual Accounts Request

curl https://api.xendit.co/available_virtual_account_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->getVirtualAccountBanks();
  print_r($response);
?>

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.xendit.co/available_virtual_account_banks")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

Get Banks for Virtual Accounts Response

Example Get Banks for Virtual Accounts Response

{
  "name": "Bank Negara Indonesia",
  "code": "BNI"
}
Parameter Description
name Full name of the bank
code Code of the bank, relevant during creation of virtual accounts

Create fixed virtual accounts

Endpoint: Create Fixed Virtual Account (FVA)

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

Fixed virtual accounts are dedicated virtual accounts under a name you choose, e.g. 'YourCompany - Becca Salim'. You will receive a callback each time this fixed virtual account is paid. Read more about fixed virtual accounts.

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

Create Fixed Virtual Accounts Request

Example Create Fixed 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
  require 'vendor/autoload.php';

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

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

  $external_id = 'demo_1475459775872';
  $bank_code = 'BNI';
  $name = 'Rika Sutanto';

  $response = $xenditPHPClient->createCallbackVirtualAccount($external_id, $bank_code, $name);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{  'external_id': 'user_1212412312',  'bank_code': 'BNI',  'name': 'William Sutanto'}");
Response response = client.target("https://api.xendit.co/callback_virtual_accounts")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Parameter 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.
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
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)
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
suggested_amount
optional
number The suggested amount you want to assign. If you do not send one, external id will be used
Note: suggested amounts is only supported for Mandiri and BRI
is_closed
optional
boolean When set to true, the virtual account will be closed and will only accept the amount specified in expected_amount
expected_amount
optional
number The amount that the virtual account will expect if is_closed is set to true
expiration_date
optional
ISO Date The time when the virtual account will be expired
is_single_use
optional
boolean When set to true, the virtual account will be inactive after it is paid

Create Fixed Virtual Accounts Response

Example Create Fixed Virtual Accounts Response

{
   "owner_id":"57b4e5181473eeb61c11f9b9",
   "external_id":"demo-1475804036622",
   "bank_code":"BNI",
   "merchant_code":"8808",
   "name":"Rika Sutanto",
   "account_number":"88082548",
   "is_closed": false,
   "id":"57f6fbf26b9f064272622aa6",
   "is_single_use": true,
   "status": "ACTIVE"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
bank_code Bank code for the relevant bank, e.g. BNI
merchant_code 5-digit merchant prefix to the full virtual account number
name Name for the fixed virtual account
account_number Complete virtual account number (including prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking.
suggested_amount OPTIONAL suggested amount for created fixed virtual account
is_closed value that determines whether a virtual account is closed or not
expected_amount OPTIONAL the amount that is expected when is_closed is true
id Unique ID for the fixed virtual account. Can be used to create invoices linked to the FVA.
is_single_use value that determines whether a virtual account will be inactive after it is paid
status Status of fixed virtual account that defines if it’s pending or inactive. Status is inactive either because it is a paid single use fixed virtual account or it is already expired.

Create Fixed Virtual Accounts Errors

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.
BANK_NOT_SUPPORTED _ERROR
400
The bank code is not currently supported.
EXPIRATION_DATE _NOT_SUPPORTED_ERROR
400
Custom expiration date for the fixed 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 fixed 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 that you want to create is already exist
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
CALLBACK_VIRTUAL_ACCOUNT_NAME_NOT_ALLOWED _ERROR
400
The name cannot contain bank or institution name

Update fixed virtual accounts

Endpoint: Update Fixed Virtual Account (FVA)

PATCH https://api.xendit.co/callback_virtual_accounts/{fixed_virtual_account_id}

Fixed Virtual Account is so adaptable, and it's all based on your needs. Therefore, we provide you this endpoint to easily update your fixed virtual account as you like.

Update Fixed Virtual Accounts Request

Parameter Description
suggested_amount
optional
number suggested amount you want to assign
expected_amount
optional
number The amount that the virtual account will expect if is_closed is set to true
expiration_date
optional
ISO 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
is_single_use
optional
boolean When set to true, the virtual account will be inactive after it is paid

Update Fixed Virtual Accounts Response

Example update Fixed Virtual Accounts Response

{
   "owner_id":"57b4e5181473eeb61c11f9b9",
   "external_id":"demo-1475804036622",
   "bank_code":"BNI",
   "merchant_code":"8808",
   "name":"Rika Sutanto",
   "account_number":"88082548",
   "suggested_amount":50000,
   "is_closed": false,
   "id":"57f6fbf26b9f064272622aa6",
   "is_single_use": true,
   "status": "ACTIVE"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon virtual account creation
bank_code Bank code for the relevant bank, e.g. BNI
merchant_code 5-digit merchant prefix to the full virtual account number
name Name for the fixed virtual account
account_number Complete virtual account number (including prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking.
suggested_amount Suggested amount of updated fixed virtual account
id Unique ID for the fixed virtual account. Can be used to create invoices linked to the FVA.
is_closed value that determines whether a virtual account is closed or not
expected_amount OPTIONAL the amount that is expected when is_closed is true
is_single_use value that determines whether a virtual account will be inactive after it is paid
status Status of fixed virtual account that defines if it’s pending or inactive. Status is inactive either because it is a paid single use fixed virtual account or it is already expired.

Update Fixed Virtual Accounts Errors

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.
BANK_NOT_SUPPORTED _ERROR
400
The bank code is not currently supported.
SUGGESTED_AMOUNT _NOT_SUPPORTED_ERROR
400
The suggested amount for the fixed 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

Fixed virtual account callback

Endpoint: Fixed Virtual Account Callback

POST https://yourcompany.com/virtual_account_paid_callback_url
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{
    id: '57fb4e076fa3fa296b7f5a97',
    payment_id: 'demo-1476087608948_1476087303080',
    callback_virtual_account_id: '57fb4df9af86ce19778ad359',
    owner_id: '57b4e5181473eeb61c11f9b9',
    external_id: 'demo-1476087608948',
    account_number: '1547',
    bank_code: 'BNI',
    amount: 99000,
    transaction_timestamp: '2016-10-10T08:15:03.080Z',
    merchant_code: '8808',
    updated: '2016-10-10T08:15:03.404Z',
    created: '2016-10-10T08:15:03.404Z'
}");
Response response = client.target("https://api.xendit.co/virtual_account_paid_callback_url")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("X-CALLBACK-TOKEN", "eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

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 and go to settings -> configuration -> fixed virtual account.

Fixed Virtual Account Payment Callback Request

Example Fixed Virtual Account Payment Callback Request

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --header "X-CALLBACK-TOKEN: eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==" \
     --data-binary "{
    id: \"57fb4e076fa3fa296b7f5a97\",
    payment_id: \"demo-1476087608948_1476087303080\",
    callback_virtual_account_id: \"57fb4df9af86ce19778ad359\",
    owner_id: \"57b4e5181473eeb61c11f9b9\",
    external_id: \"demo-1476087608948\",
    account_number: \"1547\",
    bank_code: \"BNI\",
    amount: 99000,
    transaction_timestamp: \"2016-10-10T08:15:03.080Z\",
    merchant_code: \"8808\",
    updated: \"2016-10-10T08:15:03.404Z\",
    created: \"2016-10-10T08:15:03.404Z\"
}" \
'https://api.xendit.co/virtual_account_paid_callback_url'
Parameter Description
payment_id Our internal system’s payment ID
callback_virtual_account_id The id field value from the response when the fixed virtual account was created. See Create Fixed Virtual Accounts
owner_id Your user ID
external_id An ID of your choice which you provided upon virtual account creation
account_number This is the virtual account number (excluding the 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 Bank code for the relevant bank, e.g. BNI
amount Nominal amount to transfer
merchant_code The merchant code will be the prefix for the virtual account number, e.g 01234 your_number
id ID of fixed virtual account payment

Fixed Virtual Account Creation / Update Callback Request

Example Fixed Virtual Account Creation / Update Callback Request

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --header "X-CALLBACK-TOKEN: eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==" \
     --data-binary "{
    id: \"57fb4e076fa3fa296b7f5a97\",
    owner_id: \"5824128aa6f9f9b648be9d76\",
    external_id: \"fixed-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'
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
bank_code Bank code for the relevant bank, e.g. MANDIRI
merchant_code 5-digit merchant prefix to the full virtual account number
name Name for the fixed virtual account
account_number Complete virtual account number (including prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking.
suggested_amount OPTIONAL suggested amount for created fixed virtual account
is_closed value that determines whether a virtual account is closed or not
expected_amount OPTIONAL the amount that is expected when is_closed is true
id Unique ID for the fixed virtual account. Can be used to create invoices linked to the FVA.
is_single_use value that determines whether a virtual account will be inactive after it is paid
status Status of fixed virtual account.

Fixed Virtual Account 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 fixed virtual account payment

Endpoint: Get Fixed Virtual Account payment

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

Example Get Fixed Virtual Account 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==:

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

Get Fixed Virtual Account Payment Request

Parameter Description
payment_id
required
string ID of the payment to retrieve

Get Fixed Virtual Account Payment Response

Example Get Fixed Virtual Account 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,
    "transaction_timestamp": "2017-08-11T11:14:57.080Z"
}
Parameter Description
id ID of the fixed virtual account payment
payment_id Our internal system’s payment ID
callback_virtual_account_id ID of the fixed virtual account payment that was paid
external_id External ID on the fixed virtual account payment
merchant_code 5-digit merchant prefix to the full virtual account number
account_number Account number of the virtual account
bank_code Bank code of the virtual account number
amount Amount that was paid to this virtual account payment
transaction_timestamp Date time that the fixed virtual account was paid

Get Fixed Virtual Account Payment Errors

Error Code Description
CALLBACK_VIRTUAL_ACCOUNT_PAYMENT_NOT_FOUND_ERROR
404
Could not find callback virtual account payment by payment id.

Get fixed virtual account

Endpoint: Get Fixed Virtual Account

GET https://api.xendit.co/callback_virtual_accounts/{callback_virtual_account_id}

Example Get Fixed Virtual Account Request

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

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

Get Fixed Virtual Account Request

Parameter Description
callback_virtual_account_id
required
string ID of the fixed virtual account to retrieve

Get Fixed Virtual Account Response

Example Get Fixed Virtual Account Response

{
    "owner_id": "58cd618ba0464eb64acdb246",
    "external_id": "fixed-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 Description
owner_id ID of the business that own the fixed virtual account
external_id An ID of your choice which you provided upon virtual account creation
bank_code Bank code of the virtual account number
merchant_code 4 or 5-digit merchant prefix to the full virtual account number
name Name of the virtual account
account_number Account number of the virtual account
expiration_date Expiration date of the virtual account
is_closed Flag that define the fixed virtual account is close or open
id ID of the fixed virtual account
is_single_use Flag that define the fixed virtual account is single use or multiple use
status Status of fixed virtual account that defines if it’s active or inactive. Status is inactive either because it is a paid single use fixed virtual account or it is already expired.

Get Fixed Virtual Account Payment Errors

Error Code Description
CALLBACK_VIRTUAL_ACCOUNT_NOT_FOUND_ERROR
404
Could not find callback virtual account.

Invoices

Create invoice

Endpoint: Create Invoice

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

Invoices allow you to quickly create a form for users to pay with any 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

Create Invoice Request

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=sample_email@xendit.co \
   -d description='Trip to Bali' \
   -d amount=230000
<?php
  require 'vendor/autoload.php';

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

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

  $external_id = 'demo_1475801962607';
  $amount = 230000;
  $payer_email = 'sample_email@xendit.co';
  $description = 'Trip to Bali';

  $response = $xenditPHPClient->createInvoice($external_id, $amount, $payer_email, $description);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{  'external_id': 'invoice_123124123',  'amount': 500000,  'payer_email': 'payer@test.com',  'description': 'Invoice #123124123 for Nike shoes',  'should_exclude_taxes': false,  'should_exclude_fees': false}");
Response response = client.target("https://api.xendit.co/v2/invoices")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Parameter 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 11000.
should_send_email
optional

default: false
boolean Specify should the end user get email when invoice is created, paid, or expired; or not
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

Create Invoice Response

Example Create 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": "albert@xendit.co",
  "description": "This is a description",
  "invoice_url": "https://invoice.xendit.co/web/invoices/595b6248c763ac05592e3eb4",
  "expiry_date": "2016-08-01T11:20:01.017Z",
  "available_banks": [
    {
      "bank_code": "BCA",
      "collection_type": "POOL",
      "bank_account_number": 1000008,
      "transfer_amount": 54000
    },
    {
      "bank_code": "MANDIRI",
      "collection_type": "UNIQUE",
      "bank_branch": "KCP Jkt Mayestik",
      "bank_account_number": "1261006593021",
      "account_holder_name": "SENDIRI DIGITAL INDO",
      "transfer_amount": 54002,
      "identity_amount": 2
    }
  ],
  "available_retail_outlets": [
      {
          "retail_outlet_name": "ALFAMART",
          "payment_code": "ALFA123456",
          "transfer_amount": 54000
      }
  ],
  "should_exclude_credit_card": false,
  "should_send_email": false,
  "created": "2017-06-12T14:00:00.306Z",
  "updated": "2017-06-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 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. If you'd like to change the default for your account, please contact our support team.
available_banks
bank_code
collection_type

bank_branch
account_holder_name
bank_account_number
transfer_amount
identity_amount
Available payment methods through banks as per your config
Bank code (see bank codes)
UNIQUE type is unique amounts
POOL type is nonfixed virtual account
Name of the bank branch (if unique amounts)
Name of the bank account (if unique amounts)
Bank account number for users to pay into
Amount the user should transfer
Amount to identify the payment (if unique amounts)
available_retail_outlets

retail_outlet_name
payment_code
transfer_amount
Available payment methods through retail outlet as per your config
Name of the retail outlet
Unique code that you use to pay in retail outlet
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

Create Invoice Errors

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 Rp11000.
MAXIMUM_TRANSFER _AMOUNT_ERROR
400
Could not create invoice because amount is above Rp1000000000.
NO_COLLECTION _METHODS_ERROR
400
Your account has no payment methods configured (unique amount, virtual account, credit card). Please contact support and we will set this up for you.
UNIQUE_AMOUNT _UNAVAILABLE_ERROR
404
There is no unique amount available for invoice amount that you've specified.
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.

Get an invoice

Endpoint: Get an Invoice

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

Get Invoice Request

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
  require 'vendor/autoload.php';

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

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

  $invoice_id = '587cc7b4863f2b462beb31f6';

  $response = $xenditPHPClient->getInvoice($invoice_id);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.xendit.co/v2/invoices/{invoice_id}")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Parameter Description
invoice_id
required
string ID of the invoice to retrieve

Get Invoice Response

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": "albert@xendit.co",
  "description": "This is a description",
  "invoice_url": "https://invoice.xendit.co/web/invoices/595b6248c763ac05592e3eb4",
  "expiry_date": "2016-08-01T11:20:01.017Z",
  "available_banks": [
    {
      "bank_code": "BCA",
      "collection_type": "POOL",
      "bank_account_number": 1000008,
      "transfer_amount": 54000
    },
    {
      "bank_code": "MANDIRI",
      "collection_type": "UNIQUE",
      "bank_branch": "KCP Jkt Mayestik",
      "bank_account_number": "1261006593021",
      "account_holder_name": "SENDIRI DIGITAL INDO",
      "transfer_amount": 54002,
      "identity_amount": 2
    }
  ],
  "available_retail_outlets": [
      {
          "retail_outlet_name": "ALFAMART",
          "payment_code": "ALFA123456",
          "transfer_amount": 54000
      }
  ],
  "should_exclude_credit_card": false,
  "should_send_email": false,
  "created": "2017-06-12T14:00:00.306Z",
  "updated": "2017-06-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 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. If you'd like to change the default for your account, please contact our support team.
available_banks
bank_code
collection_type

bank_branch
account_holder_name
bank_account_number
transfer_amount
identity_amount
Available payment methods as per your config
Bank code (see bank codes)
UNIQUE type is unique amounts
POOL type is nonfixed virtual account
Name of the bank branch (if unique amounts)
Name of the bank account (if unique amounts)
Bank account number for users to pay into
Amount the user should transfer
Amount to identify the payment (if unique amounts)
available_retail_outlets

retail_outlet_name
payment_code
transfer_amount
Available payment methods through retail outlet as per your config
Name of the retail outlet
Unique code that you use to pay in retail outlet
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

Get Invoice Errors

Error Code Description
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format.
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 invoice will close available payment methods: Pool Virtual Account, Retail Outlet, and Credit Card, but not Fixed Virtual Account.
  2. Expiring invoice which linked to Fixed Virtual Account 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 payment instead of invoice payment. To expire Fixed Virtual Account, change the expiration_date using Update Fixed Virtual Account Endpoint

Expire Invoice Request

Example Expire Invoice Request

curl https://api.xendit.co/invoices/{invoice_id}/expire! -X POST \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Parameter Description
invoice_id
required
string ID of the invoice to be expired / canceled

Expire Invoice Response

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": "albert@xendit.co",
  "description": "This is a description",
  "invoice_url": "https://invoice.xendit.co/web/invoices/595b6248c763ac05592e3eb4",
  "expiry_date": "2016-08-01T11:20:01.017Z",
  "available_banks": [
    {
      "bank_code": "BCA",
      "collection_type": "POOL",
      "bank_account_number": 1000008,
      "transfer_amount": 54000
    },
    {
      "bank_code": "MANDIRI",
      "collection_type": "UNIQUE",
      "bank_branch": "KCP Jkt Mayestik",
      "bank_account_number": "1261006593021",
      "account_holder_name": "SENDIRI DIGITAL INDO",
      "transfer_amount": 54002,
      "identity_amount": 2
    }
  ],
  "available_retail_outlets": [
      {
          "retail_outlet_name": "ALFAMART",
          "payment_code": "ALFA123456",
          "transfer_amount": 54000
      }
  ],
  "should_exclude_credit_card": false,
  "should_send_email": false,
  "created": "2017-06-12T14:00:00.306Z",
  "updated": "2017-06-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. If you'd like to change the default for your account, please contact our support team.
available_banks
bank_code
collection_type

bank_branch
account_holder_name
bank_account_number
transfer_amount
identity_amount
Available payment methods as per your config
Bank code (see bank codes)
UNIQUE type is unique amounts
POOL type is nonfixed virtual account
Name of the bank branch (if unique amounts)
Name of the bank account (if unique amounts)
Bank account number for users to pay into
Amount the user should transfer
Amount to identify the payment (if unique amounts)
available_retail_outlets

retail_outlet_name
payment_code
transfer_amount
Available payment methods through retail outlet as per your config
Name of the retail outlet
Unique code that you use to pay in retail outlet
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

Expire Invoice Errors

Error Code Description
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format.
INVOICE_NOT _FOUND_ERROR
404
Could not find invoice by id.

Invoice callback

Endpoint: Invoice Callback

POST https://yourcompany.com/invoice_callback_url
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{
  adjusted_xendit_fee_amount: 19064,
  adjusted_received_amount: 1980000,
  payment_method: 'UNIQUE',
  bank_code: 'MANDIRI',
  paid_amount: 1999064,
  updated: '2017-06-13T02:32:50.912Z',
  created: '2017-06-13T02:32:49.827Z',
  user_id: '5848fdf860053555135587e7',
  is_high: false,
  external_id: 'testing-invoice',
  merchant_name: 'Xendit',
  amount: 2000000,
  xendit_fee_amount: 20000,
  received_amount: 1980000,
  payer_email: 'test@xendit.co',
  description: 'Invoice callback test',
  status: 'PAID',
  id: '593f4ed1c3d3bb7f39733d83'
}");
Response response = client.target("https://api.xendit.co/invoice_callback_url")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("X-CALLBACK-TOKEN", "eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

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

This example is only used to show the body parameters that is 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 -> Configuration -> Accept Payments.

Invoice Callback Request

Example Invoice Callback Request for Payment Through Bank

curl --include \
     --request POST \
     --header "X-CALLBACK-TOKEN: eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==" \
     --header "Content-Type: application/json" \
     --data-binary "{
      id: \"593f4ed1c3d3bb7f39733d83\",
      user_id: \"5848fdf860053555135587e7\",
      external_id: \"testing-invoice\",
      is_high: false,
      merchant_name: \"Xendit\",
      amount: 2000000,
      fees_paid_amount: 5000,
      status: \"PAID\"
      payer_email: \"test@xendit.co\",
      description: \"Invoice callback test\",
      adjusted_received_amount: 1995000,
      payment_method: \"UNIQUE\",
      bank_code: \"MANDIRI\",
      paid_amount: 2000000,
      updated: \"2017-06-13T02:32:50.912Z\",
      created: \"2017-06-13T02:32:49.827Z\",
}" \
'https://api.xendit.co/invoice_callback_url'

Example Invoice Callback Request for Payment Through Retail Outlet

curl --include \
     --request POST \
     --header "X-CALLBACK-TOKEN: eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==" \
     --header "Content-Type: application/json" \
     --data-binary "{
      id: \"593f4ed1c3d3bb7f39733d83\",
      user_id: \"5848fdf860053555135587e7\",
      external_id: \"testing-invoice\",
      is_high: false,
      merchant_name: \"Xendit\",
      amount: 2000000,
      fees_paid_amount: 5000,
      status: \"PAID\"
      payer_email: \"test@xendit.co\",
      description: \"Invoice callback test\",
      adjusted_received_amount: 1995000,
      payment_method: \"RETAIL_OUTLET\",
      retail_outlet_name: \"ALFAMART\",
      paid_amount: 2000000,
      updated: \"2017-06-13T02:32:50.912Z\",
      created: \"2017-06-13T02:32:49.827Z\",
}" \
'https://api.xendit.co/invoice_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 Should unique numbers go above or below the amount. If true, it would mean a 100.000 invoice would display a unique amount above, e.g. 100.123
merchant_name The name of your company or website
amount Nominal amount for the invoice (without taxes, fees)
fees_paid_amount Xendit fees that was directly paid from this invoice - thanks for supporting a better world of payments :)
status PAID the invoice has successfully been paid
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
adjusted_received_amount Amount attributable to you net of our fees. Thanks for using us :)
payment_method The way the invoice is being paid
UNIQUE type is unique amounts
POOL type is nonfixed virtual account
CREDIT_CARD type is credit card
bank_code Code of the bank used to received the money if payment method is UNIQUE or POOL
retail_outlet_name Code of the retail outlet used to received the money if payment method is RETAIL_OUTLET
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

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

Disburse Funds

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

Create Disbursement Request

Example Create Disbursement Request

curl https://api.xendit.co/disbursements -X POST \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
   -H "X-IDEMPOTENCY-KEY: unique-id-12345" \
   -d external_id=demo_1475459775872 \
   -d bank_code=BCA \
   -d account_holder_name='Bob Jones' \
   -d account_number='1231241231' \
   -d description='Reimbursement for shoes' \
   -d amount=17000
<?php
  require 'vendor/autoload.php';

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

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

  $external_id = 'demo_1475459775872';
  $amount = 17000;
  $bank_code = 'BCA';
  $account_holder_name = 'Bob Jones';
  $account_number = '1231241231';
  $disbursement_options['description'] = 'Reimbursement for shoes';

  $response = $xenditPHPClient->createDisbursement($external_id, $amount, $bank_code, $account_holder_name, $account_number, $disbursement_options);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{  'external_id': 'disbursement_12345',  'amount': 500000,  'bank_code': 'BCA',  'account_holder_name': 'Rizky',  'account_number': '1231241231',  'description': 'Custom description'}");
Response response = client.target("https://api.xendit.co/disbursements")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Header 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
Parameter 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 the destination bank account owner

Characters Special and alphanumeric
Maximum length No maximum characters
Minimum length 1 character
account_number
required
string Number for destination bank account

Characters Numeric and hyphens
BCA maximum length10 characters
BCA minimum length 10 characters
Other banks maximum lengthNo maximum characters
Other banks minimum length 1 character

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

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, BRI, Sinarmas, CIMB) No limit***
Minimum limit (BCA, Mandiri, BNI, BRI, Sinarmas, CIMB) No limit
Maximum limit (Other bank) Rp 25.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.

Create Disbursement Response

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"
}
Parameter 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 Destination bank code. See bank codes
account_holder_name
required
string Bank account name as per the bank'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

Create Disbursement Errors

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 Dashboard > Configuration > Disbursement. 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.
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.

Get Disbursement Request

Example Get Disbursement Request

curl https://api.xendit.co/disbursements/57c9010f5ef9e7077bcb96b6 -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);

  $disbursement_id = '587cc7ea77535fb94bb4e8eb';

  $response = $xenditPHPClient->getDisbursement($disbursement_id);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.xendit.co/disbursements/{disbursement_id}")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Parameter 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

Get Disbursement Response

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"
}
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

Get Disbursement Errors

Error Code Description
INVALID_JSON_FORMAT
400
The request body is not a valid JSON format.
INVALID_PERMISSION _ERROR
403
Could not access that disbursement.
DIRECT_DISBURSEMENT _NOT_FOUND_ERROR
404
Could not find direct disbursement.

Get disbursement by external_id

Endpoint: Get Disbursement 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.

Get Disbursement Request

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
  require 'vendor/autoload.php';

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

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

  $external_id = 'disbursement_12345';

  $response = $xenditPHPClient->getDisbursementByExternalId($external_id);
  print_r($response);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.xendit.co/disbursements?external_id={external_id}")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));
Query 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

Get Disbursement Response

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"
}]
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

Get Disbursement Errors

Error Code Description
DIRECT_DISBURSEMENT _NOT_FOUND_ERROR
404
Could not find direct disbursement.

Disbursement callback

Endpoint: Disbursement Callback

POST https://yourcompany.com/disbursement_callback_url
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Entity payload = Entity.json("{  'id': '57e214ba82b034c325e84d6e',  'user_id': '57c5aa7a36e3b6a709b6e148',  'external_id': 'disbursement_123124123',  'amount': 150000,  'bank_code': 'BCA',  'xendit_fee_amount': 0,  'xendit_fee_user_id': 'XENDIT_FEES',  'account_holder_name': 'XENDIT',  'transaction_id': '57ec8b7e906aa2606ecf8ffc',  'transaction_sequence': '1799',  'disbursement_id': '57ec8b8130d2d0243f438e11',  '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'}");
Response response = client.target("https://api.xendit.co/disbursement_callback_url")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .post(payload);

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

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.

Disbursement Callback Request

Example Disbursement Callback Request

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --header "X-CALLBACK-TOKEN: eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==" \
     --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\"
}" \
'https://api.xendit.co/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

Disbursement 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 disbursement 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);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.xendit.co/available_disbursements_banks")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

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). If you would like us to support payment to a specific destination, please contact us at support@xendit.co.

Get Available Disbursement Banks Response

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
code Code of the bank 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
Header 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.
Parameter 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 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

Create Batch Disbursement Response

Example Create 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 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

Create Batch Disbursement Errors

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.

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.

Disbursement Callback Request

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

Batch Disbursement 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 disbursement 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);
?>
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.xendit.co/available_disbursements_banks")
  .request(MediaType.APPLICATION_JSON_TYPE)
  .header("Authorization", "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

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.

Get Available Disbursement Banks Response

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

Name Validator

Endpoint: Validate Name

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

Example Name Validator Request

curl https://api.xendit.co/bank_account_data_requests \
    -X POST \
    -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
    -d bank_account_number="1550001953382" \
    -d bank_code="MANDIRI"
<?php
  require 'vendor/autoload.php';

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

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

  $bank_account_number = '1550001953382';
  $bank_code = 'MANDIRI';

  $response = $xenditPHPClient->validateBankAccountHolderName($bank_account_number, $bank_code);
  print_r($response);
?>

The Name Validator can be used to look up the name of an account holder for any bank account in Indonesia, except virtual account. Because it can take a few seconds to look up the name with the banks, the result is returned in a callback if it is not already cached. Be sure to have a callback URL configured for Bank account data in the Xendit Dashboard Configuration.

Name Validator Request

Parameter Description
bank_account_number string (required)
The bank account number
bank_code string (required)
The bank code. See Bank Codes

Name Validator Response

Example Name Validator Response (Uncached)

{
  "bank_account_number": "5015378625",
  "bank_code": "BCA",
  "reference": "58cd618ba0464eb64acdb246",
  "status": "PENDING",
  "updated": "2017-07-03T10:51:44.484Z",
  "id": "59e608887eb26d005d44aeb8"
}

Example Name Validator Response (Cached - SUCCESS)

{
  "bank_account_number": "1234567899",
  "bank_account_holder_name": "JOE CONTINI",
  "bank_code": "MANDIRI",
  "reference": "58cd618ba0464eb64acdb246",
  "status": "SUCCESS",
  "updated": "2017-03-24T08:11:07.624Z",
  "id": "59e608887eb26d005d44aeb8"
}

Example Name Validator Response (Cached - FAILURE)

{
  "bank_account_number": "1234567899",
  "failure_reason": "RECIPIENT_NOT_FOUND_ERROR",
  "bank_code": "MANDIRI",
  "reference": "58cd618ba0464eb64acdb246",
  "status": "FAILURE",
  "updated": "2017-03-24T08:11:07.624Z",
  "id": "59e608887eb26d005d44aeb8"
}

Example Name Validator Callback

{
  "bank_account_number": "1234567899",
  "bank_account_holder_name": "JOE CONTINI",
  "bank_code": "MANDIRI",
  "status": "SUCCESS",
  "updated": "2017-03-24T08:11:07.624Z",
  "id": "59e608887eb26d005d44aeb8"
}

If the account number has not been cached, the response will have "status": "PENDING", and you will be a sent a callback when the request completes.

Once cached, the name will be returned immediately in the response.

Name Validator Schema

Parameter Description
bank_code string (required)
The bank code. See Bank Codes
bank_account_number string (required)
The bank account number
bank_account _holder_name string (required)
Account Holder Name
status string (required)
PENDING The name validation request is still being processed
SUCCESS The name validation request has been completed
FAILURE The name validation request has failed
failure_reason string (optional)
See Name Validator Errors
reference string (required)
The ID of the business that made the request
updated string (required)
The last updated date of the name validation request
id string (required)
Unique name validator request ID

Name Validator Errors

Error Code Description
MAX_RETRY_TIMES _EXCEED_ERROR
400
Our system has retried the request several times but still failed because of an unknown error response from the bank.
RECIPIENT_NOT_FOUND _ERROR
404
There’s no bank recipient with this account number.
UNSUPPORTED_BANK _CODE_ERROR
404
Destination bank is not supported, request is using the wrong bank code.

NPWP Validator

Endpoint: Validate NPWP

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

Example NPWP Validator Request

curl https://api.xendit.co/npwp_data_requests \
    -X POST \
    -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
    -d account_number="123456789012345" \

NPWP Validator can be used to look up the account holder name of an NPWP in Indonesia. Because it can take a few seconds to look up the account, the result is returned in a callback if it is not already cached. Be sure to have a callback URL configured for NPWP data in the Xendit Dashboard Configuration.

NPWP Validator Request

Parameter Description
account_number string (required)
NPWP number

NPWP Validator Response

Example NPWP Validator Response (Uncached)

{
  "id": "59e608887eb26d005d44aeb8",
  "created": "2017-07-03T10:51:44.484Z",
  "updated": "2017-07-03T10:51:44.484Z",
  "account_number": "123456789012345",
  "status": "PENDING"
}

Example NPWP Validator Response (Cached - SUCCESS)

{
  "id": "59e608887eb26d005d44aeb8",
  "created": "2017-07-03T10:51:44.484Z",
  "updated": "2017-07-03T10:51:44.484Z",
  "account_number": "123456789012345",
  "account_name": "JOE CONTINI",
  "status": "SUCCESS"
}

Example NPWP Validator Callback (SUCCESS)

{
  "id": "59e608887eb26d005d44aeb8",
  "created": "2017-07-03T10:51:44.484Z",
  "updated": "2017-07-03T10:51:44.484Z",
  "account_number": "123456789012345",
  "account_name": "JOE CONTINI",
  "status": "SUCCESS"
}

Example NPWP Validator Callback (FAILED)

{
  "id": "59e608887eb26d005d44aeb8",
  "created": "2017-07-03T10:51:44.484Z",
  "updated": "2017-07-03T10:51:44.484Z",
  "account_number": "123456789012346",
  "status": "FAILED",
  "failure_reason": "NPWP_NOT_FOUND_ERROR"
}

If the account number has not been cached, the response will have "status": "PENDING", and you will be a sent a callback when the request completes.

Once cached, the result will be returned immediately in the response.

NPWP Validator Schema

Parameter Description
id string (required)
Unique NPWP request ID
created string (required)
The created date of the NPWP request
updated string (required)
The last updated date of the NPWP request
account_number string (required)
NPWP number
account_name string (optional)
NPWP account holder Name
status string (required)
PENDING The NPWP request is still being processed
SUCCESS The NPWP request has been completed with the result being the NPWP is valid
FAILED The NPWP request has been completed with the result being the NPWP is invalid
failure_reason string (optional)
See NPWP Validator Failure Reasons

NPWP Validator Failure Reasons

Failure Reason Description
NPWP_NOT_FOUND _ERROR NPWP is not found

NPWP Validator Error Codes

Error Code Description
API_VALIDATION _ERROR
400
Inputs format are failing validation. The errors field contains details about which fields are violating validation. One of the most common reason is the account number does not have right length.

Foreign Exchange (Forex)

Forex trades (beta) enable you to convert foreign currencies with your Xendit account. We currently support United States Dollar (USD) to Indonesian Rupiah (IDR) currency conversions.

Create Quote

Endpoint: Create Quote

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

Create Quote Request

Example Create Quote Request

curl https://api.xendit.co/quotes -X POST \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
   -d buy_currency="IDR" \
   -d sell_amount=150 \
   -d sell_currency="USD" \
Parameter Description
buy_amount
optional
number The amount of currency being bought
buy_currency
required
string Currency being bought
sell_amount
optional
string The amount of currency being sold
sell_currency
required
string Currency being sold

Create Quote Response

Example Create Quote Response

{
  "user_id": "5785e6334d7b410667d355c4",
  "sell_currency": "USD",
  "sell_amount": 150,
  "forex_rate": 13454.67,
  "buy_currency": "IDR",
  "buy_amount": 2018201,
  "currency_pair": "USDIDR"
}
Parameter Description
user_id
required
string Your Xendit Business ID
sell_currency
required
string Currency being sold
sell_amount
required
number The amount of currency being sold
forex_rate
required
number Current currency exchange rate quoted for the currency_pair
buy_currency
required
string Currency being bought
buy_amount
required
number The amount of currency being bought
currency_pair
required
string Base currency and quote currency being traded. The first-listed currency is the base currency and the second-listed currency is the quote currency.

Create Quote Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
CURRENCY_PAIR_NOT_SUPPORTED_ERROR
400
The request contains unsupported trade currencies
SERVICE_TEMPORARILY_UNAVAILABLE_ERROR
500
Services are disrupted.

Create Conversion

Endpoint: Create Conversion

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

Create Conversion Request

Example Create Conversion Request

curl https://api.xendit.co/conversions -X POST \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
   -d buy_currency="IDR" \
   -d sell_amount=150 \
   -d sell_currency="USD" \
   -d reason="Top up IDR with USD" \
   -d description= "Convert USD to IDR"
   -d conversion_type="PREFUNDED" \
Parameter Description
buy_amount
optional
number The amount of currency being bought
buy_currency
required
string Currency being bought
sell_amount
optional
string The amount of currency being sold
sell_currency
required
string Currency being sold
reason
required
string Reason for trade
description
required
string Trade description
conversion_type
required
string Type of conversion

Create Conversion Response

Example Create Conversion Response

{
    "updated": "2017-11-20T07:35:56.382Z",
    "created": "2017-11-20T07:35:56.382Z",
    "user_id": "59a284865af9892d1b82c050",
    "sell_currency": "USD",
    "buy_currency": "IDR",
    "sell_amount": 1000000,
    "buy_amount": 13454670000,
    "reason": "for funsies",
    "description": "id_12345",
    "currency_pair": "USDIDR",
    "forex_rate": 13454.67,
    "status_updated": "2017-11-16T09:06:05.150Z",
    "status": "PENDING",
    "id": "5a1285dc088a682558d90bb9"
}
Parameter Description
updated
required
ISO DATE Time the conversion status was last updated
created
required
ISO DATE Time the conversion was created
user_id
required
string Your Xendit Business ID
sell_currency
required
string Currency being sold
buy_currency
required
string Currency being bought
sell_amount
required
number The amount of currency being sold
buy_amount
required
number The amount of currency being bought
reason
required
string Reason for trade
description
required
string Description provided for this conversion
currency_pair
required
string Base currency and quote currency being traded. The first-listed currency is the base currency and the second-listed currency is the quote currency.
forex_rate
required
number Current currency exchange rate quoted for the currency_pair
status_updated
required
string Time the conversion status was last updated
status
required
string Current conversion status
id
required
string Unique conversion ID

Create Conversion Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
CURRENCY_PAIR_NOT_SUPPORTED_ERROR
400
The request contains unsupported trade currencies
SERVICE_TEMPORARILY_UNAVAILABLE_ERROR
500
Services are disrupted.

Get Conversion

Endpoint: Get Conversion

POST https://api.xendit.co/conversions/{conversion_id}

Get Conversion Request

Example Get Conversion Request

curl https://api.xendit.co/conversions/5a1285dc088a682558d90bb9 -X GET \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
Parameter Description
conversion_id
optional
string Unique conversion ID

Get Conversion Response

Example Get Conversion Response

{
    "updated": "2017-11-20T07:35:56.382Z",
    "created": "2017-11-20T07:35:56.382Z",
    "user_id": "59a284865af9892d1b82c050",
    "sell_currency": "USD",
    "buy_currency": "IDR",
    "sell_amount": 1000000,
    "buy_amount": 13454670000,
    "reason": "for funsies",
    "description": "id_12345",
    "currency_pair": "USDIDR",
    "forex_rate": 13454.67,
    "status_updated": "2017-11-16T09:06:05.150Z",
    "status": "PENDING",
    "id": "5a1285dc088a682558d90bb9"
}
Parameter Description
updated
required
ISO DATE Time the conversion status was last updated
created
required
ISO DATE Time the conversion was created
user_id
required
string Your Xendit Business ID
sell_currency
required
string Currency being sold
buy_currency
required
string Currency being bought
sell_amount
required
number The amount of currency being sold
buy_amount
required
number The amount of currency being bought
reason
required
string Reason for trade
description
required
string Description provided for this conversion
currency_pair
required
string Base currency and quote currency being traded. The first-listed currency is the base currency and the second-listed currency is the quote currency.
forex_rate
required
number Current currency exchange rate quoted for the currency_pair
status_updated
required
string Time the conversion status was last updated
status
required
string Current conversion status
id
required
string Unique conversion ID

Get Conversion Errors

Error Code Description
API_VALIDATION_ERROR
400
Inputs are failing validation. The errors field contains details about which fields are violating validation.
CONVERSION_NOT_FOUND_ERROR
404
Invalid conversion id
SERVICE_TEMPORARILY_UNAVAILABLE_ERROR
500
Services are disrupted.

Errors

Below are some of most common errors across all our endpoints. Specific errors are located under each endpoint. If you have any questions please contact us.

Error code Meaning
400 Bad request, e.g. validation error
401 Unauthorised access, e.g. the wrong API key
403 Forbidden access, e.g. API key does not have permission for this endpoint
404 Page or data not found
500 Unhandled error - contact us when this happens. If this was a response to a request to send money, please check the status of the resource (eg. disbursement, credit card refund) before retrying to ensure that the request will not be processed twice.