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 (Money-out read permission)

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 (Money-in write permission)

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.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
VERIFICATION_TIMEOUT_ERROR
408
The credit card network timed out when trying to tokenize the card.
TEMPORARY_SERVICE_ERROR
503
There was a problem with the credit card network, which prevents tokenization.
CONNECTION_ERROR Error connecting to our server. Try again and if the error persists, try with another device/network.
TOKENIZATION_ERROR General error. Try again or try with a different card.

Create Authentication

Javascript Function: createAuthentication

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

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

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

See our Authentication Sample for an example implementation.

Example authenticationData object

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

Example Authentication Response

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

Authentication Request (Money-in write permission)

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
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
CREDIT_CARD_CHARGE_NOT_FOUND_ERROR
404
credit_card_charge_id not found

Create 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 (Money-in write permission)

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.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
TOKEN_NOT_FOUND_ERROR
404
The token ID was not found in the system.
AUTHENTICATION_NOT_FOUND_ERROR
404
Authenticated token with given authentication ID is not found.

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 (Money-in write permission)

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
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
CREDIT_CARD_CHARGE_NOT_FOUND_ERROR
404
credit_card_charge_id not found

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 (Money-in read permission)

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.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
CREDIT_CARD_CHARGE_NOT_FOUND_ERROR
404
credit_card_charge_id not found

Create Refund

Definition: Create Refund

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

Example Refund Request

curl https://api.xendit.co/credit_card_charges/5877255293ff67900c6aa64e/refunds \
    -X POST \
    -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
    -H "X-IDEMPOTENCY-KEY: unique-id-12345" \
    -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 (Money-in write permission)

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
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
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
CREDIT_CARD_CHARGE_NOT_FOUND_ERROR
404
credit_card_charge_id not found

Refund Failure Reason

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

eWallets

Create Payment

Create Payment Request (Money-in write permission)

Endpoint: Create Ewallet Payment

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

Example: Create Ewallet Payment Request

OVO:

curl https://api.xendit.co/ewallets -X POST \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
   -d external_id='ovo-ewallet' \
   -d amount=1000 \
   -d phone='08123123123'\
   -d ewallet_type='OVO'
  <?php
      $url = 'https://api.xendit.co/ewallets';
      $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
      $headers = [];
      $headers[] = 'Content-Type: application/json';
      $data = [
          'external_id ' => 'ovo-ewallet',
          'amount' => 1000,
          'phone' => '08123123123',
          'ewallet_type' => 'OVO'
      ];

      $curl = curl_init();

      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

      $result = curl_exec($curl);
      echo $result;

DANA:

curl https://api.xendit.co/ewallets -X POST \
  -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
  -d external_id = 'dana-ewallet' \\
  -d amount = 1001 \\
  -d expiration_date = '2020-02-20T00:00:00.000Z' \\
  -d callback_url = 'https://my-shop.com/callbacks' \\
  -d redirect_url = 'https://my-shop.com/home' \\
  -d ewallet_type = 'DANA'
  <?php
      $url = 'https://api.xendit.co/ewallets';
      $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
      $headers = [];
      $headers[] = 'Content-Type: application/json';
      $data = [
          'external_id ' => 'dana-ewallet',
          'amount' => 1001,
          'expiration_date' => '2020-02-20T00:00:00.000Z',
          'callback_url' => 'https://my-shop.com/callbacks',
          'redirect_url' => 'https://my-shop.com/home',
          'ewallet_type' => 'DANA'
      ];

      $curl = curl_init();

      $payload = json_encode($data);
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

      $result = curl_exec($curl);
      echo $result;

LINKAJA:

curl https://api.xendit.co/ewallets -X POST \
  -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
  --header 'content-type: application/json' \
  --data '{
    "external_id": "linkaja-ewallet",
    "phone": "081245671234",
    "amount": 300000,
    "items": [
        {
            "id": "123123",
            "name": "Phone Case",
            "price": 100000,
            "quantity": 1
        },
    {
            "id": "345678",
            "name": "Powerbank",
            "price": 200000,
            "quantity": 1
        }
    ],
    "callback_url": "https://yourwebsite.com/callback",
    "redirect_url": "https://yourwebsite.com/order/123",
    "ewallet_type": "LINKAJA",
}'
<?php
  $url = 'https://api.xendit.co/ewallets';
  $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
  $headers = [];
  $headers[] = 'Content-Type: application/json';

  $item_1 = new stdClass();
  $item_1->id = "123123";
  $item_1->name = "Phone Case";
  $item_1->price = 100000;
  $item_1->quantity = 1;

  $item_2 = new stdClass();
  $item_2->id = "345678";
  $item_2->name = "Powerbank";
  $item_2->price = 200000;
  $item_2->quantity = 1;

  $data = [
    'external_id ' => 'linkaja-ewallet',
    'amount' => 300000,
    'items' => [ $item_1, $item_2 ]
    'callback_url' => 'https://yourwebsite.com/callbacks',
    'redirect_url' => 'https://yourwebsite.com/order/123',
    'ewallet_type' => 'LINKAJA',
  ];

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;

Example: Create Ewallet Payment Success Response

OVO:

{
  transaction_date: "2019-04-07T01:35:46.658Z",
  amount: 1000,
  external_id: "ovo-ewallet",
  ewallet_type: "OVO",
  business_id: "12121212"
}
{
  transaction_date: "2019-04-07T01:35:46.658Z",
  amount: 1000,
  external_id: "ovo-ewallet",
  ewallet_type: "OVO",
  business_id: "12121212"
}

DANA:

{
  external_id: "dana-ewallet",
  checkout_url: "https://dana.id/m/portal/cashier/checkout?id=5d34079d51a9ed12c78a78d3",
  amount: 1000,
  ewallet_type: "DANA"
}
{
  external_id: "dana-ewallet",
  checkout_url: "https://dana.id/m/portal/cashier/checkout?id=5d34079d51a9ed12c78a78d3",
  amount: 1000,
  ewallet_type: "DANA"
}

LINKAJA:

{
  "redirect_url": "https://ewallet-linkaja-dev.xendit.co/checkouts/b0c464ab-dcdc-4426-9255-759a9450c9d2",
  "transaction_date": "2019-10-25T08:42:54.308Z",
  "amount": 300000,
  "external_id": "linkaja-ewallet",
  "ewallet_type": "LINKAJA"
}
{
  "redirect_url": "https://ewallet-linkaja-dev.xendit.co/checkouts/b0c464ab-dcdc-4426-9255-759a9450c9d2",
  "transaction_date": "2019-10-25T08:42:54.308Z",
  "amount": 300000,
  "external_id": "linkaja-ewallet",
  "ewallet_type": "LINKAJA"
}

Example: Create Ewallet Payment Error Response

OVO:

{
  error_code: 'USER_DID_NOT_AUTHORIZE_THE_PAYMENT',
  message: 'Payment was not authorized',
}
{
  error_code: 'USER_DID_NOT_AUTHORIZE_THE_PAYMENT',
  message: 'Payment was not authorized',
}

DANA:

{
  error_code: 'DUPLICATE_ERROR',
  message: 'Transaction with this external_id is already exist',
}
{
  error_code: 'DUPLICATE_ERROR',
  message: 'Transaction with this external_id is already exist',
}

LINKAJA:

{
  error_code: 'DUPLICATE_ERROR',
  message: 'Transaction with this external_id is already exist',
}
{
  error_code: 'DUPLICATE_ERROR',
  message: 'Transaction with this external_id is already exist',
}

OVO

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.
amount
required
number Amount end-customer will pay.
Note: minimum amount is 1 IDR and maximum is 10,000,000 IDR
phone
required
string Phone number of end-customer (e.g. 08123123123)
Note: End-customer must have an active ewallet account registered to Indonesian phone number prior to payment request.
ewallet_type
required
string The type of ewallet to be paid. Must be in capital letters.
Supported ewallet types: OVO, DANA, LINKAJA

DANA

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.
amount
required
number Amount end-customer will pay.
Note: minimum amount is 1 IDR and maximum is 10,000,000 IDR
expiration_date
optional
string End-customer cannot complete the payment past the expiration date
Note: The default is 24 hours if not specified.
callback_url
required
string The URL to receive the callback after payment made by end-customer
redirect_url
required
string The URL to redirect to after payment made by end-customer
ewallet_type
required
string The type of ewallet to be paid. Must be in capital letters.
Supported ewallet types: OVO, DANA, LINKAJA

LINKAJA

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.
phone
required
string Phone number of end-customer (e.g. 08123123123)
Note: End-customer must have an active ewallet account registered to Indonesian phone number prior to payment request.
amount
required
number Amount end-customer will pay.
Note: minimum amount is 100 IDR and maximum is 10,000,000 IDR
items
required
array of item object List of items / products.
item object
required
item object Details of an item, it should contains: id [string], name [string], price [number], quantity [number]
callback_url
required
string The URL to receive the callback after payment made by end-customer
redirect_url
required
string The URL to redirect to after payment made by end-customer
ewallet_type
required
string The type of ewallet to be paid. Must be in capital letters.
Supported ewallet types: OVO, DANA, LINKAJA

Errors

OVO

Error Code Description
USER_DID_NOT_AUTHORIZE_THE_PAYMENT
400
User did not authorize the payment request within time limit.
USER_DECLINED_THE_TRANSACTION
400
User declined the payment request.
PHONE_NUMBER_NOT_REGISTERED
400
Phone number the user tried to pay is not registered
EXTERNAL_ERROR
400
There is an error on ewallet provider side. Please contact our support for further assistance.
SENDING_TRANSACTION_ERROR
400
We cannot send the transaction. Please contact our support for further assistance.
EWALLET_APP_UNREACHABLE
400
The ewallet provider/server can't reach the user ewallet app/phone. Common cases are the ewallet app is uninstalled.
DUPLICATE_PAYMENT
400
The payment with the same external_id has already been made before.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

DANA

Error Code Description
DUPLICATE_PAYMENT
400
The payment with the same external_id has already been made before.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

LINKAJA

Error Code Description
GENERATE_CHECKOUT_TOKEN_ERROR
422
An error occured when generating the checkout_url.
API_VALIDATION_ERROR
400
Some field are missing or you don't specify the value with the correct type or length.
DUPLICATE_PAYMENT
400
The payment with the same external_id has already been made before.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

Get Payment Status (Money-in read permission)

Endpoint: Get Ewallet Payment Status

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

Example: Check Ewallet Payment Status Request

OVO

curl https://api.xendit.co/ewallets\?external_id\='ovo-ewallet'\&ewallet_type\='OVO' \
   -X GET \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
  <?php
      $url = 'https://api.xendit.co/ewallets';
      $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
      $headers = [];
      $headers[] = 'Content-Type: application/json';

      $externalId = 'ovo-ewallet';
      $ewalletType = 'OVO';

      $urlWithParams = $url . '?external_id=' . $externalId . '&ewallet_type=' . $ewalletType;

      $curl = curl_init();

      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $urlWithParams);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

      $result = curl_exec($curl);
      echo $result;

DANA

curl https://api.xendit.co/ewallets\?external_id\='dana-ewallet'\&ewallet_type\='DANA' \
   -X GET \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
  <?php
      $url = 'https://api.xendit.co/ewallets';
      $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
      $headers = [];
      $headers[] = 'Content-Type: application/json';

      $externalId = 'dana-ewallet';
      $ewalletType = 'OVO';

      $urlWithParams = $url . '?external_id=' . $externalId . '&ewallet_type=' . $ewalletType;

      $curl = curl_init();

      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
      curl_setopt($curl, CURLOPT_URL, $urlWithParams);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

      $result = curl_exec($curl);
      echo $result;

Example: Check Ewallet Payment Status Success Response OVO

{
  amount: 1000,
  external_id: "ovo-wallet",
  transaction_date: "2019-04-07T01:35:46.658Z",
  business_id: "12121212",
  ewallet_type: "OVO",
  status: "COMPLETED",
}
{
  amount: 1000,
  external_id: "ovo-wallet",
  transaction_date: "2019-04-07T01:35:46.658Z",
  business_id: "12121212",
  ewallet_type: "OVO",
  status: "COMPLETED",
}

DANA

{
  amount: 1001,
  external_id: "dana-wallet",
  expiration_date: "2019-04-07T01:35:46.658Z",
  business_id: "12121212",
  status: "PAID",
}
{
  amount: 1001,
  external_id: "dana-wallet",
  expiration_date: "2019-04-07T01:35:46.658Z",
  business_id: "12121212",
  status: "PAID",
}

Example: Check Ewallet Payment Status Error Response For OVO and DANA:

{
  error_code: 'PAYMENT_NOT_FOUND_ERROR',
  message: 'Payment not found',
}
{
  error_code: 'PAYMENT_NOT_FOUND_ERROR',
  message: 'Payment not found',
}

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

Get Payment Status (Money-in read permission)

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.
ewallet_type
required
string The type of ewallet to be paid. Must be in capital letters.
Supported ewallet types: OVO, DANA

Errors

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

Payment Status Callback

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

Example Payment Status Callback

DANA

{
  external_id: "dana-ewallet",
  amount: 1001,
  business_id: "12121212",
  payment_status: "PAID",
  transaction_date: "2019-04-07T01:35:46.658Z",
  callback_authentication_token: "MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n=="
}
{
  external_id: "dana-ewallet",
  amount: 1001,
  business_id: "12121212",
  payment_status: "PAID",
  transaction_date: "2019-04-07T01:35:46.658Z",
  callback_authentication_token: "MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n=="
}

LINKAJA

{
  "external_id": "linkaja-ewallet",
  "amount": 300000,
  "items": [
    {
      "id": "123123",
      "name": "Phone Case",
      "price": 100000,
      "quantity": 1
    },
    {
      "id": "345678",
      "name": "Powerbank",
      "price": 200000,
      "quantity": 1
    }
  ],
  "status": "SUCCESS_COMPLETED",
  "ewallet_type": "LINKAJA",
  "callback_authentication_token": "MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n=="
}
{
  "external_id": "linkaja-ewallet",
  "amount": 300000,
  "items": [
    {
      "id": "123123",
      "name": "Phone Case",
      "price": 100000,
      "quantity": 1
    },
    {
      "id": "345678",
      "name": "Powerbank",
      "price": 200000,
      "quantity": 1
    }
  ],
  "status": "SUCCESS_COMPLETED",
  "ewallet_type": "LINKAJA",
  "callback_authentication_token": "MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n=="
}

DANA

Parameter Description
external_id string Your transaction identifier that you specified in on the Generate Checkout URL request.
amount string The amount of transaction
business_id string Your business_id that registered on our system.
payment_status string The status of payment.
Notes: The statuses are: PENDING, EXPIRED, FAILED, and PAID.
transaction_date string The time that of payment was made
callback_authentication_token string Your Callback Verfication API Key that you can found on your Xendit Dashboard. You need to verify if this had the same value.

LINKAJA

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

Cardless Credit

Create Payment / Generate Checkout URL

Generate Checkout URL

Example: Generate Checkout URL

curl https://api.xendit.co/cardless-credit -X POST \
  -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
  --header 'content-type: application/json' \
  --data '{
    "cardless_credit_type": "KREDIVO",
    "external_id": "test-cardless-credit-01",
    "amount": 800000,
    "payment_type": "3_months",
    "items": [
      {
        "id": "123123",
        "name": "Phone Case",
        "price": 200000,
        "type": "Smartphone",
        "url": "http://example.com/phone/phone_case",
        "quantity": 2
      },
      {
        "id": "234567",
        "name": "Bluetooth Headset",
        "price": 400000,
        "type": "Audio",
        "url": "http://example.com/phone/bluetooth_headset",
        "quantity": 1
      }
    ],
    "customer_details": {
      "first_name": "customer first name",
      "last_name": "customer last name",
      "email": "customer@yourwebsite.com",
      "phone": "081513114262"
    },
    "shipping_address": {
      "first_name": "first name",
      "last_name": "last name",
      "address": "Jalan Teknologi No. 12",
      "city": "Jakarta",
      "postal_code": "12345",
      "phone": "081513114262",
      "country_code": "IDN"
    },
    "redirect_url": "https://example.com",
    "callback_url": "http://example.com/callback-cardless-credit"
  }'
<?php
  $url = 'https://api.xendit.co/cardless-credit';
  $apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
  $headers = [];
  $headers[] = 'Content-Type: application/json';

  $item_1 = new stdClass();
  $item_1->id = "123123";
  $item_1->name = "Phone Case";
  $item_1->price = 200000;
  $item_1->type = "Smartphone";
  $item_1->url = "http://example.com/phone/phone_case";
  $item_1->quantity = 2;

  $item_2 = new stdClass();
  $item_2->id = "234567";
  $item_2->name = "Bluetooth Headset";
  $item_2->price = 400000;
  $item_2->type = "Audio";
  $item_2->url = "http://example.com/phone/bluetooth_headset";
  $item_2->quantity = 1;

  $customer_details = new stdClass();
  $customer_details->first_name = "customer first name";
  $customer_details->last_name = "customer last name";
  $customer_details->email = "customer@email.com";
  $customer_details->phone = "081513114262";

  $shipping_address = new stdClass();
  $shipping_address->first_name = "first name";
  $shipping_address->last_name = "last name";
  $shipping_address->address = "Jalan Teknologi No. 12";
  $shipping_address->city = "Jakarta";
  $shipping_address->postal_code = "12345";
  $shipping_address->phone = "081513114262";
  $shipping_address->country_code = "IDN";

  $data = [
      "cardless_credit_type" => "KREDIVO",
      "external_id" => "test-cardless-credit-01",
      "amount" => 800000,
      "payment_type" => "3_months",
      "items" => [ $item_1, $item_2 ],
      "customer_details" => $customer_details,
      "shipping_address" => $shipping_address,
      "redirect_url" => "https://example.com",
      "callback_url" => "http://example.com/callback-cardless-credit"
  ];

  $curl = curl_init();

  $payload = json_encode($data);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = curl_exec($curl);
  echo $result;

Example: Generate Checkout URL Success Response

{
  "redirect_url": "https://sandbox.kredivo.com/kredivo/v2/signin?tk=fKhTeBntLW3Zyu23+GQ6s+RQaMMRtQ6YdZA1bnbTszt9WXcph/B4+j8nuPlV599Rfkv85FAYuE21Suajpm45tEMZqjZIdqnSgIPlt7T5gJk=",
  "transaction_id": "66403e84-c8da-4af4-8d30-d17e95522f43",
  "order_id": "123456-test-cardless-credit-01",
  "external_id": "test-cardless-credit-01",
  "cardless_credit_type": "KREDIVO"
}
{
  "redirect_url": "https://sandbox.kredivo.com/kredivo/v2/signin?tk=fKhTeBntLW3Zyu23+GQ6s+RQaMMRtQ6YdZA1bnbTszt9WXcph/B4+j8nuPlV599Rfkv85FAYuE21Suajpm45tEMZqjZIdqnSgIPlt7T5gJk=",
  "transaction_id": "66403e84-c8da-4af4-8d30-d17e95522f43",
  "order_id": "5d353767d2c80e33ddc2d252-test-cardless-credit-01",
  "external_id": "test-cardless-credit-01",
  "cardless_credit_type": "KREDIVO"
}

Example: Generate Checkout URL error response

{
  error_code: 'API_VALIDATION_ERROR',
  message: '[fieldName] is required',
}
{
  error_code: 'DUPLICATE_PAYMENT_ERROR',
  message: 'Checkout URL with the same external_id has been created before.',
}
{
  error_code: 'API_VALIDATION_ERROR',
  message: '[fieldName] is required',
}
{
  error_code: 'DUPLICATE_PAYMENT_ERROR',
  message: 'Checkout URL with the same external_id has been created before.',
}
Parameter Description
cardless_credit_type
required
string The type of cardless-credit to be paid. Must be in capital letters.
Supported Cardless Credit types: KREDIVO
external_id
required
string An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 1000 characters.
amount
required
number Amount end customer will pay.
Note: minimum amount is 1 IDR
payment_type
required
string The type of installment, you can choose between: "30_days", "3_months", "6_months" and "12_months".
items
required
array of item object List of items / products.
item object
required
item object Details of an item, it should contains: id [string], name [string], price [number], type [string], url [string], quantity [number]
customer_details
required
object Details of the customer, it should contains: first_name [string], last_name [string], email [string], phone [string]
shipping_address
required
object Details of the shipping address, it should contains: first_name [string], last_name [string], address [string], city [string], postal_code [string], phone [string], country_code [string]
redirect_url
required
string After end-customer complete the checkout they will be redirected to the url that you specify in this field. You can put your transaction details page or your home page.
callback_url
required
string We will send callback to this address when the customer completes the payment proccess.

Errors

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

Payment Callback Notification

Receive Payment Callback Notification

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

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

Example: Payment Callback Notification Request

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

Virtual Accounts

Get Virtual Account Banks

Endpoint: Get Virtual Account Available Banks

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

Example Get Virtual Account Banks Request

curl https://api.xendit.co/available_virtual_account_banks -X GET \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
  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 Virtual Account Banks Response (Money-in read permission)

Example Get Virtual Account Banks 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 Account

Endpoint: Create Fixed Virtual Account

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.

For production environments, activate the Fixed Virtual Account Range from the dashboard by going to Dashboard > Settings > Configuration > Fixed Virtual Accounts, and clicking the "Activate!" button. The Fixed VA range will be set and activated instantly. In development environments, the development VA range is assigned right away. 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 Account Request (Money-in write permission)

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. Note: External IDs cannot be changed once set
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
Note: Please do not include the merchant code
suggested_amount
optional
number The suggested amount you want to assign.
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
description
optional
string The virtual account description. This field is only supported for BRI

Create Fixed Virtual Account Response

Example Create Fixed Virtual Account 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, inactive, or active. Status is pending if virtual account creation request has been sent and request is being processed by the bank. Status is inactive either because it is a paid single use fixed virtual account or it is already expired. If status is active it is ready to be used by the end user.
description OPTIONAL description of the virtual account which will be displayed during payment. Only supported for BRI virtual accounts.

Create Fixed Virtual Account 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 minimum expected amount is Rp.1 for BNI, BRI and MANDIRI
MAXIMUM_EXPECTED_AMOUNT_ERROR
400
The maximum expected amount is Rp.50,000,000,000 for BNI, BRI and MANDIRI
CALLBACK_VIRTUAL_ACCOUNT_NAME_NOT_ALLOWED_ERROR
400
The name cannot contain bank or institution name
DESCRIPTION_NOT_SUPPORTED_ERROR
400
Description field is only supported for BRI
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

Get Fixed Virtual Account

Endpoint: Get Fixed Virtual Account

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

Example Get Fixed Virtual Account Request

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

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

Get Fixed Virtual Account Request (Money-in read permission)

Parameter Description
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 Errors

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

Update Fixed Virtual Account

Endpoint: Update Fixed Virtual Account (FVA)

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

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

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

Update Fixed Virtual Account Request (Money-in write permission)

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
description
optional
string Virtual account description shown to end user during payment

Update Fixed Virtual Account Response

Example Update Fixed Virtual Account 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.
description OPTIONAL description of the virtual account which will be displayed during payment. Only supported for BRI virtual accounts.

Update Fixed Virtual Account 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
DESCRIPTION_NOT_SUPPORTED_ERROR
400
Description field is only supported for BRI
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

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", "MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==")
  .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 or 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: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
     --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: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
     --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 Payment Request

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

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 (Money-in write permission)

Parameter Description
payment_id
required
string ID of the payment to retrieve

Get Fixed Virtual Account Payment Response

Example Get Fixed Virtual Account Payment Response

{
    "id": "598d91b1191029596846047f",
    "payment_id": "1502450097080",
    "callback_virtual_account_id": "598d5f71bf64853820c49a18",
    "external_id": "demo-1502437214715",
    "merchant_code": "77517",
    "account_number": "1000016980",
    "bank_code": "BNI",
    "amount": 5000,
    "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
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
CALLBACK_VIRTUAL_ACCOUNT_PAYMENT_NOT_FOUND_ERROR
404
Could not find callback virtual account payment by payment id.

Retail Outlets

Create Fixed Payment Code

Endpoint: Create Fixed Payment Code (FPC)

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

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

Create Fixed Payment Code Request (Money-in write permission)

Example Create Fixed Payment Code Request

curl https://api.xendit.co/fixed_payment_code -X POST \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
   -d external_id=demo_fixed_payment_code_123 \
   -d retail_outlet_name=ALFAMART \
   -d name='Rika Sutanto' \
   -d expected_amount=10000
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.
retail_outlet_name
required
string Name of the fixed payment code you want to create
name
required
string Name of user - this might be used by the Retail Outlets cashier to validate the end user
expected_amount
required
number The amount that is expected to be paid by end customer
payment_code
optional
string The fixed payment code that you want to assign. If you do not send one, one will be picked at random
expiration_date
optional
ISO Date The time when the fixed payment code will be expired
is_single_use
optional
boolean When set to true, the fixed payment code will be inactive after it is paid

Create Fixed Payment Code Response

Example Create Fixed Payment Code Response

{
    "owner_id": "5b614aa8e79f9214007244d4",
    "external_id": "123",
    "retail_outlet_name": "ALFAMART",
    "prefix": "TEST",
    "name": "Rika Sutanto",
    "payment_code": "TEST123456",
    "type": "USER",
    "expected_amount": 10000,
    "is_single_use": true,
    "expiration_date": "2049-07-31T17:00:00.000Z",
    "id": "5b61881e6cc2770f00117f73"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
retail_outlet_name Name of the Retail Outlets, e.g. ALFAMART or INDOMARET
prefix 3-6 characters that differentiate your fixed payment code from the others
name Name for the fixed payment code
payment_code Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier
expected_amount The amount that is expected to be paid by end customer
is_single_use Value that determines whether a fixed payment code will be inactive after it is paid or not
expiration_date The time when the fixed payment code will be expired
id Unique ID for the fixed payment code

Create Fixed Payment Code 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.
PAYMENT_CODE_OUTSIDE_RANGE
400
The fixed payment code you want is outside your range.
RETAIL_OUTLET_NOT_SUPPORTED_ERROR
400
The Retail Outlets is not currently supported.
DUPLICATE_PAYMENT_CODE_ERROR
400
The payment code that you want to create is already exist
EXPIRATION_DATE_INVALID_ERROR
400
Invalid custom expiration date because it's earlier than current time.
MINIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be more than or equal Rp 10,0000
MAXIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be less than or equal Rp 5,000,000
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

Update Fixed Payment Code

Endpoint: Update Fixed Payment Code (FPC)

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

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

Update Fixed Payment Code Request (Money-in write permission)

Example Create Fixed Payment Code Request

curl https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id} -X PATCH \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
   -d expected_amount=20000
   -d name='Joe Contini'
Parameter Description
name
optional
string Name for the fixed payment code
expected_amount
optional
number The amount that is expected to be paid by end customer
expiration_date
optional
ISO Date The time when the fixed payment code will be expired. You can set it to be days in the past to expire fixed payment code immediately

Update Fixed Payment Code Response

Example Update Fixed Payment Code Response

{
    "owner_id": "5b614aa8e79f9214007244d4",
    "external_id": "123",
    "retail_outlet_name": "ALFAMART",
    "prefix": "TEST",
    "name": "Joe Contini",
    "payment_code": "TEST123456",
    "type": "USER",
    "expected_amount": 20000,
    "is_single_use": true,
    "expiration_date": "2049-07-31T17:00:00.000Z",
    "id": "5b61881e6cc2770f00117f73"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
retail_outlet_name Name of the Retail Outlets, e.g. ALFAMART or INDOMARET
prefix 3-6 characters that differentiate your fixed payment code from the others
name Name for the fixed payment code
payment_code Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier
expected_amount The amount that is expected to be paid by end customer
is_single_use Value that determines whether a fixed payment code will be inactive after it is paid or not
expiration_date The time when the fixed payment code will be expired
id Unique ID for the fixed payment code

Update Fixed Payment Code 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.
PAYMENT_CODE_OUTSIDE_RANGE
400
The fixed payment code you want is outside your range.
INACTIVE_FIXED_PAYMENT_CODE_ERROR
400
Account number that you want to update is inactive.
MINIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be more than or equal Rp 10,000
MAXIMUM_EXPECTED_AMOUNT_ERROR
400
The expected amount can only be less than or equal Rp 5,000,000
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

Get Fixed Payment Code

Endpoint: Get Fixed Payment Code

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

Example Get Fixed Payment Code Request

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

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

Get Fixed Payment Code Request (Money-in read permission)

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

Get Fixed Payment Code Response

Example Get Fixed Payment Code Response

{
    "owner_id": "5b614aa8e79f9214007244d4",
    "external_id": "123",
    "retail_outlet_name": "INDOMARET",
    "prefix": "TEST",
    "name": "Joe Contini",
    "payment_code": "TEST123456",
    "type": "USER",
    "expected_amount": 20000,
    "is_single_use": true,
    "expiration_date": "2049-07-31T17:00:00.000Z",
    "id": "5b61881e6cc2770f00117f73"
}
Parameter Description
owner_id Your user ID
external_id An ID of your choice which you provided upon request
retail_outlet_name Name for the relevant Retail Outlets, e.g. ALFAMART or INDOMARET
prefix 3-6 characters that differentiate your fixed payment code from the others
name Name for the fixed payment code
payment_code Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier
expected_amount The amount that is expected to be paid by end customer
is_single_use Value that determines whether a fixed payment code will be inactive after it is paid or not
expiration_date The time when the fixed payment code will be expired
id Unique ID for the fixed payment code

Get Fixed Payment Code Errors

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

Fixed Payment Code Callback

Endpoint: Fixed Payment Code Callback

POST https://yourcompany.com/fixed_payment_code_paid_callback_url

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

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

Fixed Payment Code Payment Callback Request

Example Fixed Payment Code Payment Callback Request

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
     --data-binary "{
    fixed_payment_code_payment_id: \"5b61ffc470f7f3470165e7b3\",
    owner_id: \"5b614aa8e79f9214007244d4\",
    fixed_payment_code_id: \"5b61f49e6cc2770f00117f82\",
    payment_id:\"1533149124896\",
    external_id: \"123\",
    payment_code: \"TEST123456\",
    prefix: \"TEST\",
    retail_outlet_name: 'INDOMARET',
    amount: 20000,
    name: 'Joe Contini',
    transaction_timestamp: \"2018-07-31T08:15:03.080Z\",
    updated: \"2016-10-10T08:15:03.404Z\",
    created: \"2016-10-10T08:15:03.404Z\"
}" \
'https://api.xendit.co/fixed_payment_code_paid_callback_url'
Parameter Description
fixed_payment_code_payment_id Unique ID for the fixed payment code payment
owner_id Your user ID
fixed_payment_code_id Unique ID for the fixed payment code
payment_id Our internal system’s payment ID that can be used as payment reference
external_id An ID of your choice which you provided upon fixed payment code creation
payment_code Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier
prefix 3-6 characters that differentiate your fixed payment code from the others
retail_outlet_name Name for the relevant Retail Outlets, e.g. ALFAMART or INDOMARET
amount Nominal amount that is paid
name Name for the fixed payment code
transaction_timestamp Date time that the fixed payment code was paid

Fixed Payment Code 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.

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 (Money-in write permission)

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 10000.
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
invoice_duration
optional
number duration of time that end user have in order to pay the invoice before it's expired (in Second)
success_redirect_url
optional
string url that end user will be redirected to upon successful invoice payment.
example : https://yourcompany.com/example_item/10/success_page
failure_redirect_url
optional
string url that end user will be redirected to upon expiration of this invoice.
example : https://yourcompany.com/example_item/10/failed_checkout
payment_methods
optional
array of strings choices of payment channels that is available in your account. leave this field empty if all payment channel is expected to be available in this particular invoice.
example : ["BCA", "BRI", "MANDIRI", "BNI",
"PERMATA", "ALFAMART", "CREDIT_CARD",
"OVO"]
mid_label
optional
string MID label that you have when you are using credit card payment and have acquiring bank.
currency
optional
string Currency of the amount that you created
example : "IDR"
fixed_va
optional

default: false
boolean Input this parameter as true to enable one VA number for Your end customers.

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": "lanny@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": "MANDIRI",
            "collection_type": "POOL",
            "bank_account_number": "8860810000525",
            "transfer_amount": 50000,
            "bank_branch": "Virtual Account",
            "account_holder_name": "LANSUR13",
            "identity_amount": 0
        },
        {
            "bank_code": "BRI",
            "collection_type": "POOL",
            "bank_account_number": "2621510002426",
            "transfer_amount": 50000,
            "bank_branch": "Virtual Account",
            "account_holder_name": "LANSUR13",
            "identity_amount": 0
        },
        {
            "bank_code": "BNI",
            "collection_type": "POOL",
            "bank_account_number": "880810000689",
            "transfer_amount": 50000,
            "bank_branch": "Virtual Account",
            "account_holder_name": "LANSUR13",
            "identity_amount": 0
        }
  ],
  "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",
  "mid_label": "test-mid",
  "currency": "IDR",
  "fixed_va":true
}
Parameter Description
id An invoice ID generated by Xendit
user_id Your Xendit Business ID
external_id The invoice ID in your server, that can be used to reconcile between you and Xendit
status PENDING the invoice has yet to be paid
merchant_name The name of your company or website
merchant_profile_picture_url The URL to profile picture of your company
amount Nominal amount for the invoice
payer_email Email of the payer, we get this information from your API call
description Description for the invoice, we get this information from your API call
invoice_url Public URL for this invoice, it’s there in case you want to use our UI
expiry_date ISO date and time that the invoice expires. Default is 24 hours.
available_banks Available payment methods through banks as per your config
bank_code BCA / MANDIRI / BNI / BRI / PERMATA
collection_type POOL type is nonfixed virtual account
bank_account_number Bank account number for users to pay into
transfer_amount Amount the user should transfer
bank_branch Bank account type
account_holder_name Bank account holder name
available_retail_outlets Available payment methods through retail outlet as per your config
retail_outlet_name Name of the retail outlet
payment_code Unique code that you use to pay in retail outlet
transfer_amount Amount the user should transfer
transfer_amount Amount the user should transfer
should_exclude_credit_card A flag showing if credit card should be excluded in invoice UI or not
should_send_email A flag showing should payer get email when invoice is created, paid, or expired; or not
created An ISO timestamp that tracks when the invoice was created
updated An ISO timestamp that tracks when the invoice was updated
mid_label MID label that you have when you are using credit card payment and have acquiring bank. You will get this response when you add this parameter when create invoice through API
currency Currency of the amount that you created. You will get this response when you add this parameter when create invoice through API
fixed_va Input this parameter as true to enable one VA number for Your end customers.

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 Rp10000.
MAXIMUM_TRANSFER_AMOUNT_ERROR
400
Could not create invoice because amount is above Rp1000000000. If you are configured with Retail Outlets, then amount cannot be more than Rp5000000
NO_COLLECTION_METHODS_ERROR
400
Your account has no payment methods configured (virtual account, credit card). Please contact support and we will set this up for you.
UNAVAILABLE_PAYMENT_METHOD_ERROR
400
The payment method choices did not match with the available one on this business.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
UNIQUE_ACCOUNT_NUMBER_UNAVAILABLE_ERROR
404
There is no available virtual account in your non-fixed virtual account range.
CALLBACK_VIRTUAL_ACCOUNT_NOT_FOUND_ERROR
404
Fixed virtual account id that you've specified not found
AVAILABLE_PAYMENT_CODE_NOT_FOUND_ERROR
404
There is no available payment code in your retail outlet range.

Get an invoice

Endpoint: Get an Invoice

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

Get Invoice Request (Money-in read permission)

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": "lanny@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": "MANDIRI",
            "collection_type": "POOL",
            "bank_account_number": "8860810000525",
            "transfer_amount": 50000,
            "bank_branch": "Virtual Account",
            "account_holder_name": "LANSUR13",
            "identity_amount": 0
        },
        {
            "bank_code": "BRI",
            "collection_type": "POOL",
            "bank_account_number": "2621510002426",
            "transfer_amount": 50000,
            "bank_branch": "Virtual Account",
            "account_holder_name": "LANSUR13",
            "identity_amount": 0
        },
        {
            "bank_code": "BNI",
            "collection_type": "POOL",
            "bank_account_number": "880810000689",
            "transfer_amount": 50000,
            "bank_branch": "Virtual Account",
            "account_holder_name": "LANSUR13",
            "identity_amount": 0
        }
  ],
  "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",
  "mid_label": "test-mid",
  "currency": "IDR",
  "paid_at": "2017-06-13T11:00:00.306Z",
  "credit_card_charge_id": "579c8d61f23fa4ca35e52eas",
  "payment_method": "BANK_TRANSFER",
  "payment_channel": "BCA",
  "payment_destination": "10002233222294375",
  "success_redirect_url": "www.xendit.co",
  "failure_redirect_url": "www.xendit.co",
  "fixed_va":true
}



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

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

should_send_email

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

updated

An ISO timestamp that tracks when the invoice was updated

created

An ISO timestamp that tracks when the invoice was created

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

Get Invoice Errors

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

Expire invoice

Endpoint: Expire Invoice

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

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

Note:

  1. Expiring 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 (Money-in write permission)

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": "POOL",
      "bank_account_number": 1000009,
      "transfer_amount": 54000
    }
  ],
  "available_retail_outlets": [
      {
          "retail_outlet_name": "ALFAMART",
          "payment_code": "ALFA123456",
          "transfer_amount": 54000
      }
  ],
  "should_exclude_credit_card": false,
  "should_send_email": false,
  "created": "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.
available_banks Available payment methods through banks as per your config
bank_code BCA / MANDIRI / BNI / BRI / PERMATA
collection_type POOL type is nonfixed virtual account
bank_account_number Bank account number for users to pay into
transfer_amount Amount the user should transfer
bank_branch Bank account type
account_holder_name Bank account holder name
available_retail_outlets
Available payment methods through retail outlet as per your config
retail_outlet_name Name of the retail outlet
payment_code Unique code that you use to pay in retail outlet
transfer_amount 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.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
INVOICE_NOT_FOUND_ERROR
404
Could not find invoice by id.

List all invoice

Endpoint: List Invoice

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

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

List Invoice Request (Money-in read permission)

Example List Invoice Request

curl https://api.xendit.co/v2/invoices?limit=3&statuses=["SETTLED","EXPIRED"]&last_invoice_id=5ca186e407f3b83e34176eac&client_types=["DASHBOARD","API_GATEWAY"]&after=2016-02-24T23:48:36.697Z&before=2020-02-24T23:48:36.697Z -X GET \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:

Example List Invoice Response

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

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

List Invoice Response

List Invoice Response

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

List Invoice Errors

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

Invoice callback

Endpoint: Invoice Callback

POST https://yourcompany.com/invoice_callback_url
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: 'POOL',
  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", "MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==")
  .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: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
     --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: \"POOL\",
      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: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
     --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.
merchant_name The name of your company or website
amount Nominal amount for the invoice (without taxes, fees)
status PAID the invoice has successfully been paid
EXPIRED the invoice has been expired. It's not enabled by default. If you want to enable it for your business, please contact us
payer_email Email of the payer, we get this information from your API call
description Description for the invoice, we get this information from your API call
fees_paid_amount Xendit fees that was directly paid from this invoice - thanks for supporting a better world of payments :)
adjusted_received_amount Amount attributable to you net of our fees.
bank_code
only if payment_method is POOL
Code of the bank used to received the money only if payment method is POOL
e.g. MANDIRI
retail_outlet_name
only if payment_method is RETAIL_OUTLET
Code of the retail outlet used to received the money only if payment method is RETAIL_OUTLET
e.g. ALFAMART
ewallet_type
only if payment_method is EWALLET
Code of the e-wallet used to received the money only if payment method is EWALLET
e.g. OVO
on_demand_link
only for invoices from ondemand
Link of the ondemand that created this invoice
recurring_payment_id
only for invoices from recurring
ID of the recurring that created this invoice
paid_amount Total amount paid for the invoice
updated An ISO timestamp that tracks when the invoice was updated
created An ISO timestamp that tracks when the invoice was created
mid_label MID label that you have when you are using credit card payment and have acquiring bank. You will get this response when you add this parameter when create invoice through API
currency Currency of the amount that you created. You will get this response when you add this parameter when create invoice through API
success_redirect_url URL that end user will be redirected to upon successful invoice payment. You will get this response when you add this parameter when create invoice through API
failure_redirect_url URL that end user will be redirected to upon expiration of this invoice. You will get this response when you add this parameter when create invoice through API
paid_at Date time data when your customer pay the invoice. You will get this response when your invoice is paid
credit_card_charge_id Credit card charge ID when your customer pay the invoice with credit card. You will get this response when your invoice is paid with Credit Card
payment_method Payment method that is used when a customer pays the invoice. You will get this response when your invoice is paid
Example : ["BANK_TRANSFER", "CREDIT_CARD", "RETAIL_OUTLET",
"EWALLET"]
payment_channel The payment channel used when a customer pays the invoice. You will get this response when your invoice is paid
Example : ["BCA", "BRI", "MANDIRI",
"BNI", "PERMATA", "ALFAMART",
"OVO", "CREDIT_CARD"]
payment_destination Virtual Account number or Retail Outlet payment code used to pay the invoice (will not be shown for cards and e-wallet payments). You will get this response when your invoice is paid

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.

Recurring Payments

Create a Recurring Payment

Endpoint: Create Recurring Payment

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

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

Create Recurring Request (Money-in write permission)

Example: Create Recurring Request

curl https://api.xendit.co/recurring_payments -X POST \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
   -d external_id=recurring_31451441 \
   -d payer_email=sample_email@xendit.co \
   -d interval=MONTH \
   -d interval_count=1 \
   -d description='Monthly room cleaning service' \
   -d amount=125000
<?php
  require 'vendor/autoload.php';

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

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

  $external_id = 'recurring_31451441';
  $amount = 125000;
  $payer_email = 'sample_email@xendit.co';
  $interval = 'MONTH';
  $interval_count = 1;
  $description = 'Monthly room cleaning service';

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

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

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

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

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

Create Recurring Response

Example: Create Recurring Response

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

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

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

Create Recurring Payment 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.
INVALID_CREDIT_CARD_TOKEN_ERROR
400
Credit Card token is invalid.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

Get a Recurring Payment

Endpoint: Get a Recurring Payment

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

Get Recurring Payment Request (Money-in read permission)

Example Get Recurring Payment Request

curl https://api.xendit.co/recurring_payments/{id} \
  -X GET \
  -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Parameter Description
id
required
string ID of the recurring payment to retrieve

Get Recurring Response

Example Get Recurring Payment Response

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

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

Get Recurring Payment Errors

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

Edit Recurring Payment

Endpoint: Edit Recurring Payment

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

Edit Recurring Payment Request (Money-in write permission)

Example: Edit Recurring Payment Request

curl https://api.xendit.co/recurring_payments/579c8d61f23fa4ca35e52da3 \
   -X PATCH \
   -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
   -d amount=80000 \
   -d interval=WEEK \
   -d interval_count=2 \
   -d should_send_email=true \
   -d missed_payment_action=STOP \
   -d credit_card_token=522f0ba2ab70de5d2b409eee \
Parameter Description
id
required
string id of recurring you want to update
amount
optional
number Edit amount per invoice per interval.
The minimum amount to create an invoice is 10.000 IDR. The maximum amount is 1.000.000.000 IDR
credit_card_token
optional
string Multi use token ID for credit card autocharge. If it's empty then the autocharge is disabled. The token will still be there even if it's failed to charge
interval
optional
string Edit the frequency with which a recurring payment invoice should be billed. One of DAY, WEEK, MONTH.
interval_count
optional
number Edit the number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months.
should_send_email
optional
boolean Edit whether the end user get email when invoice is created, paid, or expired; or not
invoice_duration
optional
number duration of time that end user have in order to pay the invoice before it's expired (in Second). If it's not filled, invoice_duration will follow your business default invoice duration.

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

Edit Recurring Payment Response

Example: Edit Recurring Payment Response

{
    "id": "579c8d61f23fa4ca35e52da3",
    "user_id": "5781d19b2e2385880609791c",
    "external_id": "recurring_31451441",
    "status": "ACTIVE",
    "amount": 80000,
    "payer_email": "sample_email@xendit.co",
    "description": "Monthly room cleaning service",
    "interval": "WEEK",
    "interval_count": 2,
    "invoice_duration": 86400,
    "should_send_email": true,
    "missed_payment_action": "STOP",
    "recurring_payment_url": "https://xen.to/r/579c8d61f23fa4ca35e52da3",
    "credit_card_token": "522f0ba2ab70de5d2b409eee",
    "created": "2017-06-12T14:00:00.306Z",
    "updated": "2017-06-12T14:00:00.306Z"
}

All response parameters will be the same as get recurring

Edit Recurring Payment Errors

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

Stop Recurring Payment

Endpoint: Stop Recurring

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

Stop Recurring Payment Request (Money-in write permission)

Example: Stop Recurring Payment Request

curl https://api.xendit.co/recurring_payments/{id}/stop! -X POST \
    -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
  require 'vendor/autoload.php';

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

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

  $id = '579c8d61f23fa4ca35e52da3';

  $response = $xenditPHPClient->stopRecurring($id);
  print_r($response);
?>
Parameter Description
id
required
string ID of the recurring payment to stop

Stop Recurring Response

Example: Stop Recurring Payment Response

{
    "id": "579c8d61f23fa4ca35e52da3",
    "user_id": "5781d19b2e2385880609791c",
    "external_id": "recurring_31451441",
    "status": "STOPPED",
    "amount": 125000,
    "payer_email": "sample_email@xendit.co",
    "description": "Monthly room cleaning service",
    "interval": "MONTH",
    "interval_count": 1,
    "invoice_duration": 86400,
    "should_send_email": true,
    "missed_payment_action": "IGNORE",
    "recurring_payment_url": "https://xen.to/r/579c8d61f23fa4ca35e52da3",
    "credit_card_token": "586f0ba2ab70de5d2b409e0d",
    "created": "2017-06-12T14:00:00.306Z",
    "updated": "2018-06-12T14:00:00.306Z"
}

All response parameters will be the same as get recurring

Stop Recurring Payment Errors

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

Pause Recurring Payment

Endpoint: Pause Recurring Payment

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

Pause Recurring Payment Request (Money-in write permission)

Example Pause Recurring Payment Request

curl https://api.xendit.co/recurring_payments/{id}/pause!
  -X POST \
  -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Parameter Description
id
required
string ID of the recurring payment to pause

Pause Recurring Payment Response

Example Pause Recurring Response

{
    "id": "579c8d61f23fa4ca35e52da3",
    "user_id": "5781d19b2e2385880609791c",
    "external_id": "recurring_31451441",
    "status": "PAUSED",
    "amount": 125000,
    "payer_email": "sample_email@xendit.co",
    "description": "Monthly room cleaning service",
    "interval": "MONTH",
    "interval_count": 1,
    "invoice_duration": 86400,
    "should_send_email": true,
    "missed_payment_action": "IGNORE",
    "recurring_payment_url": "https://xen.to/r/579c8d61f23fa4ca35e52da3",
    "credit_card_token": "586f0ba2ab70de5d2b409e0d",
    "created": "2017-06-12T14:00:00.306Z",
    "updated": "2018-06-12T14:00:00.306Z"
}

All response parameters will be the same as get recurring

Pause Recurring Payment Errors

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

Resume Recurring Payment

Endpoint: Resume Recurring

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

Resume Recurring Request (Money-in write permission)

Example Resume Recurring Request

curl https://api.xendit.co/recurring_payments/{id}/resume!
  -X POST \
  -u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Parameter Description
id
required
string ID of the recurring payment to resume

Resume Recurring Response

Example Resume Recurring Response

{
    "id": "579c8d61f23fa4ca35e52da3",
    "user_id": "5781d19b2e2385880609791c",
    "external_id": "recurring_31451441",
    "status": "ACTIVE",
    "amount": 125000,
    "payer_email": "sample_email@xendit.co",
    "description": "Monthly room cleaning service",
    "interval": "MONTH",
    "interval_count": 1,
    "invoice_duration": 86400,
    "should_send_email": true,
    "missed_payment_action": "IGNORE",
    "recurring_payment_url": "https://xen.to/r/579c8d61f23fa4ca35e52da3",
    "credit_card_token": "586f0ba2ab70de5d2b409e0d",
    "created": "2017-06-12T14:00:00.306Z",
    "updated": "2018-06-12T14:00:00.306Z"
}

All response parameters will be the same as get recurring

Resume Recurring Payment Errors

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

Recurring Callback

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

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

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




Get List of Payments

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

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

Get List of Payments Request (Money-in read permission)

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















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 (Money-out write permission)

Example Create Disbursement Request

<?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 account holder as per the bank's or e-wallet's records. Used for verification and error/customer support scenarios.

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

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

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

description
required
string Description to send with the disbursement

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

Characters Numerical integers, no decimals
Maximum limit (BCA, Mandiri, BNI, BNI Syariah, BRI, Sinarmas, CIMB, Permata) No limit***
Minimum limit (BCA, Mandiri, BNI, BNI Syariah, BRI, Sinarmas, CIMB, Permata) 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.

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

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

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.
RECIPIENT_ACCOUNT_NUMBER_ERROR
400
For transfers to BCA, account_number input needs to be 10 digits. Check the account number length before retrying.
RECIPIENT_AMOUNT_ERROR
400
The transfer amount requested is lower than the prescribed minimum for the chosen destination bank. Amend the transfer amount before retrying.
MAXIMUM_TRANSFER_LIMIT_ERROR
400
The transfer amount requested is higher than the prescribed maximum for the chosen destination bank. Amend the transfer amount before retrying.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here
SERVER_ERROR
500
Error connecting to our server. Please use Get disbursement by external_id API to check whether the disbursement has already been created. If you receive DIRECT_DISBURSEMENT_NOT_FOUND_ERROR, the disbursement has not been created; please retry the disbursement request in 1-2 hours.

Get disbursement by id

Endpoint: Get Disbursement by id

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

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

Get Disbursement Request (Money-out read permission)

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

Get Disbursement Errors

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

Get 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 (Money-out read permission)

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

Get Disbursement Errors

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

Disbursement callback

Endpoint: Disbursement Callback

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

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

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). We also support disbursements to major e-wallets (GoPay, OVO, and Mandiri e-cash). If you would like us to support payment to a specific destination, please contact us at support@xendit.co.

Get Available Disbursement Banks Response (Money-out read permission)

Get Available Disbursement Banks Response

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

Batch Disbursement

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

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

Create batch disbursement

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

Endpoint: Create Batch Disbursement

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

Create batch disbursement request (Money-out write permission)

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.
REQUEST_FORBIDDEN_ERROR
403
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here

Batch disbursement callback

Endpoint: Disbursement Callback

POST https://yourcompany.com/disbursement_callback_url

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

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

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 (Money-out read permission)

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

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, key not live
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.