Introduction
Welcome! Here at Xendit, our mission is to provide payments infrastructure that helps you succeed. We help with both the money in (accepting payments) and money out (disbursing payments). Use cases range from platform business to eCommerce, SaaS, and everything else in between.
The Xendit API is organized around REST. Our API has predictable, resource-oriented URLs, and uses HTTP response codes to indicate API errors. We use built-in HTTP features and HTTP verbs, which are understood by off-the-shelf HTTP clients. JSON is returned by all API responses, including errors.
To make it easier to get familiar with our APIs, we've published a Postman Collection so that you can see examples of all of Xendit APIs in one place.
See our Postman Guide to get started!
Authentication
To successfully authenticate with Xendit's APIs, you must authenticate your secret API key using
Basic Auth
. You can obtain your API keys in Dashboard. For example if your API key is
xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==
Select
Basic Auth
authentication. Input secret API key inusername
and leave thepassword
empty
Basic Auth format
{{username}}:{{password}}
Following the format (with colon)
xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==:
Encode
Basic Auth
format above intoBase64
format
eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==
Include
Base64
encoded value in HTTP(s) header
Authorization: Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==
Xendit API is organized around REST to make it cleaner and easier to understand. All our API responses return JSON. To let you explore our APIs, make sure that you have registered an account. You can obtain and manage your API keys in API Keys Settings. We provide you API keys for both the test and live environments.
To authenticate your account, you have to include your secret API key in the request which can be accessed in Xendit Dashboard. Here are the steps to authenticate your account:
- Generate secret API key
- Obtain your secret API key from Dashboard
- Select Basic Access Authentication or
BASIC AUTH
authentication BASIC AUTH
format will be{{username}}:{{password}}
- Input Secret API key as
username
and leave thepassword
empty. Make sure to include:
at the end - Encode the value above into Base64 format
- Include the base64 encoded into
Authorization
header
All the API requests should be made over HTTPS instead of HTTP (all calls made over plain HTTP will fail). All requests made in the test environment will never hit the banking networks and will not cost you anything. Your API keys should be kept private so do not share your secret API keys. Learn more about API key here
Libraries / SDKs
Xendit has official libraries for different programming languages and mobile platforms. We are continuously developing more libraries and plugins. If you have implemented your own library or an example that you would like to share, send us a link to your code and we'll be happy to add it to the list!
Node.js
Install via npm
npm install xendit-node
See the source on Github
Node.js library is a server-side library that helps you to integrate Xendit easily using Node.js.
List of Supported Products
- Credit/debit cards
- eWallets
- Cardless Credit
- QR Codes
- Customers
- Direct Debit
- Bank Transfer via Virtual Accounts
- Retail Outlets
- Invoices
- Recurring Payments
- Payouts
- Disbursements
- Batch Disbursements
Installation
You can install our Node.js library using npm npm install xendit-node
or check out the source on Github
PHP
Download PHP package here
https://packagist.org/packages/xendit/xendit-php
PHP library is a client that is created on top of PHP so it is easier for you to integrate with us to accept payments via our supported payment channels.
You can visit our PHP library in Packagist
There are two versions of Xendit PHP libraries that we support:
- v2 (latest)
- v1
List of Supported Products - Xendit PHP v2
- Credit/debit cards
- eWallets
- Cardless Credit
- Bank Transfer via Virtual Accounts
- Retail Outlets
- Invoices
- Recurring Payments
- Payouts
- Disbursements
- Batch Disbursements
List of Supported Products - Xendit PHP v1
- Credit/debit cards
- Bank Transfer via Virtual Accounts
- Invoices
- Disbursements
Installation and Upgrade Guide
Check out our Github source to learn on how to install or upgrade Xendit PHP library
Java
Install Xendit in your Java code
Maven
<dependency>
<groupId>com.xendit</groupId>
<artifactId>xendit-java-lib</artifactId>
<version>1.0.0</version>
<type>pom</type>
</dependency>
Gradle
compile 'com.xendit:xendit-java-lib:1.0.0'
Import Xendit Library
import com.xendit.Xendit;
import com.xendit.exception.XenditException;
import com.xendit.model.AvailableBank;
import com.xendit.model.VirtualAccount;
Java library is a server-side library that helps you to integrate Xendit easily using Java.
List of Supported Products
- Credit/debit cards
- eWallets
- Cardless Credit
- Bank Transfer via Virtual Accounts
- Retail Outlets
- Invoices
- Recurring Payments
- Payouts
- Disbursements
- Batch Disbursements
Installation
Xendit Java library (Gradle and Maven) installation is easy and simple. For more detail about the steps, refer to the right section
- Add Xendit dependency in your Java code
- Import Xendit library
- Obtain your API keys in Dashboard to start using Xendit Java library APIs.
You can also learn more on our Github source for complete installation guide
Go
See the source on Github
Go library is a server-side library that helps you to integrate Xendit easily using Go programming language.
List of Supported Products
- Credit/debit cards
- eWallets
- Cardless Credit
- Bank Transfer via Virtual Accounts
- Retail Outlets
- Invoices
- Recurring Payments
- Payouts
- Disbursements
- Batch Disbursements
Installation
You can install our Go library by checking out our source on Github for complete installation guide
Python
Install via pip
pip install xendit-python
See the source on Github
Python library is a server-side library that helps you to integrate Xendit easily using Python.
List of Supported Products
- Credit/debit cards
- eWallets
- Cardless Credit
- QR Codes
- Direct Debit
- Bank Transfer via Virtual Accounts
- Retail Outlets
- Invoices
- Recurring Payments
- Payouts
- Disbursements
- Batch Disbursements
Installation
You can install our Python library using pip pip install xendit-python
or check out the source on Github
Android
Download Xendit Android SDK
https://github.com/xendit/xendit-sdk-android
Android SDK helps you to process digital payments using Xendit with features as follow:
- Tokenize credit/debit cards with single-use token
- Tokenize credit/debit cards with multiple-use token
- Authenticate credit/debit card transactions
iOS
Download Xendit iOS SDK
https://github.com/xendit/xendit-sdk-ios
iOS SDK helps you to process digital payments using Xendit with features as follow:
- Tokenize credit/debit cards with single-use token
- Tokenize credit/debit cards with multiple-use token
- Authenticate credit/debit card transactions
Versioning
Versioning Example
curl https://api.xendit.co/ewallets -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H X-API-VERSION='2020-02-01' \
-d external_id='ovo-ewallet' \
-d amount=1000 \
-d phone='08123123123'\
-d ewallet_type='OVO'
Xendit evolves APIs continuously to grow together with you. We always strive to make backward-compatible changes. When we introduce backward-incompatible changes, we release a new dated version to avoid breaking your code and you can upgrade to newer versions whenever you are ready.
To see what version you're running and upgrade to the latest one, visit your Dashboard. To test a specific API version, you can override your API version by attaching API-Version header in API requests
Header | Description |
---|---|
API-Version optional |
string Attach this parameter in the request to specify which API version you are going to request Format: YYYY-MM-DD . Example: 2020-02-01 Default value will follow your account API version settings |
Backward Compatibility
We consider the following changes to be backward compatible:
- Adding new API resources
- Adding new optional request parameters to existing API methods
- Adding new properties to existing API responses
- Changing the order of properties in existing API responses
- Changing the length or format of any object IDs
- Adding new error codes
- Adding new webhook event types
- Adding new properties to webhook payloads
Migration Guide
The following guide will help you to migrate from your current version to latest version safely
- Test new APis using explicit
API-Version
header in Test mode. Make sure you have handled new request,response, errors, and callback data correctly. Test scenarios can be found in Test Scenarios section - When everything is working as expected in Test mode, you can switch your Test mode API version in Dashboard. This switches the version used by API calls that don't have the
API-Version
header and also switches the version to render objects sent to your callback URLs - Repeat #1 and #2 respectively in Live mode
- When faced with any disruption during migration process, you can always switch back to previous versions
Changelog
Version Date | API | Resources Path | Changelog |
---|---|---|---|
2020-02-21 | eWallets | /ewallets |
Create OVO Payment will be processed asynchronously and callback will be sent after process has been completed |
2019-05-01 | Credit Cards | /credit_card_charges/refunds |
Create Refund will be processed synchronously |
Errors
Your Xendit integration might have to deal with errors at some point when making API requests to Xendit. These errors fall into a few major categories:
- Content errors occur because the content in the API request was invalid in some way. They return an HTTP response with a
4xx
error code. For example, the API servers might return a401
if an invalid API key was provided, or a400
if a required parameter was missing - Network errors occur as a result of intermittent communication problems between client and server. They return low-level errors, like socket or timeout exceptions. For example, a client might time out while trying to read from Xendit's servers, or an API response might never be received because a connection terminates prematurely. Note that a network errors wouldn't necessarily have otherwise been a successful request --- it can also be another type of error that's been cloaked by an intermittent problem
- Server errors occur because of a problem on Xendit's servers. Server errors return an HTTP response with a
5xx
error code. Xendit works to make these errors as rare as posslble, but integrations should be able to handle them when they do arise
The right approach and idempotency semantics to use for handling errors depend on the type of error being handled.
HTTP Status Code
Xendit uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx
range indicate success. Codes in the 4xx
range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a charge failed, etc). Codes in the 5xx
range indicate an error with Xendit's servers (these are rare).
Status Code | Description |
---|---|
200 - OK | Everything worked as expected |
400 - Bad Request | The request was unacceptable, often due to missing a required parameter |
401 - Unauthorized | No valid API key provided |
403 - Forbidden | The API key doesn't have permissions to perform the request |
404 - Not Found | The requested resources doesn't exist |
500 - Server Errors | Something went wrong on Xendit's end (These are rare) |
Error Code
Below are some of most common errors across all our endpoints. Specific errors are located under each endpoint.
Error Code | Description |
---|---|
API_VALIDATION_ERROR | Invalid request errors arise when your request has invalid parameters |
INVALID_API_KEY | No valid API key provided |
REQUEST_FORBIDDEN |
The API key doesn't have permissions to perform the request |
SERVER_ERROR | API errors cover any other type of problem (e.g. a temporary problem with Xendit's servers), and are extremely uncommon |
Error Handling
Safely retry requests with idempotency
A key part of web API design is the idea of idempotency, defined as being able to apply the same operation multiple times without changing the result beyond the first try. Because a certain amount of intermittent failure is to be expected, clients need a way of reconciling failed requests with a server, and idempotency provides a mechanism for that.
The Xendit API guarantees the idempotency of GET
requests, so it's always safe to retry them. Including an idempotency key makes POST
and PATCH
request idempotent, which prompts the API to do the bookkeeping required to prevent duplicate operations. For example, if a request to create disbursements does not respond due to network connection error, you can retry the request with the same idempotency key to guarantee that no more than one disbursement is created.
Idempotency keys are sent in the x-idempotency-key
header, and you should use them for all POST
requests to Xendit's API whenever supported. A few common strategies for generating idempotency keys are:
- Use an algorithm that generates a token with good randomness, like UUID v4
- Derive the key from a user-attached object like the ID of a shopping cart. This provides a relatively easy way to protect against double submissions
A response that's being replayed from the server because it had already executed previously can be identified by the error code DUPLICATE_TRANSACTION_ERROR
Content errors
Content errros are the result of the contents of an API request being invalid and return a 4xx
error code. Integrations should correct the original request and try again. Depending of the type of user error, it may be possible to handle the problem programmatically.
For a POST
operation using an idempotency key, as long as an API method began execution, Xendit's API servers will cache the results of the request regardless of what they were. A request that returns a 400
will send back the same 400
if followed by a new request with the same idempotency key. A fresh idempotency key should be generated when modifying the original request to get a successful result. The safest strategy where 4xx
errors are concerned is to always generate a new idempotency key.
Network errors
Network errors are the result of connectivity problems between client and server and tend to manifest as low-level errors like socket or timeout exceptions.
This class of errors is where the value of idempotency keys and request retries is most obvious. When intermittent problems occur, clients are usually left in a state where they don't know whether or not the server received the request. To get a definitive answer, they should retry such requests with the same idempotency keys and the same parameters until they're able to receive a result from the server. Sending the same idempotency with different parameters will produce an error indicating that the new request didn't match the original.
Server errors
Server errors are the result of a server-side problem and return a 5xx
error code. These errors are the most difficult to handle, so we try to ensure that they happen as infrequently as possible.
As with the errors, retrying them with the same idempotency key will usually produce the same result. The request can be retried with a new idempotency key, but we'd advice against it because it's possible for the original one to have produced side effects.
The result of a 500
request should be treated as indeterminate. The exact nature of any retroactive changes in the system depend heavily on the type of request. For example, if creating a disbursement returns a 500
error but we detect that the information has gone out to a payment network, we'll try to roll it forward and send callback after it has been completed. If not, we'll try to roll it back. However, ideal results under these circumstances are not guaranteed, and requests resulting in a 500
error may proeduce user-visible side effects.
Integration that want to maximize robustness must configure callback handlers that are capable of receiving events that have never been seen in an API response.
Callback
Xendit uses callback to notify your application any time an event happens on your account. Set up callback for events that Xendit doesn't already notify you of, like when a disbursement has been completed, a Virtual Account has been created and paid, or your invoice has expired.
Setup
You need to provide an endpoint in your system to receive callback from us. The callback notification will be sent over POST request to your callback URL that you have set. Setup your callback URL in Callback settings. You can use a tool like ngrok to make your endpoint available for receiving callback during testing.
Delivery Attempts and Retries
Understand how to view delivery attempts and retry logic when callback events aren't acknowledged
View events
When viewing information about a specific event through the Dashboard's Callback tab, you can check how many times Xendit attempted to send an event to the endpoint. This shows the latest response from your endpoint, a list of all attempted callback, and the respective HTTP status codes Xendit received.
Retry logic
Xendit attempts to deliver your callback six times with exponential backoff between each interval and will stop retrying until we have received response from your server or there is still no response yet
Retry Number | Interval (relative to last retry) | Interval (relative to original attempt) |
---|---|---|
1 | 15m | 15m |
2 | 45m | 1h |
3 | 2h | 3h |
4 | 3h | 6h |
5 | 6h | 12h |
6 | 12h | 24h |
Receive callback statistics via email
You can also receive summary of your callback statistics (number of success and failed callback) via email every 6 hours. You can enable this feature in Email Recipient settings
Event Handling
Handling callback events correctly is crucial to making sure your integration's business logic works as expected
Acknowledge events immediately
If your callback script performs complex logic, or makes network calls, it's possible that the script would time out before Xendit sees its complete execution. Ideally, your callback handler code (acknowledging receipt of an event by returning a 2xx
status code) is separate of any other logic you do for that event.
Handle duplicate events
Callback endpoints might occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing idempotent. One way of doing this is logging the events you've processed, and then not processing already-logged events.
Order of events
Xendit does not guarantee delivery of events in the order in which they are generated. Your endpoint should not expect delivery of these events in this order and should handle this accordingly. You can also use the API to fetch any missing objects.
Security
Keeping your endpoints secure is critical to protecting your customers' information. Xendit provides several ways for you to verify events are coming from Xendit in a secure manner.
Receive events with an HTTPS server
If you use an HTTPS URL for your callback endpoint, Xendit will validate that the connection to your server is secure before sending your callback data. For this to work, your server must be correctly configured to support HTTPS with a valid server certificate.
Verify events are sent from Xendit
Xendit can optionally sign the callback events it sends to your endpoints. We do so by including a token in each event's x-callback-token
header. This allows you to verify that the events were sent by Xendit, not by a third party.
Header Parameter | Description |
---|---|
x-callback-token |
string Your Xendit unique callback token to verify the origin of the callback |
Before you can verify tokens, you need to retrieve your callback token from Dashboard's Callback settings. Each secret is unique to each environments.
Balances
Get Balance
Endpoint: Get Balance
GET https://api.xendit.co/balance?account_type={account_type}
Balance is like your wallet since it will tell you how much money is available to you on Xendit. You can retrieve it to see the current balance on your Xendit cash account. Your balance is debited on any money out transaction, e.g. when performing disbursements or Xendit fees are charged. Your balance is credited when money comes into your account, e.g. invoices are paid or you deposit funds.
Request Parameters
Example Get Balance Request
curl https://api.xendit.co/balance -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=='); // this is Xendit API key example, you can go to Setting > API Key to get your API Key
$getBalance = \Xendit\Balance::getBalance('CASH');
var_dump($getBalance);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Balance } = x;
const balanceSpecificOptions = {};
const b = new Balance(balanceSpecificOptions);
const resp = await b.getBalance()
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Balance balance = Balance.get();
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := balance.GetParams{
AccountType: "CASH",
}
resp, err := balance.Get(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("balance: %+v\n", resp)
from xendit import Xendit, BalanceAccountType
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Balance = xendit_instance.Balance
balance = Balance.get(
account_type=BalanceAccountType.CASH,
)
print(balance)
Get Balance allows you to retrieve the balance of your cash and pending balance. Some use cases include: deciding when you may need to withdraw funds, and determining if you have funds to disburse
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Query Parameter | Type | Description |
---|---|---|
account_type optional default: CASH |
string |
The selected balance type available values: CASH , HOLDING , TAX |
Response Parameters
Example Get Balance Response
{
"balance": 1241231
}
Parameter | Description |
---|---|
balance | The balance remaining in your cash account |
Payment Channels
Get Payment Channels
Endpoint: Get Payment Channels API
GET https://api.xendit.co/payment_channels
Example Get Payment Channels
curl https://api.xendit.co/payment_channels -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Request Parameters
Returns an array of payment channel objects. Use this to identify which payment channels have been enabled for your business.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The Sub-account user-id that you want to make this transaction for This header is only used if you have access to xenPlatform. See xenPlatform for more information. |
Response Parameters
Example Get Payment Channels Response
[
{
"business_id": "xxxxxxxx",
"is_livemode": true,
"channel_code": "BRI",
"name": "BRI Virtual account",
"currency": "IDR",
"channel_category": "VIRTUAL_ACCOUNT",
"is_enabled": false
},
{
"business_id": "xxxxxxxx",
"is_livemode": true,
"channel_code": "MASTERCARD",
"name": "Mastercard credit and debit cards",
"currency": "IDR",
"channel_category": "CREDIT_CARD",
"is_enabled": true
},
{
"business_id": "xxxxxxxx",
"is_livemode": true,
"channel_code": "MASTERCARD",
"name": "Mastercard credit and debit cards",
"currency": "USD",
"channel_category": "CREDIT_CARD",
"is_enabled": true
}
...
]
Parameter | Type | Description |
---|---|---|
business_id required |
string |
Your business ID |
is_livemode required |
boolean |
true When making the request with your live API key. false when making the request with your test API key |
channel_code required |
string |
Payment channel code |
name required |
string |
Payment channel name |
currency required |
string |
Processing currency of the payment channel. Based on ISO 4217 currency code. |
channel_category required |
string |
Payment channel category. Available values: |
is_enabled required |
boolean |
When true , an API request can be successfully made for the business with the payment channel. When false , the API request will fail. You should activate the payment channel in the dashboard settings to make it successfully |
Customers
An API to manage end customer information. Supports storage of customer profiles for businesses and individuals, along with their KYC documentation and other account information. For use in support of various payment use-cases throughout the Xendit Payment APIs, including utilising the Direct Debit channel, to fulfil KYC requirements for remittance payments, or for enhanced payments reporting.
Customer Object
Example Customer Object
{
"id": "239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "demo_1475801962607",
"email": "customer@website.com",
"mobile_number": null,
"given_names": "John",
"description": null,
"middle_name": null,
"surname": "Doe",
"phone_number": "+6285300000000",
"nationality": "ID",
"addresses": [{
"country": "ID",
"street_line1": "Jalan Makan",
"street_line2": "Kecematan Kebayoran Baru",
"city": "Jakarta Selatan",
"province": "Daerah Khusus Ibukota Jakarta",
"state": null,
"postal_code": "12160"
}],
"date_of_birth": "2000-01-01",
"metadata": null
}
Version
You are currently viewing API version 2020-05-19. New version is available! Click here to view newer versions.
Parameter | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id |
string Unique ID generated by Xendit for the particular customer |
||||||||||||||||
reference_id |
string Identifer you provided during request |
||||||||||||||||
mobile_number |
string Mobile number of the customer |
||||||||||||||||
string Email address of the customer |
|||||||||||||||||
given_names |
string Primary of first name/s of the customer |
||||||||||||||||
middle_name |
string Middle name of the customer |
||||||||||||||||
surname |
string Surname of the customer |
||||||||||||||||
description |
string Description you provided for the customer object |
||||||||||||||||
phone_number |
string Alternate or landline phone number |
||||||||||||||||
nationality |
string Country code for the customer's nationality |
||||||||||||||||
addresses |
object array Array of objects containing the specific customer's address information
|
||||||||||||||||
date_of_birth |
string Date of birth of the customer in YYYY-MM-DD format |
||||||||||||||||
metadata |
object A free-format JSON for additional information that you provded during request. |
Create Customer
A customer object is required in order to link a payment method for direct debit. This allows you to easily link and track payment methods and transactions.
Endpoint: Create Customer
POST https://api.xendit.co/customers
Version
You are currently viewing API version 2020-05-19. New version is available! Click here to view newer versions.
Create Customer - Request
Example Create Customer Request
curl https://api.xendit.co/customers -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d reference_id=demo_1475801962607 \
-d given_names="John" \
-d mobile_number="+6287774441111" \
-d email="customer@website.com" \
<?php
$url = "https://api.xendit.co/customers";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$data = [
"given_names" => "John",
"reference_id" => "demo_1475801962607",
"mobile_number" => "+6287774441111",
"email" => "customer@website.com"
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { Customer } = x;
const customerSpecificOptions = {};
const c = new Customer(customerSpecificOptions);
const resp = await c.createCustomer({
referenceID:'demo_1475801962607',
givenNames: 'John',
mobileNumber: '+6287774441111',
email: 'customer@website.com',
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
customer = DirectDebit.create_customer(
reference_id="merc-1594279037",
email="t@x.co",
given_names="Adyaksa",
)
print(customer)
Header | Description |
---|---|
for-user-id optional |
string The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Request Body Parameter | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
reference_id required |
string Merchant-provided identifier for the customer |
||||||||||||||||
mobile_number either mobile_number or email is required |
string Mobile number of the customer in E.164 international standard. Format: +(country code)(subscriber number)
|
||||||||||||||||
email either mobile_number or email is required |
string Email address of the customer |
||||||||||||||||
given_names required |
string Primary of first name/s of the customer |
||||||||||||||||
middle_name optional |
string Middle name of the customer |
||||||||||||||||
surname optional |
string Surname of the customer |
||||||||||||||||
description optional |
string Merchant-provided description for the customer object |
||||||||||||||||
phone_number optional |
string Alternate or landline phone number in E.164 international standard. Format: +(country code)(subscriber number)
|
||||||||||||||||
nationality optional |
string
2-letter ISO 3166-2 country code for the customer's nationality |
||||||||||||||||
addresses optional |
array of object Array of objects containing the specific customer's address informationEach object may have the following properties:
|
||||||||||||||||
date_of_birth optional |
string Date of birth of the customer in YYYY-MM-DD format |
||||||||||||||||
metadata optional |
object A free-format JSON for additional information that you may use. |
Create Customer - Response
Example Create Customer Success Response
{
"id": "239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "demo_1475801962607",
"email": "customer@website.com",
"mobile_number": null,
"given_names": "John",
"description": null,
"middle_name": null,
"surname": null,
"phone_number": null,
"nationality": null,
"addresses": null,
"date_of_birth": null,
"metadata": null
}
Parameter | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id |
string Unique ID generated by Xendit for the particular customer |
||||||||||||||||
reference_id |
string Identifer you provided during request |
||||||||||||||||
mobile_number |
string Mobile number of the customer |
||||||||||||||||
string Email address of the customer |
|||||||||||||||||
given_names |
string Primary of first name/s of the customer |
||||||||||||||||
middle_name |
string Middle name of the customer |
||||||||||||||||
surname |
string Surname of the customer |
||||||||||||||||
description |
string Description you provided for the customer object |
||||||||||||||||
phone_number |
string Alternate or landline phone number |
||||||||||||||||
nationality |
string Country code for the customer's nationality |
||||||||||||||||
addresses |
object array Array of objects containing the specific customer's address information
|
||||||||||||||||
date_of_birth |
string Date of birth of the customer in YYYY-MM-DD format |
||||||||||||||||
metadata |
object A free-format JSON for additional information that you provded during request. |
Create Customer - Errors
See other common errors here.
Error Code | Description |
---|---|
DUPLICATE_ERROR 409
|
The provided reference_id has been used before. Please enter a unique reference_id and try again. |
Get Customer by Reference ID
Retrieves an array with a customer object that matches the provided reference_id
- the identifier provided by you
Endpoint: Get Customer by Reference ID
GET https://api.xendit.co/customers?reference_id={reference_id}
Version
You are currently viewing API version 2020-05-19. New version is available!
Get Customer by Reference ID - Request
Example Get Customer by Reference ID Request
curl https://api.xendit.co/customers?reference_id=demo_1475801962607 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$url = "https://api.xendit.co/customers";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$queryString = "?reference_id=demo_1475801962607";
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url.$queryString);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { Customer } = x;
const customerSpecificOptions = {};
const c = new Customer(customerSpecificOptions);
const resp = await c.getCustomerByReferenceID({
referenceID: 'demo_1475801962607',
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
customer = DirectDebit.get_customer_by_ref_id(
reference_id="merc-1594279037",
)
print(customer)
Query String Parameter | Description |
---|---|
reference_id required |
string Merchant-provided identifier for the customer |
Get Customer by Reference ID - Response
Example Get Customer by Reference ID Success Response
[{
"id": "239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "demo_1475801962607",
"email": "customer@website.com",
"mobile_number": null,
"given_names": "John",
"description": null,
"middle_name": null,
"surname": null,
"phone_number": null,
"nationality": null,
"addresses": null,
"date_of_birth": null,
"metadata": null
}]
Header | Description |
---|---|
for-user-id optional |
string The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Parameter | Description |
---|---|
id |
string Unique ID generated by Xendit for the particular customer |
reference_id |
string Identifer you provided during request |
mobile_number |
string Mobile number of the customer |
string Email address of the customer |
|
given_names |
string Primary of first name/s of the customer |
middle_name |
string Middle name of the customer |
surname |
string Surname of the customer |
description |
string Description you provided for the customer object |
phone_number |
string Alternate or landline phone number |
nationality |
string Country code for the customer's nationality |
addresses |
object array Array of objects containing the specific customer's address information |
date_of_birth |
string Date of birth of the customer in YYYY-MM-DD format |
metadata |
object A free-format JSON for additional information that you provded during request. |
Get Customer by Reference ID - Errors
See other common errors here.
Files
An API to store and manage files for any purpose. Files may be used in any payments endpoint, including for example, KYC documentation for customers and remittance payments, or providing evidence to help support chargeback investigations.
Upload File
Make a POST request to this endpoint to upload a file. We currently support uploading PNG, JPG/JPEG, PDF files of less than 10 MB.
Endpoint: Upload File
POST https://api.xendit.co/files
Request parameters
Example Upload File Request
curl https://api.xendit.co/files -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
--form 'file=@/Users/utkarshagarwal/Desktop/Screenshot 2020-10-13 at 5.28.45 PM.png' \
--form 'purpose=CHARGEBACK_EVIDENCE'
<?php
$url = "https://api.xendit.co/files";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==";
$headers = [];
$headers[] = "Content-Type: application/json";
$payload = array('file'=> new CURLFILE('~/yourpath/file.png'),'purpose' => 'CHARGEBACK_EVIDENCE');
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==";
let url = "https://api.xendit.co/files";
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
var formdata = new FormData();
formdata.append("file", fileInput.files[0], "file.png");
formdata.append("purpose", "CHARGEBACK_EVIDENCE");
var requestOptions = {
method: 'POST',
headers: headers,
body: formdata,
redirect: 'follow'
};
fetch(url, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
import requests
import base64
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
url = "https://api.xendit.co/files"
api_key_bytes = api_key.encode('ascii')
base64_bytes = base64.b64encode(api_key_bytes)
base64_token = base64_bytes.decode('ascii')
payload={'purpose': 'CHARGEBACK_EVIDENCE'}
files=[
('file', open('/yourpath/file.png','rb'))
]
auth_token = 'Basic ' + base64_token
headers = {
'Authorization': auth_token
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
Body Parameter | Type | Description |
---|---|---|
purposerequired |
string |
Purpose of the file being uploaded Supported values: KYC_DOCUMENT , CHARGEBACK_EVIDENCE |
filerequired |
file |
The file. Supported types: application/pdf , image/png , image/jpg , image/jpeg |
Response parameters
Example Upload File Success Response
{
"id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412",
"business_id": "ec700c1c-db17-4496-b1fb-04ebe551b412",
"purpose": "CHARGEBACK_EVIDENCE",
"created": "2020-10-08T06:38:33.479Z",
"updated": "2020-10-08T06:38:33.479Z",
"type": "image/png",
"size": 10000,
"url": "https://files.xendit.co/file-ec700c1c-db17-4496-b1fb-04ebe551b412"
}
Body Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique ID generated by Xendit for the particular file |
business_idrequired |
string |
Your Xendit business id |
purposerequired |
string |
Purpose of the file |
createdrequired |
string |
UTC Timestamp of file upload in ISO format |
updatedrequired |
string |
UTC Timestamp of last file update in ISO format |
typerequired |
string |
Type of the file |
sizerequired |
integer |
Size of the file in bytes |
urlrequired |
string |
URL to download the file |
Error Codes
See other common errors here.
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
FILE_TOO_LARGE413 |
The file size is greater than 2000000 bytes and exceeded size limits. Please compress the payload before retrying |
UNSUPPORTED_CONTENT_TYPE415 |
The file format is not supported. Please review the file type before retrying |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
RATE_LIMIT_EXCEEDED 429 |
You have reached the rate limit for file transfer. Please exponentially back off requests until you no longer receive this error |
Get File by Id
Make a GET request to this endpoint to get file details
Endpoint: Get File
GET https://api.xendit.co/files/{file-id}
Example Get File Request
curl https://api.xendit.co/files/file-ec700c1c-db17-4496-b1fb-04ebe551b412 --request GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$fileId = "file-ec700c1c-db17-4496-b1fb-04ebe551b412";
$url = "https://api.xendit.co/files/" . $fileId;
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==";
let fileId= "file-ec700c1c-db17-4496-b1fb-04ebe551b412";
let url = "https://api.xendit.co/files/"+fileId;
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
var requestOptions = {
method: 'GET',
headers: headers,
redirect: 'follow'
};
fetch(url, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
import requests
import base64
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
url = "https://api.xendit.co/files/file-ec700c1c-db17-4496-b1fb-04ebe551b412"
api_key_bytes = api_key.encode('ascii')
base64_bytes = base64.b64encode(api_key_bytes)
base64_token = base64_bytes.decode('ascii')
payload={}
auth_token = 'Basic ' + base64_token
headers = {
'Authorization': auth_token
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
Response parameters
Example Get File Success Response
{
"id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412",
"business_id": "ec700c1c-db17-4496-b1fb-04ebe551b412",
"purpose": "CHARGEBACK_EVIDENCE",
"created": "2020-10-08T06:38:33.479Z",
"updated": "2020-10-08T06:38:33.479Z",
"type": "image/png",
"size": 10000,
"url": "https://files.xendit.co/file-ec700c1c-db17-4496-b1fb-04ebe551b412"
}
Body Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique ID generated by Xendit for the particular file |
business_idrequired |
string |
Your Xendit business id |
purposerequired |
string |
Purpose of the file |
createdrequired |
string |
UTC Timestamp of file upload in ISO format |
updatedrequired |
string |
UTC Timestamp of last file update in ISO format |
typerequired |
string |
Type of the file |
sizerequired |
integer |
Size of the file in bytes |
urlrequired |
string |
URL to download the file |
Error Codes
See other common errors here.
Error Code | Description |
---|---|
DATA_NOT_FOUND 404 |
File not found for the given id |
Download File by Id
Make a GET request to this endpoint to download a file
Endpoint: Download File
GET https://api.xendit.co/files/{file-id}/download
Example Download File Request
curl https://api.xendit.co/files/file-ec700c1c-db17-4496-b1fb-04ebe551b412/download --request GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$fileId = "file-ec700c1c-db17-4496-b1fb-04ebe551b412";
$url = "https://api.xendit.co/files/" . $fileId . "/download";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==";
let fileId= "file-ec700c1c-db17-4496-b1fb-04ebe551b412";
let url = "https://api.xendit.co/files/"+fileId+"/download";
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
var requestOptions = {
method: 'GET',
headers: headers,
redirect: 'follow'
};
fetch(url, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
import requests
import base64
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
url = "https://api.xendit.co/files/file-ec700c1c-db17-4496-b1fb-04ebe551b412/download"
api_key_bytes = api_key.encode('ascii')
base64_bytes = base64.b64encode(api_key_bytes)
base64_token = base64_bytes.decode('ascii')
payload={}
auth_token = 'Basic ' + base64_token
headers = {
'Authorization': auth_token
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response)
Error Codes
See other common errors here.
Error Code | Description |
---|---|
DATA_NOT_FOUND 404 |
File not found for the given id |
RATE_LIMIT_EXCEEDED 429 |
You have reached the rate limit for file transfer. Please exponentially back off requests until you no longer receive this error |
Delete File by Id
Make a Delete request to this endpoint to delete the file
Endpoint: Delete File
DELETE https://api.xendit.co/files/{file-id}
Example Delete File Request
curl https://api.xendit.co/files/file-ec700c1c-db17-4496-b1fb-04ebe551b412 --request DELETE \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$fileId = "file-ec700c1c-db17-4496-b1fb-04ebe551b412";
$url = "https://api.xendit.co/files/" . $fileId;
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==";
let fileId= "file-ec700c1c-db17-4496-b1fb-04ebe551b412";
let url = "https://api.xendit.co/files/"+fileId;
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
var requestOptions = {
method: 'DELETE',
headers: headers,
redirect: 'follow'
};
fetch(url, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
import requests
import base64
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
url = "https://api.xendit.co/files/file-ec700c1c-db17-4496-b1fb-04ebe551b412"
api_key_bytes = api_key.encode('ascii')
base64_bytes = base64.b64encode(api_key_bytes)
base64_token = base64_bytes.decode('ascii')
payload={}
auth_token = 'Basic ' + base64_token
headers = {
'Authorization': auth_token
}
response = requests.request("DELETE", url, headers=headers, data=payload)
print(response.text)
Response parameters
Example Delete File Success Response
{
"is_deleted": true,
"id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412",
"business_id": "b647524d-9c5d-414c-843a-3c819853d6b0"
}
Body Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique ID generated by Xendit for the particular file |
business_idrequired |
string |
Your Xendit business id |
is_deletedrequired |
boolean |
Deletion status. True if file was successfully deleted |
Error Codes
See other common errors here.
Error Code | Description |
---|---|
DATA_NOT_FOUND 404 |
File not found for the given id |
Credit Cards
Our Credit Cards API enables you to seamlessly charge Indonesian and international credit / debit cards from major schemes: Visa, MasterCard and JCB. To accept AMEX payments, you'll need your own merchant account with Bank Central Asia in Indonesia.
Our APIs are designed to be modular so you can have full control over each step of the card payment process. No sensitive card data will reach your servers when using Xendit - we take care of that for you. We build our integrations to optimize card acceptance rates for all the cards that we help you accept. To date, we've charged cards from over 100 countries.
For full details on each API as well as help on integration, please refer to our documentation.
Using a plugin like Shopify or WooCommerce (Wordpress)? Xendit supports card payments on these as well, see here.
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. It is important to pass us the details of the cardholder such as their contact details and billing/shipping details, as these will be used for 3DS authentication later on.
Example tokenData object with billing details
{
"amount": "10000",
"card_data": {
"account_number": "4456530000001096",
"exp_month": "12",
"exp_year": "2020"
},
"card_cvn": "123",
"is_multiple_use": false,
"should_authenticate": true,
"billing_details": {
"given_names": "John",
"surname": "Hudson",
"email": "john@xendit.co",
"mobile_number": "+6208123123123",
"phone_number": "+6208123123123",
"address": {
"country": "ID",
"street_line1": "Panglima Polim IV",
"street_line2": "Ruko Grand Panglima Polim, Blok E",
"city": "Jakarta Selatan",
"province_state": "DKI Jakarta",
"postal_code": "12345"
}
}
}
Example tokenData object with customer object
{
"amount": "10000",
"card_data": {
"account_number": "4456530000001096",
"exp_month": "12",
"exp_year": "2020"
},
"card_cvn": "123",
"is_multiple_use": false,
"should_authenticate": true,
"customer": {
"reference_id": "123e4567-e89b-12d3-a456-426614174000",
"mobile_number": "+6208123123123",
"email": "john@xendit.co",
"given_names": "John",
"surname": "Hudson",
"phone_number": "+6208123123123",
"nationality": "ID",
"addresses": [{
"country": "ID",
"street_line1": "Panglima Polim IV",
"street_line2": "Ruko Grand Panglima Polim, Blok E",
"city": "Jakarta Selatan",
"province_state": "DKI Jakarta",
"postal_code": "12345",
"category": "WORK"
}],
"date_of_birth": "1990-04-13",
"description": "customer using promo",
"metadata": {}
}
}
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 for web application. For SDK implementation, please refer to Xendit Documentation for Android SDK and IOS SDK.
Single Use Tokens
For single-use tokens, authentication is performed by default, and so the amount
field is also required. If optional authentication is enabled on your account, it can be bypassed by setting should_authenticate
to false.
Multiple Use Tokens
When tokenizing a card for multi-use, the amount
field is optional. If you want to use Authentication for a multi-use token, the amount
field must be specified during Authentication. See Create Authentication for more details.
Request Parameters (Money-in write permission)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description | |||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
amount optional |
string |
The charge amount. Only required for single use tokens with bundled authentication. | |||||||||||||||||||||||||||||||||||||||||||
card_number required |
string |
Card number which will be converted into a secured token | |||||||||||||||||||||||||||||||||||||||||||
card_exp_month required |
string |
Card expiration month | |||||||||||||||||||||||||||||||||||||||||||
card_exp_year required |
string |
Card expiration year | |||||||||||||||||||||||||||||||||||||||||||
card_cvn optional |
string |
Three digit code written on the back of the card (usually called CVV/CVN). Optional but highly recommended. Required for cards issued in Europe. | |||||||||||||||||||||||||||||||||||||||||||
is_multiple_use optional default: false |
boolean |
Whether or not to save token for multiple use | |||||||||||||||||||||||||||||||||||||||||||
currency optional default: IDR |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. Xendit supports IDR and PHP by default. Other currencies are supported only if you are using your own MIDs. If left blank, defaults to IDR | |||||||||||||||||||||||||||||||||||||||||||
should_authenticate default:
|
boolean |
Whether or not to bundle authentication with tokenization. By default, authentication is required for all transactions. You can request to enable optional authentication via your Xendit Dashboard. |
|||||||||||||||||||||||||||||||||||||||||||
billing_details optional |
object |
Billing details of the cardholder. If entered, should correspond with billing details registered by the cardholder with their issuer. These are required for US / CA / UK cards to be verified by the Address Verification System (AVS), and are also required for 3DS 2.0 authentication. billing details child parameters
|
|||||||||||||||||||||||||||||||||||||||||||
customeroptional |
object |
Information about your customer (the cardholder), e.g. their contact details. Sending these details is recommended as they are needed for the best authentication protocols, improving acceptance rates and fraud prevention. Use this object to pass Xendit the customer’s shipping address if they provide it. Customer object child parameters
| |
Example Tokenization Response
{
"id": "5fcd8deb93e9a90020d8fd2d",
"masked_card_number": "445653XXXXXX1096",
"authentication_id": "5fcd8deb93e9a90020d8fd2e",
"status": "IN_REVIEW",
"card_info": {
"bank": "PT. Bank Rakyat Indonesia (Persero)",
"country": "ID",
"type": "CREDIT",
"brand": "VISA"
},
"payer_authentication_url": "https://redirect-staging.xendit.co/redirects/authentications/bundled/5fcd8deb93e9a90020d8fd2d?api_key=xnd_public_development_bPgL7lc65YTfywEk10f5qneRuu537yonRbfgQRMBLPUr1mZP4nNVd7iNHU"
}
Response Parameters
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
id required |
string |
The token ID. This will be used later to Charge the funds from the credit card. | ||||||||||
authentication_id required |
string |
ID for the authentication process. This should be attached during charge in authentication_id field | ||||||||||
masked_card_number required |
string |
The first 6 digits and last 4 digits of the tokenized card. | ||||||||||
statusrequired |
string |
Tokenization status. See Tokenization Statuses | ||||||||||
payer_authentication_url optional |
string |
Returned only if authentication is bundled with tokenization, and the status returned is IN_REVIEW. This field contains the URL to the page for users to authenticate themselves using 3DS. See Tokenization Statuses. | ||||||||||
failure_reason optional |
string |
If the tokenization status is FAILED, this describes the reason for failure. See Tokenization Failure Reasons | ||||||||||
card_info optional |
object |
Information of the card that's already tokenized. card info child parameters
|
Statuses
Status | Description |
---|---|
IN_REVIEW | Returned only if authentication is bundled with tokenization, and therefore the customer must authenticate their identity. Xendit provides a URL which you should navigate your users to for easily performing 3DS. |
VERIFIED | This means that a token was successfully created. If authentication was bundled with tokenization, it also means that the user has successfully authenticated their identity via 3DS. It is now safe to send the token to your backend for charging. |
FAILED | Returned only if authentication is bundled with tokenization, and authentication has failed. Will always return AUTHENTICATION_FAILED as the failure reason.The token will still be created and authentication can be attempted again using the created token. |
Failure Reasons
Failure Reason | Description |
---|---|
AUTHENTICATION |
This status means the customer tried to authenticate using 3DS but did not successfully complete the authentication. |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not valid JSON. |
ACCOUNT_NUMBER400 |
Credit card number is invalid. |
VALIDATION_ERROR 400 |
Data was passed in an incorrect format. |
BRAND_NOT400 |
Card brand is not supported. Ask user to try a Visa/Mastercard. |
AUTHENTICATION400 |
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_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
VERIFICATION408 |
The credit card network timed out when trying to tokenize the card. |
TEMPORARY503 |
There was a problem with the credit card network, which prevents tokenization. |
CONNECTION_ERROR 500 |
Error connecting to our server. Try again and if the error persists, try with another device/network. |
Get Token
Definition: Get Token
GET https://api.xendit.co/credit_card_tokens/:credit_card_token_id
Example Get Token Request Using Token ID (Default)
curl https://api.xendit.co/credit_card_tokens/605c05d3f81fa60011b2fa4e \
-X GET \
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==:
Example Get Token Response
{
"business_id": "602103396f17450020ca2246",
"created": "2021-03-25T03:38:59.318Z",
"id": "605c05d3f81fa60011b2fa4e",
"status": "VALID",
"card_expiration_month": "12",
"card_expiration_year": "2025",
"metadata": {
"bank": "PT. Bank Rakyat Indonesia (Persero)",
"country_code": "US",
"type": "CREDIT",
"brand": "VISA",
},
"card_info": {
"bank": "PT. Bank Rakyat Indonesia (Persero)",
"country": "ID",
"type": "CREDIT",
"brand": "VISA",
"card_art_url": "",
"fingerprint": "6021f7d3717e0500115fbb0d",
},
}
This is endpoint to get a token object. You need to specify the id
in the query parameter.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to the token for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Query Parameter | Type | Description |
---|---|---|
credit_card_token_id required |
string |
token id of credit card that has been tokenized. |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
CREDIT_CARD_TOKEN404 |
credit_card_token_id not found |
Create Authentication
Javascript Function: createAuthentication
Xendit.card.createAuthentication(authenticationData, function (err, data) {
if (err) {
//Define error handling
}
if (data.status === 'VERIFIED') {
// Handle success
} else if (data.status === 'IN_REVIEW') {
// Handle authentication (3DS)
} else if (data.status === 'FAILED') {
// Handle failure
}
});
To authenticate a token, use the Xendit.card.createAuthentication
function in Xendit.js. This function accepts an authenticationData
object and returns an authentication_id
which can be used to authenticate a charge. For more details on creating a charge, see Create Charge.
See our Authentication Sample for an example implementation.
Example authenticationData object
{
"amount": "10000",
"token_id": "58e2096018b815f555c8a524"
}
Example Authentication Response
{
"id": "58e2097218b815f555c8a526",
"status": "VERIFIED"
}
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
amount required |
string |
Authentication amount |
token_id required |
string |
Token to authenticate |
currency optional default: IDR |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code Supported currencies include IDR, PHP & USD. |
xenditResponseHandler required |
function |
Response handler, called after authentication attempt to handle errors and response. |
Response Parameters
Parameter | Type | Description |
---|---|---|
id required |
string |
Authentication ID returned by Xendit, used when creating a Charge. If authentication status is FAILED , this id will still be returned but authentication will need to be performed again. |
status required |
string |
Authentication status. See Tokenization Statuses |
payer_authentication_url optional |
string |
If status is IN_REVIEW , this contains the URL for authenticating users with 3DS |
failure_reason optional |
string |
If status is FAILED , this describes the failure. See Tokenization Failure Reasons. |
Failure Reasons
Failure Reason | Description |
---|---|
AUTHENTICATION |
The customer tried to authenticate using 3DS but did not successfully complete the authentication. |
Create Authorization
Definition: Create authorization
POST https://api.xendit.co/credit_card_charges
Example Create Authorization Request
curl -X POST \
https://api.xendit.co/credit_card_charges \
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
-d '{
"token_id" : "598d5d0e51e0870d44c61534",
"external_id": "postman-charge-1502436817",
"amount": 140000,
"authentication_id":"598d5d0f51e0870d44c61535",
"card_cvn":"123",
"capture":false
}'
<?php
require 'vendor/autoload.php';
$options['secret_api_key'] = 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==';
$xenditPHPClient = new XenditClient\XenditPHPClient($options);
$external_id = 'sample-external-id-1475459775872';
$token_id = 'sample-token-id-1475459775872';
$amount = 140000;
$authentication_id = '58e2097218b815f555c8a526';
$capture = false;
$response = $xenditPHPClient->captureCreditCardPayment($external_id, $token_id, $amount);
print_r($response);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);
const resp = await card.createAuthorization({
externalID: 'sample-external-id-1475459775872',
tokenID: 'sample-token-id-1475459775872',
amount: 140000,
authID: '58e2097218b815f555c8a526',
})
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
CreditCardCharge creditCardCharge = CreditCard.createAuthorization(
"token_id", // tokenId
"postman-charge-1502436793", // externalId
140000, // amount
"auth_id", // authenticationId
"123", // Card CVN
false // capture
);
} catch (XenditException e) {
e.printStackTrace();
}
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
CreditCard = xendit_instance.CreditCard
charge = CreditCard.create_authorization(
token_id="5f0410898bcf7a001a00879d",
external_id="card_preAuth-1594106356",
amount=75000,
card_cvn="123",
)
print(charge)
Example Create Authorization Response
{
"created": "2020-01-11T07:33:14.442Z",
"status": "AUTHORIZED",
"business_id": "5850e55d8d9791bd40096364",
"authorized_amount": 140000,
"external_id": "postman-charge-1502436793",
"merchant_id": "xendit",
"merchant_reference_code": "598d5d0d51e0870d44c61533",
"card_type": "CREDIT",
"masked_card_number": "400000XXXXXX0002",
"charge_type": "SINGLE_USE_TOKEN",
"card_brand": "VISA",
"bank_reconciliation_id": "5132390610356134503009",
"eci": "05",
"id": "598d5dba51e0870d44c61539"
}
You can do authorization using create charge endpoint. Just capture field as false, and you will receive an authorized charge response.
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.
Example Zero Amount Authorization Request
curl -X POST \
https://api.xendit.co/credit_card_charges \
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
-d '{
"token_id" : "598d5d0e51e0870d44c61534",
"external_id": "postman-charge-1502436817",
"amount": 0,
"authentication_id":"598d5d0f51e0870d44c61535",
"card_cvn":"123"
}'
<?php
require 'vendor/autoload.php';
$options['secret_api_key'] = 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==';
$xenditPHPClient = new XenditClient\XenditPHPClient($options);
$external_id = 'sample-external-id-1475459775872';
$token_id = 'sample-token-id-1475459775872';
$amount = 0;
$authentication_id = '58e2097218b815f555c8a526';
$response = $xenditPHPClient->captureCreditCardPayment($external_id, $token_id, $amount);
print_r($response);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);
const resp = await card.createAuthorization({
externalID: 'sample-external-id-1475459775872',
tokenID: 'sample-token-id-1475459775872',
amount: 0,
authID: '58e2097218b815f555c8a526',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
CreditCardCharge creditCardCharge = CreditCard.createAuthorization(
"token_id", // tokenId
"test_id", // externalId
0, // amount
"auth_id", // authenticationId
"123", // Card CVN
false // capture
);
} catch (XenditException e) {
e.printStackTrace();
}
Example Zero Amount Authorization Response
{
"created": "2020-01-11T07:33:14.442Z",
"status": "AUTHORIZED",
"business_id": "5850e55d8d9791bd40096364",
"authorized_amount": 0,
"external_id": "postman-charge-1502436793",
"merchant_id": "xendit",
"merchant_reference_code": "598d5d0d51e0870d44c61533",
"card_type": "CREDIT",
"masked_card_number": "400000XXXXXX0002",
"charge_type": "SINGLE_USE_TOKEN",
"card_brand": "VISA",
"bank_reconciliation_id": "5132390610356134503009",
"eci": "05",
"id": "598d5dba51e0870d44c61539"
}
Reverse Authorization
Definition: Reversing Authorized Charge
POST https://api.xendit.co/credit_card_charges/:charge_id/auth_reversal
Example Reverse Authorization
curl -X POST \
https://api.xendit.co/credit_card_charges/:charge_id/auth_reversal \
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-d '{
"external_id": "reverse-authorization-1502436817",
}'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '5ecc82736275b80019591c91';
$params = ['external_id' => 'reverse-authorization-1502436817'];
$reverseAuth = \Xendit\Cards::reverseAuthorization(
$id,
$params
);
var_dump($reverseAuth);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);
const resp = await card.reverseAuthorization({
externalID: 'reverse-authorization-1502436817',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
CreditCardReverseAuth creditCardReverseAuth = CreditCard.reverseAuthorization(
"1234567", //chargeId
"reverse-authorization-1502436817" //externalId
);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
reverseAuthorizationData := card.ReverseAuthorizationParams{
ChargeID: "123",
ExternalID: "reverse-authorization-1502436817",
}
reverseAuthorizationResp, err := card.ReverseAuthorization(&reverseAuthorizationData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("reversed authorization: %+v\n", reverseAuthorizationResp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
CreditCard = xendit_instance.CreditCard
reverse_authorization = CreditCard.reverse_authorizatiton(
credit_card_charge_id="5f0421fa8cc1e8001973a1d6",
external_id="reverse-authorization-1594106387",
)
print(reverse_authorization)
Example of request body
{
"external_id": "reverse-authorization-1502436817",
}
Example of Reverse Authorization Response
{
"status": "SUCCEEDED",
"currency": "IDR",
"credit_card_charge_id": "5ecc82640d679500199621ad",
"business_id": "5dd7928f4e6d9a2ec299ea43",
"external_id": "reverse-authorization-1502436817",
"amount": 5000,
"created": "2020-05-26T02:44:03.458Z",
"id": "5ecc82736275b80019591c91"
}
This API provides reversing charge when the charge has AUTHORIZED
status and hasn't yet captured.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
external_id required |
string |
Reverse authorization reference to help you track your request |
Response Parameters
Parameter | Type | Description |
---|---|---|
status required |
string |
Status of the reverse authorization. See Reverse Authorization Statuses. |
currency required |
string |
Currency of the charge that requested to be reversed. |
credit_card_charge_id required |
string |
The ID of the charge that requested to be reversed. |
business_id required |
string |
The ID of your business in Xendit. |
external_id required |
string |
Unique Identifier for your Reversed Charge reference |
amount required |
number |
The amount that requested to be reversed for this charge. |
created required |
string |
An ISO timestamp that tracks when the reverse authorization was made. |
id required |
string |
ID of the charge transaction in Xendit system that requested to be reversed. |
failure_reason optional |
string |
If status is FAILED, this describes the failure. See Reverse Authorization Failure Reasons. |
Statuses
Recommendation | Description |
---|---|
SUCCEEDED |
Reverse Authorization request is success |
FAILED |
Reverse Authorization is failed with detailed failure reason |
Failure Reasons
Failure Reason | Description |
---|---|
REVERSE_AUTHORIZATION_REJECTED_BY_BANK | The authorization that you requested to be reversed is rejected by the bank. There's possibility that the authorization is no longer valid and the authorized amount is already reversed back automatically to the card holder's credit balance. |
PROCESSOR_ERROR | The reverse authorization failed because there's an integration issue between card processor and the bank. Contact us if you encounter this issue. |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
CHARGE_ALREADY_REVERSED400 |
Charge already reversed, therefore cannot be reversed |
CHARGE_ALREADY_CAPTURED400 |
Charge already captured, therefore cannot be reversed |
CHARGE_FAILED400 |
Charge is failed, therefore cannot be reversed |
REQUEST_FORBIDDEN403 |
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_CHARGE404 |
credit_card_charge_id not found for this transaction. Please try with another valid charge ID |
INVALID_AMOUNT_FOR_REVERSE_AUTHORIZATION_ERROR 400 |
Invalid charge amount to be reversed. Please make sure that the authorized amount that you requested to be reversed is no 0. |
Create Charge
Definition: Create Charge
POST https://api.xendit.co/credit_card_charges
Example Charge Request
curl -X POST \
https://api.xendit.co/credit_card_charges \
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
-d '{
"token_id" : "598d5d0e51e0870d44c61534",
"external_id": "postman-charge-1502436817",
"amount": 900000,
"authentication_id": "598d5d0f51e0870d44c61535",
"card_cvn": "123",
"descriptor": "My new store"
"currency": "IDR",
"mid_label": "IDR_MID",
"billing_details": {
"given_names": "John",
"surname": "John Doe",
"email": "johndoe@xendit.co",
"mobile_number": "+62899336634448",
"phone_number": "+629934448",
"address": {
"street_line1": "Panglima Polim IV",
"street_line2": "Ruko Grand Panglima Polim, Blok E",
"suburb": "Kebayoran",
"city": "Jakarta Selatan",
"province": "DKI Jakarta",
"state": "South Jakarta",
"zip_code": "993448",
"country": "Indonesia"
}
},
"promotion": {
"reference_id": "BCA_10",
"original_amount": 1000000
},
"installment": {
"count": 3,
"interval": "month"
}
}'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'token_id' => '5e2e8231d97c174c58bcf644',
'external_id' => 'card_' . time(),
'authentication_id' => '5e2e8658bae82e4d54d764c0',
'amount' => 15000,
'card_cvn' => '123',
'capture' => false
];
$createCharge = \Xendit\Cards::create($params);
var_dump($createCharge);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);
const resp = await card.createCharge({
externalID: 'sample-external-id-1475459775872',
tokenID: 'sample-token-id-1475459775872',
amount: 900000,
authID: '58e2097218b815f555c8a526',
cardCvn: "123",
descriptor: "My new store",
currency: "IDR",
midLabel: "IDR_MID",
billing_details: {
given_names: "John",
surname: "John Doe",
email: "johndoe@xendit.co",
mobile_number: "+62899336634448",
phone_number: "+629934448",
address: {
street_line1: "Panglima Polim IV",
street_line2: "Ruko Grand Panglima Polim, Blok E",
suburb: "Kebayoran",
city: "Jakarta Selatan",
province: "DKI Jakarta",
postal_code: "993448",
country: "Indonesia"
}
},
promotion: {
referenceId: "BCA_10",
originalAmount: 1000000
},
installment: {
count: 3,
interval: "month"
}
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
CreditCardCharge creditCardCharge = CreditCard.createCharge(
"token_id", //tokenId
"postman-authorize-1502437417", //externalId
90000, //amount
"auth_id", //authenticationId
"123", //Card CVN
"XENDIT*MYBUSINESS-MY NEW STORE" //Descriptor
);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
createChargeData := card.CreateChargeParams{
TokenID: "example-token-id",
AuthenticationID: "example-authentication-id",
ExternalID: "postman-charge-1502436793",
Amount: 900000,
Capture: new(bool),
}
chargeResp, err := card.CreateCharge(&createChargeData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created charge: %+v\n", chargeResp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
CreditCard = xendit_instance.CreditCard
charge = CreditCard.create_charge(
token_id="5f0410898bcf7a001a00879d",
external_id="card_charge-1594106478",
amount=75000,
card_cvn="123",
)
print(charge)
Once you have a token, that token can be used to charge a card.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
token_id required |
string |
The token ID used to charge the card. | |||||||||||||||||||||||||||||||||
external_id required |
string |
A unique identifier of your choice. Max 64 characters. | |||||||||||||||||||||||||||||||||
amount required |
number |
Amount that expected to be charged. | |||||||||||||||||||||||||||||||||
authentication_id optional |
string |
Authentication ID for authenticating charge. Optional only if charge was already authenticated with a single-use token, or if optional authentication is enabled for your account. | |||||||||||||||||||||||||||||||||
card_cvn optional |
string |
3 or 4 digit CVN (CVC) code. Optional but highly recommended. Required for cards issued in Europe. | |||||||||||||||||||||||||||||||||
capture optionaldefault:
|
boolean |
Whether or not to capture immediately. Set to false to issue an authorization (hold funds) only, to be captured later with the capture endpoint.Note: Authorizations expire in 7 days. |
|||||||||||||||||||||||||||||||||
descriptor optional |
string |
Specific descriptor to define merchant's identity. Note: For aggregator merchant, it will always return XENDIT*[MERCHANT_NAME]-DESCRIPTOR For switcher merchant, it will always return [MERCHANT_NAME]-DESCRIPTOR |
|||||||||||||||||||||||||||||||||
currency optionaldefault:
|
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. If left blank, it will default to IDR | |||||||||||||||||||||||||||||||||
mid_label optional |
string |
Specific string value which labels any of your Merchant IDs (MID) set up with Xendit. This can be configured in the list of MIDs on your Dashboard settings. (If this is not included in a request, and you have more than 1 MID in your list, the transaction will proceed using your prioritized MID (first MID on your list)). Note: Only available in the response for switcher merchant |
|||||||||||||||||||||||||||||||||
billing_details optional |
object
|
Billing details of the cardholder. If entered, should correspond with billing details registered by cardholder with their issuer. Required for a card to be verified by the Address Verification System (AVS) - only for USA / Canadian / Great Britain cards. billing details child parameters
|
|||||||||||||||||||||||||||||||||
promotion optional |
object |
If you are want to apply a Promotion to a charge, you must input these parameters. promotion details child parameters
|
|||||||||||||||||||||||||||||||||
installmentoptional |
object |
These parameters are required to mark a transaction as an installment. installment details child parameters
|
Example Charge Response
{
"created": "2020-01-11T07:33:14.442Z",
"status": "CAPTURED",
"business_id": "5850e55d8d9791bd40096364",
"authorized_amount": 900000,
"external_id": "postman-charge-1502436793",
"merchant_id": "xendit",
"merchant_reference_code": "598d5d0d51e0870d44c61533",
"card_type": "CREDIT",
"masked_card_number": "400000XXXXXX0002",
"charge_type": "SINGLE_USE_TOKEN",
"card_brand": "VISA",
"bank_reconciliation_id": "5132390610356134503009",
"eci": "05",
"capture_amount": 900000,
"descriptor": "XENDIT*MYBUSINESS-MY NEW STORE",
"id": "598d5dba51e0870d44c61539",
"mid_label": "IDR_MID",
"promotion": {
"reference_id": "BCA_10",
"original_amount": "1000000"
},
"installment": {
"count": 3,
"interval": "month"
}
}
Example Authorization Response
{
"created": "2020-01-11T07:43:39.563Z",
"status": "AUTHORIZED",
"business_id": "5850e55d8d9791bd40096364",
"authorized_amount": 90000,
"external_id": "postman-authorize-1502437417",
"merchant_id": "xendit",
"merchant_reference_code": "598d5ffb51e0870d44c6153a",
"card_type": "CREDIT",
"masked_card_number": "400000XXXXXX0002",
"charge_type": "SINGLE_USE_TOKEN",
"card_brand": "VISA",
"bank_reconciliation_id": "5132390610356134503009",
"eci": "05",
"descriptor": "XENDIT*MYBUSINESS-MY NEW STORE",
"id": "598d602b51e0870d44c6153d",
"mid_label": "IDR_MID",
"promotion": {
"reference_id": "BCA_10",
"original_amount": "100000"
},
"installment": {
"count": 3,
"interval": "month"
}
}
Charge Response
Parameter | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
createdrequired |
string |
An ISO timestamp that tracks when the charge was made.The token ID used to charge the card. The timezone will be default Timezone:
|
||||||
charge_type required |
string |
Types of charges. See Charge types. | ||||||
business_id required |
string |
The ID of your business in Xendit. | ||||||
authorized_amount required |
number |
The amount that've been authorized for this charge. | ||||||
external_id required |
string |
A unique identifier of your choice. | ||||||
card_type required |
string |
Type of card (CREDIT or DEBIT ). |
||||||
merchant_id required |
string |
Your merchant ID used for processing credit cards with the bank. | ||||||
masked_card_number required |
string |
Masked card number. The first 6 digits are the BIN (Bank Identification Number). | ||||||
charge_type required |
string |
Types of charges. See Charge types. | ||||||
card_brand required |
string |
Card scheme (VISA , MASTERCARD , JCB , ...). |
||||||
bank_reconciliation_id required |
string |
ID of the transaction that can be reconciled with the bank. | ||||||
eci optional |
string |
Status of 3DS authentication. See ECI codes. | ||||||
capture_amount optional |
number |
Amount captured for this charge. Can be up to authorized_amount . |
||||||
status required |
string |
Status of the charge transaction in xendit system. See [Charge Statuses] (#statuses). | ||||||
failure_reason optional |
string |
If status is FAILED, this describes the failure. See Charge Failure Reasons. | ||||||
approval_code optional |
string |
Represents the five or six numbers generated by an issuing bank, or the bank of a buyer using a credit card, for the purpose of validating a credit card whenever it is approved in the transaction. | ||||||
cvn_code optional |
string |
Response from validating the CVN (3-digit security code on back of card). See CVN Codes. | ||||||
merchant_reference_code required |
string |
An ID used to reconcile transactions with the bank. | ||||||
descriptor optional |
string |
Description which already inputted by merchant when creating a charge. Note: For aggregator merchant, it will always return XENDIT*[MERCHANT_NAME]-DESCRIPTOR For switcher merchant, it will always return [MERCHANT_NAME]-DESCRIPTOR |
||||||
currency optionaldefault:
|
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. If left blank, it will default to IDR | ||||||
mid_label optional |
string |
Specific string value which labels any of your Merchant IDs (MID) set up with Xendit. This can be configured in the list of MIDs on your Dashboard settings. (If this is not included in a request, and you have more than 1 MID in your list, the transaction will proceed using your prioritized MID (first MID on your list)). Note: Only available in the response for switcher merchant |
||||||
id required |
string |
ID of the charge transaction in Xendit system. | ||||||
promotion optional |
object |
Detail of promotion that used for this transaction. promotion details child parameters
|
||||||
installmentoptional |
object |
These parameters will be returned to mark a transaction as an installment. installment details child parameters
|
Statuses
Status | Description |
---|---|
CAPTURED | Charge is successfully captured and the funds will be settled according to the settlement schedule. |
AUTHORIZED | Charge is successfully authorized. |
REVERSED | Charge is successfully reversed. |
FAILED | Charge failed. See Charge Failure Reasons |
CVN Codes
Code | Description |
---|---|
M | Match - CVN provided matches the CVN on the issuer's record. |
N | Not match - CVN provided does not match CVN on the issuer's record. |
P | Not processed - either the card does not have a valid CVN, or the CVN was somehow not accepted by the issuer. Retry again and if the response persists, try a different card. |
Failure Reasons
Failure Reason | Description |
---|---|
EXPIRED_CARD | The card you are trying to capture is expired. Ask your customer for a different card |
CARD_DECLINED | The card you are trying to capture has been declined by the bank. Ask your customer for a different card |
INSUFFICIENT_BALANCE | The card you are trying to capture does not have enough balance to complete the capture |
STOLEN_CARD | The card you are trying to capture has been marked as stolen. Ask your customer for a different card |
INACTIVE_CARD | The card you are trying to capture is inactive. Ask your customer for a different card |
INVALID_CVN | The cvn that being submitted is not correct. |
PROCESSOR_ERROR | The charge failed because there's an integration issue between card processor and the bank. Contact us if you encounter this issue. |
BIN_BLOCK | The cards' BIN has been blocked by request from the Bank. |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT 400 |
The request body is not valid JSON. |
TOKEN_ALREADY_USED_ERROR 400 |
The single-use token ID has already been used in a charge. |
AUTHENTICATION_ALREADY_USED_ERROR 400 |
The authentication ID has already been used in a charge. |
INVALID_TOKEN_ID_ERROR 400 |
The token ID format is invalid. |
INVALID_CVN_LENGTH_ERROR 400 |
The length of CVN is invalid. For AMEX card, CVN length must be 4 digit and for the others card type it must be 3. |
AUTHENTICATION_ID_MISSING_ERROR 400 |
Authentication ID is required for this charge. |
AMOUNT_GREATER_THAN_AUTHENTICATED_ERROR 400 |
Charge amount was greater than what was authenticated. |
INVALID_AUTHENTICATION_ID_ERROR 400 |
The authentication ID format is invalid. |
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
TOKEN_NOT_FOUND_ERROR 404 |
The token ID was not found in the system. |
AUTHENTICATION_NOT_FOUND_ERROR 404 |
Authenticated token with given authentication ID is not found. |
MID_NOT_FOUND_ERROR 404 |
The MID specified in "mid_label" cannot be found. Check if you have registered this MID, or if you entered the MID label incorrectly |
INVALID_PROMOTION_DETAILS 400 |
The promotion detail which inputted in this request is invalid. Please change the input or check if you have available promotion in your system or not. |
CARDHOLDER_NAME_REQUIRED 400 |
Please send cardholder name fields in the billing_details object in your request body. |
INSTALLMENT_BELOW_MINIMUM_AMOUNT 400 |
Amount is below the minimum allowed for installments. BRI, BNI: Rp 500.000 |
INSTALLMENT_UNAVAILABLE 404 |
Possible error messages: |
AMOUNT_BELOW_MINIMUM_LIMIT 400 |
The amoubnt which inputted in this request is below your minimum limit. Please send another request with amount equal to or greater than the minimum limit. Default minimum limit based on currency: |
AMOUNT_ABOVE_MAXIMUM_LIMIT 400 |
The amoubnt which inputted in this request is above your maximum limit. Please send another request with amount equal to or lower than the maximum limit. Default maximum limit based on currency: |
Charge Types
Status | Description |
---|---|
SINGLE_USE_TOKEN | Charge created with single-use token |
MULTIPLE_USE_TOKEN | Charge created with multiple-use token |
RECURRING | Charge a recurring charge in a subscription |
ECI Codes
ECI | Description |
---|---|
0 | Unable to Authenticate (MasterCard) |
1 | Authentication attempted (MasterCard) |
2 | Successful authentication (MasterCard) |
5 | Successful authentication (Visa, AMEX, JCB) |
6 | Authentication attempted (Visa, AMEX, JCB) |
7 | Unable to Authenticate (Visa, AMEX, JCB) |
Safe Acceptance
An alternative to the Charge API endpoint, for the following use cases:
- Creating credit/debit card payments by sending Xendit the full card number from your frontend client without needing to use our Tokenization API (for standard Visa/MasterCard/JCB/AMEX transactions)
- Creating credit/debit card payments where the payment interface is controlled by the processor and the end-customer is redirected to the payment processor's interface to enter card details.
Payment Processor Integration Methods in Safe Acceptance
A strength of our Safe Acceptance API is that it is flexible to support card processing using the most common integration methods offered by payment processors. These are generally known as 2.5 or 3-party methods, explained below:
-
2.5 party Merchant will perform 3DS authentication and the payment itself in a single API request. Merchant sends the full card number to Xendit, who will forward it to the processor. Before processing the payment, Xendit will initiate 3DS with the processor and redirect the merchant to the processor's 3DS 2-Factor Authentication page which the cardholder will use to enter the One-Time Password (or other authentication method).
-
3 party Merchant will perform 3DS authentication and the payment according to the processor's flow. Safe Acceptance will be used to initiate the payment, and Xendit will redirect the merchant to the processor's interface immediately. The cardholder enters the card number in the processor's checkout page directly, and engages in 3DS authentication on the same page. The card number is not sent by the merchant to Xendit and is instead received directly by the processor.
Note that because the Safe Acceptance API accepts token_id
as a valid field, you are still able to use Xendit Tokenization with it if you choose.
Definition: Create Safe Acceptance
POST
https://api.xendit.co/credit_cards/safe_acceptance
Example Safe Acceptance Request
{
"amount": "1200000",
"return_url": "https://mybusiness.co",
"reference_id": "xdt-safe-acceptance-007",
"transaction_type": "SALES",
"request_timestamp": "2021-01-10T09:50:40+03:00",
"descriptor": "INV-SAFE-ACCEPTANCE-007",
"card_number": "1889800000000171",
"card_exp_year": "2021",
"card_exp_month": "03",
"card_cvn": "101",
"should_authenticate": true,
"currency": "IDR",
"authorization": "Basic eG5kX3B1YmxpY19kZXZlbG9wbWVudF9PNDZBZkw4azFlRGtwSnRmN3RPSERDV01OQ2w4dFI0azNibVJ4bm1EUnIyb0NnZHdnQTo=",
"signed_field_names": "reference_id,amount,currency,request_timestamp,return_url,authorization,signed_field_names",
"signature": "37c0323212908b9d4fe607f9d237c95aae2503a799d278afdc663268b5f8906e"
}
Example Safe Acceptance Webhook Response (Visa / MasterCard / JCB cards)
{
"created": "2021-01-10T09:50:40+03:00",
"business_id": "5d08a4nfea3b620019cfa213c",
"authorized_amount": 1200000,
"reference_id": "ecm-8112",
"merchant_reference_code": "5d1ec8f4a3bcd10019a7e2de",
"masked_card_number": "400000XXXXXX0002",
"charge_type": "SINGLE_USE_TOKEN",
"card_brand": "VISA",
"card_type": "CREDIT",
"status": "CAPTURED",
"bank_reconciliation_id": "5622988916826241203012",
"eci": "05",
"capture_amount": "1200000",
"currency": "IDR",
"id": "5d1eca0ca3bcd10019a7e2ee",
"authorized_amount": "1200000",
"merchant_id" : "00080091009103589348501",
"descriptor": "INV-SAFE-ACCEPTANCE-007",
"signed_field_names": "create,business_id,authorized_amount,reference_id,merchant_reference_code,masked_card_number,charge_type,card_brand,card_type,status,bank_reconciliation_id,eci,capture_amount,currency,id,authorized_amount,merchant_id,mid_label,descriptor",
"signature": "25798ae4db8361fa4ee423e7321a1558a1b0bf0863e8082e0551e62fd8e7a771"
}
Example Safe Acceptance Webhook Response (BCA-branded cards)
{
"created": "2021-01-10T09:50:40+03:00",
"business_id": "5d08a4nfea3b620019cfa213c",
"authorized_amount": 1200000,
"reference_id": "ecm-8112",
"merchant_reference_code": "5d1ec8f4a3bcd10019a7e2de",
"masked_card_number": "143481XXXXXX0002",
"charge_type": "SINGLE_USE_TOKEN",
"card_brand": "BCA",
"status": "CAPTURED",
"bank_reconciliation_id": "5622988916826241203012",
"eci": "05",
"capture_amount": "1200000",
"currency": "IDR",
"id": "5d1eca0ca3bcd10019a7e2ee",
"authorized_amount": "1200000",
"merchant_id" : "00080091009103589348501",
"descriptor": "INV-SAFE-ACCEPTANCE-007",
"signed_field_names": "create,business_id,authorized_amount,reference_id,merchant_reference_code,masked_card_number,charge_type,card_brand,card_type,status,bank_reconciliation_id,eci,capture_amount,currency,id,authorized_amount,merchant_id,mid_label,descriptor",
"signature": "25798ae4db8361fa4ee423e7321a1558a1b0bf0863e8082e0551e62fd8e7a771"
}
Example Safe Acceptance Webhook Response (GPN-branded cards)
{
"created": "2021-01-10T09:50:40+03:00",
"business_id": "5d08a4nfea3b620019cfa213c",
"authorized_amount": 1200000,
"reference_id": "ecm-8112",
"merchant_reference_code": "5d1ec8f4a3bcd10019a7e2de",
"masked_card_number": "143481XXXXXX0002",
"charge_type": "SINGLE_USE_TOKEN",
"card_brand": "GPN",
"status": "CAPTURED",
"bank_reconciliation_id": "5622988916826241203012",
"eci": "05",
"capture_amount": "1200000",
"currency": "IDR",
"id": "5d1eca0ca3bcd10019a7e2ee",
"authorized_amount": "1200000",
"merchant_id" : "00080091009103589348501",
"descriptor": "INV-SAFE-ACCEPTANCE-007",
"signed_field_names": "create,business_id,authorized_amount,reference_id,merchant_reference_code,masked_card_number,charge_type,card_brand,card_type,status,bank_reconciliation_id,eci,capture_amount,currency,id,authorized_amount,merchant_id,mid_label,descriptor",
"signature": "25798ae4db8361fa4ee423e7321a1558a1b0bf0863e8082e0551e62fd8e7a771"
}
Request Parameters
Parameter | Type | Description |
---|---|---|
amountrequired |
number |
Amount of the card payment being processed. |
reference_id required |
string |
A unique identifier of your choice. Max 64 chars. |
request_timestamp required |
string |
Timestamp when you sent the request, in ISO8601 format. Required for creating the signature and subsequent validation by Xendit. Example: 2021-01-10T09:50:40+03:00 |
currency required |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. Supported currencies:
|
return_url required |
string |
This is a URL that your customers will be redirected to after the transaction is completed. The URL will be called using a form POST with the results of the transaction. A signature will be sent in the response for the merchant to verify. |
authorization required |
string |
Your Xendit Public API key (must be base-64 encoded). |
signature required |
string |
This value is generated by retrieving your Xendit secret API key from your Xendit Dashboard, then hashing it with SHA256. See our Safe Acceptance Docs for guide. |
signed_field_names required |
string |
The value here should be the names of all the fields you want to use for verification with the created signature, separated with commas.
Mandatory(if your request contains them):
amount, currency, authorization, reference_id, request_timestamp,mid_label, channel_code, return_url, should_authenticate
|
channel_code optional |
string |
Value used to determine the connector which the Safe Acceptance request runs through. Defaults to Visa/MasterCard/JCB/AMEX connectors if left blank. For other transactions, please see:
|
card_number optional |
string |
Credit / debit card number 16 digits. Note: Required when 2 or 2.5 party processors are used |
card_exp_year optional |
string |
Credit / debit card expiration year (4 digit number) Note: Required when 2 or 2.5 party processors are used |
card_exp_month optional |
string |
Credit / debit card expiration month (2 digit number) Note: Required when 2 or 2.5 party processors are used |
card_cvn optional |
string |
Security code on back of card 3 or 4 digits Note: Required when 2 or 2.5 party processors are used |
card_holder_name optional |
string |
Full name of the cardholder |
token_id optional |
string |
ID of the token created during Tokenization. Only required if the selected processor requires Tokenization, and you have a Token ID from a Tokenization request previously sent. |
should_authenticate optional |
boolean |
Whether or not to initiate 3D-Secure authentication for this transaction. If not inputted, will follow the merchant's 3DS settings. Accepted values:
|
given_namesoptional |
string |
Primary or first name/s of the customer minimum length : 1 character maximum length : 255 characters |
surnameoptional |
string |
Surname or last name of the customer minimum length : 1 character maximum length : 255 characters |
emailoptional |
string |
Enduser's email address which associated with the card |
mobile_numberoptional |
string |
Enduser's mobile phone number which associated with the card |
phone_number optional |
string |
Enduser's other phone number which associated with the card (e.g. landline) |
country required |
string |
2-letter ISO 3166-2 country code for the customer's country of residence |
street_line1 optional |
string |
Building name and apartment unit number minimum length : 1 character maximum length : 255 characters |
street_line2 optional |
string |
Building street address minimum length : 1 character maximum length : 255 characters |
cityoptional |
string |
City, village or town as appropriate minimum length : 1 character maximum length : 255 characters |
province_state optional |
string |
Use this to enter province, state or region of residence. If the user is USA citizen, make sure to use state code (e.g put CA instead of California) minimum length : 1 character maximum length : 255 characters |
postal_code optional |
string |
Postal, zip or rural delivery code, if applicable minimum length : 1 character maximum length : 255 characters |
descriptor optional |
string |
Specific descriptor to define merchant's identity. This is the message that will be printed in the credit card statement. minimum length : 1 character maximum length : 20 characters |
use_reward optional |
boolean |
Whether to use cardholder’s rewards balance available with their issuing bank for the payment. Should only be sent if merchant has received a Get Charge Option stating that the card is eligible for rewards. Values: ‘true’: all available rewards balance on the card will be used ‘false’: no rewards balance on the card will be used |
installment_count optional |
number |
Together with the "interval" parameter, this defines your installment tenor. If you want the installment tenor to be 3 months, then the value of "count" should be 3 |
installment_interval optional |
string |
Together with the "count" parameter, this defines your installment tenor. If you want the installment tenor to be 3 months, then the value of "interval" should be "month". |
installment_code optional |
string |
Used to identify the installment type and associated features such as interest rates and fees. Mandatory if Xendit has returned an installment_code in a Get Charge Option response for this card. |
mid_label optional |
string |
Label assigned to a Merchant ID. Merchant IDs are accounts opened with acquirers to enable Visa/MasterCard (and others) transactions.Use only if you have your own MID with an acquirer, and have configured its label in the Xendit Dashboard. |
Response Parameters
Parameter | Type | Description |
---|---|---|
id required |
string |
Unique ID of the transaction in Xendit’s system. |
created required |
string |
An ISO timestamp that tracks when the charge was made (Timezone: GMT+0). |
reference_id required |
string |
A unique identifier of your choice, included in the request. |
business_id required |
string |
The ID of your business in Xendit. |
card_brand required |
string |
Card scheme (VISA, MASTERCARD, JCB, ...) |
card_type required |
string |
Type of card (CREDIT or DEBIT) |
masked_card_number required |
number |
Masked card number. The first 6 digits are the BIN (Bank Identification Number). |
authorized_amount required |
number |
Amount that was authorized for this charge. |
capture_amount required |
number |
Amount that was captured for this charge. Can be up to the authorized_amount . |
currency required |
string |
Currency in which the payment was made, included in the request. |
status required |
string |
Status of the charge transaction in xendit system. See Charge Statuses. |
eci required |
string |
"Electroni" Commerce Indicator”, which tells you whether 3DS authentication was successful or not. Status of 3DS authentication. See ECI codes. |
cvn_code optional |
string |
Response from validating the CVN (3-digit security code on back of card). See CVN Codes. |
merchant_id optional |
string |
Merchant ID used for processing credit cards. Will return the Merchant ID number provided by the acquirer. Use this to identify the MID used, and reconcile transactions processed with each MID. Only returned if you are using your own MID. |
merchant_reference_code required |
string |
Unique identification code used by the card processor to identify the transaction.Used as another unique identifier for referencing the transaction. |
bank_reconciliation_id required |
string |
Secondary ID used by the processor and bank to reconcile the transaction. Used for reconciling the transaction with acquirers, e.g. when finding out when funds will be settled or if there is an amount discrepancy. |
descriptor optional |
string |
Freetext you can use to describe the transaction. Used to add notes about the transaction e.g. "recurrin" payment for meal plan ABCDE”. |
signed_field_names required |
string |
Names of all the fields used for verification with the created signature, separated with commas. |
signature required |
string |
Signature you provided in the request. |
reward_balance required |
string |
Balance of rewards left in the issuing bank for this card. Only returned if ‘use_reward’ was set to ‘true’ in the Safe Acceptance request. |
installment_count required |
string |
Returned to mark a transaction as an installment. Together with the "interval" parameter, this defines your installment tenor. |
installment_interval required |
string |
Returned to mark a transaction as an installment. Together with the "count" parameter, this defines your installment tenor. |
installment_code required |
string |
Returned to mark a transaction as an installment. Used to identify the installment type and associated features such as interest rates and fees. |
approval_code required |
string |
Represents the five or six numbers generated by an issuing bank, or the bank of a buyer using a credit card, for the purpose of validating a credit card whenever it is approved in the transaction. |
Statuses
Status | Description |
---|---|
CAPTURED | Charge is successfully captured and the funds will be settled according to the settlement schedule. |
AUTHORIZED | Charge is successfully authorized. |
REVERSED | Charge is successfully reversed. |
FAILED | Charge failed. See Charge Failure Reasons |
CVN Codes
Code | Description |
---|---|
M | Match - CVN provided matches the CVN on the issuer's record. |
N | Not match - CVN provided does not match CVN on the issuer's record. |
P | Not processed - either the card does not have a valid CVN, or the CVN was somehow not accepted by the issuer. Retry again and if the response persists, try a different card. |
Failure Reasons
Failure Reason | Description |
---|---|
EXPIRED_CARD | The card you are trying to capture has expired. 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. |
INVALID_CVN | The CVN that is being submitted is not correct. |
CARD_DECLINED | The card you are trying to capture has been declined by the issuing bank. Ask your customer for a different card. |
ISSUING_BANK_UNAVAILABLE | The card you are trying to use is either a test or invalid card, or the issuing bank is not enrolled in 3DS. |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON. |
INVALID_API_KEY400 |
Please include your public API key as an authorization. |
SIGNATURE_VALIDATION_ERROR 400 |
The signature created for this transaction is not valid. |
Capture Charge
Definition: Capture Charge
POST https://api.xendit.co/credit_card_charges/:credit_card_charge_id/capture
Example Capture Charge Request
curl https://api.xendit.co/credit_card_charges/5877255293ff67900c6aa64e/capture \
-X POST \
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-d amount=15000
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '598942c4bb91a4ec309e9a37';
$params = ['amount' => 10000];
$captureCharge = \Xendit\Cards::capture($id, $params);
var_dump($captureCharge);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);
const resp = await card.captureCharge({
chargeID: id,
amount: 10000,
});
console.log(resp)
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
CreditCardCharge creditCardCharge = CreditCard.captureCharge(
"12345678", //chargeId
10000 //amount
);
} catch (XenditException e) {
e.printStackTrace();
}
captureChargeData := card.CaptureChargeParams{
ChargeID: "598942c4bb91a4ec309e9a37",
Amount: 9900,
}
chargeResp, err := card.CaptureCharge(&captureChargeData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("captured charge: %+v\n", chargeResp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
CreditCard = xendit_instance.CreditCard
charge = CreditCard.capture_charge(
credit_card_charge_id="5f0422aa2bbbe50019a368c2",
amount=75000,
)
print(charge)
Example Capture Charge Response
{
"created": "2020-01-08T04:49:08.815Z",
"status": "CAPTURED",
"business_id": "5848fdf860053555135587e7",
"authorized_amount": 10000,
"external_id": "test-pre-auth",
"merchant_id": "xendit",
"merchant_reference_code": "598942aabb91a4ec309e9a35",
"card_type": "CREDIT",
"masked_card_number": "400000XXXXXX0002",
"charge_type": "SINGLE_USE_TOKEN",
"card_brand": "VISA",
"bank_reconciliation_id": "5132390610356134503009",
"capture_amount": 9900,
"descriptor": "My new store",
"id": "598942c4bb91a4ec309e9a37"
}
Capturing a charge only needed if you do pre-authorization by specifying capture
to false in create charge request. You can capture a charge with amount different than authorized amount as long as it's less than authorized amount. Response for this endpoint is the same as create charge response
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Query Parameter | Type | Description |
---|---|---|
credit_card_charge_id required |
string |
Charge ID of authorization |
Body Parameter | Type | Description |
---|---|---|
amount required |
string |
Amount to be captured. Can be up to amount of authorization but not more |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT 400 |
The request body is not valid JSON. |
AMOUNT_GREATER_THAN400 |
Capture amount is larger than authorized amount |
INVALID_CHARGE400 |
Charge status is not AUTHORIZED |
REQUEST_FORBIDDEN403 |
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_CHARGE404 |
credit_card_charge_id not found |
AUTHORIZATION_EXPIRED 400 |
It is likely that the authorization has been reversed because it expired. Please create another authorization or charge. |
Create Refund
Definition: Create Refund
POST https://api.xendit.co/credit_card_charges/:credit_card_charge_id/refunds
Example Refund Request
curl https://api.xendit.co/credit_card_charges/5877255293ff67900c6aa64e/refunds \
-X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H "X-IDEMPOTENCY-KEY: unique-id-12345" \
-H "x-api-version: 2019-05-01" \
-d "amount": 15000
-d "external_id": unique-external-id
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'external_id' => 'postman-charge-1502436793',
'amount' => 15000,
'X-IDEMPOTENCY-KEY' => 'unique-id'
];
$refund = \Xendit\Cards::createRefund($id, $params);
var_dump($refund);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);
const resp = await card.createRefund({
chargeID: '5877255293ff67900c6aa64e',
amount: 15000,
externalID: 'unique-external-id',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
CreditCardRefund creditCardRefund = CreditCard.createRefund(
"1234567", //id
15000, //amount
"unique-external-id" //externalId
);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
createRefundData := card.CreateRefundParams{
IdempotencyKey: "unique-idempotency-key",
ChargeID: "58f984f09d1b74bc08506c34",
Amount: 15000,
ExternalID: "unique-external-id",
}
refundResp, err := card.CreateRefund(&createRefundData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("refunded charge: %+v\n", refundResp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
CreditCard = xendit_instance.CreditCard
refund = CreditCard.create_refund(
credit_card_charge_id="5f0422aa2bbbe50019a368c2",
amount=10000,
external_id="card_refund-1594106755",
)
print(refund)
Example Refund Response
{
"updated": "2020-01-21T04:05:09.755Z",
"created": "2020-01-21T04:05:04.936Z",
"credit_card_charge_id": "58f89041780d51ed097896c5",
"user_id": "57c5aa7a36e3b6a709b6e148",
"amount": 15000,
"external_id": "unique-external-id",
"status": "REQUESTED",
"fee_refund_amount": 150,
"id": "58f984f09d1b74bc08506c34"
}
The Refund API accepts two parameters, amount
and external_id
. The charge ID, which is returned after a successful charge, must be used in request URL per the definition. Several partial refund calls can be made, so long as the total amount refunded is not greater than the total charge amount.
Note: Idempotency can be achieved by sending a header with the key X-IDEMPOTENCY-KEY.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
X-IDEMPOTENCY-KEYoptional |
string |
A unique key to prevent processing duplicate requests. Must be unique across test & live mode. |
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
x-api-versionrequired |
string |
Value of this must be "2019-05-01". |
Body Parameter | Type | Description |
---|---|---|
amount required |
string |
The amount to be refunded. |
external_id required |
string |
A unique identifier of your choice. Max 64 characters. |
Response Parameters
Parameter | Type | Description |
---|---|---|
updated required |
string |
ISO timestamp that tracks when the last time refund was updated. |
created required |
string |
ISO timestamp that tracks when the refund was made Timezone: . |
credit_card_charge_id required |
string |
charge ID, a unique identifier for each charge. |
user_id required |
string |
ID of your business in Xendit's system. |
amount required |
number |
Refund amount. |
external_id required |
string |
Unique identifier for refund request, provided by you. |
status required |
string |
Status of the refund. See Refund Statuses |
failure_reason optional |
string |
Reason provided if refund request fails. See Refund Failure Reasons |
fee_refund_amount required |
number |
Amount of Xendit's fee refunded (proportional to the refund amount). |
id required |
string |
Unique ID referencing the refund request. |
Statuses
Status | Description |
---|---|
REQUESTED | Refund request succeeded |
FAILED | Refund failed |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT 400 |
The request body is not valid JSON. |
REFUND_AMOUNT400 |
Refunded amount would exceed total charge |
DUPLICATE_REFUND400 |
external_id has already been used |
REQUEST_FORBIDDEN403 |
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_CHARGE404 |
credit_card_charge_id not found |
Failure Reason
Failure Reason | Description |
---|---|
INSUFFICIENT_BALANCE | Your Xendit balance has insufficient funds to create a refund |
REFUND_FAILED | The refund request has been rejected by the processor. Please try again or contact us at help@xendit.co |
REFUND_PERIOD_EXPIRED | Refund period expired. The period where this charge can be refunded has expired. You can try refunding the charge by making a disbursement |
Get Charge
Definition: Get Charge
GET https://api.xendit.co/credit_card_charges/:credit_card_id?id_type=charge
Example Get Charge Request Using External ID
curl https://api.xendit.co/credit_card_charges/5877255293ff67900c6aa64e?id_type=external \
-X GET \
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==:
Example Get Charge Request Using Charge ID (Default)
curl https://api.xendit.co/credit_card_charges/5877255293ff67900c6aa64e \
-X GET \
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '598942c4bb91a4ec309e9a37';
$getCharge = \Xendit\Cards::retrieve($id);
var_dump($getCharge);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Card } = x;
const cardSpecificOptions = {};
const card = new Card(cardSpecificOptions);
const resp = await card.getCharge({ chargeID: '5877255293ff67900c6aa64e' });
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
CreditCardCharge creditCardCharge = CreditCard.getCharge("5877255293ff67900c6aa64e");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
getChargeData := card.GetChargeParams{
ChargeID: "598942c4bb91a4ec309e9a37",
}
chargeResp, err := card.GetCharge(&getChargeData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved charge: %+v\n", chargeResp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
CreditCard = xendit_instance.CreditCard
charge = CreditCard.get_charge(
credit_card_charge_id="5f0422aa2bbbe50019a368c2",
)
print(charge)
Example Get Charge Response
{
"created": "2020-01-08T04:49:08.815Z",
"status": "CAPTURED",
"business_id": "5848fdf860053555135587e7",
"authorized_amount": 10000,
"external_id": "test-pre-auth",
"merchant_id": "xendit",
"merchant_reference_code": "598942aabb91a4ec309e9a35",
"card_type": "CREDIT",
"masked_card_number": "400000XXXXXX0002",
"charge_type": "SINGLE_USE_TOKEN",
"card_brand": "VISA",
"bank_reconciliation_id": "5132390610356134503009",
"capture_amount": 9900,
"descriptor": "My new store",
"id": "598942c4bb91a4ec309e9a37"
}
This is endpoint to get a charge object. You need to specify the id
in the query parameter which you can choose between charge
to use charge_id
and external
to use the external id / reference provided in your create charge request. Response for this endpoint is the same as create charge response
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Query Parameter | Type | Description |
---|---|---|
credit_card_id required |
string |
Can be either charge id of the payment that have been authorized / captured OR external_id of the payment that already requested by the user |
id_type optional |
string |
Defined in [ID Types] (#id-types). If not filled, value will use charge by default. |
ID Types
Type | Description |
---|---|
charge | Use charge ID provided by xendit which can be retrieved from the charge response to retrieve the transaction detail (default value) |
external | Use external ID submitted by the user during charge / authorization request to retrieve the transaction detail |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
REQUEST_FORBIDDEN403 |
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_CHARGE404 |
credit_card_charge_id not found |
Get Charge Option
When accepting credit card payments from your customers, you may wish to give them additional payment options. These can include:
- Paying by installments
- Giving a discount through a Promotion
These options must be selected by a customer before you create a Charge. For example, you would check if a card is eligible for a Promotion, and discount the Charge amount if so, before you initiate payment you would check if a card can be used for installments, and return the option to the customer, to let them choose if they want to do so
Our GET Charge Option API endpoint helps you with this. Send a request to this endpoint with info entered by your customer (such as card Bank Identification Number (BIN), promo code) and Xendit checks to see what Charge Options are available. The response will contain all options available for that card. You can select an option and create a Charge with the details from that option. This API will only return promotion response with ACIVE
status.
Definition: Get Charge Option
GET https://api.xendit.co/credit_card_charges/option?amount={amount}&bin={bin}¤cy={currency}
Example Get Charge Option Using First 6 Digits of Card
curl -X GET \
https://api.xendit.co/credit_card_charges/option?amount=1000000&bin=552002¤cy=IDR
-u xnd_public_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
Example Get Charge Option Using Token ID
curl -X POST \
https://api.xendit.co/credit_card_charges/option?amount=1000000&token_id=598d5d0e51e0870d44c61534¤cy=IDR
-u xnd_public_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
Get Charge Option Request
Query Parameter | Type | Description |
---|---|---|
bin required but optional if token_id exists |
string |
The BIN (first 6 digits of a card) entered by the cardholder, which you want to check if it is associated with any Charge Option. |
amount required |
number |
The amount of the original transaction. |
currency optional |
string |
The currency which payment will be made in. For banks with branches in more than one country, a Promotion will only apply to cards based on the currency. e.g. if currency is IDR and channel_code is DBS , then the Promotion will apply only to BINs issued by DBS Indonesia. |
promo_code optional |
string |
Promo code which can be used by an end user to activate the promo. Include this if you want your Promotion be activated by your user entering a promo code is entered.
|
token_id optional |
string |
Token ID of a card, obtained during tokenization with Xendit. We will look up the token to associate it with a BIN and get the available options. |
card_cvn optional |
number |
Three digit code written on the back of the card (usually called CVV/CVN). Recommended to include if the token_id you are sending is for a multiple use token. |
Example Get Charge Option Response
{
"business_id": "5ea2a0cdb62b6a00108ed248",
"bin": "552002",
"promotions":[{
"reference_id": "some_promo_1",
"discount_percent": "25",
"original_amount": 1000000,
"final_amount": 975000,
"currency": "IDR",
"min_original_amount": 500000,
"max_discount_amount": 25000
}],
"installments" : [{
"count": 3,
"interval": "month",
"acquirer": "BRI",
"currency": "IDR",
"minimum_amount": 500000
},{
"count": 6,
"interval": "month",
"acquirer": "BRI",
"currency": "IDR",
"minimum_amount": 500000
},{
"count": 12,
"interval": "month",
"acquirer": "BRI",
"currency": "IDR",
"minimum_amount": 500000
}]
}
Get Charge Option Response
Parameter | Type | Description | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
business_id required |
string |
The ID of your business in Xendit. | ||||||||||||||||||||||
binrequired |
string |
The BIN (first 6 digits of a card) entered by the cardholder, which you sent in the Get Charge Option request. | ||||||||||||||||||||||
promotions optional |
array |
Array containing details of all promotions applicable to the card. promotion details child parameters
|
||||||||||||||||||||||
installments optional |
array
|
Define the available installment option. installments details child parameters
|
||||||||||||||||||||||
reward optional |
object
|
If Rewards are available for the card, this object will be returned. reward details child parameters
|
Create Promotion
A great way to attract more customers is to offer discounts based on the type of card that they use. Issuing banks often collaborate with merchants to provide discounts to users if they choose to use their cards. An important feature in the payment flow is the ability to check if the card number entered by a user is issued by a specific bank.
Xendit's Promotion APIs fully support such promotions. They allow you to create a Promotion and select a range of credit card Bank Identification Numbers (BINs) to whitelist (BINs are the first 6 digits of a card, e.g. 480012). During the card payment process, send us a request to GET a Promotion Calculation. If an applicable Promotion for the type of card exists, Xendit automatically applies the promotion discount rate and returns you the information so you can charge the discounted amount.
Definition: Create Promotion
POST https://api.xendit.co/promotions
Example Create Promotion Request
curl -X POST \
https://api.xendit.co/promotions
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
-d {
"reference_id": "BRI_20_JAN",
"description": "20% discount applied for all BRI cards",
"bin_list": [
"400000",
"460000"
],
"discount_percent": 20,
"channel_code": "BRI",
"currency": "IDR",
"min_original_amount": 25000,
"max_discount_amount": 5000
}
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
CreditCard = xendit_instance.CreditCard
promotion = CreditCard.create_promotion(
reference_id="BRI_20_JAN-1594176600",
description="20% discount applied for all BRI cards",
discount_amount=10000,
bin_list=['400000', '460000'],
start_time="2020-01-01T00:00:00.000Z",
end_time="2021-01-01T00:00:00.000Z",
min_original_amount=25000,
max_discount_amount=5000
)
print(promotion)
Example Create Promotion Response
{
"id": "36ab1517-208a-4f22-b155-96fb101cb378",
"business_id": "5e61664b3dba955c203d232e",
"reference_id": "BRI_20_JAN",
"description": "20% discount applied for all BRI cards",
"start_time": "2020-01-01 00:00:00.000Z",
"end_time": "2020-01-01 00:00:00.000Z",
"status": "ACTIVE",
"bin_list": [
"400000",
"460000"
],
"discount_percent": 20,
"channel_code": "BRI",
"currency": "IDR",
"min_original_amount": 25000,
"max_discount_amount": 5000
}
Request Parameters
Body Parameter | Type | Description |
---|---|---|
reference_id required |
string |
Unique reference, such as an ID or name, you wish to assign to the created Promotion.
|
description required |
text |
The description of the Promotion. This will later be returned in the Get Promotions Calculation response, and you can expose it to the user on your user interface. |
promo_code optional |
string |
Promo code which can be used by an end user to activate the promo. Include this if you want your Promotion to be activated by the end user entering a code. A Promotion can be created with both the promo_code and bin_list or channel_code , if you want only certain cards to be able to use the promo code.
|
bin_list optional |
array of strings |
The list of BINs whitelisted for a specific Promotion. Example: [ "400000", "460000" ] |
channel_code optional |
string |
The bank whitelisted for a specific Promotion. When a specific bank is chosen, any BIN which Xendit associates with that bank will be eligible for the Promotion. |
discount_percent optional |
number |
Percentage discount applicable for a specific Promotion. e.g. you want the Promotion to be a 20% discount. Either discount_percent or discount_amount is required.
|
discount_amount optional |
number |
Amount of discount applicable for a specific Promotion. e.g. you want the Promotion to be a 50000 IDR discount. Either discount_percent or discount_amount is required.
|
currency required default: IDR |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. For banks with branches in more than one country, a Promotion will only apply to cards based on the currency. e.g. if currency is IDR and channel_code is DBS , then the Promotion will apply only to BINs issued by DBS Indonesia. |
start_time required |
ISO |
All created Promotions will start immediately by default. If you want a Promotion to start later, use this field to enter the start date of the promotion. Promo end date must be a date in the future. |
end_time required |
ISO |
Date which the Promotion will end. Promo end date must be a date in the future. |
min_original_amount optional |
number |
Minimum of the original amount for a certain promo to be applicable or calculated. |
max_discount_amount optional |
number |
Maximum of the discount amount that will be applied for a certain promo. |
Response Parameters
Promotion Object
Parameter | Type | Description |
---|---|---|
id | string |
Unique ID of the created Promotion (generated by Xendit). |
business_id | string |
ID of your account with Xendit, used to identify you as a unique merchant. |
status | string |
Status of the Promotion. See Promotion Statuses |
reference_id | string |
Unique reference, such as an ID or name, you wish to assign to the created Promotion.
|
description | text |
The description of the Promotion. You can expose this to the user on your user interface to give them details about the Promotion. |
promo_code | string |
Promo code which can be used by an end user to activate the promo. Include this if you want your Promotion to be activated by the end user entering a code. A Promotion can be created with both the promo_code and bin_list or channel_code , if you want only certain cards to be able to use the promo code..
|
bin_list | array of strings |
The list of BINs whitelisted for a specific Promotion. |
channel_code | string |
The bank whitelisted for a specific Promotion. When a specific bank is chosen, any BIN which Xendit associates with that bank will be eligible for the Promotion. The channel code must match the channel codes here precisely. |
discount_percent | number |
Percentage discount applicable for a specific Promotion.
|
discount_amount | number |
Amount of discount applicable for a specific Promotion.
|
currency default: IDR |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. For banks with branches in more than one country, a Promotion will only apply to cards based on the currency. e.g. if currency is IDR and channel_code is DBS , then the Promotion will apply only to BINs issued by DBS Indonesia. |
start_time | ISO |
All created Promotions will start immediately by default. If you want a Promotion to start later, use this field to enter the start date of the promotion. Promo end date must be a date in the future. |
end_time | ISO |
Date which the Promotion will end. Promo end date must be a date in the future. |
min_original_amount | number |
Minimum of the original amount for a certain promo to be applicable or calculated. |
max_discount_amount | number |
Maximum of the discount amount that will be applied for a certain promo. |
Promotion Statuses
Status | Description |
---|---|
ACTIVE | Promotion is active and eligible |
INACTIVE | Promotion is still valid but inactive due to not yet started |
EXPIRED | Promotion is already passed the end_time |
PAUSED | Promotion is paused in the middle of the period based on user's request |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT 400 |
The request body is not valid JSON. |
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have the necessary permissions to perform the request. Please assign proper permissions for the key, or use a different key. |
REFERENCE_IN_USE409 |
This Promotion name has been used for a previous or existing Promotion. Please use a different name. |
PROMO_CODE_IN_USE409 |
This Promotion code has been used for a previous or existing Promotion. Please use a different code |
Get Promotions
Use this API endpoint to obtain details of a created Promotion. Useful to get a quick snapshot of your available Promotions. If more than one Promotion matches a field you have entered, an array of all the relevant Promotions will be returned.
Definition: Get Promotions
GET https://api.xendit.co/promotions?reference_id={reference_id}
Example Get Promotions Request
curl -X GET \
https://api.xendit.co/promotions?reference_id=BRI_20_JAN
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
Example Get Promotions Response
{
"id": "36ab1517-208a-4f22-b155-96fb101cb378",
"business_id": "5e61664b3dba955c203d232e",
"reference_id": "BRI_20_JAN",
"description": "20% discount applied for all BRI cards",
"start_time": "2020-01-01 00:00:00.000Z",
"end_time": "2020-01-01 00:00:00.000Z",
"status": "ACTIVE",
"bin_list": [
"400000",
"460000"
],
"discount_percent": 20,
"channel_code": "BRI",
"currency": "IDR",
"min_original_amount": 25000,
"max_discount_amount": 5000
}
Request Parameters
Query Parameter | Type | Description |
---|---|---|
reference_id optional |
string |
Enter the specific reference_id of a single Promotion. |
status required |
enum |
Status of the Promotion.ACTIVE or INACTIVE . |
bin optional |
string |
A specific BIN. Example: 460000 |
channel_code optional |
string |
The bank whitelisted for a specific Promotion. |
currency optional default: IDR |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. currently, only IDR is accepted. |
Response Parameters
The array returns details of available Promotions depending on what fields you included in your query, in the Promotion Object format. For example, if you entered the bin_list
value as [ "400000" ], an array of all available Promotions which include that BIN value will be returned.
If no promotions match the query, an empty array will be returned.
Get Promotions Calculation
This endpoint is used to calculate how much discount should be applied to an amount being charged. It accepts a BIN or a promo_code
, as well as the original charge amount. If the BIN or promo_code
matches an available Promotion, Xendit will apply the discount to the original amount and return the discounted amount in the response. This API will only perform calculation for promotion with ACIVE
status.
We've built a page for you to test sending Get Promotion Calculations requests before you integrate. Try it out here. You'll need your Public API key, which you can obtain from registering on our Dashboard and heading to the Settings page.
Definition: Get Promotions Calculation
GET https://api.xendit.co/promotions/calculate?amount={amount}&bin={bin}
Example Get Promotions Calculation Request using Bin
curl -X GET \
https://api.xendit.co/promotions/calculate?amount=1000000&bin=460000
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
Example Get Promotions Calculation Request using Token ID
curl -X GET \
https://api.xendit.co/promotions/calculate?amount=1000000&token_id=598d5d0e51e0870d44c61534
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
Get Promotions Calculation Request
Query Parameter | Type | Description |
---|---|---|
amount required |
number |
The amount of the original transaction (before the Promotion discount). |
bin optional |
string |
The BIN entered by the cardholder, which you want to check if it is associated with any active Promotion. |
promo_code optional |
string |
The promo_code entered by the cardholder, which you want to check if it is associated with any active Promotion. |
currency optional default: IDR |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. |
token_id optional |
string |
Token ID of a card, obtained during tokenization with Xendit. We will look up the token to associate it with a BIN and get the available options. |
Example Get Promotions Calculation Response
{
"original_amount": 1000000,
"discount_percent": 20,
"reference_id": "BRI_20_JAN",
"final_amount": 900000,
"currency": "IDR",
"description": "20% discount applied for all BRI cards with maximum discount amount 100000",
"min_original_amount": 500000,
"max_discount_amount": 100000
}
Get Promotions Calculation Response
Parameter | Type | Description |
---|---|---|
reference_id required |
string |
Unique reference which you assigned to the created Promotion. |
original_amount required |
number |
The amount of the original transaction (before the Promotion discount). |
discount_percent optional |
number |
Percentage discount applicable for a specific Promotion. Returned if the Promotion was created using discount_percent . |
discount_amount optional |
number |
Amount of discount applicable for a specific Promotion. Returned if the Promotion was created using discount_amount . |
final_amount required |
number |
The final amount, after the Promotion discount has been applied. You should use this sum to charge the card. |
description required |
text |
The description of the Promotion. Returned in the Get Promotions Calculation response so you can expose it on your user interface. |
min_original_amount optional |
number |
Minimum of the original amount for a certain promo to be applicable or calculated. |
max_discount_amount optional |
number |
Maximum of the discount amount that will be applied for a certain promo. |
Update Promotion
Use this endpoint to update the details of an existing Promotion.
Definition: Update Promotion
PATCH https://api.xendit.co/promotions/:promotion_id
Example Update Promotion request
curl -X PATCH \
https://api.xendit.co/promotions/36ab1517-208a-4f22-b155-96fb101cb378
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
-H 'content-type: application/json' \
-d {
"description": "20% discount applied for all BCA cards",
"bin_list": [
"411455",
"422566"
],
"discount_percent": 20,
"channel_code": "BCA",
"currency": "IDR"
}
Example Update Promotion response
{
"id": "36ab1517-208a-4f22-b155-96fb101cb378",
"business_id": "5e61664b3dba955c203d232e",
"reference_id": "BCA_20",
"description": "20% discount applied for all BRI cards",
"start_time": "2020-01-01 00:00:00.000Z",
"end_time": "2020-01-01 00:00:00.000Z",
"transaction_limit": 0,
"is_deleted": false,
"status": "ACTIVE",
"bin_list": [
"411455",
"422566"
],
"discount_percent": 20,
"channel_code": "BCA",
"currency": "IDR",
"min_original_amount": 25000,
"max_discount_amount": 5000
}
Request Parameters
Path Parameter | Type | Description |
---|---|---|
promotion_id required |
string |
Enter promotion id which provided by Xendit in promotion object |
Not every parameter in the Promotion Object can be updated. Those that can be updated can be found below.
Body Parameter | Type | Description |
---|---|---|
description optional |
text |
The description of the Promotion. This will later be returned in the Get Promotions Calculation response, and you can expose it to the user on your user interface. |
promo_code optional |
string |
Promo code which can be used by an end user to activate the promo. Include this if you want your Promotion to be activated by the end user entering a code. A Promotion can be created with both the promo_code and bin_list or channel_code , if you want only certain cards to be able to use the promo code.
|
bin_list optional |
array of strings |
The list of BINs whitelisted for a specific Promotion. |
channel_code optional |
string |
The bank whitelisted for a specific Promotion. When a specific bank is chosen, any BIN which Xendit associates with that bank will be eligible for the Promotion. The channel code must match the channel codes here precisely. |
discount_percent optional |
number |
Percentage discount applicable for a specific Promotion. e.g. you want the Promotion to be a 20% discount. Either discount_percent or discount_amount is required.
|
discount_amount optional |
number |
Amount of discount applicable for a specific Promotion. e.g. you want the Promotion to be a 50000 IDR discount. Either discount_percent or discount_amount is required.
|
currency default: IDR |
string |
The currency which payment will be made in. For banks with branches in more than one country, a Promotion will only apply to cards based on the currency. e.g. if currency is IDR and channel_code is DBS , then the Promotion will apply only to BINs issued by DBS Indonesia. |
start_time optional |
ISO |
All created Promotions will start immediately by default. If you want a Promotion to start later, use this field to enter the start date of the promotion. Promo end date must be a date in the future. |
end_time optional |
ISO |
Date which the Promotion will end. Promo end date must be a date in the future. |
min_original_amount optional |
number |
Minimum of the original amount for a certain promo to be applicable or calculated. |
max_discount_amount optional |
number |
Maximum of the discount amount that will be applied for a certain promo. |
Response Parameters
Returns Promotion Object. The parameters which you updated via the Update Promotion request will be the new parameters.
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT 400 |
The request body is not valid JSON. |
PROMOTION_NOT_FOUND_ERROR 404 |
Promotion not found. Please try again with valid promotion id. |
PROMO_CODE_IN_USE 400 |
This Promotion code has been used for a previous or existing Promotion. Please use a different promo_code. |
INVALID_DISCOUNT_TYPE 400 |
Promotion with promotion_id has [discount_amount / discount_percent] type. Please use the correct discount type |
INVALID_START_TIME_UPDATE 400 |
Promotion with promotion_id has end time. Please try again with an updated start time that is before the end time. |
Delete Promotion
Use this endpoint to delete an existing Promotion from your list of available Promotions.
Definition: Delete Promotion
DELETE https://api.xendit.co/promotions/:promotion_id
Example Delete Promotion request
curl -X DELETE \
https://api.xendit.co/promotions/6055a96c-a870-4a2f-b61f-4015af6478cb
-u xnd_development_OYiAfOR3gbOunJU4frcaHmLCYNLy8oQuknDm+R1r9G3S/byhDAB+gA==: \
Example Delete Promotion response
{
"id":"6055a96c-a870-4a2f-b61f-4015af6478cb",
"created":"2020-07-29T10:57:47.426Z",
"business_id":"5edfb2a5d40e3040347d91fd",
"reference_id":"Cypress-Test-Promo-Delete-1596020266435",
"start_time":"2020-07-29T10:57:46.373Z",
"end_time":"2020-07-30T10:57:46.373Z",
"status":"DELETED",
"type":"PROMO_CODE",
"discount_amount":5000,
"promo_code":"Cypress-Test-Promo-Delete-1596020266435",
"currency":"IDR"
}
}
Delete Promotion Request
Path Parameter | Type | Description |
---|---|---|
promotion_id required |
string |
Enter promotion id which provided by Xendit in promotion object |
Delete Promotion Response
Parameter | Type | Description |
---|---|---|
id | string |
Unique ID of the deleted Promotion (generated by Xendit). |
is_deleted | boolean |
Status of a promotion to describe that it's already deleted. |
Error Codes
Error Code | Description |
---|---|
PROMOTION_NOT_FOUND_ERROR 404 |
Promotion with id not found. Please try again with valid id. |
eWallets
Our eWallet API allows you to seamlessly charge and receive payments directly from top ewallets providers in SEA. With one integration, get access to all our available eWallets and upcoming eWallets integrations as well. To date, we've processed millions of eWallet transactions and support various business use cases
For full details on each API as well as help on integration, please refer to our documentation
Create eWallet Charge
Endpoint: Create eWallet Charge Request
POST https://api.xendit.co/ewallets/charges
Version
You are currently viewing the newest version of our eWallets API. In this API version, integrate once to get access to all available eWallets and future eWallets in Xendit! This API will also be used to support tokenized payment flow and auth/capture payment flow in the near future. Click here to view older versions.
Version | Changelog |
---|---|
2021-01-25 Latest |
New simple and consistent eWallets API to support top eWallets providers in Indonesia and Philippines No API Versioning is required. You can access the new API easily by calling POST /ewallets/charges |
2020-02-01 | Implemented the asynchronous flow for OVO payment callbacks. |
2019-02-04 | Returns a response immediately without any callbacks returned. |
eWallet
Request Parameters
Example: Create eWallet Charge Request
curl https://api.xendit.co/ewallets/charges -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--data '{
"reference_id": "order-id-123",
"currency": "IDR",
"amount": 25000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://redirect.me/payment"
},
"metadata": {
"branch_area": "PLUIT",
"branch_city": "JAKARTA"
}
}' \
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
Map<String, String> channelProperties = new HashMap<>();
channelProperties.put("success_redirect_url", "https://dashboard.xendit.co/register/1");
Map<String, String> metadata = new HashMap<>();
metadata.put("branch_code", "tree_branch");
Map<String, Object> params = new HashMap<>();
params.put("reference_id", "test-reference-id");
params.put("currency", "IDR");
params.put("amount", 1000);
params.put("checkout_method", "ONE_TIME_PAYMENT");
params.put("channel_code", "ID_SHOPEEPAY");
params.put("channel_properties", channelProperties);
params.put("metadata", metadata);
EWalletCharge charge = EWalletCharge.createEWalletCharge(params);
} catch (XenditException e) {
e.printStackTrace();
}
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'reference_id' => 'test-reference-id',
'currency' => 'IDR',
'amount' => 1000,
'checkout_method' => 'ONE_TIME_PAYMENT',
'channel_code' => 'ID_SHOPEEPAY',
'channel_properties' => [
'success_redirect_url' => 'https://dashboard.xendit.co/register/1',
],
'metadata' => [
'branch_code' => 'tree_branch'
]
];
$createEWalletCharge = \Xendit\EWallets::createEWalletCharge($ewalletChargeParams);
var_dump($createEWalletCharge);
?>
from xendit import EWallet
ewallet_charge = EWallet.create_ewallet_charge(
reference_id="test-reference-id",
currency="IDR",
amount=1000,
checkout_method="ONE_TIME_PAYMENT",
channel_code="ID_SHOPEEPAY",
channel_properties={
"success_redirect_url": "https://dashboard.xendit.co/register/1",
},
metadata={
"branch_code": "tree_branch",
},
)
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := ewallet.CreateEWalletChargeParams{
ReferenceID: "test-reference-id",
Currency: "IDR",
Amount: 1000,
CheckoutMethod: "ONE_TIME_PAYMENT",
ChannelCode: "ID_SHOPEEPAY",
ChannelProperties: map[string]string{
"success_redirect_url": "https://dashboard.xendit.co/register/1",
},
Metadata: map[string]interface{}{
"branch_code": "tree_branch",
},
}
charge, chargeErr := ewallet.CreateEWalletCharge(&data)
if chargeErr != nil {
log.Fatal(chargeErr)
}
fmt.Printf("created e-wallet charge: %+v\n", charge)
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { EWallet } = x;
const ewalletSpecificOptions = {};
const ew = new EWallet(ewalletSpecificOptions);
const resp = await ew.createEWalletCharge({
referenceID: 'test-reference-id',
currency: 'IDR',
amount: 1000,
checkoutMethod: 'ONE_TIME_PAYMENT',
channelCode: 'ID_SHOPEEPAY',
channelProperties: {
successRedirectURL: 'https://dashboard.xendit.co/register/1',
},
metadata: {
branch_code: 'tree_branch'
}
});
console.log(resp);
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
with-fee-ruleoptional |
string |
Fee Rule ID that you would like to apply to payments coming into this invoice Please note: If you include this parameter, we will return the fee_rule_id and the fee_id in the header of the API response. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
reference_idrequired |
string |
Reference ID provided by merchant (255 characters) Note: It has to be unique per charge request |
||||||||||||||||||||||||
currencyrequired |
string |
Currency used for the transaction in ISO4217 format - IDR , PHP |
||||||||||||||||||||||||
amountrequired |
number |
Transaction amount to be paid Min - 100 IDR or 1 PHP Max - based on eWallet holding limit |
||||||||||||||||||||||||
checkout_methodrequired |
string |
Checkout method determines the payment flow used to process the transactionONE_TIME_PAYMENT is used for single guest checkoutsTOKENIZED_PAYMENT can be used for recurring payment |
||||||||||||||||||||||||
channel_coderequired if checkout_method =
|
string |
Channel Code specifies which eWallet will be used to process the transaction - ID_OVO , ID_DANA , ID_LINKAJA , ID_SHOPEEPAY , PH_PAYMAYA , PH_GCASH , PH_GRABPAY |
||||||||||||||||||||||||
channel_propertiesrequired if checkout_method =
|
object |
Channel specific information required for the transaction to be initiated OVO required fields
DANA, LINKAJA, SHOPEEPAY required fields
GCASH, GRABPAY required fields
PAYMAYA required fields
|
||||||||||||||||||||||||
payment_method_idrequired if checkout_method =
|
string |
ID of the payment method | ||||||||||||||||||||||||
customer_idoptional |
string |
ID of the customer object to which the account token will be linked to | ||||||||||||||||||||||||
basketoptional |
array |
Array of objects describing the item(s) purchased Object parameters details
|
||||||||||||||||||||||||
metadataoptional |
object |
Object of additional information the user may use. Users define the JSON properties and values. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. This will only be used by the user and not Xendit. |
Response Parameters
Example: Create eWallet Charge Request API Success Response
{
"id": "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
"business_id": "5f218745736e619164dc8608",
"reference_id": "test-reference-id",
"status": "PENDING",
"currency": "IDR",
"charge_amount": 1000,
"capture_amount": 1000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://dashboard.xendit.co/register/1"
},
"actions": {
"desktop_web_checkout_url": null,
"mobile_web_checkout_url": null,
"mobile_deeplink_checkout_url": "https://deeplinkcheckout.this/",
"qr_checkout_string": "ID123XenditQRTest321DI"
},
"is_redirect_required": true,
"callback_url": "https://calling-back.com/xendit/shopeepay",
"created": "2017-07-21T17:32:28Z",
"updated": "2017-07-21T17:32:28Z",
"voided_at": null,
"capture_now": true,
"customer_id": null,
"payment_method_id": null,
"failure_code": null,
"basket": null,
"metadata": {
"branch_code": "tree_branch"
}
}
Body Parameter | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for charge request transaction. It will always have the prefix of 'ewc_', followed by a UUIDv4 | |||||||||||||||||||||||||||||||||||||||||||||
business_idrequired |
string |
Business ID of the merchant | |||||||||||||||||||||||||||||||||||||||||||||
reference_idrequired |
string |
Reference ID provided by merchant Note: It has to be unique per payment request. |
|||||||||||||||||||||||||||||||||||||||||||||
statusrequired |
string |
Status of charge request
|
|||||||||||||||||||||||||||||||||||||||||||||
currencyrequired |
string |
Currency used for the transaction in ISO4217 format - IDR , PHP |
|||||||||||||||||||||||||||||||||||||||||||||
charge_amountrequired |
number |
Requested charge amount from merchant | |||||||||||||||||||||||||||||||||||||||||||||
capture_amountoptional |
number |
Requested capture amount from merchant. In requests where checkout_method = ONE_TIME_PAYMENT, capture_amount will always be the same as charge_amount | |||||||||||||||||||||||||||||||||||||||||||||
checkout_methodrequired |
string |
Checkout method determines the payment flow used to process the transactionONE_TIME_PAYMENT is used for single guest checkouts |
|||||||||||||||||||||||||||||||||||||||||||||
channel_coderequired |
string |
Channel Code specifies which eWallet will be used to process the transaction - ID_OVO , ID_DANA , ID_LINKAJA , ID_SHOPEEPAY , PH_PAYMAYA , PH_GCASH , PH_GRABPAY |
|||||||||||||||||||||||||||||||||||||||||||||
channel_propertiesoptional |
object |
Channel specific information required for the transaction to be initiated OVO required fields
DANA, LINKAJA, SHOPEEPAY required fields
GCASH, GRABPAY required fields
PAYMAYA required fields
|
|||||||||||||||||||||||||||||||||||||||||||||
actionsoptional |
string |
Redirection actions to be taken when is_redirect_required returned in response is true . Merchants should choose one of the available options based on the ideal experience for their payment flows
Channels with redirection required more info
|
|||||||||||||||||||||||||||||||||||||||||||||
is_redirect_requiredrequired |
boolean |
Flag which indicates whether redirection is required for end user to complete payment When True, merchants should redirect the end user to the url given in the “actions” field. When False, there is no need for redirection for payment process to continue |
|||||||||||||||||||||||||||||||||||||||||||||
callback_urlrequired |
string |
Callback URL which payment notifications will be sent | |||||||||||||||||||||||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for charge object creation. Timezone UTC+0 | |||||||||||||||||||||||||||||||||||||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest charge object update. Timezone UTC+0 | |||||||||||||||||||||||||||||||||||||||||||||
voided_atoptional |
string |
ISO 8601 Timestamp when transaction was voided. Timezone UTC+0 | |||||||||||||||||||||||||||||||||||||||||||||
capture_nowrequired |
string |
Default: true . Field not in use currently |
|||||||||||||||||||||||||||||||||||||||||||||
customer_idoptional |
string |
ID of the customer object created with Xendit. ID to will be linked to the transaction | |||||||||||||||||||||||||||||||||||||||||||||
payment_method_idoptional |
string |
Xendit’s identifier for end user payment tokens binded with merchant. Only used for channels which support tokenized payments | |||||||||||||||||||||||||||||||||||||||||||||
failure_codeoptional |
string |
Reason for failure of payment by end user or eWallet issuer. The failure_code is notified to the merchant in the payment callback or GET payment status after transaction is attempted by end user | |||||||||||||||||||||||||||||||||||||||||||||
basketoptional |
array |
Array of objects describing the item(s) purchased Object parameters details
|
|||||||||||||||||||||||||||||||||||||||||||||
metadataoptional |
object |
User defined object with JSON properties and values passed in during charge creation. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Error Codes
Example: Create eWallet Charge Request API Error Response
{
"error_code": "UNSUPPORTED_CURRENCY",
"message": "The payment currency request is not supported for this payment channel. Please refer to our API reference or docs to pick available currencies"
}
Error Code | Description |
---|---|
DUPLICATE_PAYMENT_REQUEST_ERROR400 |
The charge with the same reference_id has already been created before |
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
UNSUPPORTED_CURRENCY400 |
The payment currency request is not supported for this payment channel. Please refer to our API reference or docs to pick available currencies |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
Merchant credentials met with an error with the eWallet provider. Please contact Xendit customer support to resolve this issue |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
CHANNEL_NOT_ACTIVATED403 |
Payment request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
CALLBACK_URL_NOT_FOUND404 |
Payment request failed because there was no input of callback url in Xendit Dashboard or request headers. Please save your callback url in Xendit Dashboard |
UNSUPPORTED_CONTENT_TYPE403 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
CHANNEL_UNAVAILABLE503 |
The payment channel requested is currently experiencing unexpected issues. The eWallet provider will be notified to resolve this issue |
Get eWallet Charge Status
Endpoint: Get eWallet Charge Status
GET https://api.xendit.co/ewallets/charges/{id}
This endpoint is used to get payment status of a charge request. You need to specify the id
in the response body when hitting create eWallet charge request
Version
You are currently viewing the newest version of our eWallets API. Click here to view older versions.
Request Parameters
Example: Check eWallet Charge Status Request
curl 'https://api.xendit.co/ewallets/charges/ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2' \
-X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
EWalletCharge charge = EWalletCharge.getEWalletChargeStatus("ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2");
} catch (XenditException e) {
e.printStackTrace();
}
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$charge_id = 'ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2';
$getEWalletChargeStatus = \Xendit\EWallets::getEWalletChargeStatus($charge_id);
var_dump($getEWalletChargeStatus);
?>
from xendit import EWallet
ewallet_charge = EWallet.get_ewallet_charge_status(
charge_id="ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
)
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := ewallet.GetEWalletChargeStatusParams{
ChargeID: "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
}
charge, chargeErr := ewallet.GetEWalletChargeStatus(&data)
if chargeErr != nil {
log.Fatal(chargeErr)
}
fmt.Printf("retrieved e-wallet charge: %+v\n", charge)
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { EWallet } = x;
const ewalletSpecificOptions = {};
const ew = new EWallet(ewalletSpecificOptions);
const resp = await ew.getEWalletChargeStatus({
chargeID: 'ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2',
});
console.log(resp);
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Query Parameter | Type | Description |
---|---|---|
charge_id required |
string |
You need to specify the id in the response body when hitting create eWallet charge request |
Example: Check eWallet Charge Status Success Responses
Check eWallet Charge Status Success Responses
{
"id": "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
"business_id": "5f218745736e619164dc8608",
"reference_id": "test-reference-id",
"status": "PENDING",
"currency": "IDR",
"charge_amount": 1000,
"capture_amount": 1000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://dashboard.xendit.co/register/1"
},
"actions": {
"desktop_web_checkout_url": null,
"mobile_web_checkout_url": null,
"mobile_deeplink_checkout_url": "https://deeplinkcheckout.this/",
"qr_checkout_string": "ID123XenditQRTest321DI"
},
"is_redirect_required": true,
"callback_url": "https://calling-back.com/xendit/shopeepay",
"created": "2017-07-21T17:32:28Z",
"updated": "2017-07-21T17:32:28Z",
"voided_at": null,
"capture_now": true,
"customer_id": null,
"payment_method_id": null,
"failure_code": null,
"basket": null,
"metadata": {
"branch_code": "tree_branch"
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for charge request transaction. It will always have the prefix of 'ewc_', followed by a UUIDv4 | ||||||||||||||||||||||||
business_idrequired |
string |
Business ID of the merchant | ||||||||||||||||||||||||
reference_idrequired |
string |
Reference ID provided by merchant Note: It has to be unique per payment request. |
||||||||||||||||||||||||
statusrequired |
string |
Status of charge request
|
||||||||||||||||||||||||
currencyrequired |
string |
Currency used for the transaction in ISO4217 format - IDR , PHP |
||||||||||||||||||||||||
charge_amountrequired |
number |
Requested charge amount from merchant | ||||||||||||||||||||||||
capture_amountoptional |
number |
Requested capture amount from merchant. In requests where checkout_method = ONE_TIME_PAYMENT, capture_amount will always be the same as charge_amount | ||||||||||||||||||||||||
checkout_methodrequired |
string |
Checkout method determines the payment flow used to process the transactionONE_TIME_PAYMENT is used for single guest checkoutsTOKENIZED_PAYMENT can be used for recurring payment |
||||||||||||||||||||||||
channel_coderequired |
string |
Channel Code specifies which eWallet will be used to process the transaction - ID_OVO , ID_DANA , ID_LINKAJA , ID_SHOPEEPAY , PH_PAYMAYA ,PH_GCASH , PH_GRABPAY |
||||||||||||||||||||||||
channel_propertiesoptional |
object |
Channel specific information required for the transaction to be initiated OVO required fields
DANA, LINKAJA, SHOPEEPAY required fields
GCASH, GRABPAY required fields
PAYMAYA required fields
|
||||||||||||||||||||||||
actionsoptional |
string |
Redirection actions to be taken when is_redirect_required returned in response is true . Merchants should choose one of the available options based on the ideal experience for their payment flows
|
||||||||||||||||||||||||
is_redirect_requiredrequired |
boolean |
Flag which indicates whether redirection is required for end user to complete payment When True, merchants should redirect the end user to the url given in the “actions” field. When False, there is no need for redirection for payment process to continue |
||||||||||||||||||||||||
callback_urlrequired |
string |
Callback URL which payment notifications will be sent | ||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for charge object creation. Timezone UTC+0 | ||||||||||||||||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest charge object update. Timezone UTC+0 | ||||||||||||||||||||||||
voided_atoptional |
string |
ISO 8601 Timestamp when transaction was voided. Timezone UTC+0 | ||||||||||||||||||||||||
capture_nowrequired |
string |
Default: true . Field not in use currently |
||||||||||||||||||||||||
customer_idoptional |
string |
ID of the customer object created with Xendit. ID to will be linked to the transaction | ||||||||||||||||||||||||
payment_method_idoptional |
string |
ID of the payment method. Only used for channels which support tokenized payments | ||||||||||||||||||||||||
failure_codeoptional |
string |
Reason for failure of payment by end user or eWallet issuer. The failure_code is notified to the merchant in the payment callback or GET payment status after transaction is attempted by end user | ||||||||||||||||||||||||
basketoptional |
array |
Array of objects describing the item(s) purchased Object parameters details
|
||||||||||||||||||||||||
metadataoptional |
object |
User defined object with JSON properties and values passed in during charge creation. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Error Codes
Example: Create eWallet Charge Request API Error Response
{
"error_code": "INVALID_API_KEY",
"message": "API key format is invalid"
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
Merchant credentials met with an error with the eWallet provider. Please contact Xendit customer support to resolve this issue |
DATA_NOT_FOUND404 |
Charge ID specified was not found. Please check your query again. |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Tokenized - Create Customer
There are 4 steps required to perform account linking and making a transaction using our tokenization flow, starting with a customer object creation and ending in our charge creation.
Step 1 - a customer object is first required to initiate account linking for tokenized eWallets. The customer_id
created will be used in the next API call to identify the end user who is performing account linking. customer_id
also allows you to easily link and track other payment methods and transactions associated with this end user. Please refer to Customer section to create customer object.
Tokenized - Initiate Account Linking
Step 2 - Account linking in tokenized eWallet refers to end user authorizing merchants to perform transactions via a token (linking) for the end user's eWallet (account). This endpoint starts the authorization process and a linked account token will be created as a result. End users needs to be redirected to eWallet provider's hosted page to authorize the account linking.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Initialize Linked Account Tokenization
POST https://api.xendit.co/linked_account_tokens/auth
Initialize Linked Account Tokenization - Request
Example Initialize Linked Account Tokenization Request
curl https://api.xendit.co/linked_account_tokens/auth -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
--data-raw '{
"customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"channel_code": "PH_GRABPAY",
"properties": {
"success_redirect_url": "https://www.my-shop.co/auth/success",
"failure_redirect_url": "https://www.my-shop.co/auth/failed",
"cancel_redirect_url": "https://www.my-shop.co/auth/cancel"
}
}'
Request Body Parameter | Type | Description | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
customer_id required |
string
|
ID of the customer object to which the account token will be linked to. Call Tokenized - Create Customer to generate Customer ID | ||||||||||||||
channel_code required |
string
|
Identifier for the specific channel of the account to be linked. Code must be in uppercase. Supported eWallets and their respective channel codes:
|
||||||||||||||
properties required |
object
|
JSON that contains information needed to proceed with authorization. Values inside properties change based on eWallet provider: GRABPAY required fields
PAYMAYA required fields
|
||||||||||||||
metadata optional |
object
|
Object of additional information the user may use. Users define the JSON properties and values. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Initialize Linked Account Tokenization - Response
Example Initialize Linked Account Tokenization Success Response
{
"id": "lat-aa620619-124f-41db-995b-66a52abe036a",
"customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"channel_code": "PH_GRABPAY",
"authorizer_url": "https://link-web.xendit.co/oauth/lat-4ec01c8d-0326-4a35-bc11-b64c85f7408e/confirm",
"status": "PENDING",
"metadata": null
}
Parameter | Type | Description |
---|---|---|
id | string |
Unique ID generated by Xendit for the particular linked account token authorization |
customer_id | string |
Customer object ID |
channel_code | string |
Code identifier for the channel |
authorizer_url | string |
URL generated from eWallet provider for end user to authorize the account linking. End user should be redirected to this URL for tokenization to proceed. |
status | string |
Status of the authorization. A successful API request will respond with a PENDING status. Upon successful account linking, the status will be updated to COMPLETED . If account linking fails, the status will be updated to FAILED . |
metadata | object |
User defined object with JSON properties and values passed in during account linking. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Initialize Linked Account Tokenization - Errors
See other common errors here.
Error Code | Description |
---|---|
CHANNEL_CODE_NOT_SUPPORTED_ERROR 400 |
Provided channel_code is not supported or has not yet activated for this account. |
CUSTOMER_NOT_FOUND_ERROR 404 |
Provided customer_id in the request does not exist or access is unauthorized |
CHANNEL_UNAVAILABLE 503 |
The target channel is currently unavailable. This is possibly due to partner channel downtime or error. |
INVALID_ACCOUNT_DETAILS 400 |
Provided values in properties in the request does not match any records with the eWallet provider |
ACCOUNT_ACCESS_BLOCKED 400 |
The eWallet provider has rejected the linking. This maybe the bank account is inaccessible or not activated for this service. |
Tokenized - Retrieve Accessible Accounts by Linked Account Token
Step 3 - This endpoint returns a list of eWallets accounts accessible by the linked account token. The linked account id (prefix la-
) returned in the response from this endpoint is required for the next step in creation of payment method.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Get Accessible Accounts by Linked Account Token
GET https://api.xendit.co/linked_account_tokens/{linked_account_token_id}/accounts
Retrieve Accessible Accounts by Linked Account Token - Request
Example Get Accessible Accounts by Linked Account Token Request
curl https://api.xendit.co/linked_account_tokens/lat-aa620619-124f-41db-995b-66a52abe036a/accounts -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Path Parameter | Type | Description |
---|---|---|
linked_account_token_idrequired |
string |
Linked account token id received from Initialize Account Authorization. This has the lat- prefix. |
Retrieve Accessible Accounts by Linked Account Token - Response
This endpoint returns an array of objects with the following properties:
Example Get Accessible Accounts by Linked Account Token Success Response
[
{
"id": "la-f8b41ad0-180a-44d5-bad5-3291cd7262ac",
"channel_code": "PH_GRABPAY",
"type": "EWALLET",
"properties": {
"account_details": null,
"account_type": "EWALLET",
"balance": 1000000,
"currency": "PHP",
"description": null,
"name": null,
"point_balance": null
},
}
]
Parameter | Type | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id |
string
|
Unique identifier for the ewallet account. This has a prefix of la- . |
||||||||||||||||
channel_code |
string
|
Code identifier for the channel | ||||||||||||||||
type |
string
|
Type of account that has been linked. Expected values: EWALLET
|
||||||||||||||||
properties |
object
|
Object containing information regarding the account.
|
Retrieve Accessible Accounts by Linked Account Token - Errors
See other common errors here.
Error Code | Description |
---|---|
DATA_NOT_FOUND_ERROR 404 |
Provided linked_account_token_id is not supported or has not yet activated for this account. |
Tokenized - Create Payment Method
Step 4 - A payment method object is used to represent the token (created from account linking step) to make payment transactions. To create a payment method, a customer object and linked account object has to be created and included in the request to this endpoint.
With the payment_method_id
(prefix pm-) returned in the response of this endpoint, you can specify payment_method_id
in the eWallets charge endpoint to initiate a tokenized payment.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Create Payment Method
POST https://api.xendit.co/payment_methods
Create Payment Method - Request
Example Create Payment Method Request
curl https://api.xendit.co/payment_methods -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
--data-raw '{
"customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"type": "EWALLET",
"properties": {
"id": "la-aa620619-124f-41db-995b-66a52abe036a"
}
}'
Request Body Parameter | Type | Description | ||||
---|---|---|---|---|---|---|
customer_id required |
string
|
ID of the customer object to which the account token will be linked to | ||||
type required |
string
|
Type of payment method Supported values: EWALLET
|
||||
properties required |
object
|
JSON that contains information that identifies the payment method:
|
||||
metadata optional |
object
|
Object of additional information the user may use. Users define the JSON properties and values. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Method - Response
Example Create Payment Method Success Response
{
"id": "pm-fea3b000-f9dc-41c5-9bfc-fd37c2b0d84d",
"type": "EWALLET",
"properties": {
"id": "la-f8b41ad0-180a-44d5-bad5-3291cd7262ac"
},
"customer_id": "f0ac5e6f-436b-4228-ac56-7324a2aec6f4",
"status": "ACTIVE",
"created": "2021-04-01T10:12:03.564Z",
"updated": "2021-04-01T10:12:03.564Z",
"metadata": {},
}
Parameter | Type | Description | ||||
---|---|---|---|---|---|---|
id |
string
|
Unique identifier for the payment method. This has a prefix of pm- . |
||||
type |
string
|
Type of account that has been linked. Expected values: EWALLET
|
||||
properties |
object
|
Object containing information regarding the account.
|
||||
customer_id |
string
|
ID of the customer object in which this payment method is linked to |
||||
status |
string
|
Status of the payment method. Will be equal to ACTIVE upon creation. |
||||
created |
string
|
Timestamp in ISO 8601 when the request was madeFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||
updated |
string
|
Timestamp in ISO 8601 when transaction information was updatedFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||
metadata |
object
|
User defined object with JSON properties and values passed in during payment method creation. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Method - Errors
See other common errors here.
Error Code | Description |
---|---|
LIINKED_ACCOUNT_NOT_FOUND_ERROR 400 |
Provided properties and type combination in the request does not exist or access is unauthorized |
CUSTOMER_NOT_FOUND_ERROR 400 |
Provided customer_id in the request does not exist or access is unauthorized |
DUPLICATE_ERROR 409 |
There is already an existing ACTIVE payment method that relates to the same account |
Payment Status Callback
You need to provide an endpoint your system to receive all payment callback notification from our system. You will receive the callback when end-customer attempted payments for available eWallets. Please specify this endpoint in Xendit dashboard callback url page under eWallets paid
The payment callback notification will be sent as POST request to the "callback_url" that you have set in the dashboard. Note: Please give this notification a response back with status 200
so we know that our notification is received and will not attempt to retry the notification.
Version
You are currently viewing the newest version of our eWallets API. Click here to view older versions.
Example Payment Status Callback
Callback Payload
Example: Success Payment Callback Payload
{
"event": "ewallet.capture",
"business_id": "5abe2389ewpejrt238",
"created": "2020-04-20T16:25:52Z",
"data": {
"id": "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
"business_id": "5f218745736e619164dc8608",
"reference_id": "test-reference-id",
"status": "SUCCEEDED",
"currency": "IDR",
"charge_amount": 1000,
"capture_amount": 1000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://dashboard.xendit.co/register/1"
},
"actions": {
"desktop_web_checkout_url": null,
"mobile_web_checkout_url": null,
"mobile_deeplink_checkout_url": "https://deeplinkcheckout.this/",
"qr_checkout_string": "ID123XenditQRTest321DI"
},
"is_redirect_required": true,
"callback_url": "https://calling-back.com/xendit/shopeepay",
"created": "2017-07-21T17:32:28Z",
"updated": "2017-07-21T17:32:28Z",
"voided_at": null,
"capture_now": true,
"customer_id": null,
"payment_method_id": null,
"failure_code": null,
"basket": null,
"metadata": {
"branch_code": "tree_branch"
}
}
}
Header Parameter | Description |
---|---|
x-callback-token |
string Your Xendit unique callback token to verify the origin of the callback |
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
eventrequired |
string |
Identifies the event triggering a notification to merchant. ewallet.capture occurs when eWallet issuer confirms the payment status of a transaction |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
business_idrequired |
string |
Business ID of the merchant | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dataoptional |
object |
eWallets charge object will be nested in this parameter. See here for full definitions Data fields
|
Failure Codes
Example: Failed Payment Callback Payload
{
"event": "ewallet.capture",
"business_id": "5abe2389ewpejrt238",
"created": "2020-04-20T16:25:52Z",
"data": {
"id": "ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2",
"business_id": "5f218745736e619164dc8608",
"reference_id": "test-reference-id",
"status": "FAILED",
"currency": "IDR",
"charge_amount": 1000,
"capture_amount": 1000,
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "ID_SHOPEEPAY",
"channel_properties": {
"success_redirect_url": "https://dashboard.xendit.co/register/1"
},
"actions": {
"desktop_web_checkout_url": null,
"mobile_web_checkout_url": null,
"mobile_deeplink_checkout_url": "https://deeplinkcheckout.this/",
"qr_checkout_string": "ID123XenditQRTest321DI"
},
"is_redirect_required": true,
"callback_url": "https://calling-back.com/xendit/shopeepay",
"created": "2017-07-21T17:32:28Z",
"updated": "2017-07-21T17:32:28Z",
"voided_at": null,
"capture_now": true,
"customer_id": null,
"payment_method_id": null,
"failure_code": "USER_DID_NOT_AUTHORIZE_THE_PAYMENT",
"basket": null,
"metadata": {
"branch_code": "tree_branch"
}
}
}
Failure Code | Failure Message |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End user’s account cannot be accessed as it has been restricted by the eWallet provider. End user should contact the provider for resolution. |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the eWallet provider. Please contact Xendit customer support to resolve this issue. |
USER_DECLINED_PAYMENT |
End user declined the payment request. |
INVALID_ACCOUNT_DETAILS |
End user provided incorrect information for this transaction. |
MAXIMUM_LIMIT_REACHED |
Accumulated value of payment requested for this end user went above the maximum transaction limit set by end user or eWallets. Payment can be retried when the transaction limit is reset. |
USER_UNREACHABLE |
End user’s device cannot be reached at this moment. Common reasons include unstable network, device error or jailbroken device. |
CHANNEL_UNAVAILABLE |
The payment channel requested is currently experiencing unexpected issues. The eWallet provider will be notified to resolve this issue. |
INSUFFICIENT_BALANCE |
End user has insufficient balance to complete the transaction. |
ACCOUNT_NOT_ACTIVATED |
End user’s account cannot be accessed as it has not been activated. End user should set up their account and ensure there is sufficient balance before retrying. |
INVALID_TOKEN |
Binding for this end user has expired. Please reinitiate binding before retrying. |
Cardless Credit
Cardless credit payment channel allows you to receive payments upfront from the credit provider. End users get the option to split their payments into installments.
Create Payment / Generate Checkout URL
Endpoint: Generate Checkout URL
POST https://api.xendit.co/cardless-credit
Request Parameters
Example: Generate Checkout URL
curl https://api.xendit.co/cardless-credit -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
--header 'content-type: application/json' \
--data '{
"cardless_credit_type": "KREDIVO",
"external_id": "test-cardless-credit-01",
"amount": 800000,
"payment_type": "3_months",
"items": [
{
"id": "123123",
"name": "Phone Case",
"price": 200000,
"type": "Smartphone",
"url": "http://example.com/phone/phone_case",
"quantity": 2
},
{
"id": "234567",
"name": "Bluetooth Headset",
"price": 400000,
"type": "Audio",
"url": "http://example.com/phone/bluetooth_headset",
"quantity": 1
}
],
"customer_details": {
"first_name": "customer first name",
"last_name": "customer last name",
"email": "customer@yourwebsite.com",
"phone": "081513114262"
},
"shipping_address": {
"first_name": "first name",
"last_name": "last name",
"address": "Jalan Teknologi No. 12",
"city": "Jakarta",
"postal_code": "12345",
"phone": "081513114262",
"country_code": "IDN"
},
"redirect_url": "https://example.com",
"callback_url": "http://example.com/callback-cardless-credit"
}'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'cardless_credit_type' => 'KREDIVO',
'external_id' => 'test-cardless-credit-01',
'amount' => 800000,
'payment_type' => '3_months',
'items' => [
[
'id' => '123123',
'name' => 'Phone Case',
'price' => 200000,
'type' => 'Smartphone',
'url' => 'http=>//example.com/phone/phone_case',
'quantity' => 2
],
[
'id' => '234567',
'name' => 'Bluetooth Headset',
'price' => 400000,
'type' => 'Audio',
'url' => 'http=>//example.com/phone/bluetooth_headset',
'quantity' => 1
]
],
'customer_details' => [
'first_name' => 'customer first name',
'last_name' => 'customer last name',
'email' => 'customer@yourwebsite.com',
'phone' => '081513114262'
],
'shipping_address' => [
'first_name' => 'first name',
'last_name' => 'last name',
'address' => 'Jalan Teknologi No. 12',
'city' => 'Jakarta',
'postal_code' => '12345',
'phone' => '081513114262',
'country_code' => 'IDN'
],
'redirect_url' => 'https://example.com',
'callback_url' => 'http://example.com/callback-cardless-credit'
];
$createPayment = \Xendit\CardlessCredit::create($params);
var_dump($createPayment);
?>
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
//items
CardlessCreditItem items[] = new CardlessCreditItem[1];
items[0] =
CardlessCreditItem.builder()
.id("123")
.name("Phone Case")
.price(200000)
.type("Smartphone")
.url("https://www.example.org")
.quantity(1)
.build();
//address
CardlessCreditShippingAddress address =
CardlessCreditShippingAddress.builder()
.firstName("Lorem")
.lastName("Ipsum")
.address("Jalan teknologi")
.city("Jakarta")
.postalCode("12345")
.countryCode("IDN")
.phone("08129748247684")
.build();
//Customer
CardlessCreditCustomer customer =
CardlessCreditCustomer.builder()
.firstName("Lorem")
.lastName("Ipsum")
.email("email@example.com")
.phone("08129748247684")
.build();
CardlessCredit cardlessCredit = CardlessCredit.create(
"KREDIVO",
"external_id",
200000,
CardlessCredit.PaymentType.THREE_MONTHS.getVal(),
items,
customer,
address,
"www.example.com",
"www.example.com"
);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
createPaymentData := cardlesscredit.CreatePaymentParams{
CardlessCreditType: xendit.CardlessCreditTypeEnumKREDIVO,
ExternalID: "test-cardless-credit-01",
Amount: 200000,
PaymentType: xendit.PaymentTypeEnum3Months,
Items: []cardlesscredit.Item{
{
ID: "123",
Name: "Laptop Asus Ila",
Price: 200000,
Type: "Laptop",
URL: "http://asus-ila.com",
Quantity: 1,
},
},
CustomerDetails: cardlesscredit.CustomerDetails{
FirstName: "Michael",
LastName: "Belajarrock",
Email: "michaelbelajarrock@mail.com",
Phone: "08123123123",
},
ShippingAddress: cardlesscredit.ShippingAddress{
FirstName: "Michael",
LastName: "Belajarjazz",
Address: "Jalan Teknologi No. 12",
City: "Jakarta",
PostalCode: "40000",
Phone: "08123123123",
CountryCode: "IDN",
},
RedirectURL: "https://sandbox.kredivo.com/kredivo/v2/signin?tk=fKhTeBntLW3Zyu23+GQ6s+RQaMMRtQ6YdZA1bnbTszt9WXcph/B4+j8nuPlV599Rfkv85FAYuE21Suajpm45tEMZqjZIdqnSgIPlt7T5gJk=",
CallbackURL: "https://google.com",
}
resp, err := cardlesscredit.CreatePayment(&createPaymentData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created payment: %+v\n", resp)
from xendit import Xendit, CardlessCreditType
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
CardlessCredit = xendit_instance.CardlessCredit
cardless_credit_items = []
cardless_credit_items.append(
CardlessCredit.helper_create_item(
id="item-123",
name="Phone Case",
price=200000,
type="Smartphone",
url="http://example.com/phone/phone_case",
quantity=2,
)
)
customer_details = CardlessCredit.helper_create_customer_details(
first_name="customer first name",
last_name="customer last name",
email="customer@email.com",
phone="0812332145",
)
shipping_address = CardlessCredit.helper_create_shipping_address(
first_name="first name",
last_name="last name",
address="Jl Teknologi No. 12",
city="Jakarta",
postal_code="12345",
phone="081513114262",
country_code="IDN",
)
cardless_credit_payment = CardlessCredit.create_payment(
cardless_credit_type=CardlessCreditType.KREDIVO,
external_id="id-1595923113",
amount=10000,
payment_type="3_months",
items=cardless_credit_items,
customer_details=customer_details,
shipping_address=shipping_address,
redirect_url="https://my-shop.com/home",
callback_url="https://my-shop.com/callback",
)
print(cardless_credit_payment)
Example: Generate Checkout URL Success Response
{
"redirect_url": "https://sandbox.kredivo.com/kredivo/v2/signin?tk=fKhTeBntLW3Zyu23+GQ6s+RQaMMRtQ6YdZA1bnbTszt9WXcph/B4+j8nuPlV599Rfkv85FAYuE21Suajpm45tEMZqjZIdqnSgIPlt7T5gJk=",
"transaction_id": "66403e84-c8da-4af4-8d30-d17e95522f43",
"order_id": "123456-test-cardless-credit-01",
"external_id": "test-cardless-credit-01",
"cardless_credit_type": "KREDIVO"
}
Parameter | Type | Description |
---|---|---|
cardless_credit_type required |
string |
The type of cardless-credit to be paid. Must be in capital letters. Supported Cardless Credit types: KREDIVO |
external_id required |
string |
An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 1000 characters. |
amount required |
number |
Amount end customer will pay. Note: minimum amount is 1 IDR |
payment_type required |
string |
The type of installment, you can choose between: "30_days", "3_months", "6_months" and "12_months". |
items required |
array of item object |
List of items / products. |
item objectrequired |
item object |
Details of an item, it should contains: id [string], name [string], price [number], type [string], url [string], quantity [number] |
customer_detailsrequired |
object |
Details of the customer, it should contains: first_name [string], last_name [string], email [string], phone [string] |
shipping_addressrequired |
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_urlrequired |
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_urlrequired |
string |
We will send callback to this address when the customer completes the payment proccess. |
Error Codes
Example: Generate Checkout URL error response
{
"error_code": "API_VALIDATION_ERROR",
"message": "[fieldName] is required"
}
{
"error_code": "DUPLICATE_PAYMENT_ERROR",
"message": "Checkout URL with the same external_id has been created before."
}
Error Code | Description |
---|---|
MERCHANT_NOT_FOUND422 |
You are not registered yet to use this payment method. |
GENERATE_CHECKOUT_URL_ERROR422 |
Your request did not meet the requirement or there is a problem in the Kredivo / Partner server. |
DUPLICATE_PAYMENT_ERROR422 |
Checkout URL with the same external_id has been created before. |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Calculate Payment Types
Calculate Payment Types feature helps merchants to get an accurate value of the installment offered to end customers by the cardless credit provider. Merchants can use this to calculate and display installment plans before end customer is redirected for authentication.
Endpoint: Calculate Payment Types
POST https://api.xendit.co/cardless-credit/payment-types
Calculate Payment Types
Example: Calculate Payment Types Request
curl https://api.xendit.co/cardless-credit/payment-types -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
--header 'content-type: application/json' \
--data '{
"cardless_credit_type": "KREDIVO",
"amount": 2000000,
"items":
[
{
"id": "123123",
"name": "Phone Case",
"price": 1000000,
"type": "Smartphone",
"url": "http://example.com/phone/phone_case",
"quantity": 1
}
]
}'
<?php
$url = 'https://api.xendit.co/cardless-credit/payment-types';
$apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
$headers = [];
$headers[] = 'Content-Type: application/json';
$item_1 = new stdClass();
$item_1->id = "123123";
$item_1->name = "Phone Case";
$item_1->price = 200000;
$item_1->type = "Smartphone";
$item_1->url = "http://example.com/phone/phone_case";
$item_1->quantity = 2;
$data = [
"cardless_credit_type" => "KREDIVO",
"amount" => 800000,
"items" => [ $item_1 ],
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
from xendit import Xendit, CardlessCreditType
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
xendit_instance = Xendit(api_key=api_key)
CardlessCredit = xendit_instance.CardlessCredit
cardless_credit_items = []
cardless_credit_items.append(
CardlessCredit.helper_create_item(
id="item-123",
name="Phone Case",
price=200000,
type="Smartphone",
url="http://example.com/phone/phone_case",
quantity=2,
)
)
cardless_credit_payment_types = CardlessCredit.calculate_payment_type(
cardless_credit_type=CardlessCreditType.KREDIVO,
amount=10000,
items=cardless_credit_items,
)
print(cardless_credit_payment_types)
Parameter | Description |
---|---|
cardless_credit_type required |
string The type of cardless-credit to be paid. Must be in capital letters. Supported Cardless Credit types: KREDIVO |
amount required |
number Amount end customer will pay. Note: minimum amount is 1 IDR |
items required |
array of item object List of items / products. |
items.id required |
string Merchant product ID of specified product in transaction |
items.name required |
string Name of specified product in transaction |
items.price required |
number Unit price of specified product in transaction |
items.type required |
string Category of specified product in transaction |
items.url required |
string Web url of specified product in transaction |
items.quantity required |
number Quantity of specified product in transaction |
Calculate Payment Types Response
Example: Calculate Payment Types Response
{
"message": "Available payment types are listed.",
"payments": [
{
"raw_monthly_installment": 187534.6668043921,
"name": "Bayar dalam 6 bulan",
"amount": 1000000,
"installment_amount": 1125240,
"raw_amount": 1000000,
"rate": 2.95,
"down_payment": 0,
"monthly_installment": 187540,
"discounted_monthly_installment": 0,
"tenure": 6,
"id": "6_months"
},
{
"raw_monthly_installment": 1020000,
"name": "Bayar dalam 30 hari",
"amount": 1020000,
"installment_amount": 1020000,
"raw_amount": 1020000,
"rate": 0,
"down_payment": 0,
"monthly_installment": 1020000,
"discounted_monthly_installment": 0,
"tenure": 1,
"id": "30_days"
},
{
"raw_monthly_installment": 356786.46273702476,
"name": "Bayar dalam 3 bulan",
"amount": 1000000,
"installment_amount": 1070370,
"raw_amount": 1000000,
"rate": 2.95,
"down_payment": 0,
"monthly_installment": 356790,
"discounted_monthly_installment": 0,
"tenure": 3,
"id": "3_months"
}
]
}
Parameter | Description |
---|---|
message required |
string “Available payment types are listed |
payments required |
array List of calculated payment types |
payments.raw_monthly_installment required |
number Monthly installment before rounding |
payments.name required |
string Name of installment plan |
payments.amount required |
number Total payment amount before interest |
payments.installment_amount required |
number Total payment amount after interest |
payments.raw_amount required |
number Payment amount before interest before rounding |
payments.rate required |
number Applied interest rates |
payments.down_payment required |
number Amount paid upfront |
payments.monthly_installment required |
number Monthly installment offered by Kredivo to end user |
payments.discounted_monthly_installment required |
number Monthly installment offered by Kredivo to end user after discount (if any) |
payments.tenure required |
number Repayment term of installment in months |
payments.id required |
string ID of installment type |
Payment Callback Notification
Callback Payload
You need to provide an endpoint in your system to receive payment callback notification from our system. We will send the payment callback notification when the end-customer completes the payment on the Checkout page.
The payment callback notification will be sent as POST request to the "callback_url" that you sepecified on the Generate Checkout URL request.
Example: Payment Callback Notification Request
{
"external_id": "test-cardless-credit-01",
"order_id": "75191237c81273jajsh7291c-test-cardless-credit-01",
"transaction_id": "ashd7129-sh82-a9ks-js82-asj82912bajs",
"amount": 800000,
"transaction_status": "settlement",
"payment_type": "3_months",
"items": [
{
"id": "123123",
"name": "Phone Case",
"price": 200000,
"type": "Smartphone",
"url": "http://example.com/phone/phone_case",
"quantity": 2
},
{
"id": "234567",
"name": "Bluetooth Headset",
"price": 400000,
"type": "Audio",
"url": "http://example.com/audio/bluetooth_headset",
"quantity": 1
}
],
"customer_details": {
"first_name": "customer first name",
"last_name": "customer last name",
"email": "customer@yourwebsite.com",
"phone": "081513114262"
},
"shipping_address": {
"first_name": "first name",
"last_name": "last name",
"address": "Jalan Teknologi No. 12",
"city": "Jakarta",
"postal_code": "12345",
"phone": "081513114262",
"country_code": "IDN"
},
"cardless_credit_type": "KREDIVO",
"callback_authentication_token": "MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n=="
}
Parameter | Type | Description |
---|---|---|
external_id | string |
Your transaction identifier that you specified in on the Generate Checkout URL request. |
order_id | string |
Unique Identifier that we gave to the cardless credit payment partner. |
transaction_id | string |
Transaction ID given by Cardless Credit partner. |
transaction_status | string |
Transaction status, the value is: settlement: Transaction is successful pending: End-User has not completed the transaction deny: Transaction has been denied by our Cardless Credit Partner cancel: Transaction has been cancelled expire: End-User did not complete transaction in 24 hours, thus transaction is expired |
payment_type | string |
the type of installment. |
amount | number |
Amount that you specified in on the Generate Checkout URL request. |
items | array of item |
List of items / products that you specified in on the Generate Checkout URL request. |
item object |
item detail |
Details of an item, it should contains: id [string], name [string], price [number], type [string], url [string], quantity [number] |
customer_details | object |
Details of the customer, it should contains: first_name [string], last_name [string], email [string], phone [string] |
shipping_address | object |
Details of the shipping address, it should contains: first_name [string], last_name [string], address [string], city [string], postal_code [string], phone [string], country_code [string] |
cardless_credit_type | string |
The type of cardless-credit. Supported Cardless Credit types: KREDIVO |
callback_authentication_token | string |
Your Callback Verfication API Key that you can found on your Xendit Dashboard. You need to verify if this had the same value. |
QR Codes
QR codes payment instrument allows you to receive payments directly from end user's mobile banking app balance or eWallet balance. In Indonesia, our merchants can receive payments from any providers connected on QRIS network. (e.g. OVO, Gopay, DANA, LinkAja, BCA, CIMB, Shopeepay)
Create QR Code
Endpoint: Create QR Code
POST https://api.xendit.co/qr_codes
Request Parameters
Example: Create QRIS QR Code
curl https://api.xendit.co/qr_codes -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
-d external_id='testing_id_123' \
-d type='DYNAMIC' \
-d callback_url='https://yourwebsite.com/callback'\
-d amount=1500
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.xendit.co/qr_codes');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "external_id=testing_id_123&type=DYNAMIC&callback_url=https://yourwebsite.com/callback&amount=1500");
curl_setopt($ch, CURLOPT_USERPWD, 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==' . ':' . '');
$headers = array();
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { QrCode } = x;
const qrcodeSpecificOptions = {};
const q = new QrCode(qrcodeSpecificOptions);
const resp = await q.createCode({
externalID: "testing_id_123",
type: "DYNAMIC",
callbackURL: "https://yourwebsite.com/callback",
amount: 1500,
});
console.log(resp);
from xendit import Xendit, QRCodeType
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
QRCode = xendit_instance.QRCode
qrcode = QRCode.create(
external_id="qrcode-id-1594794038",
type=QRCodeType.DYNAMIC,
callback_url="https://webhook.site",
amount=4000,
)
print(qrcode)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
external_id required |
string |
An ID of your choice. Often it is unique identifier in your system like customer ID or order ID Note: It has to be unique per creation request |
type required |
string |
DYNAMIC or STATIC Note: DYNAMIC QR code contains the payment value upon scanning and can be paid multiple times Note: STATIC QR code requires end user to input the payment value and can be paid multiple times |
callback_urlrequired |
string |
The URL to receive payment notification after payment has been made by end user |
amountoptional |
number |
The payment value embedded in the QR code, end user can only pay the specified amount after scanning the QR code. For STATIC QR code, amount parameter will be ignored. Note: Min amount is 1,500 IDR Note: Max amount is 2,000,000 IDR |
metadataoptional |
object |
Object of additional information the user may use. Users define the JSON properties and values. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Response Parameters
Example: Create QRIS QR Code API Success Response
{
"id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
"external_id": "testing_id_123",
"amount": 1500,
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52 045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"callback_url": "https://yourwebsite.com/callback",
"type": "DYNAMIC",
"status": "ACTIVE",
"created": "2020-01-08T18:18:18.661Z",
"updated": "2020-01-08T18:18:18.661Z",
"metadata": {
"branch_code": "senayan_372",
}
}
Parameter | Type | Description |
---|---|---|
id required |
string |
Unique identifier for this transaction |
external_id required |
string |
Unique identifier specified by merchant for QR code creation |
amount required |
number |
Amount specified in request Note: Value will be NULL if QR type is STATIC |
qr_string required |
string |
QR string to be rendered for display to end users. QR string to image rendering are commonly available in software libraries (e.g Nodejs, PHP, Java) |
callback_url required |
string |
The URL provided by merchant to receive payment notification after payment has been made by end user |
type required |
string |
DYNAMIC or STATIC |
status required |
string |
ACTIVE (QR code can be paid) or INACTIVE (QR code has been paid for DYNAMIC QR) |
created required |
string |
Timestamp ISO 8601 when the QR code was created (in UTC) |
updated required |
string |
Timestamp ISO 8601 when the QR code was patched (in UTC) |
metadata optional |
object |
User defined object with JSON properties and values passed in during charge creation. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Error Codes
Example: Create QRIS QR Code API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "Amount must be within range [1500, 2000000]"
}
Error Code | Description |
---|---|
DUPLICATE_ERROR409 |
The payment with the same external_id has already been made before. |
DATA_NOT_FOUND409 |
QRIS merchant not found, please contact our customer success team for activation. |
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields. |
Get QR Code by External ID
GET https://api.xendit.co/qr_codes/:external_id
Request Parameters
Example: Get QR Code by external_id
curl https://api.xendit.co/qr_codes/external_id -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.xendit.co/qr_codes/external_id');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_USERPWD, 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==' . ':' . '');
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { QrCode } = x;
const qrcodeSpecificOptions = {};
const q = new QrCode(qrcodeSpecificOptions);
const resp = await q.getCode({
externalID: "testing_id_123",
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
QRCode = xendit_instance.QRCode
qrcode = QRCode.get_by_ext_id(
external_id="qrcode-id-1594794038",
)
print(qrcode)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
external_id required |
string |
Merchant provided unique ID used to create QR code |
Response Parameters
Example: Get QR Code by external_id Success Response
{
"id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
"external_id": "testing_id_123",
"amount": 1500,
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"callback_url": "https://yourwebsite.com/callback",
"type": "DYNAMIC",
"status": "ACTIVE",
"created": "2020-01-08T18:18:18.661Z",
"updated": "2020-01-08T18:18:18.661Z",
"metadata": {
"branch_code": "senayan_372",
}
}
Parameter | Type | Description |
---|---|---|
id required |
string |
Unique identifier for this transaction |
external_id required |
string |
Unique identifier specified by merchant for QR code creation |
amount required |
number |
Amount specified in request Note: Value will be NULL if QR type is STATIC |
qr_string required |
string |
QR string to be rendered for display to end users. QR string to image rendering are commonly available in software libraries (e.g Nodejs, PHP, Java) |
callback_url required |
string |
The URL provided by merchant to receive payment notification after payment has been made by end user |
type required |
string |
Type of QR code - DYNAMIC or STATIC |
status required |
string |
ACTIVE (QR code can be paid) or INACTIVE (QR code has been paid for DYNAMIC QR) |
created required |
string |
Timestamp ISO 8601 when the QR code was created (in UTC) |
updated required |
string |
Timestamp ISO 8601 when the QR code was patched (in UTC) |
metadata optional |
object |
User defined object with JSON properties and values passed in during charge creation. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Error Codes
Example: Create QRIS QR Code API Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "QR code with external_id testing_id_123 not found"
}
Error Code | Description |
---|---|
DATA_NOT_FOUND404 |
The QR code with specified external_id does not exist. |
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Get Payments by External ID
Provides the feature to retrieve all payments that were made into a particular QR code. This endpoint is particularly useful if each QR code is set up to receive multiple payments (e.g. offline static QR codes)
GET https://api.xendit.co/qr_codes/payments?external_id={external_id}&from={created}&to={created}&limit={number}
Request Parameters
Example: Get Array of Payments by external_id
curl 'https://api.xendit.co/qr_codes/payments?external_id=testing_qr&from=2021-01-04T08:09:30.000Z&to=2021-01-04T08:22:29.000Z&limit=2' -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.xendit.co/qr_codes/payments?external_id=testing_qr&from=2021-01-04T08:09:30.000Z&to=2021-01-04T08:22:29.000Z&limit=2');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_USERPWD, 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==' . ':' . '');
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { QrCode } = x;
const qrcodeSpecificOptions = {};
const q = new QrCode(qrcodeSpecificOptions);
const resp = await q.getPayments({
externalID: "testing_id_123",
from: "2021-01-04T08:09:30.000Z",
to: "2021-02-04T07:44:20.332Z",
limit: 10,
});
console.log(resp);
Path Parameter | Type | Description |
---|---|---|
external_id required |
string |
Merchant provided unique transaction ID used to create QR code |
limit optional |
number |
Default = 10. Number of payment transactions to be returned in response array |
from optional |
string |
Starting timestamp for time based filters using created , timestamp must be earlier than to parameter |
to optional |
string |
Ending timestamp for time based filters using created , timestamp must be later than from parameter |
Response Parameters
Example: Get Array of Payments by external_id Success Response
[
{
"id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
"amount": 1500,
"created": "2020-01-08T18:18:18.857Z",
"qr_code": {
"id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
"external_id": "testing_id_123",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"type": "DYNAMIC",
"metadata": {
"branch_code": "senayan_372",
}
},
"status": "COMPLETED"
},
{
"id": "qrpy_8182837te-87st-49ing-8696-1229bd22222",
"amount": 1500,
"created": "2020-01-08T18:18:20.857Z",
"qr_code": {
"id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
"external_id": "testing_id_123",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"type": "DYNAMIC",
"metadata": {
"branch_code": "senayan_372",
}
},
"status": "COMPLETED"
}
]
Parameter | Type | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for this transaction | ||||||||||||
amountrequired |
number |
Amount paid by end user | ||||||||||||
createdrequired |
string |
Timestamp ISO 8601 when the QR code was paid (in UTC) | ||||||||||||
qr_coderequired |
object |
QR code object associated with the QR code payment QR code fields
|
||||||||||||
statusrequired |
string |
Status of payment. Possible value(s): COMPLETED |
Error Codes
Example: Get Array of Payments by external_id
{
"error_code": "DATA_NOT_FOUND",
"message": "QR code with external_id testing_id_123 not found"
}
Error Code | Description |
---|---|
DATA_NOT_FOUND404 |
The QR code with specified external_id does not exist. |
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Simulate Payment (for completion of payment in test mode)
POST https://api.xendit.co/qr_codes/:external_id/payments/simulate
Request Parameters (test mode)
Example: Simulate Payment in Test Mode
curl https://api.xendit.co/qr_codes/:external_id/payments/simulate -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
-d amount=1500
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.xendit.co/qr_codes/:external_id/payments/simulate');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "amount=1500");
curl_setopt($ch, CURLOPT_USERPWD, 'xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==' . ':' . '');
$headers = array();
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { QrCode } = x;
const qrcodeSpecificOptions = {};
const q = new QrCode(qrcodeSpecificOptions);
const resp = await q.simulate({
externalID: "testing_id_123",
});
console.log(resp);
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
external_id required |
string |
Unique identifier specified by merchant for QR code creation |
Body Parameter | Type | Description |
---|---|---|
amountoptional |
number |
The payment value for simulation in callback to test mode endpoint Note: Min amount is 1,500 IDR Note: Max amount is 2,000,000 IDR |
Response Parameters (test mode)
Example: Simulate Payment (test mode) Success Response
{
"id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
"amount": 1500,
"created": "2020-01-08T18:18:18.857Z",
"qr_code": {
"id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
"external_id": "testing_id_123",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"type": "DYNAMIC",
"metadata": {
"branch_code": "senayan_372",
}
},
"status": "COMPLETED"
}
Parameter | Type | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for this transaction | ||||||||||||
amountrequired |
number |
Amount paid by end user | ||||||||||||
createdrequired |
string |
Timestamp ISO 8601 when the QR code was paid (in UTC) | ||||||||||||
qr_coderequired |
object |
QR code object associated with the QR code payment QR code fields
|
||||||||||||
statusrequired |
string |
Status of payment. Possible value(s): COMPLETED |
Error Codes
Example: Create QRIS QR Code API Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "QR code with external_id testing_id_123 not found"
}
Error Code | Description |
---|---|
INACTIVE_QR_CODE410 |
Payment simulation for DYNAMIC QRIS has been completed previously. DYNAMIC QRIS is inactive. |
DATA_NOT_FOUND404 |
The QR code with specified external_id does not exist. |
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields. |
Payment Status Callback
You will need to provide an endpoint in your system to receive payment callback notification from our system. You will receive the callback when end-customer completed the QR code payment.
Note: Please give this notification a response back with status 200
so we know that our notification is received.
Callback Payload
{
"event": "qr.payment",
"id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
"amount": 1500,
"created": "2020-01-08T18:18:18.857Z",
"qr_code": {
"id": "qr_8182837te-87st-49ing-8696-1239bd4d759c",
"external_id": "testing_id_123",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"type": "DYNAMIC",
"metadata": {
"branch_code": "senayan_372",
}
},
"status": "COMPLETED"
}
Parameter | Type | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
eventrequired |
string |
Available value: "qr.payment" | ||||||||||||
idrequired |
string |
Unique identifier for this transaction | ||||||||||||
amountrequired |
number |
Amount paid by end user | ||||||||||||
createdrequired |
string |
Timestamp ISO 8601 when the QR code was paid (in UTC) | ||||||||||||
qr_coderequired |
object |
QR code object associated with the QR code payment QR code fields
|
||||||||||||
statusrequired |
string |
Status of payment. Possible value(s): COMPLETED |
Direct Debit
Direct Debit enables merchants to pull payments directly from their end user’s account bank balance by linking their debit card or bank account access.
For the integration guide, and list of supported channels and corresponding linking type, see our documentation.
Initialize Linked Account Tokenization
Account authorizations are represented by linked account tokens. This endpoint initializes the authorization process and linked account token creation.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Initialize Linked Account Tokenization
POST https://api.xendit.co/linked_account_tokens/auth
Initialize Linked Account Tokenization - Request
Example Initialize Linked Account Tokenization Request
curl https://api.xendit.co/linked_account_tokens/auth -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
--data-raw '{
"customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"channel_code": "DC_BRI",
"properties": {
"account_mobile_number": "+62818555988",
"card_last_four": "1234",
"card_expiry": "06/24",
"account_email": "email@email.com"
}
}'
<?php
$url = "https://api.xendit.co/linked_account_tokens/auth";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$data = [
"customer_id" => "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"channel_code" => "DC_BRI",
"properties" => [
"account_mobile_number" => "+62818555988",
"card_last_four" => "1234",
"card_expiry" => "06/24",
"account_email" => "email@email.com"
]
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { DirectDebit } = x;
const directDebitSpecificOptions = {};
const dd = new DirectDebit(directDebitSpecificOptions);
const resp = await dd.initializeTokenization({
customerID: 'ba830b92-4177-476e-b097-2ad5ae4d3e55',
channelCode: 'DC_BRI',
properties: {
accountMobileNumber: '+62818555988',
cardLastFour: '1234',
cardExpiry: '06/24',
accountEmail: 'email@email.com',
},
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
card_linking = DirectDebit.helper_create_card_link(
account_mobile_number="+62818555988",
card_last_four="8888",
card_expiry="06/24",
account_email="test.email@xendit.co",
)
linked_account = DirectDebit.initialize_tokenization(
customer_id="ed20b5db-df04-41fc-8018-8ea4ac4d1030",
channel_code="DC_BRI",
properties=card_linking,
)
print(linked_account)
Request Body Parameter | Type | Description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
customer_id required |
string
|
ID of the customer object to which the account token will be linked to. Call Customer API to generate Customer ID | ||||||||||||||||||
channel_code required |
string
|
Identifier for the specific channel of the account to be linked. Code must be in uppercase. Supported banks and their respective channel codes:
|
||||||||||||||||||
properties optional |
object
|
JSON that contains information needed to proceed with authorization. Values inside properties change based on type of account: For Debit Card Linking (BRI):
|
||||||||||||||||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. |
Initialize Linked Account Tokenization - Response
Example Initialize Linked Account Tokenization Success Response
{
"id": "lat-aa620619-124f-41db-995b-66a52abe036a",
"customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"channel_code": "DC_BRI",
"authorizer_url": null,
"status": "PENDING",
"metadata": null
}
Parameter | Type | Description |
---|---|---|
id | string |
Unique ID generated by Xendit for the particular linked account token authorization |
customer_id | string |
Customer object ID |
channel_code | string |
Code identifier for the channel |
authorizer_url | string |
URL to be rendered for end user to confirm authorization for linking via online banking access. For debit card linking (BRI), this will always be null ; proceed to the "Validate OTP for Linked Account Token" step instead. |
status | string |
Status of the authorization. Will always be PENDING for successful initiations. |
metadata | object |
A free-format JSON for additional information that you provded during request. |
Initialize Linked Account Tokenization - Errors
See other common errors here.
Error Code | Description |
---|---|
CHANNEL_CODE_NOT_SUPPORTED_ERROR 400 |
Provided channel_code is not supported or has not yet activated for this account. |
CUSTOMER_NOT_FOUND_ERROR 400 |
Provided customer_id in the request does not exist or access is unauthorized |
INVALID_ACCOUNT_DETAILS 400 |
Provided values in properties in the request does not match any records with the bank |
ACCOUNT_ACCESS_BLOCKED 400 |
The bank has rejected the linking. This maybe the bank account is inaccessible or not activated for this service. |
MAX_ACCOUNT_LINKING 400 |
Cannot link the account because it has reached the maximum number of linking allowed by the bank. Please unlink any existing binding for this account. |
OTP_DELIVERY_ERROR 400 |
The bank failed to send the OTP to the end-user. Please try again. |
CHANNEL_UNAVAILABLE 503 |
The target channel is currently unavailable. This is possibly due to partner channel downtime or error. |
Validate OTP for Linked Account Token
Account linking for debit cards requires an OTP to proceed. Upon successful initialization, the bank will send an OTP to the customer's registered mobile number directly. This endpoint validates the OTP with the bank.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Validate OTP for Linked Account Token
POST https://api.xendit.co/linked_account_tokens/{linked_account_token_id}/validate_otp
Validate OTP for Linked Account Token - Request
Example Validate OTP for Linked Account Token Request
curl https://api.xendit.co/linked_account_tokens/lat-aa620619-124f-41db-995b-66a52abe036a/validate_otp -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
--data-raw '{
"otp_code":"123456"
}'
<?php
$linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
$url = "https://api.xendit.co/linked_account_tokens/" . $linkedAccountTokenId . "/validate_otp";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$data = [
"otp_code" => "123456"
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { DirectDebit } = x;
const directDebitSpecificOptions = {};
const dd = new DirectDebit(directDebitSpecificOptions);
const resp = await dd.validateOTPforLinkedAccount({
tokenID: 'lat-aa620619-124f-41db-995b-66a52abe036a',
otpCode: '123456',
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
linked_account = DirectDebit.validate_token_otp(
linked_account_token_id="lat-f325b757-0aae-4c24-92c5-3661e299e154",
otp_code="333000",
)
print(linked_account)
Path Parameter | Type | Description |
---|---|---|
linked_account_token_id required |
string |
Linked account token id received from Initialize Account Authorization. This has the lat- prefix. |
Request Body Parameter | Type | Description |
---|---|---|
otp_code required |
string |
OTP received by the customer from the partner bank for account linking |
Validate OTP for Linked Account Token - Response
Example Validate OTP for Linked Account Token Success Response
{
"id": "lat-aa620619-124f-41db-995b-66a52abe036a",
"customer_id": "239c16f4-866d-43e8-9341-7badafbc019f",
"channel_code": "DC_BRI",
"status": "SUCCESS"
}
Parameter | Type | Description |
---|---|---|
id | string |
Unique ID generated by Xendit for the particular linked account token authorization |
customer_id | string |
Customer object ID |
channel_code | string |
Code identifier for the channel |
status | string |
Status of the authorization - SUCCESS if the validation went through. Else, error will be thrown |
Validate OTP for Linked Account Token - Errors
See other common errors here.
Error Code | Description |
---|---|
DATA_NOT_FOUND_ERROR 404 |
Provided linked_account_token_id is not supported or has not yet activated for this account. |
INVALID_OTP_ERROR 400 |
The otp_code provided was incorrect. |
EXPIRED_OTP_ERROR 400 |
The otp_code provided has expired. |
MAX_OTP_ATTEMPTS_ERROR 400 |
Reached the channel’s allowed maximum attempts for OTP verification |
ACCOUNT_LINKING_ALREADY_COMPLETED 409 |
The request is a duplicate of an already processed linked account token that has been successfully completed. |
ACCOUNT_LINKING_ALREADY_FAILED 409 |
The request is a duplicate of an already processed linked account token that has failed. |
Retrieve Accessible Accounts by Linked Account Token
This endpoint returns a list of bank accounts accessible by the linked account token. The response information from this endpoint is required for creation of payment method.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Get Accessible Accounts by Linked Account Token
GET https://api.xendit.co/linked_account_tokens/{linked_account_token_id}/accounts
Retrieve Accessible Accounts by Linked Account Token - Request
Example Get Accessible Accounts by Linked Account Token Request
curl https://api.xendit.co/linked_account_tokens/lat-aa620619-124f-41db-995b-66a52abe036a/accounts -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
$url = "https://api.xendit.co/linked_account_tokens/" . $linkedAccountTokenId . "/accounts";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { DirectDebit } = x;
const directDebitSpecificOptions = {};
const dd = new DirectDebit(directDebitSpecificOptions);
const resp = await dd.retrieveAccountsByTokenID({
tokenID: 'lat-aa620619-124f-41db-995b-66a52abe036a',
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
accessible_accounts = DirectDebit.get_accessible_account_by_token(
linked_account_token_id="lat-f325b757-0aae-4c24-92c5-3661e299e154",
)
print(accessible_accounts)
Path Parameter | Type | Description |
---|---|---|
linked_account_token_idrequired |
string |
Linked account token id received from Initialize Account Authorization. This has the lat- prefix. |
Retrieve Accessible Accounts by Linked Account Token - Response
This endpoint returns an array of objects with the following properties:
Example Get Accessible Accounts by Linked Account Token Success Response
[{
"id": "la-aa620619-124f-41db-995b-66a52abe036a",
"channel_code": "DC_BRI",
"type": "DEBIT_CARD",
"properties": {
"card_last_four": "1234",
"card_expiry": "06/24",
"currency": "IDR",
"description": ""
}
}]
Parameter | Type | Description | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id |
string
|
Unique identifier for the bank account. This has a prefix of la- . |
||||||||||||||||||||||
channel_code |
string
|
Code identifier for the channel | ||||||||||||||||||||||
type |
string
|
Type of account that has been linked. Expected values: DEBIT_CARD or BANK_ACCOUNT
|
||||||||||||||||||||||
properties |
object
|
Object containing information regarding the account. The values inside properties change based on the type of account: For type DEBIT_CARD (BRI):
BANK_ACCOUNT (BPI):
|
Retrieve Accessible Accounts by Linked Account Token - Errors
See other common errors here.
Error Code | Description |
---|---|
DATA_NOT_FOUND_ERROR 404 |
Provided linked_account_token_id is not supported or has not yet activated for this account. |
Unbind a Linked Account Token
Unlinks or unbinds a successful linked account token.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Unbind a Linked Account Token
DELETE https://api.xendit.co/linked_account_tokens/{linked_account_token_id}
Unbind a Linked Account Token - Request
Example Unbind a Linked Account Token Request
curl https://api.xendit.co/linked_account_tokens/lat-aa620619-124f-41db-995b-66a52abe036a/validate_otp -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
$url = "https://api.xendit.co/linked_account_tokens/" . $linkedAccountTokenId;
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
let linkedAccountTokenId = "lat-aa620619-124f-41db-995b-66a52abe036a";
let url = "https://api.xendit.co/linked_account_tokens/" + linkedAccountTokenId;
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
var requestOptions = {
method: 'DELETE',
headers: headers,
redirect: 'follow'
};
fetch(url, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Path Parameter | Type | Description |
---|---|---|
linked_account_token_id required |
string |
Linked account token id received from Initialize Account Authorization. This has the lat- prefix. |
Unbind a Linked Account Token - Response
Example Unbind a Linked Account Token Success Response
{
"id": "lat-aa620619-124f-41db-995b-66a52abe036a",
"is_deleted": true
}
Parameter | Type | Description |
---|---|---|
id | string |
Unique ID generated by Xendit for the particular linked account token authorization |
is_deleted | boolean |
Describes whether or not the linked account token was successfully deleted |
Unbind a Linked Account Token - Errors
See other common errors here.
Error Code | Description |
---|---|
DATA_NOT_FOUND_ERROR 404 |
Provided linked_account_token_id is not found or inaccessible for this account. |
Create Payment Method
Payment methods enable you to abstract sources of funds and use them for making direct debit payments or recurring payments. Currently, only supports linked accounts.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Create Payment Method
POST https://api.xendit.co/payment_methods
Create Payment Method - Request
Example Create Payment Method Request
curl https://api.xendit.co/payment_methods -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
--data-raw '{
"customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"type": "DEBIT_CARD",
"properties": {
"id": "la-aa620619-124f-41db-995b-66a52abe036a"
}
}'
<?php
$url = "https://api.xendit.co/payment_methods";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$data = [
"customer_id" => "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"type" => "DEBIT_CARD",
"properties" => [
"id" => "la-aa620619-124f-41db-995b-66a52abe036a"
]
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { DirectDebit } = x;
const directDebitSpecificOptions = {};
const dd = new DirectDebit(directDebitSpecificOptions);
const resp = await dd.createPaymentMethod({
customerID: 'ba830b92-4177-476e-b097-2ad5ae4d3e55',
type: 'DEBIT_CARD',
properties: {
id: 'la-aa620619-124f-41db-995b-66a52abe036a',
},
});
console.log(resp);
from xendit import Xendit, DirectDebitPaymentMethodType
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
payment_method = DirectDebit.create_payment_method(
customer_id="ed20b5db-df04-41fc-8018-8ea4ac4d1030",
type=DirectDebitPaymentMethodType.DEBIT_CARD,
properties={'id': 'la-fac7e744-ab40-4100-a447-cbbb16f29ded'},
)
print(payment_method)
Request Body Parameter | Type | Description | ||||
---|---|---|---|---|---|---|
customer_id required |
string
|
ID of the customer object to which the account token will be linked to | ||||
type required |
string
|
Type of payment method Supported values: DEBIT_CARD , BANK_ACCOUNT
|
||||
properties required |
object
|
JSON that contains information that identifies the payment method: For Debit Card Linking (BRI) or Bank Account Access (BPI):
|
||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. |
Create Payment Method - Response
Example Create Payment Method Success Response
{
"id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"type": "DEBIT_CARD",
"properties": {
"id": "la-aa620619-124f-41db-995b-66a52abe036a",
"channel_code": "DC_BRI",
"currency": "IDR",
"card_last_four": "1234",
"card_expiry": "06/24",
"description": null,
},
"customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"status": "ACTIVE",
"created": "2020-03-19T05:34:55+0800",
"updated": "2020-03-19T05:24:55+0800",
"metadata": null
}
Parameter | Type | Description | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id |
string
|
Unique identifier for the payment method. This has a prefix of pm- . |
||||||||||||||||||||||
type |
string
|
Type of account that has been linked. Expected values: DEBIT_CARD or BANK_ACCOUNT
|
||||||||||||||||||||||
properties |
object
|
Object containing information regarding the account. The values inside properties change based on the type of account: For type DEBIT_CARD (BRI):
BANK_ACCOUNT (BPI):
|
||||||||||||||||||||||
customer_id |
string
|
ID of the customer object in which this payment method is linked to |
||||||||||||||||||||||
status required |
string
|
Status of the payment method. Will be equal to ACTIVE upon creation. |
||||||||||||||||||||||
created |
string
|
Timestamp in ISO 8601 when the request was madeFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||||||||||||||||
updated |
string
|
Timestamp in ISO 8601 when transaction information was updatedFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||||||||||||||||
metadata |
object
|
A free-format JSON for additional information that you provded during request. |
Create Payment Method - Errors
See other common errors here.
Error Code | Description |
---|---|
LIINKED_ACCOUNT_NOT_FOUND_ERROR 400 |
Provided properties and type combination in the request does not exist or access is unauthorized |
CUSTOMER_NOT_FOUND_ERROR 400 |
Provided customer_id in the request does not exist or access is unauthorized |
DUPLICATE_ERROR 409 |
There is already an existing ACTIVE payment method that relates to the same account |
Create Recurring Payment with Direct Debit
Endpoint: Create Recurring Payment
POST https://api.xendit.co/recurring_payments
Recurring payments allow you to use the auto debit feature in direct debit to pull funds from your customers bank account on a scheduled basis.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Request Parameters
Example: Create Recurring Request
curl https://api.xendit.co/recurring_payments -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d external_id=recurring_31451441 \
-d payment_method_id=pm_testing_id_123\
-d payer_email=sample_email@xendit.co \
-d interval=MONTH \
-d interval_count=1 \
-d description='Monthly room cleaning service' \
-d total_recurrence=10\
-d charge_immediately=true\
-d invoice_duration=300\
-d amount=125000
<?php
require 'vendor/autoload.php';
$options['secret_api_key'] = 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==';
$xenditPHPClient = new XenditClient\XenditPHPClient($options);
$external_id = 'recurring_31451441';
$amount = 125000;
$payment_method_id='pm_testing_id_123';
$payer_email = 'sample_email@xendit.co';
$interval = 'MONTH';
$interval_count = 1;
$description = 'Monthly room cleaning service';
$total_recurrence=10;
$charge_immediately=true;
$invoice_duration=300;
$response = $xenditPHPClient->createRecurringPayment($external_id, $amount, $payer_email, $interval, $interval_count, $description);
print_r($response);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RecurringPayment } = x;
const rpSpecificOptions = {};
const rp = new RecurringPayment(rpSpecificOptions);
const resp = await rp.createPayment({
externalID: 'recurring_31451441',
amount: 125000,
payerEmail: 'sample_email@xendit.co',
interval: RecurringPayment.Interval.Month,
intervalCount: 1,
description: 'Monthly room cleaning service',
payment_method_id: 'pm_testing_id_123',
total_recurrence: 10,
charge_immediately: true,
invoice_duration: 300
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RecurringPayment = xendit_instance.RecurringPayment
recurring_payment = RecurringPayment.create_recurring_payment(
external_id="recurring_12345",
payer_email="test@x.co",
description="Test Curring Payment",
amount=100000,
interval="MONTH",
interval_count=1,
payment_method_id="pm_testing_id_123",
)
print(recurring_payment)
Body Parameter | Type | Description |
---|---|---|
external_id required |
string |
ID of your choice (typically the unique identifier of a recurring payment in your system) |
payment_method_id optional |
string |
Fill this with the payment method id created for the customer in create payment method |
payer_email required |
string |
Email of the end user you're charging |
description required |
string |
Description for the recurring payment and invoices |
amount required |
number |
Amount per invoice per interval. The minimum amount to create an invoice is 10.000 IDR. The maximum amount is 1.000.000 IDR for direct debit |
interval required |
string |
One of DAY , WEEK , MONTH . The frequency with which a recurring payment invoice should be billed. |
interval_count required |
number |
The number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months. |
invoice_duration required |
number |
Set this value to 300 for direct debit recurring to work. Duration of time that end user have in order to pay the invoice before it's expired (in Second). |
total_recurrence optional |
number |
The number of times you will charge your customer. If you input it as 3, Xendit will charge your customer 3 times. If you input total_recurrence as 3, interval_count as 1 and interval as "DAY", Xendit will charge customer 3 times in first day after you trigger create recurring api, the day after and 2 days after you trigger create recurring api. |
should_send_email optional |
boolean |
Specify should the end user get email when invoice is created, paid, or expired; or not default:
|
missed_payment_action optional |
string |
One of IGNORE , STOP . If there is an invoice from a recurring payment that expired, IGNORE will continue with the recurring payment as usual. STOP will stop the recurring payment. default:
|
start_date optional |
string (ISO 8601) |
time when the first invoice will be issued. When left blank, the invoice will be created immediately |
charge_immediately optional |
boolean |
Specify should the first invoice created immediately when creating recurring payment with a valid start_date , The next invoice will be created at start_date and the calculation for the following recurring invoice will be at interval *interval_count + start_date |
Response Parameters
Example: Create Recurring Response
{
"id": "579c8d61f23fa4ca35e52da3",
"user_id": "5781d19b2e2385880609791c",
"external_id": "recurring_31451441",
"status": "ACTIVE",
"amount": 125000,
"payer_email": "sample_email@xendit.co",
"description": "Monthly room cleaning service",
"interval": "MONTH",
"interval_count": 1,
"recurrence_progress": 1,
"should_send_email": false,
"missed_payment_action": "IGNORE",
"last_created_invoice_url": "https://invoice-staging.xendit.co/web/invoices/5dddeea6bdb99f4b23e5eef7",
"created": "2017-06-12T14:00:00.306Z",
"updated": "2017-06-12T14:00:00.306Z",
"start_date": "2017-07-12T14:00:00.306Z",
"recharge": true,
"payment_method_id": "pm_testing_id_123"
}
Parameter | Type | Description |
---|---|---|
id | string |
An recurring ID generated by Xendit |
user_id | string |
Your Xendit Business ID |
external_id | string |
The recurring ID in your server, that can be used to reconcile between you and Xendit |
status | string |
ACTIVE the recurring payment is currently activeSTOPPED the recurring payment has been stoppedPAUSED the recurring payment is currently paused and will not automatically creating invoices. resume to reactivate |
amount | number |
Nominal amount of the recurring payment in IDR |
payer_email | string |
Email of the payer, we get this information from your API call |
description | string |
Description for the recurring payment and invoices |
should_send_email | boolean |
A flag showing should payer get email when invoice is created, paid, or expired; or not |
interval | string |
One of DAY , WEEK , MONTH . The frequency with which a recurring payment invoice should be billed. |
interval_count | number |
The number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months. |
recurrence_progress | number |
The current cycle of recurring payment. If your end customer is on the 4th cycle of the recurring, you will get 4 from recurrence_progress response |
last_created_invoice_url | string |
url leading to the last invoice create by this recurring payment |
invoice_duration | number |
Ensure that this value is 300duration of time that end user have in order to pay the invoice before it's expired (in Second). |
created | string (ISO 8601) |
An ISO timestamp that tracks when the recurring payment was created. Timezone is UTC+0 |
updated | string (ISO 8601) |
An ISO timestamp that tracks when the recurring payment was updated. Timezone is UTC+0 |
charge_immediately optional |
boolean |
A flag showing should the first invoice created immediately when creating recurring payment with a valid start_date |
recharge | boolean |
This parameter will be true for direct debit payments. |
payment_method_id | string |
the payment_method_id assigned to this recurring payment |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation The errors field contains details about which fields are violating validation |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format |
INVALID_PAYMENT_METHOD_ID_ERROR400 |
Payment method id is invalid |
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Other Recurring Operations
For post recurring payment creation operations like get, edit, pause, resume, stop - refer to recurring payments
Create Direct Debit Payment
Create a debit to pull funds from the end customer's account using an active payment method. BRI (ID) and BPI (PH) supports sending OTPs to complete a payment; UBP (PH) does not require any OTP.
Endpoint: Create Direct Debit Payment
POST https://api.xendit.co/direct_debits
Create Payment - Request
Example Create Payment Request
curl https://api.xendit.co/direct_debits -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
-H 'Idempotency-key: Test_Idempotent_Key'\
--data-raw '{
"reference_id": "customer_test_reference_id",
"payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"currency": "IDR",
"amount": 1500,
"enable_otp": true,
"callback_url": "https://payment-callback-listener/"
}'
<?php
$url = "https://api.xendit.co/direct_debits";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = $headers = [
"Content-Type : application/json",
"Idempotency-key: Test_Idempotent_Key",
];
$data = [
"reference_id" => "customer_test_reference_id",
"payment_method_id" => "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"currency" => "IDR",
"amount" => 1500,
"enable_otp" => true,
"callback_url" => "https://payment-callback-listener/"
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { DirectDebit } = x;
const directDebitSpecificOptions = {};
const dd = new DirectDebit(directDebitSpecificOptions);
const resp = await dd.createDirectDebitPayment({
idempotencyKey: 'Test_Idempotent_Key',
referenceID: 'customer_test_reference_id',
paymentMethodID: 'pm-c30d4800-afe4-4e58-ad5f-cc006d169139',
currency: 'IDR',
amount: 10000,
callbackURL: 'https://payment-callback-listener/',
enableOTP: true,
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
payment = DirectDebit.create_payment(
reference_id="direct-debit-ref-1594718940",
payment_method_id="pm-b6116aea-8c23-42d0-a1e6-33227b52fccd",
currency="IDR",
amount="60000",
callback_url="http://webhook.site/",
enable_otp=True,
idempotency_key="idemp_key-1594718940",
)
print(payment)
Header | Type | Description |
---|---|---|
Idempotency-key required |
string |
Provided by the merchant to prevent duplicate requests. May be equal to any GUID. Note: Max 100 characters |
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Request Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
reference_id required |
string
|
Merchant-provided identifier for this transaction Note: Max 255 characters |
||||||||||||||||||||||||
payment_method_id required |
string
|
Xendit’s identifier for specific payment method. You can create one using Create Payment Method API if you haven't already generated one. Use Get Payment Method API to retrieve the ID | ||||||||||||||||||||||||
currency required |
string
|
Currency of amount to debit in ISO 4217. e.g. "IDR", "PHP" | ||||||||||||||||||||||||
amount required |
number
|
Amount to debit from the end-customer’s account Note: Maximum amount that can be charged without OTP is 999,999 |
||||||||||||||||||||||||
callback_url optional |
string
|
URL where payment notification will be sent after transaction process Note: Max 255 characters |
||||||||||||||||||||||||
enable_otp optional |
boolean |
true to charge end customer's account with OTPfalse to charge end customer's account without OTPDefaults to true for DC_BRI . For BA_BPI and BA_UBP , this parameter is not supported. |
||||||||||||||||||||||||
description optional |
string
|
Description for the direct debit transaction. | ||||||||||||||||||||||||
basket optional |
array
|
Array of objects describing the item/s purchased using direct debit
|
metadata optional |
object
|
Object of additional information the user may use. User defines the JSON properties and values. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long |
Create Payment - Response
Example Create Payment Success Response
{
"id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
"reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
"channel_code": "DC_BRI",
"payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"currency": "IDR",
"amount": "10000",
"description": null,
"status": "PENDING",
"basket": null,
"failure_code": null,
"is_otp_required": true,
"otp_mobile_number": "+6287774441111",
"otp_expiration_timestamp": null,
"created": "2020-03-26T05:44:26+0800",
"updated": null,
"metadata": null
}
Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the transaction |
reference_id | string |
Reference ID provided by merchant |
channel_code | string |
Code identifier for the channel |
payment_method_id | string |
Payment method ID of end-customer source of funds |
currency | string |
Currency of the payment |
amount | number |
Amount to debit from the end-customer’s account |
description | string |
Description provided by merchant |
status | string |
Status of the payment - "PENDING", "COMPLETED", "FAILED" |
failure_code | string |
Reason if direct debit has failed. List of failure codes can be found here |
is_otp_required | boolean |
The flag for merchant to know whether OTP is required for the particular direct debit transaction |
otp_mobile_number | string |
Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled. |
otp_expiration_timestamp | string |
Timestamp until when the OTP is valid. Empty string if OTP was not enabled. |
created | string |
Timestamp in ISO 8601 when transaction information was updated Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
updated | string |
Timestamp in ISO 8601 when transaction information was updated Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
basket | array |
Array of basket objects provided by merchant |
metadata | object |
Metadata provided by merchant |
Create Payment - Errors
Example Create Payment Error Response
{
"error_code" : "DUPLICATE_ERROR",
"message" : "Idempotency key has been used before. Use a unique idempotency key and try again"
}
Error Code | Description |
---|---|
DUPLICATE_ERROR409 |
Idempotency key has been used before. Use a unique idempotency key and try again. |
PAYMENT_METHOD_NOT_FOUND_ERROR400 |
Provided payment_method_id is invalid, not found or access is unauthorized |
INVALID_PAYMENT_METHOD_ERROR400 |
The payment method has expired or has been invalidated. |
INSUFFICIENT_BALANCE400 |
The source payment method doesn't have enough balance to complete the transaction |
ACCOUNT_ACCESS_BLOCKED400 |
The source account is blocked and cannot be accessed. |
MAX_AMOUNT_LIMIT_ERROR400 |
The amount for the transaction exceeds the account's aggregated limits set by the partner bank. |
Validate OTP for Direct Debit Payment
Validate OTP provided by end customer via this endpoint to complete the transaction when OTP is enabled.
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Validate OTP for Direct Debit Payment
POST https://api.xendit.co/direct_debits/:direct_debit_id/validate_otp/
Validate Payment OTP - Request
Example Validate Payment OTP Request
curl https://api.xendit.co/direct_debits/ddpy-623dca10-5dad-4916-test/validate_otp/ -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
--data-raw '{
"otp_code": "111222"
}'
<?php
$direct_debit_id = "ddpy-623dca10-5dad-4916-test";
$url = "https://api.xendit.co/direct_debits/" . $direct_debit_id . "/validate_otp";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$data = [
"otp_code" => "111222"
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { DirectDebit } = x;
const directDebitSpecificOptions = {};
const dd = new DirectDebit(directDebitSpecificOptions);
const resp = await dd.validateOTPforPayment({
directDebitID: 'ddpy-623dca10-5dad-4916-test',
otpCode: '111222',
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
payment = DirectDebit.validate_payment_otp(
direct_debit_id="ddpy-eaa093b6-b669-401a-ba2e-61ac644b2aff",
otp_code="222000",
)
print(payment)
Path Parameter | Type | Description |
---|---|---|
direct_debit_id required |
string |
Merchant provided identifier for specified direct debit transaction |
Request Body Parameter | Type | Description |
---|---|---|
otp_code required |
string |
One-time-password input from end customer |
Validate Payment OTP - Response
Will return a successful 200
HTTP response as soon as the bank has validated the OTP, otherwise an error is returned.
Example Get Payment Status by ID Success Response
{
"id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
"reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
"channel_code": "BA_BPI",
"payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"currency": "PHP",
"amount": "1000.00",
"description": "",
"status": "PENDING",
"basket": [],
"failure_code": "",
"is_otp_required": true,
"otp_mobile_number": "+63907XXXX123",
"otp_expiration_timestamp": "2020-03-26T05:45:06+0800",
"created": "2020-03-26T05:44:26+0800",
"updated": "2020-03-26T05:44:46+0800",
"metadata": {}
}
Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the transaction |
reference_id | string |
Reference ID provided by merchant |
channel_code | string |
Code identifier for the channel |
payment_method_id | string |
Payment method ID of end-customer source of funds |
currency | string |
Currency of the payment |
amount | number |
Amount to debit from the end-customer’s account |
description | string |
Description provided by merchant |
status | string |
Status of the payment |
failure_code | string |
Reason if direct debit has failed. List of failure codes can be found here |
is_otp_required | boolean |
The flag for merchant to know OTP is required for the particular direct debit transaction |
otp_mobile_number | string |
Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled. |
otp_expiration_timestamp | string |
Timestamp until when the OTP is valid. Empty string if OTP was not enabled. |
created | string |
Timestamp in ISO 8601 when the request was madeFormat: YYYY-MM-DDTHH:mm:ssZTimezone: UTC+0 |
updated | string |
Timestamp in ISO 8601 when transaction information was updated Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
basket | array |
Array of basket objects provided by merchant |
metadata | object |
Metadata provided by merchant |
Validate Payment OTP - Errors
Example Create Payment Error Response
{
"error_code" : "DUPLICATE_ERROR",
"message" : "Idempotency key has been used before. Use a unique idempotency key and try again"
}
Error Code | Description |
---|---|
DATA_NOT_FOUND_ERROR 404 |
Provided direct_debit_id does not exist |
INVALID_OTP_ERROR 400 |
OTP provided is invalid |
EXPIRED_OTP_ERROR 400 |
OTP provided has expired |
MAX_OTP_ATTEMPTS_ERROR 400 |
Payment method reached the channel’s allowed maximum attempts for OTP verification |
INSUFFICIENT_BALANCE 400 |
The source payment method doesn't have enough balance to complete the transaction |
ACCOUNT_ACCESS_BLOCKED 400 |
The source account is blocked and cannot be accessed. |
MAX_AMOUNT_LIMIT_ERROR 400 |
The amount for the transaction exceeds the account's aggregated limits set by the partner bank. |
DIRECT_DEBIT_ALREADY_COMPLETED 409 |
The request is a duplicate of an already processed linked account token that has been successfully completed. |
DIRECT_DEBIT_ALREADY_FAILED 409 |
The request is a duplicate of an already processed linked account token that has failed. |
Get Payment Methods by Customer ID
This endpoint returns an array of payment methods that are linked to the provided customer_id
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Get Payment Methods by Customer ID
GET https://api.xendit.co/payment_methods?customer_id={customer_id}
Get Payment Methods by Customer ID - Request
Example Get Payment Methods by Customer ID Request
curl https://api.xendit.co/payment_methods?customer_id=ba830b92-4177-476e-b097-2ad5ae4d3e55 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$url = "https://api.xendit.co/payment_methods";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$queryString = "?customer_id=ba830b92-4177-476e-b097-2ad5ae4d3e55";
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url.$queryString);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { DirectDebit } = x;
const directDebitSpecificOptions = {};
const dd = new DirectDebit(directDebitSpecificOptions);
const resp = await dd.getPaymentMethodsByCustomerID({
customerID: 'ba830b92-4177-476e-b097-2ad5ae4d3e55',
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
payment_methods = DirectDebit.get_payment_methods_by_customer_id(
customer_id="ed20b5db-df04-41fc-8018-8ea4ac4d1030",
)
print(payment_methods)
Query String Parameter | Type | Description |
---|---|---|
customer_id required |
string |
Customer object ID of interest |
Get Payment Methods by Customer ID - Response
This endpoint returns an array of matching objects with the following properties:
Example Get Payment Methods by Customer ID Success Response
[{
"id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"type": "DEBIT_CARD",
"properties": {
"id": "la-aa620619-124f-41db-995b-66a52abe036a",
"channel_code": "DC_BRI",
"currency": "IDR",
"card_last_four": "1234",
"card_expiry": "06/24",
"description": null,
},
"customer_id": "ba830b92-4177-476e-b097-2ad5ae4d3e55",
"status": "ACTIVE",
"created": "2020-03-19T05:34:55+0800",
"updated": "2020-03-19T05:24:55+0800",
"metadata": null
}]
Parameter | Type | Description | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id |
string
|
Unique identifier for the payment method. This has a prefix of pm- . |
||||||||||||||||||||||
type |
string
|
Type of account that has been linked. Expected values: DEBIT_CARD or BANK_ACCOUNT
|
||||||||||||||||||||||
properties |
object
|
Object containing information regarding the account. The values inside properties change based on the type of account: For type DEBIT_CARD (BRI):
BANK_ACCOUNT (BPI):
|
||||||||||||||||||||||
customer_id |
string
|
ID of the customer object in which this payment method is linked to |
||||||||||||||||||||||
status |
string
|
Status of the payment method. Will be equal to ACTIVE upon creation. |
||||||||||||||||||||||
created |
string
|
Timestamp in ISO 8601 when the request was madeFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||||||||||||||||
updated |
string
|
Timestamp in ISO 8601 when transaction information was updatedFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||||||||||||||||
metadata |
object
|
A free-format JSON for additional information that you provded during request. |
Get Payment Methods by Customer ID - Errors
See other common errors here.
Get Direct Debit Payment Status by ID
Retrieve the details of a direct debit payment by Xendit transaction ID
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Get Payment Status by ID
POST https://api.xendit.co/direct_debits/:direct_debit_id/
Get Payment Status by ID - Request
Example Payment Status by ID Request
curl https://api.xendit.co/direct_debits/ddpy-623dca10-5dad-4916-test/ -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$direct_debit_id = "ddpy-623dca10-5dad-4916-test";
$url = "https://api.xendit.co/direct_debits/" . $direct_debit_id . "/";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { DirectDebit } = x;
const directDebitSpecificOptions = {};
const dd = new DirectDebit(directDebitSpecificOptions);
const resp = await dd.getDirectDebitPaymentStatusByID({
directDebitID: 'ddpy-623dca10-5dad-4916-test',
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
payment = DirectDebit.get_payment_status(
direct_debit_id="ddpy-38ef50a8-00f0-4019-8b28-9bca81f2cbf1",
)
print(payment)
Path Parameter | Type | Description |
---|---|---|
direct_debit_idrequired |
string |
Xendit identifier for specified direct debit transaction |
Get Payment Status by ID - Response
Example Get Payment Status by ID Success Response
{
"id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
"reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
"channel_code": "DC_BRI",
"payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"currency": "IDR",
"amount": "10000",
"description": "",
"status": "PENDING",
"basket": [],
"failure_code": "",
"is_otp_required": true,
"otp_mobile_number": "",
"otp_expiration_timestamp": "",
"created": "2020-03-26T05:44:26+0800",
"updated": "",
"metadata": {}
}
Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the transaction |
reference_id | string |
Reference ID provided by merchant |
channel_code | string |
Code identifier for the channel |
payment_method_id | string |
Payment method ID of end-customer source of funds |
currency | string |
Currency of the payment |
amount | number |
Amount to debit from the end-customer’s account |
description | string |
Description provided by merchant |
status | string |
Status of the payment |
failure_code | string |
Reason if direct debit has failed. List of failure codes can be found here |
is_otp_required | boolean |
The flag for merchant to know whether OTP is required for the particular direct debit transaction |
otp_mobile_number | string |
Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled. |
otp_expiration_timestamp | string |
Timestamp until when the OTP is valid. Empty string if OTP was not enabled. |
created | string |
Timestamp in ISO 8601 when the request was madeFormat: YYYY-MM-DDTHH:mm:ssZTimezone: UTC+0 |
updated | string |
Timestamp in ISO 8601 when transaction information was updated Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
basket | array |
Array of basket objects provided by merchant |
metadata | object |
Metadata provided by merchant |
Get Direct Debit Payment Status by Reference ID
Retrieve the details of a direct debit payment by merchant provided transaction ID
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Get Payment Status by Reference ID
POST https://api.xendit.co/direct_debits?reference_id={reference_id}
Get Payment Status by Reference ID - Request
Example Payment Status by Reference ID Request
curl https://api.xendit.co/direct_debits?reference_id=test_merchant_reference_id/ -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$url = "https://api.xendit.co/direct_debits/";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$queryString = "?reference_id=test_merchant_reference_id";
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url.$queryString);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
const x = new require("xendit-node")({
secretKey:
"xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==",
});
const { DirectDebit } = x;
const directDebitSpecificOptions = {};
const dd = new DirectDebit(directDebitSpecificOptions);
const resp = await dd.getDirectDebitPaymentStatusByReferenceID({
referenceID: 'test_merchant_reference_id',
});
console.log(resp);
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
DirectDebit = xendit_instance.DirectDebit
payments = DirectDebit.get_payment_status_by_ref_id(
reference_id="direct-debit-ref-1594717458",
)
print(payments)
Query String Parameter | Type | Description |
---|---|---|
reference_id required |
string |
Merchant provided identifier for specified direct debit transaction |
Get Payment Status by ID - Response
Example Get Payment Status by ID Success Response
{
"id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
"reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
"channel_code": "DC_BRI",
"payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"currency": "IDR",
"amount": "10000",
"description": "",
"status": "PENDING",
"basket": [],
"failure_code": "",
"is_otp_required": true,
"otp_mobile_number": "",
"otp_expiration_timestamp": "",
"created": "2020-03-26T05:44:26+0800",
"updated": "",
"metadata": {}
}
Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the transaction |
reference_id | string |
Reference ID provided by merchant |
channel_code | string |
Code identifier for the channel |
payment_method_id | string |
Payment method ID of end-customer source of funds |
currency | string |
Currency of the payment |
amount | number |
Amount to debit from the end-customer’s account |
description | string |
Description provided by merchant |
status | string |
Status of the payment |
failure_code | string |
Reason if direct debit has failed. List of failure codes can be found here |
is_otp_required | boolean |
The flag for merchant to know whether OTP is required for the particular direct debit transaction |
otp_mobile_number | string |
Masked mobile number of the OTP recipient from the channel. Empty string if OTP was not enabled. |
otp_expiration_timestamp | string |
Timestamp until when the OTP is valid. Empty string if OTP was not enabled. |
created | string |
Timestamp in ISO 8601 when the request was madeFormat: YYYY-MM-DDTHH:mm:ssZTimezone: UTC+0 |
updated | string |
Timestamp in ISO 8601 when transaction information was updated Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
basket | array |
Array of basket objects provided by merchant |
metadata | object |
Metadata provided by merchant |
Callback Notifications
In our direct debit flow, there are up to 2 types of callbacks that could be sent. We will send callback to your system during Linked Account Tokenization and Direct Debit Payment process. Merchants need to set up URL to receive callback notifications from our system.
Linked Account Tokenization Callback
Payload
Linked Account Tokenization callback is only supported for BPI and Unionbank. Merchants can skip this flow if they are only integrating for BRI/debit card flow.
Example: Linked Account Tokenization Callback Payload
{
"event": "linked_account_token.successful",
"timestamp": "2020-03-27T05:45:06+0800",
"channel_code": "BA_BPI",
"id": "lat-aa620619-124f-41db-995b-66a52abe036a",
"accounts": [
{
"id": "l-acc-7f2bc3ad-8049-42ff-8b57-6578088e9641",
"account_details": "XXXXXXX123",
"account_hash": "5789fb5c4b051701928af5ac268c8178",
"currency": "PHP",
"account_type": "SAVINGS",
"description": null
}
]
}
Parameter | Description | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
event |
string Identifier of the event - "linked_account_token.successful" |
||||||||||||||
timestamp |
string ISO 8601 timestamp of the event. Timezone is UTC+0 |
||||||||||||||
id |
string Unique identifier for the Linked Account Tokenization. This has a prefix of lat- . |
||||||||||||||
channel_code |
string Code identifier for the channel |
||||||||||||||
accounts |
array An array of objects containing bank account informations linked to the authorization.
|
Direct Debit Payment Callback
Payload
Example: Payload
{
"event": "direct_debit.payment",
"timestamp": "2020-03-26T05:44:26+0800",
"id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
"reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
"channel_code": "BA_BPI",
"payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"currency": "PHP",
"amount": "1000.00",
"description": null,
"status": "COMPLETED",
"failure_code": null,
"metadata": null
}
Parameter | Description |
---|---|
event |
string Identifier of the event - "direct_debit.payment" |
timestamp |
string ISO 8601 timestamp of the event. Timezone is UTC+0 |
id |
string Unique identifier for the transaction |
reference_id |
string Reference ID provided by merchant |
channel_code |
string Code identifier for the channel |
payment_method_id |
string Payment method ID of end-customer source of funds |
currency |
string Currency of the payment |
amount |
number Amount to debited from the end-customer’s account |
description |
string Description provided by merchant |
status |
string Status of the payment - "PENDING", "COMPLETED", "FAILED" |
failure_code |
string Reason if direct debit has failed. List of failure codes can be found here
|
metadata |
object Metadata provided by merchant |
Payment Status Callback - Failure Reasons
Example: Payment Status Failure Examples
{
"event": "direct_debit.payment",
"timestamp": "2020-03-26T05:44:26+0800",
"id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
"reference_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
"channel_code": "BA_BPI",
"payment_method_id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"currency": "PHP",
"amount": 1000.00,
"description": "",
"status": "FAILED",
"failure_code": "INSUFFICIENT_BALANCE",
"metadata": {}
}
Failure Code | Description |
---|---|
MAX_AMOUNT_LIMIT_ERROR |
End customer's daily limit has been reached, unable to process debit request. End user required to increase daily limit or retry another day |
INSUFFICIENT_BALANCE |
End customer has insufficient balance, unable to process debit request. End user required to top up balance |
CHANNEL_UNAVAILABLE |
Bank service for direct debit is currently unavailable, unable to process debit request. |
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
MAX_OTP_ATTEMPTS_ERROR |
The transaction has been failed because the maximum attempts for validating the OTP has been reached. |
INVALID_PAYMENT_METHOD_ERROR |
The payment_method_id provided either does not exist or has already expired. |
SERVER_ERROR |
There was an unexpected error while processing with the bank. |
Recurring Payment Callback
Payload
{
"id": "5ebd6test32631dda4ef73",
"external_id": "testing_123_123-1589472179990",
"user_id": "5ebd26b7da0bf912db2fc716",
"is_high": false,
"payment_method": "DIRECT_DEBIT",
"status": "PAID",
"merchant_name": "Live Validation Test 2",
"amount": 15000,
"paid_amount": 15000,
"paid_at": "2020-05-14T16:03:00.504Z",
"payer_email": "test@xendit.co",
"description": "description",
"adjusted_received_amount": 15000,
"fees_paid_amount": 0,
"created": "2020-05-14T16:03:00.154Z",
"updated": "2020-05-14T16:03:02.765Z",
"recurring_payment_id": "5ebd6bb37d674631dda4ef72",
"currency": "IDR",
"payment_channel": "DC_BRI"
}
Parameter | Type | Description |
---|---|---|
id | string |
An invoice ID generated by Xendit |
user_id | string |
Your Xendit Business ID |
external_id | string |
The reference ID used to generate the recurring payment. This can be used to reconcile between you and Xendit |
is_high (DEPRECATED) | boolean |
Should unique numbers go above or below the amount. |
merchant_name | string |
The name of your company or website |
amount | number |
Nominal amount for the invoice (without taxes, fees) |
status | string |
PAID the recurring direct debit has successfully been paid or EXPIRED the recurring direct debit has failed |
payer_email | string |
Email of the payer, we get this information from your API call |
description | string |
Description for the invoice, we get this information from your API call |
fees_paid_amount | number |
Xendit fees that was directly paid from this invoice - thanks for supporting a better world of payments :) |
adjusted_received_amount | number |
Amount attributable to you net of our fees. |
recurring_payment_id | string |
ID of the recurring that created this invoice |
paid_amount | number |
Total amount paid for the invoice |
updated | string (ISO 8601) |
An ISO timestamp that tracks when the invoice was updated. Timezone is UTC+0 |
created | string (ISO 8601) |
An ISO timestamp that tracks when the invoice was created. Timezone is UTC+0 |
currency | string (ISO 4217) |
Currency of the amount that you created. |
paid_at | string (ISO 8601) |
Date time data when your customer pay the invoice. You will get this response when your invoice is paid |
payment_method | string |
Payment method that is used when a customer pays the invoice. You will get this response when your invoice is paid - DIRECT_DEBIT |
payment_channel | string |
The payment channel used when a customer pays the invoice. You will get this response when your invoice is paid Example : DC_BRI |
Virtual Accounts
Virtual Accounts are virtual bank accounts that can be created and assigned to your customers and act as medium to receive payments where your customers will pay via Bank Transfer.
Create Virtual Account
Endpoint: Create Virtual Account
POST https://api.xendit.co/callback_virtual_accounts
For live environments, activate the Virtual Account Range from the dashboard by going to Dashboard > Settings > Accepting Money > Payment Methods > Virtual Account, and clicking the "Activate!" button. The VA range will be set and activated instantly. In test environments, the test VA range is assigned right away. Read more about virtual accounts.
Looking for your virtual accounts to be tied to a transaction rather than a user? Use our invoices API.
Request Parameters
Example Create Virtual Accounts Request
curl https://api.xendit.co/callback_virtual_accounts -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d external_id=demo_virtual_account_1475459775872 \
-d bank_code=BNI \
-d name='Rika Sutanto'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
"external_id" => "demo-1475804036622",
"bank_code" => "BNI",
"name" => "Rika Sutanto"
];
$createVA = \Xendit\VirtualAccounts::create($params);
var_dump($createVA);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { VirtualAcc } = x;
const vaSpecificOptions = {};
const va = new VirtualAcc(vaSpecificOptions);
const resp = await va.createFixedVA({
externalID: 'demo_1475459775872',
bankCode: 'BNI',
name: 'Rika Sutanto',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("external_id", "demo_virtual_account_1475459775872");
params.put("bank_code", BankCode.BNI.getText());
params.put("expected_amount", 100000);
params.put("name", "Rika Sutanto");
//For closed virtual account
FixedVirtualAccount closedVirtualAccount = FixedVirtualAccount.createClosed(params);
//For open virtual account
FixedVirtualAccount openVirtualAccount = FixedVirtualAccount.createOpen(params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := virtualaccount.CreateFixedVAParams{
ExternalID: "demo-1475804036622",
BankCode: "BNI",
Name: "Rika Sutanto",
}
resp, err := virtualaccount.CreateFixedVA(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created fixed va: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
VirtualAccount = xendit_instance.VirtualAccount
virtual_account = VirtualAccount.create(
external_id="demo_1475459775872",
bank_code="BNI",
name="Rika Sutanto",
)
print(virtual_account)
JSON
{
"external_id": "demo-1475804036622",
"bank_code": "BNI",
"name": "Rika Sutanto"
}
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
external_idrequired |
string |
An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID. Maximum length allowed is 950 characters. Note: External IDs cannot be changed once set
|
bank_coderequired |
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
|
namerequired |
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 length restriction depending on the banks. And also cannot contains name from bank/institution/government.
|
virtual_account_numberoptional |
string |
The virtual account number you want to assign. If you do not send one, one will be picked at random Note: Please do not include the merchant code (4 or 5 digit merchant prefix to the full virtual account number) default:
|
suggested_amountoptional |
integer positive |
The suggested amount you want to assign. Note: Suggested amounts is the amounts that can see as a suggestion, but user can still put any numbers (only supported for Mandiri and BRI) default:
|
is_closedoptional |
boolean |
When set to true , the virtual account will be closed and will only accept the amount specified in expected_amount default:
|
expected_amountoptional |
integer positive |
The specific amount that the virtual account will expect and accept if is_closed is set to true default:
|
expiration_dateoptional |
ISO 8601 Date |
The time when the virtual account will be expiredtimezone:
|
is_single_useoptional |
boolean |
When set to true , the virtual account will be inactive after it is paiddefault:
|
descriptionoptional |
string |
The virtual account description. This field is only supported for BRI
|
Response Parameters
Example Create Virtual Account Response
{
"owner_id":"57b4e5181473eeb61c11f9b9",
"external_id":"demo-1475804036622",
"bank_code":"BNI",
"merchant_code":"8808",
"name":"Rika Sutanto",
"account_number":"8808999939380502",
"is_closed": false,
"expiration_date": "2051-09-27T17:00:00.000Z",
"id":"57f6fbf26b9f064272622aa6",
"is_single_use": false,
"currency" : "IDR",
"status": "PENDING"
}
Example response with description if bank code is BRI
{
"owner_id": "5de8d83cafcf47000f8e76bc",
"external_id": "1576132512",
"bank_code": "BRI",
"merchant_code": "26215",
"name": "rezki",
"account_number": "262159999857807",
"expected_amount": 700000,
"is_single_use": false,
"description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
"currency": "IDR",
"status": "PENDING",
"expiration_date": "2050-12-11T17:00:00.000Z",
"is_closed": false,
"id": "5df1dfa06c3736110078f9a1"
}
Parameter | Type | Description |
---|---|---|
owner_idrequired |
string |
Your user ID |
external_idrequired |
string |
An ID of your choice which you provided upon request |
bank_coderequired |
string |
Bank code for the relevant bank, e.g. BNI |
merchant_coderequired |
string |
Prefix for the Virtual Account Number. Often this is Xendit Merchant ID or your Merchant ID on bank, e.g 01234 your_number |
namerequired |
string |
Name for the virtual account |
account_numberrequired |
string |
Complete virtual account number (including merchant code as prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking. |
is_closedrequired |
boolean |
Value that determines whether a virtual account is closed or not |
idrequired |
string |
Unique ID for the virtual account that generated randomly by system. Can be used to create invoices linked to the VA. |
is_single_userequired |
boolean |
When it is true , the virtual account will be inactive after it is paid |
statusrequired |
string |
Status of virtual account that defines if it’s PENDING , INACTIVE , or ACTIVE . PENDING if virtual account creation request has been sent and request is being processed by the bank. INACTIVE either the single use virtual account has been paid or already expired. ACTIVE the virtual account is ready to be used by the end user. |
suggested_amountoptional |
string |
suggested amount for the virtual account |
expected_amountoptional |
string |
the amount that is expected when is_closed is true |
descriptionoptional |
string |
description of the virtual account which will be displayed during payment. Only supported for BRI virtual accounts. |
currencyrequired |
string |
The currency in which the VA operates. Available for API version 2018-12-21 . |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
VIRTUAL_ACCOUNT400 |
The virtual account number you want is outside your range. You can check your VA range in Virtual Accounts Settings |
BANK_NOT_SUPPORTED400 |
The bank code is not currently supported. You can check the available bank with get virtual account banks endpoint. |
EXPIRATION_DATE400 |
Custom expiration date (the time when the virtual account will be expired) for the virtual account is not currently supported. |
EXPIRATION_DATE400 |
Invalid custom expiration date because it's earlier than current time. |
SUGGESTED_AMOUNT400 |
The suggested amount for the virtual account is not currently supported. |
EXPECTED_AMOUNT400 |
The expected_amount is required when is_closed is set to true . |
CLOSED_VA_NOT400 |
The closed option for this virtual account is not currently supported. |
DUPLICATE_CALLBACK400 |
The account number already exist |
MINIMUM_EXPECTED400 |
The minimum expected amount is Rp.1 for BNI, BRI and MANDIRI |
MAXIMUM_EXPECTED400 |
The maximum expected amount is Rp.50,000,000,000 for BNI, BRI and MANDIRI |
CALLBACK_VIRTUAL_ACCOUNT_NAME_NOT_ALLOWED400 |
The name cannot contain bank or institution name |
DESCRIPTION_NOT400 |
Description field is only supported for BRI |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Get Virtual Account Banks
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Endpoint: Get Virtual Account Available Banks
GET https://api.xendit.co/available_virtual_account_banks
Example Get Virtual Account Banks Request
curl https://api.xendit.co/available_virtual_account_banks -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$getVABanks = \Xendit\VirtualAccounts::getVABanks();
var_dump($getVABanks);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { VirtualAcc } = x;
const vaSpecificOptions = {};
const va = new VirtualAcc(vaSpecificOptions);
const resp = await va.getVABanks();
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
AvailableBank[] availableBanks = FixedVirtualAccount.getAvailableBanks();
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
availableBanks, err := virtualaccount.GetAvailableBanks()
if err != nil {
log.Fatal(err)
}
fmt.Printf("available va banks: %+v\n", availableBanks)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
VirtualAccount = xendit_instance.VirtualAccount
virtual_account_banks = VirtualAccount.get_banks()
print(virtual_account_banks)
Response Parameters
Example Get Virtual Account Banks Response
{
"name": "Bank Negara Indonesia",
"code": "BNI"
}
Parameter | Type | Description |
---|---|---|
namerequired |
string |
Full name of the bank |
coderequired |
string |
Code of the bank, relevant during creation of virtual accounts |
Get Virtual Account
Endpoint: Get Virtual Account
GET https://api.xendit.co/callback_virtual_accounts/:id
Example Get Virtual Account Request
curl https://api.xendit.co/callback_virtual_accounts/:id -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Sometime, you need to know the detail for your virtual account. This endpoint can be used to get the latest details from your virtual account
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '59e03a976fab8b1850fdf347';
$getVA = \Xendit\VirtualAccounts::retrieve($id);
var_dump($getVA);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { VirtualAcc } = x;
const vaSpecificOptions = {};
const va = new VirtualAcc(vaSpecificOptions);
const resp = await va.getFixedVA({ id: '59e03a976fab8b1850fdf347' });
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
FixedVirtualAccount fpa = FixedVirtualAccount.getFixedVA("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := virtualaccount.GetFixedVAParams{
ID: "59e03a976fab8b1850fdf347",
}
resp, err := virtualaccount.GetFixedVA(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved fixed va: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
VirtualAccount = xendit_instance.VirtualAccount
virtual_account = VirtualAccount.get(
id="5eec3a3e8dd9ea2fc97d6728",
)
print(virtual_account)
Sometime, you need to know the detail for your fixed virtual account. This endpoint can be used to get the latest details from your fixed virtual account
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Query Parameter | Type | Description |
---|---|---|
id required |
string |
ID of the virtual account to retrieve |
Response Parameters
Example Get Virtual Account Response
{
"owner_id": "58cd618ba0464eb64acdb246",
"external_id": "va-1507867286",
"bank_code": "BRI",
"merchant_code": "26215",
"name": "Steve Wozniak",
"account_number": "262151000393993",
"is_single_use": false,
"status": "ACTIVE",
"expiration_date": "2048-10-12T17:00:00.000Z",
"is_closed": false,
"id": "59e03a976fab8b1850fdf347"
}
Parameter | Type | Description |
---|---|---|
owner_idrequired |
string |
ID of the business that own the virtual account |
external_idrequired |
string |
An ID of your choice which you provided upon virtual account creation |
bank_coderequired |
string |
Bank code of the virtual account number |
merchant_coderequired |
string |
4 or 5-digit merchant prefix to the full virtual account number |
namerequired |
string |
Name of the virtual account |
account_numberrequired |
string |
Account number of the virtual account |
expiration_daterequired |
string |
Expiration date of the virtual account |
is_closedrequired |
boolean |
Flag that define the virtual account is close or open |
idrequired |
string |
ID of the virtual account |
is_single_userequired |
boolean |
Flag that define the virtual account is single use or multiple use |
statusrequired |
string |
Status of virtual account that defines if it’s PENDING , INACTIVE , or ACTIVE . PENDING if virtual account creation request has been sent and request is being processed by the bank. INACTIVE either the single use virtual account has been paid or already expired. ACTIVE the virtual account is ready to be used by the end user. |
Error Codes
Error Code | Description |
---|---|
REQUEST_FORBIDDEN403 |
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_ERROR404 |
Could not find callback virtual account. |
Update Virtual Account
Endpoint: Update Virtual Account (VA)
PATCH https://api.xendit.co/callback_virtual_accounts/:id
Virtual Account is adaptable, and can be customized to fit your needs. Therefore, we provide you this endpoint to easily update your virtual account as you like. You can update multiple use VAs as well as active single use VAs, though inactive single use VAs cannot be updated.
Example Update Fixed Virtual Accounts Request
curl https://api.xendit.co/callback_virtual_accounts/57f6fbf26b9f064272622aa6 -X PATCH \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d expected_amount=100000
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = 'VA-id';
$updateParams = ["suggested_amount" => 6000];
$updateVA = \Xendit\VirtualAccounts::update($id, $updateParams);
var_dump($updateVA);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { VirtualAcc } = x;
const vaSpecificOptions = {};
const va = new VirtualAcc(vaSpecificOptions);
const resp = await va.updateFixedVA({
id: '57f6fbf26b9f064272622aa6',
expectedAmt: 1000000,
})
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("is_single_use", true);
FixedVirtualAccount fixedVirtualAccount = FixedVirtualAccount.update("EXAMPLE_ID", params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
expirationDate := time.Now().AddDate(0, 0, 1)
updateFixedVAData := virtualaccount.UpdateFixedVAParams{
ID: "5df745b92b50911700f37e86",
ExpirationDate: &expirationDate,
ExpectedAmount: 6000,
}
resp, err := virtualaccount.UpdateFixedVA(&updateFixedVAData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("updated fixed va: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
VirtualAccount = xendit_instance.VirtualAccount
virtual_account = VirtualAccount.update(
id="5eec3a3e8dd9ea2fc97d6728",
is_single_use=True,
)
print(virtual_account)
Fixed Virtual Account is adaptable, and can be customized to fit your needs. Therefore, we provide you this endpoint to easily update your fixed virtual account as you like. You can update multiple use VAs as well as active single use VAs, though inactive single use VAs cannot be updated.
Note: Closed virtual accounts can not be changed to open virtual accounts, and vice versa.
Request Parameters
Example Update Virtual Accounts Request
{
"expiration_date": "2019-11-12T23:46:00.000Z",
"expected_amount": 6000
}
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
suggested_amountoptional |
integer positive |
suggested amount you want to assign |
expected_amountoptional |
integer positive |
The amount that the virtual account will expect if is_closed is set to true |
expiration_dateoptional |
ISO 8601 Date |
The time when the virtual account will be expired. You can set it to be days in the past to expire virtual account immediately timezone:
|
is_single_useoptional |
boolean |
When set to true , the virtual account status will be inactive after it is paiddefault:
|
descriptionoptional |
string |
Virtual account description shown to end user during payment
|
Response Parameters
Example Update Virtual Account Response
{
"owner_id": "5de8d83cafcf47000f8e76bc",
"external_id": "demo_virtual_account_1475459775872",
"bank_code": "BNI",
"merchant_code": "8808",
"name": "Rika Sutanto",
"account_number": "8808999947012640",
"is_single_use": false,
"expected_amount": 6000,
"currency": "IDR",
"status": "PENDING",
"expiration_date": "2019-11-12T23:46:00.000Z",
"is_closed": false,
"id": "5df745b92b50911700f37e86"
}
Parameter | Type | Description |
---|---|---|
owner_idrequired |
string |
Your user ID |
external_idrequired |
string |
An ID of your choice which you provided upon request |
bank_coderequired |
string |
Bank code for the relevant bank, e.g. BNI |
merchant_coderequired |
string |
The merchant code will be the prefix for the virtual account number, e.g 01234 your_number |
namerequired |
string |
Name for the virtual account |
account_numberrequired |
string |
Complete virtual account number (including merchant code as prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking. |
is_closedrequired |
boolean |
Value that determines whether a virtual account is closed or not |
idrequired |
string |
Unique ID for the virtual account that generated randomly by system. Can be used to create invoices linked to the VA. |
is_single_userequired |
boolean |
When it is true , the virtual account will be inactive after it is paid |
statusrequired |
string |
Status of virtual account that defines if it’s PENDING , INACTIVE , or ACTIVE . PENDING if virtual account creation request has been sent and request is being processed by the bank. INACTIVE either the single use virtual account has been paid or already expired. ACTIVE the virtual account is ready to be used by the end user. |
suggested_amountoptional |
string |
suggested amount for the virtual account |
expected_amountoptional |
string |
the amount that is expected when is_closed is true |
descriptionoptional |
string |
description of the virtual account which will be displayed during payment. Only supported for BRI virtual accounts. |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
VIRTUAL_ACCOUNT400 |
The virtual account number you want is outside your range. You can check your VA range in Virtual Accounts Settings |
BANK_NOT_SUPPORTED400 |
The bank code is not currently supported. You can check the available bank with get virtual account banks endpoint. |
SUGGESTED_AMOUNT400 |
The suggested amount for the virtual account is not currently supported. |
EXPECTED_AMOUNT400 |
The expected amount is required when is_closed is set to true . |
CLOSED_VA_NOT400 |
The closed option for this virtual account is not currently supported. |
INACTIVE_VIRTUAL_ACCOUNT_ERROR400 |
Account number that you want to update is inactive. |
MINIMUM_EXPECTED400 |
The expected amount can only be more than zero |
MAXIMUM_EXPECTED400 |
The expected amount can only be less than Rp.1000000000 |
DESCRIPTION_NOT400 |
Description field is only supported for BRI |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Virtual Account Callback
Endpoint: Virtual Account Callback
POST https://yourcompany.com/virtual_account_paid_callback_url
When someone pays into your fixed virtual account, our callback APIs will hit your URL that you already set in dashboard. Our callback API will also hit your URL upon fixed virtual account creations and updates. Please see Create Fixed Virtual Accounts for more details. For further information about callbacks please read these docs.
This example is only used to show the body parameters that send from Xendit APIs to your callback URL and cannot be tested in here. If you want to test this callback request, use the test feature in dashboard or go to Callback settings.
Payment Callback Payload
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
Example Virtual Account Payment Callback Request
curl --include \
--request POST \
--header "Content-Type: application/json" \
--header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
--data-binary "{
id: \"57fb4e076fa3fa296b7f5a97\",
payment_id: \"demo-1476087608948_1476087303080\",
callback_virtual_account_id: \"57fb4df9af86ce19778ad359\",
owner_id: \"57b4e5181473eeb61c11f9b9\",
external_id: \"demo-1476087608948\",
account_number: \"8808999939380502\",
bank_code: \"BNI\",
amount: 99000,
transaction_timestamp: \"2016-10-10T08:15:03.080Z\",
merchant_code: \"8808\",
sender_name: \"JOHN DOE\",
updated: \"2016-10-10T08:15:03.404Z\",
created: \"2016-10-10T08:15:03.404Z\"
}" \
'https://api.xendit.co/virtual_account_paid_callback_url'
JSON
{
"amount": 50000,
"callback_virtual_account_id": "5f8e658568ed5f402a1faadb",
"payment_id": "5f8e658f8d65ab385241f17a",
"external_id": "demo-va-callback",
"account_number": "9999624535",
"merchant_code": "88608",
"bank_code": "MANDIRI",
"transaction_timestamp": "2020-10-20T04:20:31.000Z",
"currency": "IDR",
"created": "2020-10-20T04:20:31.937Z",
"updated": "2020-10-20T04:20:33.074Z",
"id": "5f8e658fc5710a7ae00f75db",
"owner_id": "5c2323c67d6d305ac433ba20"
}
Body Parameter | Type | Description |
---|---|---|
payment_idrequired |
string |
Our internal system’s payment ID |
callback_virtual_account_idrequired |
string |
The id field value from the response when the virtual account was created. See Create Virtual Accounts |
owner_idrequired |
string |
Your user ID |
external_idrequired |
string |
An ID of your choice which you provided upon virtual account creation |
account_numberrequired |
string |
This is the virtual account number (including merchant code as prefix). This works just like a bank account and is what a user will need to enter in their internet banking/ATM to send funds. |
bank_coderequired |
string |
Bank code for the relevant bank, e.g. BNI |
amountrequired |
string |
Nominal amount to transfer |
merchant_coderequired |
string |
The merchant code will be the prefix for the virtual account number, e.g 01234 your_number |
idrequired |
string |
ID of virtual account payment |
transaction_timestamprequired |
string |
Date time that the virtual account was paid |
sender_name |
string |
Name of the end user that paid into the virtual account. This field is only supported for Sahabat Sampoerna virtual accounts. |
Creation / Update Callback Payload
Example Virtual Account Creation / Update Callback Request
curl --include \
--request POST \
--header "Content-Type: application/json" \
--header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
--data-binary "{
id: \"57fb4e076fa3fa296b7f5a97\",
owner_id: \"5824128aa6f9f9b648be9d76\",
external_id: \"va-1487156410\",
merchant_code: \"88608\",
account_number: \"886081000123456\",
bank_code: \"MANDIRI\",
name: \"John Doe\",
is_closed: false,
is_single_use: false,
status: \"ACTIVE\",
expiration_date: \"2048-02-15T11:01:52.722Z\",
updated: \"2016-10-10T08:15:03.404Z\",
created: \"2016-10-10T08:15:03.404Z\"
}" \
'https://api.xendit.co/virtual_account_created_callback_url'
JSON
{
"id": "57fb4e076fa3fa296b7f5a97",
"owner_id": "5824128aa6f9f9b648be9d76",
"external_id": "va-1487156410",
"merchant_code": "88608",
"account_number": "886081000123456",
"bank_code": "MANDIRI",
"name": "John Doe",
"is_closed": false,
"is_single_use": false,
"status": "ACTIVE",
"expiration_date": "2048-02-15T11:01:52.722Z",
"updated": "2016-10-10T08:15:03.404Z",
"created": "2016-10-10T08:15:03.404Z"
}
Body Parameter | Type | Description |
---|---|---|
owner_idrequired |
string |
Your user ID |
external_idrequired |
string |
An ID of your choice which you provided upon request |
bank_coderequired |
string |
Bank code for the relevant bank, e.g. MANDIRI |
merchant_coderequired |
string |
The merchant code will be the prefix for the virtual account number, e.g 01234 your_number |
namerequired |
string |
Name for the virtual account |
account_numberrequired |
string |
Complete virtual account number (including merchant code as prefix). This is what a user will need to enter into an ATM or their Internet/mobile banking. |
suggested_amountoptional |
string |
suggested amount for created virtual account |
is_closedrequired |
boolean |
value that determines whether a virtual account is closed or not |
expected_amountoptional |
string |
the amount that is expected when is_closed is true |
idrequired |
string |
Unique ID for the virtual account. Can be used to create invoices linked to the VA. |
is_single_userequired |
boolean |
value that determines whether a virtual account will be inactive after it is paid |
statusrequired |
string |
Status of virtual account that defines if it’s PENDING , INACTIVE , or ACTIVE . PENDING if virtual account creation request has been sent and request is being processed by the bank. INACTIVE either the single use virtual account has been paid or already expired. ACTIVE the virtual account is ready to be used by the end user. |
Error Codes
Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.
Get Virtual Account Payment
Endpoint: Get Virtual Account Payment
GET https://api.xendit.co/callback_virtual_account_payments/payment_id={payment_id}
Example Get Virtual Account Payment Request
curl https://api.xendit.co/callback_virtual_account_payments/payment_id={payment_id} -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$paymentID = '1502450097080';
$getFVAPayment = \Xendit\VirtualAccounts::getFVAPayment($paymentID);
var_dump($getFVAPayment);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { VirtualAcc } = x;
const vaSpecificOptions = {};
const va = new VirtualAcc(vaSpecificOptions);
const resp = await va.getVAPayment({
paymentID: '598d91b1191029596846047f',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
FixedVirtualAccountPayment payment = FixedVirtualAccount.getPayment("EXAMPLE_PAYMENT_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
payment, err := virtualaccount.GetPayment(&virtualaccount.GetPaymentParams{
PaymentID: "1502450097080",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved va payment: %+v\n", payment)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
VirtualAccount = xendit_instance.VirtualAccount
virtual_account_payment = VirtualAccount.get_payment(
payment_id="5ef18efca7d10d1b4d61fb52",
)
print(virtual_account_payment)
When you receive our callback in your URL, you can verify that the callback you receive is coming from us.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Query Parameter | Type | Description |
---|---|---|
payment_idrequired |
string |
ID of the payment to retrieve |
Response Parameters
Example Get Virtual Account Payment Response
{
"id": "598d91b1191029596846047f",
"payment_id": "1502450097080",
"callback_virtual_account_id": "598d5f71bf64853820c49a18",
"external_id": "demo-1502437214715",
"merchant_code": "77517",
"account_number": "1000016980",
"bank_code": "BNI",
"amount": 5000,
"sender_name": "JOHN DOE",
"transaction_timestamp": "2017-08-11T11:14:57.080Z"
}
Parameter | Type | Description |
---|---|---|
idrequired |
string |
ID of the virtual account payment |
payment_idrequired |
string |
Our internal system’s payment ID |
callback_virtual_account_idrequired |
string |
ID of the virtual account payment that was paid |
external_idrequired |
string |
External ID on the virtual account payment |
merchant_coderequired |
string |
5-digit merchant prefix to the full virtual account number |
account_numberrequired |
string |
Account number of the virtual account |
bank_coderequired |
string |
Bank code of the virtual account number |
amountrequired |
integer positive |
Amount that was paid to this virtual account payment |
transaction_timestamprequired |
string |
Date time that the virtual account was paid |
sender_name |
string |
Name of the end user that paid into the virtual account. This field is only supported for Sahabat Sampoerna virtual accounts. |
Error Codes
Error Code | Description |
---|---|
REQUEST_FORBIDDEN403 |
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_ERROR404 |
Could not find callback virtual account payment by payment id. |
Retail Outlets
Create Fixed Payment Code
Endpoint: Create Fixed Payment Code (FPC)
POST https://api.xendit.co/fixed_payment_code
One way for your customer to pay through Retail Outlets is by providing them Fixed Payment Code. Fixed payment code is a dedicated payment code under a name you choose, e.g. 'YourCompany - Becca Salim'. You will receive a callback each time this fixed payment code is paid.
Request Parameters
Example Create Fixed Payment Code Request
curl https://api.xendit.co/fixed_payment_code -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d external_id=demo_fixed_payment_code_123 \
-d retail_outlet_name=ALFAMART \
-d name='Rika Sutanto' \
-d expected_amount=10000
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'external_id' => '123',
'retail_outlet_name' => 'ALFAMART',
'name' => 'Rika Sutanto',
'expected_amount' => 10000
];
$createFPC = \Xendit\Retail::create($params);
var_dump($createFPC);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RetailOutlet } = x;
const retailOutletSpecificOptions = {};
const ro = new RetailOutlet(retailOutletSpecificOptions);
const resp = await ro.createFixedPaymentCode({
externalID: 'demo_fixed_payment_code_123',
retailOutletName: 'ALFAMART',
name: 'Rika Sutanto',
expectedAmt: 10000,
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("external_id", "test");
params.put("retail_outlet_name", "ALFAMART");
params.put("name", "Rika Sutanto");
params.put("expected_amount", 10000);
FixedPaymentCode fpc = RetailOutlet.createFixedPaymentCode(params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := retailoutlet.CreateFixedPaymentCodeParams{
ExternalID: "123",
RetailOutletName: xendit.RetailOutletNameAlfamart,
Name: "Rika Sutanto",
ExpectedAmount: 10000,
}
resp, err := retailoutlet.CreateFixedPaymentCode(&data)
if err != nil {
log.Fatal(err.ErrorCode)
}
fmt.Printf("created retail outlet fixed payment code: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RetailOutlet = xendit_instance.RetailOutlet
retail_outlet = RetailOutlet.create_fixed_payment_code(
external_id="demo_fixed_payment_code_123",
retail_outlet_name="ALFAMART",
name="Rika Sutanto",
expected_amount=10000,
)
print(retail_outlet)
JSON
{
"external_id": "123",
"retail_outlet_name": "ALFAMART",
"name": "Rika Sutanto",
"expected_amount": 10000
}
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
external_idrequired |
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_namerequired |
string |
Name of the fixed payment code you want to create |
namerequired |
string |
Name of user - this might be used by the Retail Outlets cashier to validate the end user
|
expected_amountrequired |
integer positive |
The amount that is expected to be paid by end customer |
payment_codeoptional |
string |
The fixed payment code that you want to assign, e.g 12345. If you do not send one, one will be picked at random default:
|
expiration_dateoptional |
ISO 8601 Date |
The time when the fixed payment code will be expired timezone:
|
is_single_useoptional |
boolean |
When set to true , the fixed payment code will be inactive after it is paiddefault:
|
Response Parameters
Example Create Fixed Payment Code Response
{
"is_single_use": false,
"status": "ACTIVE",
"owner_id": "5c2323c67d6d305ac433ba20",
"external_id": "123",
"retail_outlet_name": "ALFAMART",
"prefix": "TEST",
"name": "Rika Sutanto",
"payment_code": "TEST906558",
"type": "USER",
"expected_amount": 10000,
"expiration_date": "2051-11-01T17:00:00.000Z",
"id": "5f9fb01c4134b42c56b034c1"
}
Parameter | Type | Description |
---|---|---|
owner_idrequired |
string |
Your user ID |
external_idrequired |
string |
An ID of your choice which you provided upon request |
retail_outlet_namerequired |
string |
Name of the Retail Outlets, e.g. ALFAMART or INDOMARET |
prefixrequired |
string |
3-6 characters that differentiate your fixed payment code from the others |
namerequired |
string |
Name for the fixed payment code |
payment_coderequired |
string |
Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. You can append payment_code into the barcode page URL (barcode page currently only supports Alfamart):TEST : https://retail-outlet-barcode-dev.xendit.co/alfamart/:payment_codeLIVE : https://retail-outlet-barcode.xendit.co/alfamart/:payment_code |
expected_amountrequired |
integer positive |
The amount that is expected to be paid by end customer |
is_single_userequired |
boolean |
Value that determines whether a fixed payment code will be inactive after it is paid or not |
expiration_daterequired |
ISO 8601 Date |
The time when the fixed payment code will be expired |
idrequired |
string |
Unique ID for the fixed payment code that generated randomly by sistem. |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
PAYMENT_CODE400 |
The fixed payment code you want is outside your range. Can resolve by check the dashboard to see the range Retail Outlets Settings |
RETAIL_OUTLET_NOT400 |
The Retail Outlets is not currently supported. |
DUPLICATE_PAYMENT400 |
The payment code that you want to create is already exist |
EXPIRATION_DATE400 |
Invalid custom expiration date because it's earlier than current time. |
MINIMUM_EXPECTED400 |
The expected amount can only be more than or equal Rp 10,0000 |
MAXIMUM_EXPECTED400 |
The expected amount can only be less than or equal Rp 5,000,000 |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Update Fixed Payment Code
Endpoint: Update Fixed Payment Code (FPC)
PATCH https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id}
Fixed Payment Code is so adaptable, and it's all based on your needs. Therefore, we provide you this endpoint to easily update your fixed payment code as you like.
Request Parameters
Example Update Fixed Payment Code Request
curl https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id} -X PATCH \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d expected_amount=20000
-d name='Joe Contini'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '5b61881e6cc2770f00117f73';
$updateParams = ['expected_amount' => 20000];
$updateFPC = \Xendit\Retail::update($id, $updateParams);
var_dump($updateFPC);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RetailOutlet } = x;
const retailOutletSpecificOptions = {};
const ro = new RetailOutlet(retailOutletSpecificOptions);
const resp = await ro.updateFixedPaymentCode({
id: '5b61881e6cc2770f00117f73',
name: 'Joe Contini',
expectedAmt: 20000,
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("name", "Lorem Ipsum");
FixedPaymentCode fpc = RetailOutlet.updateFixedPaymentCode("EXAMPLE_ID", params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
expirationDate := time.Now().AddDate(0, 0, 1)
updateFixedPaymentCodeData := retailoutlet.UpdateFixedPaymentCodeParams{
FixedPaymentCodeID: "5b61881e6cc2770f00117f73",
Name: "Joe Contini",
ExpectedAmount: 20000,
ExpirationDate: &expirationDate,
}
resp, err := retailoutlet.UpdateFixedPaymentCode(&updateFixedPaymentCodeData)
if err != nil {
log.Fatal(err.ErrorCode)
}
fmt.Printf("updated retail outlet fixed payment code: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RetailOutlet = xendit_instance.RetailOutlet
retail_outlet = RetailOutlet.update_fixed_payment_code(
fixed_payment_code_id="5ef2f0f8e7f5c14077275493",
name="Joe Contini",
)
print(retail_outlet)
JSON
{
"expected_amount": 20000,
"name": "Joe Contini"
}
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
nameoptional |
string |
Name for the fixed payment code
|
expected_amountoptional |
integer positive |
The amount that is expected to be paid by end customer |
expiration_dateoptional |
ISO 8601 Date |
The time when the fixed payment code will be expired. You can set it to be days in the past to expire fixed payment code immediately timezone:
|
Response Parameters
Example Update Fixed Payment Code Response
{
"is_single_use": false,
"status": "ACTIVE",
"owner_id": "5c2323c67d6d305ac433ba20",
"external_id": "123",
"retail_outlet_name": "ALFAMART",
"prefix": "TEST",
"name": "JOHN DOE",
"payment_code": "TEST906558",
"type": "USER",
"expected_amount": 25000,
"expiration_date": "2051-11-01T17:00:00.000Z",
"id": "5f9fb01c4134b42c56b034c1"
}
Parameter | Type | Description |
---|---|---|
owner_idrequired |
string |
Your user ID |
external_idrequired |
string |
An ID of your choice which you provided upon request |
retail_outlet_namerequired |
string |
Name of the Retail Outlets, e.g. ALFAMART or INDOMARET |
prefixrequired |
string |
3-6 characters that differentiate your fixed payment code from the others |
namerequired |
string |
Name for the fixed payment code |
payment_coderequired |
string |
Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. You can append payment_code into the barcode page URL (barcode page currently only supports Alfamart):TEST : https://retail-outlet-barcode-dev.xendit.co/alfamart/:payment_codeLIVE : https://retail-outlet-barcode.xendit.co/alfamart/:payment_code |
expected_amountrequired |
integer positive |
The amount that is expected to be paid by end customer |
is_single_userequired |
boolean |
Value that determines whether a fixed payment code will be inactive after it is paid or not |
expiration_daterequired |
ISO 8601 Date |
The time when the fixed payment code will be expired |
idrequired |
string |
Unique ID for the fixed payment code that generated randomly by sistem. |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
PAYMENT_CODE400 |
The fixed payment code you want is outside your range. Can resolve by check the dashboard to see the range Retail Outlets Settings |
INACTIVE_FIXED_PAYMENT_CODE_ERROR400 |
Account number that you want to update is inactive. |
MINIMUM_EXPECTED400 |
The expected amount can only be more than or equal Rp 10,000 |
MAXIMUM_EXPECTED400 |
The expected amount can only be less than or equal Rp 5,000,000 |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Get Fixed Payment Code
Endpoint: Get Fixed Payment Code
GET https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id}
Example Get Fixed Payment Code Request
curl https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id} -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '5b61881e6cc2770f00117f73';
$getFPC = \Xendit\Retail::retrieve($id);
var_dump($getFPC);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RetailOutlet } = x;
const retailOutletSpecificOptions = {};
const ro = new RetailOutlet(retailOutletSpecificOptions);
const resp = await ro.getFixedPaymentCode({
id: '5b61881e6cc2770f00117f73',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
FixedPaymentCode fpc = RetailOutlet.getFixedPaymentCode("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
getFixedPaymentCodeData := retailoutlet.GetFixedPaymentCodeParams{
FixedPaymentCodeID: "5b61881e6cc2770f00117f73",
}
resp, err := retailoutlet.GetFixedPaymentCode(&getFixedPaymentCodeData)
if err != nil {
log.Fatal(err.ErrorCode)
}
fmt.Printf("retrieved retail outlet fixed payment code: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RetailOutlet = xendit_instance.RetailOutlet
retail_outlet = RetailOutlet.get_fixed_payment_code(
fixed_payment_code_id="5ef2f0f8e7f5c14077275493",
)
print(retail_outlet)
Sometimes, you need to know the detail for your fixed payment code. This endpoint can be used to get the latest details from your fixed payment code
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
fixed_payment_code_id required |
string |
ID of the fixed payment code to retrieve |
Response Parameters
Example Get Fixed Payment Code Response
{
"is_single_use": false,
"status": "ACTIVE",
"owner_id": "5c2323c67d6d305ac433ba20",
"external_id": "123",
"retail_outlet_name": "ALFAMART",
"prefix": "TEST",
"name": "JOHN DOE",
"payment_code": "TEST906558",
"type": "USER",
"expected_amount": 25000,
"expiration_date": "2051-11-01T17:00:00.000Z",
"id": "5f9fb01c4134b42c56b034c1"
}
Parameter | Type | Description |
---|---|---|
owner_idrequired |
string |
Your user ID |
external_idrequired |
string |
An ID of your choice which you provided upon request |
retail_outlet_namerequired |
string |
Name of the Retail Outlets, e.g. ALFAMART or INDOMARET |
prefixrequired |
string |
3-6 characters that differentiate your fixed payment code from the others |
namerequired |
string |
Name for the fixed payment code |
payment_coderequired |
string |
Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. You can append payment_code into the barcode page URL (barcode page currently only supports Alfamart):TEST : https://retail-outlet-barcode-dev.xendit.co/alfamart/:payment_codeLIVE : https://retail-outlet-barcode.xendit.co/alfamart/:payment_code |
expected_amountrequired |
integer positive |
The amount that is expected to be paid by end customer |
is_single_userequired |
boolean |
Value that determines whether a fixed payment code will be inactive after it is paid or not |
expiration_daterequired |
ISO 8601 Date |
The time when the fixed payment code will be expired |
idrequired |
string |
Unique ID for the fixed payment code that generated randomly by sistem. |
Error Codes
Error Code | Description |
---|---|
REQUEST_FORBIDDEN403 |
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_ERROR404 |
Could not find fixed payment code. |
Fixed Payment Code Callback
Endpoint: Fixed Payment Code Callback
POST https://yourcompany.com/fixed_payment_code_paid_callback_url
When someone pays into your fixed payment code, our callback APIs will hit your URL that you already set in dashboard.
This example is only used to show the body parameters that send from Xendit APIs to your callback URL and cannot be tested in here. If you want to test this callback request, use the test feature in dashboard and go to Callbacks settings.
Callback Payload
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
Example Fixed Payment Code Payment Callback Request
curl --include \
--request POST \
--url https://yourcompany.com/fixed_payment_code_paid_callback_url \
--header 'content-type: application/json' \
--header 'x-callback-token: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==' \
--data '{
"id": "58a435201b6ce2a355f46070",
"external_id": "fixed-payment-code-14876410",
"prefix": "TEST",
"payment_code": "TEST123",
"retail_outlet_name": "ALFAMART",
"name": "John Doe",
"amount": 123456,
"status": "SETTLING",
"transaction_timestamp": "2019-11-08T11:51:28.613Z",
"payment_id": "1573213888613",
"fixed_payment_code_payment_id": "5dc556c07a58de7c114f0347",
"fixed_payment_code_id": "5dc5567bdf120fd64988a79b",
"owner_id": "5be9b2f03ef77262c2bd49e6"
}'
JSON
{
"id": "58a435201b6ce2a355f46070",
"external_id": "fixed-payment-code-14876410",
"prefix": "TEST",
"payment_code": "TEST123",
"retail_outlet_name": "ALFAMART",
"name": "John Doe",
"amount": 123456,
"status": "SETTLING",
"transaction_timestamp": "2019-11-08T11:51:28.613Z",
"payment_id": "1573213888613",
"fixed_payment_code_payment_id": "5dc556c07a58de7c114f0347",
"fixed_payment_code_id": "5dc5567bdf120fd64988a79b",
"owner_id": "5be9b2f03ef77262c2bd49e6"
}
Body Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique identifier for this transaction |
external_idrequired |
string |
An ID of your choice which you provided upon fixed payment code creation |
prefixrequired |
string |
3-6 characters that differentiate your fixed payment code from the others |
payment_coderequired |
string |
Complete fixed payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. You can append payment_code into the barcode page URL (barcode page currently only supports Alfamart):TEST : https://retail-outlet-barcode-dev.xendit.co/alfamart/:payment_codeLIVE : https://retail-outlet-barcode.xendit.co/alfamart/:payment_code |
retail_outlet_namerequired |
string |
Name for the relevant Retail Outlets, e.g. ALFAMART or INDOMARET |
namerequired |
string |
Name for the fixed payment code |
amountrequired |
integer positive |
Nominal amount that is paid |
statusrequired |
string |
Status of payment. Possible value(s): SETTLING or COMPLETED |
transaction_timestamprequired |
ISO 8601 Date |
Date time that the fixed payment code was paid |
payment_idrequired |
string |
Our internal system’s payment ID that can be used as payment reference |
fixed_payment_code_payment_idrequired |
string |
Unique ID for the fixed payment code payment |
fixed_payment_code_idrequired |
string |
Unique ID for the fixed payment code |
owner_idrequired |
string |
Your user ID |
Error Codes
Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.
Invoices
Create Invoice
Endpoint: Create Invoice
POST https://api.xendit.co/v2/invoices
Invoices allow you to quickly collect payments using with all of our payment methods. When payment is complete, a callback is made regardless of the payment method used.
Learn more about invoices in our documentation
Request Parameters
Example Create Invoice Request
curl https://api.xendit.co/v2/invoices -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d external_id=demo_1475801962607 \
-d payer_email=alfina@xendit.co \
-d description='Trip to Bali' \
-d amount=230000
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'external_id' => 'demo_1475801962607',
'payer_email' => 'alfina@xendit.co',
'description' => 'Trip to Bali',
'amount' => 50000
];
$createInvoice = \Xendit\Invoice::create($params);
var_dump($createInvoice);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Invoice } = x;
const invoiceSpecificOptions = {};
const i = new Invoice(invoiceSpecificOptions);
const resp = await i.createInvoice({
externalID: 'demo_1475801962607',
amount: 230000,
payerEmail: 'sample_email@xendit.co',
description: 'Trip to Bali',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("external_id", "demo_1475801962607");
params.put("amount", 50000);
params.put("payer_email", "customer@domain.com");
params.put("description", "Trip to Bali");
Invoice invoice = Invoice.create(params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := invoice.CreateParams{
ExternalID: "demo_1475801962607",
Amount: 50000,
PayerEmail: "alfina@xendit.co",
Description: "Trip to Bali",
}
resp, err := invoice.Create(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created invoice: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Invoice = xendit_instance.Invoice
invoice = Invoice.create(
external_id="invoice-1593684000",
amount=20000,
payer_email="customer@domain.com",
description="Invoice Demo #123",
)
print(invoice)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
with-fee-ruleoptional |
string |
Fee Rule ID that you would like to apply to payments coming into this invoice Please note: If you include this parameter, we will return the fee_rule_id and the fee_id in the header of the API response. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
external_id required |
string |
ID of your choice (typically the unique identifier of an invoice in your system) |
payer_email required |
string |
Email of the end user you're charging |
description required |
string |
Description of the invoice |
amount required |
number |
Amount on the invoice. The minimum amount to create an invoice is 1 IDR or PHP |
should_send_email optionaldefault:
|
boolean |
Specify whether you want us to email the end customer when an invoice is created, paid, or expired |
callback_virtual_account_id optional |
string |
To allow payment via Fixed Virtual Account, pass in the id field value from the response when the fixed virtual account was created. See Create Fixed Virtual Accounts |
invoice_duration optional |
number |
Duration of time that the end customer is given to pay the invoice before expiration (in seconds, since creation). Default is 24 hours (86,400 seconds). |
success_redirect_url optional |
string |
URL that the end customer 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 |
Choice of payment channels that is available in your account. Leave this field empty if all payment channel is expected to be available in this particular invoice, or if you want to use the defaults set in your Xendit Dashboard. example : ["BCA", "BRI", "MANDIRI", "BNI", "PERMATA", "ALFAMART", "CREDIT_CARD", "OVO"] |
mid_label optional |
string |
MID label when you have an acquiring bank, and are using credit cards. |
currency optional |
string |
Currency of the amount that you created example : "IDR" or "PHP" |
fixed_va optionaldefault:
|
boolean |
Input this parameter as true to enable using a single, persistent VA number your end customers, determined by email address. |
reminder_time optional |
integer positive |
Reminder email will be sent reminder_time day(s) before the invoice expires. Allowed values are 1, 3, 7, 15, 30 days before invoice expires |
Response Parameters
Example Create Invoice Response
{
"id": "579c8d61f23fa4ca35e52da4",
"user_id": "5781d19b2e2385880609791c",
"external_id": "demo_1475801962607",
"status": "PENDING",
"merchant_name": "Xendit",
"merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1493610897264_473.png",
"amount": 50000,
"payer_email": "alfina@xendit.co",
"description": "Trip to Bali",
"invoice_url": "https://invoice.xendit.co/web/invoices/595b6248c763ac05592e3eb4",
"expiry_date": "2020-08-01T11:20:01.017Z",
"available_banks": [
{
"bank_code": "MANDIRI",
"collection_type": "POOL",
"bank_account_number": "8860810000525",
"transfer_amount": 50000,
"bank_branch": "Virtual Account",
"account_holder_name": "LANSUR13",
},
{
"bank_code": "BRI",
"collection_type": "POOL",
"bank_account_number": "2621510002426",
"transfer_amount": 50000,
"bank_branch": "Virtual Account",
"account_holder_name": "LANSUR13",
},
{
"bank_code": "BNI",
"collection_type": "POOL",
"bank_account_number": "880810000689",
"transfer_amount": 50000,
"bank_branch": "Virtual Account",
"account_holder_name": "LANSUR13",
}
],
"available_retail_outlets": [
{
"retail_outlet_name": "ALFAMART",
"payment_code": "ALFA123456",
"transfer_amount": 54000
}
],
"should_exclude_credit_card": false,
"should_send_email": false,
"created": "2020-01-12T14:00:00.306Z",
"updated": "2020-01-12T14:00:00.306Z",
"mid_label": "test-mid",
"currency": "IDR",
"fixed_va":true
}
Parameter | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | An invoice ID generated by Xendit | ||||||||||||
user_id | Your Xendit Business ID | ||||||||||||
external_id | The invoice ID in your server, that can be used to reconcile between you and Xendit | ||||||||||||
status |
PENDING the invoice has yet to be paid |
||||||||||||
merchant_name | The name of your company or website | ||||||||||||
merchant_profile_picture_url | The URL to profile picture of your company | ||||||||||||
amount | Nominal amount for the invoice | ||||||||||||
payer_email | Email of the payer, we get this information from your API call | ||||||||||||
description | Description for the invoice, we get this information from your API call | ||||||||||||
invoice_url | Public URL for this invoice, it’s there in case you want to use our UI | ||||||||||||
expiry_date | ISO date and time that the invoice expires. Default is 24 hours. | ||||||||||||
available_banks | Available payment methods through banks as per your config
|
||||||||||||
available_retail_outlets | Available payment methods through retail outlet as per your config
|
||||||||||||
transfer_amount (DEPRECATED) | Amount the user should transfer |
||||||||||||
should_exclude_credit_card | A flag showing if credit card should be excluded in invoice UI or not | ||||||||||||
should_send_email | A flag showing should payer get email when invoice is created, paid, or expired; or not | ||||||||||||
created | An ISO timestamp that tracks when the invoice was created | ||||||||||||
updated | An ISO timestamp that tracks when the invoice was updated | ||||||||||||
mid_label | MID label that you have when you are using credit card payment and have acquiring bank. You will get this response when you add this parameter when create invoice through API | ||||||||||||
currency | Currency of the amount that you created. You will get this response when you add this parameter when create invoice through API | ||||||||||||
fixed_va | Input this parameter as true to enable one VA number for Your end customers. |
||||||||||||
reminder_date optional |
ISO8601 An ISO timestamp that the customer will be sent an invoice reminder email (when they send reminder_time for invoice creation). Timezone:
|
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
MINIMAL_TRANSFER400 |
Could not create invoice because amount is below Rp10000. |
MAXIMUM_TRANSFER400 |
Could not create invoice because amount is above Rp1000000000. If you are configured with Retail Outlets, then amount cannot be more than Rp5000000 |
NO_COLLECTION400 |
Your account has no payment methods configured (virtual account, credit card). Please contact support and we will set this up for you. |
UNAVAILABLE400 |
The payment method choices did not match with the available one on this business. |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
UNIQUE_ACCOUNT404 |
There is no available virtual account in your non-fixed virtual account range. |
CALLBACK_VIRTUAL404 |
Fixed virtual account id that you've specified not found |
AVAILABLE_PAYMENT404 |
There is no available payment code in your retail outlet range. |
INVALID_REMINDER_TIME400 |
The reminder_time value is not allowed. |
Get Invoice
Endpoint: Get an Invoice
GET https://api.xendit.co/v2/invoices/{invoice_id}
Request Parameters
Example Get Invoice Request
curl https://api.xendit.co/v2/invoices/{invoice_id} -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '579c8d61f23fa4ca35e52da4';
$getInvoice = \Xendit\Invoice::retrieve($id);
var_dump($getInvoice);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Invoice } = x;
const invoiceSpecificOptions = {};
const i = new Invoice(invoiceSpecificOptions);
const resp = await i.getInvoice({
invoiceID: '587cc7b4863f2b462beb31f6',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Invoice invoice = Invoice.getById("my_external_id");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := invoice.GetParams{
ID: "579c8d61f23fa4ca35e52da4",
}
resp, err := invoice.Get(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved invoice: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Invoice = xendit_instance.Invoice
invoice = Invoice.get(
invoice_id="5efda8a20425db620ec35f43",
)
print(invoice)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Query Parameter | Type | Description |
---|---|---|
invoice_id required |
string |
ID of the invoice to retrieve |
Response Parameters
Example Get Invoice Response
{
"id": "579c8d61f23fa4ca35e52da4",
"user_id": "5781d19b2e2385880609791c",
"external_id": "invoice_123124123",
"status": "PENDING",
"merchant_name": "Xendit",
"merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1493610897264_473.png",
"amount": 50000,
"payer_email": "alfina@xendit.co",
"description": "This is a description",
"invoice_url": "https://invoice.xendit.co/web/invoices/595b6248c763ac05592e3eb4",
"expiry_date": "2020-01-31T11:20:01.017Z",
"available_banks": [
{
"bank_code": "MANDIRI",
"collection_type": "POOL",
"bank_account_number": "8860810000525",
"transfer_amount": 50000,
"bank_branch": "Virtual Account",
"account_holder_name": "LANSUR13",
},
{
"bank_code": "BRI",
"collection_type": "POOL",
"bank_account_number": "2621510002426",
"transfer_amount": 50000,
"bank_branch": "Virtual Account",
"account_holder_name": "LANSUR13",
},
{
"bank_code": "BNI",
"collection_type": "POOL",
"bank_account_number": "880810000689",
"transfer_amount": 50000,
"bank_branch": "Virtual Account",
"account_holder_name": "LANSUR13",
}
],
"available_retail_outlets": [
{
"retail_outlet_name": "ALFAMART",
"payment_code": "ALFA123456",
"transfer_amount": 54000
}
],
"should_exclude_credit_card": false,
"should_send_email": false,
"created": "2020-01-01T14:00:00.306Z",
"updated": "2020-01-01T14:00:00.306Z",
"mid_label": "test-mid",
"currency": "IDR",
"paid_at": "2020-01-02T11:00:00.306Z",
"credit_card_charge_id": "579c8d61f23fa4ca35e52eas",
"payment_method": "BANK_TRANSFER",
"payment_channel": "BCA",
"payment_destination": "10002233222294375",
"success_redirect_url": "www.xendit.co",
"failure_redirect_url": "www.xendit.co",
"fixed_va":true
}
Parameter | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | An invoice ID generated by Xendit | ||||||||||||
user_id | Your Xendit Business ID | ||||||||||||
external_id | The invoice ID in your server, that can be used to reconcile between you and Xendit | ||||||||||||
status |
PENDING the invoice has yet to be paid PAID the invoice has successfully been paidSETTLED the amount of paid invoice has been settled to cash balanceEXPIRED 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
|
||||||||||||
available_retail_outlets |
Available payment methods through retail outlet as per your config
|
||||||||||||
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. |
Error Codes
Error Code | Description |
---|---|
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
INVOICE_NOT404 |
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:
- Expiring an invoice will close available payment methods: Pool Virtual Account, Retail Outlet, and Credit Card, but not Fixed Virtual Account.
- Expiring an invoice which is linked to Fixed Virtual Accounts will only unlink the Fixed Virtual Account's relation to the invoice, so further payments to this Fixed Virtual Account will be detected as Fixed Virtual Account payments instead of invoice payments. To expire Fixed Virtual Accounts, change the
expiration_date
using Update Fixed Virtual Account Endpoint
Request Parameters
Example Expire Invoice Request
curl https://api.xendit.co/invoices/{invoice_id}/expire! -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '579c8d61f23fa4ca35e52da4';
$expireInvoice = \Xendit\Invoice::expireInvoice($id);
var_dump($expireInvoice);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Invoice } = x;
const invoiceSpecificOptions = {};
const i = new Invoice(invoiceSpecificOptions);
const resp = await i.expireInvoice({
invoiceID: '587cc7b4863f2b462beb31f6',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Invoice invoice = Invoice.expire("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := invoice.ExpireParams{
ID: "579c8d61f23fa4ca35e52da4",
}
resp, err := invoice.Expire(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("expired invoice: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Invoice = xendit_instance.Invoice
invoice = Invoice.expire(
invoice_id="5efda8a20425db620ec35f43",
)
print(invoice)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Query Parameter | Type | Description |
---|---|---|
invoice_id required |
string |
ID of the invoice to be expired / canceled |
Response Parameters
Example Expire Invoice Response
{
"id": "579c8d61f23fa4ca35e52da4",
"user_id": "5781d19b2e2385880609791c",
"external_id": "invoice_123124123",
"status": "EXPIRED",
"merchant_name": "Xendit",
"merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1493610897264_473.png",
"amount": 50000,
"payer_email": "alfina@xendit.co",
"description": "This is a description",
"invoice_url": "https://invoice.xendit.co/web/invoices/595b6248c763ac05592e3eb4",
"expiry_date": "2020-04-01T11:20:01.017Z",
"available_banks": [
{
"bank_code": "BCA",
"collection_type": "POOL",
"bank_account_number": 1000008,
"transfer_amount": 54000
},
{
"bank_code": "MANDIRI",
"collection_type": "POOL",
"bank_account_number": 1000009,
"transfer_amount": 54000
}
],
"available_retail_outlets": [
{
"retail_outlet_name": "ALFAMART",
"payment_code": "ALFA123456",
"transfer_amount": 54000
}
],
"should_exclude_credit_card": false,
"should_send_email": false,
"created": "2020-01-12T14:00:00.306Z",
"updated": "2020-01-12T14:00:00.306Z"
}
Parameter | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | An invoice ID generated by Xendit | ||||||||||||
user_id | Your Xendit Business ID | ||||||||||||
external_id | The invoice ID in your server, that can be used to reconcile between you and Xendit | ||||||||||||
status |
EXPIRED the invoice has been expired |
||||||||||||
merchant_name | The name of your company or website | ||||||||||||
merchant_profile_picture_url | The URL to profile picture of your company | ||||||||||||
amount | Nominal amount for the invoice | ||||||||||||
payer_email | Email of the payer, we get this information from your API call | ||||||||||||
description | Description for the invoice, we get this information from your API call | ||||||||||||
invoice_url | Public URL for this invoice, it’s there in case you want to use our UI | ||||||||||||
expiry_date | ISO date and time that the invoice expires. Default is 24 hours. | ||||||||||||
available_banks | Available payment methods through banks as per your config
|
||||||||||||
available_retail_outlets |
Available payment methods through retail outlet as per your config
|
||||||||||||
should_exclude_credit_card |
A flag showing if credit card should be excluded in invoice UI or not |
||||||||||||
should_send_email |
A flag showing should payer get email when invoice is created, paid, or expired; or not |
||||||||||||
updated |
An ISO timestamp that tracks when the invoice was updated |
||||||||||||
created |
An ISO timestamp that tracks when the invoice was created |
Error Codes
Error Code | Description |
---|---|
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
REQUEST_FORBIDDEN403 |
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_ERROR404 |
Could not find invoice by id. |
List All Invoices
Endpoint: List Invoice
GET https://api.xendit.co/v2/invoices
You can list all invoices, or list the invoices for a specific updated time. The invoices are returned sorted by created date, with the most recently created invoices appearing first.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Example List Invoice Request
curl https://api.xendit.co/v2/invoices?limit=3&statuses=["SETTLED","EXPIRED"]&last_invoice_id=5ca186e407f3b83e34176eac&client_types=["DASHBOARD","API_GATEWAY"]&after=2016-02-24T23:48:36.697Z&before=2020-02-24T23:48:36.697Z -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$getAllInvoice = \Xendit\Invoice::retrieveAll();
var_dump(($getAllInvoice));
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Invoice } = x;
const invoiceSpecificOptions = {};
const i = new Invoice(invoiceSpecificOptions);
const resp = await i.getAllInvoices({
statuses: ["SETTLED", "EXPIRED"],
lastInvoiceID: '5ca186e407f3b83e34176eac',
clientTypes: ["DASHBOARD","API_GATEWAY"],
});
console.log(resp);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
createdAfter, _ := time.Parse(time.RFC3339, "2016-02-24T23:48:36.697Z")
data := invoice.GetAllParams{
Statuses: []string{"EXPIRED", "SETTLED"},
Limit: 5,
CreatedAfter: createdAfter,
}
resps, err := invoice.GetAll(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("invoices: %+v\n", resps)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Invoice = xendit_instance.Invoice
invoices = Invoice.list_all(
limit=3,
)
print(invoices)
Example List Invoice Response
[
{
"id": "5c65be6880a55b02867b2b6f",
"external_id": "627",
"user_id": "5bbe23e1c901a730130f5b15",
"status": "EXPIRED",
"merchant_name": "Your Business Name",
"merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1545257692599_408.jpg",
"amount": 838838,
"payer_email": "alfina@xendit.co",
"description": "Trip to Bali",
"expiry_date": "2020-02-24T23:48:36.697Z",
"invoice_url": "https://invoice-staging.xendit.co/web/invoices/5c65be6880a55b02867b2b6f",
"available_banks": [
{
"bank_code": "MANDIRI",
"collection_type": "POOL",
"bank_account_number": "8860838034047",
"transfer_amount": 838838,
"bank_branch": "Virtual Account",
"account_holder_name": "YOUR BUSINESS NAME",
},
{
"bank_code": "BRI",
"collection_type": "POOL",
"bank_account_number": "2621545817176",
"transfer_amount": 838838,
"bank_branch": "Virtual Account",
"account_holder_name": "YOUR BUSINESS NAME",
},
{
"bank_code": "BNI",
"collection_type": "POOL",
"bank_account_number": "880845676187",
"transfer_amount": 838838,
"bank_branch": "Virtual Account",
"account_holder_name": "YOUR BUSINESS NAME",
}
],
"available_ewallets": [],
"should_exclude_credit_card": false,
"should_send_email": false,
"created": "2020-01-14T23:48:56.907Z",
"updated": "2020-01-24T23:49:03.296Z"
},
{
"id": "5c6398b710a54b0c867b2b52",
"external_id": "1242",
"user_id": "5bbe23e1c901a730130f5b15",
"status": "SETTLED",
"merchant_name": "Your Business Name",
"merchant_profile_picture_url": "https://xnd-companies.s3.amazonaws.com/prod/1545257692599_408.jpg",
"amount": 67888,
"paid_amount": 67888,
"bank_code": "MANDIRI",
"payer_email": "budi@xendit.co",
"description": "Trip to Bali",
"expiry_date": "2020-02-24T16:34:24.341Z",
"invoice_url": "https://invoice-staging.xendit.co/web/invoices/5c6398b710a54b0c867b2b52",
"available_banks": [
{
"bank_code": "MANDIRI",
"collection_type": "POOL",
"bank_account_number": "8860838033759",
"transfer_amount": 67888,
"bank_branch": "Virtual Account",
"account_holder_name": "YOUR BUSINESS NAME",
},
{
"bank_code": "BRI",
"collection_type": "POOL",
"bank_account_number": "2621545816888",
"transfer_amount": 67888,
"bank_branch": "Virtual Account",
"account_holder_name": "YOUR BUSINESS NAME",
},
{
"bank_code": "BNI",
"collection_type": "POOL",
"bank_account_number": "880845675899",
"transfer_amount": 67888,
"bank_branch": "Virtual Account",
"account_holder_name": "YOUR BUSINESS NAME",
}
],
"available_ewallets": [],
"should_exclude_credit_card": false,
"adjusted_received_amount": 62938,
"should_send_email": false,
"created": "2020-01-14T16:35:03.573Z",
"updated": "2020-01-22T04:33:14.806Z"
}
]
Parameter | Type | Description |
---|---|---|
statuses optional |
array of strings |
Indicates the status of the invoices that will be available in the list. It contains PENDING , PAID , SETTLED , EXPIRED |
limit optionaldefault:
|
number |
A limit on the number of invoice objects to be returned. Limit can range between 1 and 100. |
created_after optional |
string (ISO 8601) |
Return invoices where the created field is greater than this value. Both created_after and created_before field should be used in the same time for the filter to take effect |
created_before optional |
string (ISO 8601) |
Return invoices where the created field is less than this value. Both created_after and created_before field should be used in the same time for the filter to take effect |
paid_after optional |
string (ISO 8601) |
Return invoices where the paid_at field is greater than this value. Both paid_after and paid_before field should be used in the same time for the filter to take effect |
paid_before optional |
string (ISO 8601) |
Return invoices where the paid_at field is less than this value. Both paid_after and paid_before field should be used in the same time for the filter to take effect |
expired_after optional |
string (ISO 8601) |
Return invoices where the expiry_date field is greater than this value. Both expired_after and expired_before field should be used in the same time for the filter to take effect |
expired_before optional |
string (ISO 8601) |
Return invoices where the expiry_date field is less than this value. Both expired_after and expired_before field should be used in the same time for the filter to take effect |
last_invoice_id optional |
string |
A cursor for use in pagination.last_invoice_id is an invoice ID that defines your starting point for the list. For instance, if you make a list request and receive 10 objects, starting with obj_bar , your subsequent call can include last_invoice_id =obj_bar in order to fetch the previous page of the list. |
client_types optional |
array of strings |
Indicates the method used to create the invoice. It contains: API_GATEWAY Invoice created via create invoice API DASHBOARD Invoice created via dashboard INTEGRATION Invoice created via 3rd party integration such as Shopify and WoocommerceON_DEMAND Invoice created via On Demand RECURRING Invoice created via Recurring Payment MOBILE Invoice created via Mobile App |
payment_channels optional |
array of strings |
Indicates the channels used to pay the invoice. |
on_demand_link optional |
string |
The link for the specific on demand. If you input on_demand_link, it will return invoices that created from that specific on demand link. |
recurring_payment_id optional |
string |
The recurring payment id for specific recurring payment, it will return invoices that created from that specific recurring payment id. |
Response Parameters
List invoice response will return array of get invoices response. Please refer get an invoice for more information.
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Invoice Callback
Endpoint: Invoice Callback
POST https://yourcompany.com/invoice_callback_url
When an invoice is paid, our systems will send a callback to the URL configured in the dashboard. For further instructions about callbacks, please read the invoices documentation
This example is only used to show the body parameters that are sent from Xendit APIs to your callback URL. If you want to test this callback request, use the test feature in dashboard and go to Settings > Developers > Callbacks.
Callback Payload
Example Invoice Callback Request for Payment Through Bank
curl --include \
--request POST \
--header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
--header "Content-Type: application/json" \
--data-binary "{
id: \"593f4ed1c3d3bb7f39733d83\",
external_id: \"testing-invoice\",
user_id: \"5848fdf860053555135587e7\",
is_high: false,
payment_method: \"BANK_TRANSFER\",
status: \"PAID\",
merchant_name: \"Xendit\",
amount: 2000000,
paid_amount: 2000000,
bank_code: \"MANDIRI\",
paid_at: \"2020-01-14T02:32:50.912Z\",
payer_email: \"test@xendit.co\",
description: \"Invoice callback test\",
adjusted_received_amount: 1995000,
fees_paid_amount: 5000,
created: \"2020-01-13T02:32:49.827Z\",
updated: \"2020-01-13T02:32:50.912Z\",
currency: \"IDR\",
payment_channel: \"MANDIRI\",
payment_destination: \"8458478548758748\",
}" \
'{{your_company_domain}}/{{callback_url}}'
Example Invoice Callback Request for Payment Through Retail Outlet
curl --include \
--request POST \
--header "X-CALLBACK-TOKEN: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
--header "Content-Type: application/json" \
--data-binary "{
id: \"593f4ed1c3d3bb7f39733d83\",
external_id: \"testing-invoice\",
user_id: \"5848fdf860053555135587e7\",
is_high: false,
payment_method: \"RETAIL_OUTLET\",
status: \"PAID\",
merchant_name: \"Xendit\",
amount: 2000000,
paid_amount: 2000000,
paid_at: \"2020-01-14T02:32:50.912Z\",
payer_email: \"test@xendit.co\",
description: \"Invoice callback test\",
adjusted_received_amount: 1995000,
fees_paid_amount: 5000,
created: \"2020-01-13T02:32:49.827Z\",
updated: \"2020-01-13T02:32:50.912Z\",
currency: \"IDR\",
payment_channel: \"ALFAMART\",
payment_destination: \"TEST815\",
}" \
'{{your_company_domain}}/{{callback_url}}'
Parameter | Description |
---|---|
id | An invoice ID generated by Xendit |
user_id | Your Xendit Business ID |
external_id | The invoice ID in your server, that can be used to reconcile between you and Xendit |
is_high (DEPRECATED) | Should unique numbers go above or below the amount. |
merchant_name | The name of your company or website |
amount | Nominal amount for the invoice (without taxes, fees) |
status | PAID the invoice has successfully been paid EXPIRED the invoice has expired. Expired invoice callbacks are not enabled by default - if you want to enable it for your business, you can do so in your Xendit Dashboard |
payer_email | Email of the payer, we get this information from your API call |
description | Description for the invoice, we get this information from your API call |
fees_paid_amount | Xendit fees that was directly paid from this invoice - thanks for supporting a better world of payments :) |
adjusted_received_amount | Amount attributable to you net of our fees. |
bank_code only if payment_method is POOL |
Code of the bank used to received the money only if payment method is POOL e.g. MANDIRI |
retail_outlet_name only if payment_method is RETAIL_OUTLET |
Code of the retail outlet used to received the money only if payment method is RETAIL_OUTLET e.g. ALFAMART |
ewallet_type only if payment_method is EWALLET |
Code of the e-wallet used to received the money only if payment method is EWALLET e.g. OVO |
on_demand_link only for invoices from ondemand |
Link of the ondemand that created this invoice |
recurring_payment_id only for invoices from recurring |
ID of the recurring that created this invoice |
paid_amount | Total amount paid for the invoice |
updated | An ISO timestamp that tracks when the invoice was updated |
created | An ISO timestamp that tracks when the invoice was created |
mid_label | MID label that you have when you are using credit card payment and have acquiring bank. You will get this response when you add this parameter when create invoice through API |
currency | Currency of the amount that you created. You will get this response when you add this parameter when create invoice through API |
success_redirect_url | URL that end user will be redirected to upon successful invoice payment. You will get this response when you add this parameter when create invoice through API |
failure_redirect_url | URL that end user will be redirected to upon expiration of this invoice. You will get this response when you add this parameter when create invoice through API |
paid_at | Date time data when your customer pay the invoice. You will get this response when your invoice is paid |
credit_card_charge_id | Credit card charge ID when your customer pay the invoice with credit card. You will get this response when your invoice is paid with Credit Card |
payment_method | Payment method that is used when a customer pays the invoice. You will get this response when your invoice is paid Example : ["BANK_TRANSFER", "CREDIT_CARD", "RETAIL_OUTLET", "EWALLET"] |
payment_channel | The payment channel used when a customer pays the invoice. You will get this response when your invoice is paid Example : ["BCA", "BRI", "MANDIRI", "BNI", "PERMATA", "ALFAMART", "OVO", "CREDIT_CARD"] |
payment_destination | Virtual Account number or Retail Outlet payment code used to pay the invoice (will not be shown for cards and e-wallet payments). You will get this response when your invoice is paid |
Callback Errors
Note that in the case where we don't get a successful response from your servers on the first try, we will retry 2 times more with a 30 second delay between each retry. After 3 failures, we get internal alerts that a callback has failed. Our team will then contact you to resolve the issue.
Recurring Payments
Create a Recurring Payment
Endpoint: Create Recurring Payment
POST https://api.xendit.co/recurring_payments
Recurring payments allow you to automatically bill your customers using our system.
Request Parameters
Example: Create Recurring Request
curl https://api.xendit.co/recurring_payments -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d external_id=recurring_31451441 \
-d payer_email=sample_email@xendit.co \
-d interval=MONTH \
-d interval_count=1 \
-d description='Monthly room cleaning service' \
-d amount=125000
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'external_id' => 'recurring_31451441',
'payer_email' => 'sample_email@xendit.co',
'description' => 'Monthly room cleaning service',
'amount' => 125000,
'interval' => 'MONTH',
'interval_count' => 1
];
$createRecurring = \Xendit\Recurring::create($params);
var_dump($createRecurring);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RecurringPayment } = x;
const rpSpecificOptions = {};
const rp = new RecurringPayment(rpSpecificOptions);
const resp = await rp.createPayment({
externalID: 'recurring_31451441',
amount: 125000,
payerEmail: 'sample_email@xendit.co',
interval: RecurringPayment.Interval.Month,
intervalCount: 1,
description: 'Monthly room cleaning service',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String , Object> params = new HashMap<>();
params.put("external_id", "recurring_31451441");
params.put("payer_email", "sample_email@xendit.co");
params.put("interval", "MONTH");
params.put("interval_count", 1);
params.put("description", "Monthly room cleaning service");
params.put("amount", 125000);
RecurringPayment recurringPayment = RecurringPayment.create(params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
createData := recurringpayment.CreateParams{
ExternalID: "recurring_31451441",
Amount: 125000,
PayerEmail: "sample_email@xendit.co",
Description: "Monthly room cleaning service",
Interval: xendit.RecurringPaymentIntervalDay,
IntervalCount: 1,
}
resp, err := recurringpayment.Create(&createData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created recurring payment: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RecurringPayment = xendit_instance.RecurringPayment
recurring_payment = RecurringPayment.create(
external_id="recurring_12345",
payer_email="test@x.co",
description="Test Curring Payment",
amount=100000,
interval="MONTH",
interval_count=1,
)
print(recurring_payment)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
external_id required |
string |
ID of your choice (typically the unique identifier of a recurring payment in your system) |
payer_email required |
string |
Email of the end user you're charging |
description required |
string |
Description for the recurring payment and invoices |
amount required |
number |
Amount per invoice per interval. The minimum amount to create an invoice is 1 IDR. The maximum amount is 1.000.000.000 IDR |
interval required |
string |
One of DAY , WEEK , MONTH . The frequency with which a recurring payment invoice should be billed. |
interval_count required |
number |
The number of intervals (specified in the interval property) between recurring. For example, interval=MONTH and interval_count=3 bills every 3 months. |
total_recurrence optional |
number |
The number of times you will charge your customer. If you input it as 3, Xendit will charge your customer 3 times. If you input total_recurrence as 3, interval_count as 1 and interval as "DAY", Xendit will charge customer 3 times in first day after you trigger create recurring api, the day after and 2 days after you trigger create recurring api. |
invoice_duration optional |
number |
duration of time that end user have in order to pay the invoice before it's expired (in Second). If it's not filled, invoice_duration will follow your business default invoice duration. invoice_duration should and will always be less than the interval-interval_count combination. |
should_send_email optionaldefault:
|
boolean |
Specify should the end user get email when invoice is created, paid, or expired; or not |
missed_payment_action optionaldefault:
|
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 optionaldefault:
|
boolean |
Input this parameter as true when you want to enable auto-charged and capture card information through XenInvoice. |
charge_immediately optional |
boolean |
Specify should the first invoice created immediately when creating recurring payment with a valid start_date , The next invoice will be created at start_date and the calculation for the following recurring invoice will be at interval *interval_count + start_date |
payment_method_id optional |
string |
ID of direct debit token (called payment_method) created for this customer |
currency optional |
string |
Currency of the amount that you created example : "IDR" |
Response Parameters
Example: Create Recurring Response
{
"id": "579c8d61f23fa4ca35e52da3",
"user_id": "5781d19b2e2385880609791c",
"external_id": "recurring_31451441",
"status": "ACTIVE",
"amount": 125000,
"payer_email": "sample_email@xendit.co",
"description": "Monthly room cleaning service",
"interval": "MONTH",
"interval_count": 1,
"recurrence_progress": 1,
"should_send_email": false,
"missed_payment_action": "IGNORE",
"last_created_invoice_url": "https://invoice-staging.xendit.co/web/invoices/5dddeea6bdb99f4b23e5eef7",
"created": "2017-06-12T14:00:00.306Z",
"updated": "2017-06-12T14:00:00.306Z",
"start_date": "2017-07-12T14:00:00.306Z",
"recharge": true
}
Parameter | Type | Description |
---|---|---|
id | An recurring ID generated by Xendit | |
user_id | Your Xendit Business ID | |
external_id | The recurring ID in your server, that can be used to reconcile between you and Xendit | |
status | ACTIVE the recurring payment is currently activeSTOPPED the recurring payment has been stoppedPAUSED 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. |
|
payment_method_id | ID of direct debit token (called payment_method) bound to this recurring payment | |
currency optional |
string |
Currency of the amount that you created |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
INVALID_CREDIT_CARD_TOKEN_ERROR400 |
Credit Card token is invalid. |
INVALID_PAYMENT_METHOD_ID_ERROR400 |
Payment method id is invalid. |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
UNSUPPORTED_CURRENCY400 |
The currency is not configured yet in the settings, please contact us. |
Get a Recurring Payment
Endpoint: Get a Recurring Payment
GET https://api.xendit.co/recurring_payments/{id}
Request Parameters
Example Get Recurring Payment Request
curl https://api.xendit.co/recurring_payments/{id} \
-X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '579c8d61f23fa4ca35e52da3';
$getRecurring = \Xendit\Recurring::retrieve($id);
var_dump($getRecurring);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RecurringPayment } = x;
const rpSpecificOptions = {};
const rp = new RecurringPayment(rpSpecificOptions);
const resp = await rp.getPayment({ id: '579c8d61f23fa4ca35e52da3' });
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
RecurringPayment recurringPayment = RecurringPayment.get("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
getData := recurringpayment.GetParams{
ID: "579c8d61f23fa4ca35e52da3",
}
resp, err := recurringpayment.Get(&getData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved recurring payment: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RecurringPayment = xendit_instance.RecurringPayment
recurring_payment = RecurringPayment.get(
id="5f05825ff9f52d3ed204c687",
)
print(recurring_payment)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string |
ID of the recurring payment to retrieve |
Response Parameters
Example Get Recurring Payment Response
{
"id": "579c8d61f23fa4ca35e52da3",
"user_id": "5781d19b2e2385880609791c",
"external_id": "recurring_31451441",
"status": "ACTIVE",
"amount": 125000,
"payer_email": "sample_email@xendit.co",
"description": "Monthly room cleaning service",
"interval": "MONTH",
"interval_count": 1,
"recurrence_progress": 1,
"should_send_email": true,
"missed_payment_action": "IGNORE",
"last_created_invoice_url": "https://invoice-staging.xendit.co/web/invoices/5dddeea6bdb99f4b23e5eef7",
"created": "2017-06-12T14:00:00.306Z",
"updated": "2018-06-12T14:00:00.306Z",
"start_date": "2017-07-12T14:00:00.306Z",
"recharge":true
}
Parameter | Type | Description |
---|---|---|
id | An recurring ID generated by Xendit | |
user_id | Your Xendit Business ID | |
external_id | The recurring ID in your server, that can be used to reconcile between you and Xendit | |
status | ACTIVE the recurring payment is currently activeSTOPPED the recurring payment has been stoppedPAUSED 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). |
next_scheduled_at |
An ISO timestamp of when the next invoice will be issued | |
created | An ISO timestamp that tracks when the recurring payment was created | |
updated | An ISO timestamp that tracks when the recurring payment was updated | |
charge_immediately optional |
boolean |
A flag showing should the first invoice created immediately when creating recurring payment with a valid start_date |
recharge | When this parameter is true , it means you want to enable auto-charged and capture card information through XenInvoice. |
Error Codes
Error Code | Description |
---|---|
REQUEST_FORBIDDEN403 |
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_ERROR404 |
Could not find recurring by id. |
Edit Recurring Payment
Endpoint: Edit Recurring Payment
PATCH https://api.xendit.co/recurring_payments/{id}
Request Parameters
Example: Edit Recurring Payment Request
curl https://api.xendit.co/recurring_payments/579c8d61f23fa4ca35e52da3 \
-X PATCH \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d amount=80000 \
-d interval=WEEK \
-d interval_count=2 \
-d should_send_email=true \
-d missed_payment_action=STOP \
-d credit_card_token=522f0ba2ab70de5d2b409eee \
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '579c8d61f23fa4ca35e52da3';
$params = ['amount' => 80000];
$editRecurring = \Xendit\Recurring::update($id, $params);
var_dump($editRecurring);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RecurringPayment } = x;
const rpSpecificOptions = {};
const rp = new RecurringPayment(rpSpecificOptions);
const resp = await rp.editPayment({
id: '579c8d61f23fa4ca35e52da3',
amount: 80000,
interval: RecurringPayment.Interval.Week,
intervalCount: 2,
shouldSendEmail: true,
missedPaymentAction: RecurringPayment.Action.Stop,
creditCardToken: '522f0ba2ab70de5d2b409eee',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("amount", 80000);
params.put("interval", "WEEK");
RecurringPayment recurringPayment = RecurringPayment.edit("EXAMPLE_ID", params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
editData := recurringpayment.EditParams{
ID: "579c8d61f23fa4ca35e52da3",
Amount: 80000,
Interval: xendit.RecurringPaymentIntervalWeek,
IntervalCount: 2,
}
resp, err := recurringpayment.Edit(&editData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("edited recurring payment: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RecurringPayment = xendit_instance.RecurringPayment
recurring_payment = RecurringPayment.edit(
id="5f05825ff9f52d3ed204c687",
interval_count=2,
)
print(recurring_payment)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
idrequired |
string |
id of recurring you want to update |
Body Parameter | Type | Description |
---|---|---|
amountoptional |
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. |
reschedule_at optional |
string (ISO 8601) |
Time when the next invoice will be issued. If left blank, the invoice will be issued based on previous recurring payment settings. |
missed_payment_action optional |
string |
Edit action if there is an invoice from a recurring payment that expired, IGNORE will continue with the recurring payment as usual. STOP will stop the recurring payment. |
payment_method_id optional |
string |
Fill this with the direct debit token (called) created for this end customer |
customer_id optional |
string |
fill this with customer id that you want to assign the recurring payment to |
Response Parameters
Example: Edit Recurring Payment Response
{
"id": "579c8d61f23fa4ca35e52da3",
"user_id": "5781d19b2e2385880609791c",
"external_id": "recurring_31451441",
"status": "ACTIVE",
"amount": 80000,
"payer_email": "sample_email@xendit.co",
"description": "Monthly room cleaning service",
"interval": "WEEK",
"interval_count": 2,
"recurrence_progress": 1,
"should_send_email": true,
"recharge": true,
"missed_payment_action": "STOP",
"created": "2017-06-12T14:00:00.306Z",
"updated": "2017-06-12T14:00:00.306Z",
"start_date": "2017-06-19T14:00:00.306Z"
}
All response parameters will be the same as get recurring
Error Codes
Error Code | Description |
---|---|
NOT_FOUND_ERROR404 |
Could not find recurring by id. |
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
INVALID_CREDIT_CARD_TOKEN_ERROR400 |
Credit card token is invalid. |
INVALID_PAYMENT_METHOD_ID_ERROR400 |
Payment method id is invalid. |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more here |
Stop Recurring Payment
Endpoint: Stop Recurring
POST https://api.xendit.co/recurring_payments/{id}/stop!
Request Parameters
Example: Stop Recurring Payment Request
curl https://api.xendit.co/recurring_payments/{id}/stop! -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '579c8d61f23fa4ca35e52da3';
$stopRecurring = \Xendit\Recurring::stop($id);
var_dump($stopRecurring);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RecurringPayment } = x;
const rpSpecificOptions = {};
const rp = new RecurringPayment(rpSpecificOptions);
const resp = await rp.stopPayment({ id: '579c8d61f23fa4ca35e52da3' });
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
RecurringPayment recurringPayment = RecurringPayment.stop("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
stopData := recurringpayment.StopParams{
ID: "579c8d61f23fa4ca35e52da3",
}
resp, err := recurringpayment.Stop(&stopData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("stopped recurring payment: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RecurringPayment = xendit_instance.RecurringPayment
recurring_payment = RecurringPayment.stop(
id="5f05825ff9f52d3ed204c687",
)
print(recurring_payment)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string |
ID of the recurring payment to stop |
Response Parameters
Example: Stop Recurring Payment Response
{
"id": "579c8d61f23fa4ca35e52da3",
"user_id": "5781d19b2e2385880609791c",
"external_id": "recurring_31451441",
"status": "STOPPED",
"amount": 125000,
"payer_email": "sample_email@xendit.co",
"description": "Monthly room cleaning service",
"interval": "MONTH",
"interval_count": 1,
"recurrence_progress": 1,
"should_send_email": true,
"missed_payment_action": "IGNORE",
"recharge": true,
"created": "2017-06-12T14:00:00.306Z",
"updated": "2018-06-12T14:00:00.306Z",
"start_date": "2017-07-12T14:00:00.306Z"
}
All response parameters will be the same as get recurring
Error Codes
Error Code | Description |
---|---|
REQUEST_FORBIDDEN403 |
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_ERROR404 |
Could not find recurring by id. |
Pause Recurring Payment
Endpoint: Pause Recurring Payment
POST https://api.xendit.co/recurring_payments/{id}/pause!
Request Parameters
Example Pause Recurring Payment Request
curl https://api.xendit.co/recurring_payments/{id}/pause!
-X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '579c8d61f23fa4ca35e52da3';
$pauseRecurring = \Xendit\Recurring::pause($id);
var_dump($pauseRecurring);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RecurringPayment } = x;
const rpSpecificOptions = {};
const rp = new RecurringPayment(rpSpecificOptions);
const resp = await rp.pausePayment({ id: '579c8d61f23fa4ca35e52da3' });
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
RecurringPayment recurringPayment = RecurringPayment.pause("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
pauseData := recurringpayment.PauseParams{
ID: "579c8d61f23fa4ca35e52da3",
}
resp, err := recurringpayment.Pause(&pauseData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("paused recurring payment: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RecurringPayment = xendit_instance.RecurringPayment
recurring_payment = RecurringPayment.pause(
id="5f05825ff9f52d3ed204c687",
)
print(recurring_payment)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string |
ID of the recurring payment to pause |
Response Parameters
Example Pause Recurring Response
{
"id": "579c8d61f23fa4ca35e52da3",
"user_id": "5781d19b2e2385880609791c",
"external_id": "recurring_31451441",
"status": "PAUSED",
"amount": 125000,
"payer_email": "sample_email@xendit.co",
"description": "Monthly room cleaning service",
"interval": "MONTH",
"interval_count": 1,
"recurrence_progress": 1,
"should_send_email": true,
"recharge": true,
"missed_payment_action": "IGNORE",
"created": "2017-06-12T14:00:00.306Z",
"updated": "2018-06-12T14:00:00.306Z",
"start_date": "2017-07-12T14:00:00.306Z"
}
All response parameters will be the same as get recurring
Error Codes
Error Code | Description |
---|---|
REQUEST_FORBIDDEN403 |
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_ERROR404 |
Could not find recurring by id. |
Resume Recurring Payment
Endpoint: Resume Recurring
POST https://api.xendit.co/recurring_payments/{id}/resume!
Request Parameters
Example Resume Recurring Request
curl https://api.xendit.co/recurring_payments/{id}/resume!
-X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '579c8d61f23fa4ca35e52da3';
$resumeRecurring = \Xendit\Recurring::resume($id);
var_dump($resumeRecurring);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RecurringPayment } = x;
const rpSpecificOptions = {};
const rp = new RecurringPayment(rpSpecificOptions);
const resp = await rp.resumePayment({ id: '579c8d61f23fa4ca35e52da3' });
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
RecurringPayment recurringPayment = RecurringPayment.resume("579c8d61f23fa4ca35e52da3");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
resumeData := recurringpayment.ResumeParams{
ID: "579c8d61f23fa4ca35e52da3",
}
resp, err := recurringpayment.Resume(&resumeData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("resumed recurring payment: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RecurringPayment = xendit_instance.RecurringPayment
recurring_payment = RecurringPayment.resume(
id="5f05825ff9f52d3ed204c687",
)
print(recurring_payment)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string |
ID of the recurring payment to resume |
Response Parameters
Example Resume Recurring Response
{
"id": "579c8d61f23fa4ca35e52da3",
"user_id": "5781d19b2e2385880609791c",
"external_id": "recurring_31451441",
"status": "ACTIVE",
"amount": 125000,
"payer_email": "sample_email@xendit.co",
"description": "Monthly room cleaning service",
"interval": "MONTH",
"interval_count": 1,
"recurrence_progress": 1,
"should_send_email": true,
"missed_payment_action": "IGNORE",
"recharge": true,
"created": "2017-06-12T14:00:00.306Z",
"updated": "2018-06-12T14:00:00.306Z",
"start_date": "2017-07-12T14:00:00.306Z"
}
All response parameters will be the same as get recurring
Error Codes
Error Code | Description |
---|---|
REQUEST_FORBIDDEN403 |
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_ERROR404 |
Could not find recurring by id. |
Recurring Callback
Xendit will notify you of all Recurring Payment Invoice activity via the usual invoice callback. Please visit invoice callback to get more information about setting up your callback URL and getting invoice callbacks.
Additional parameters from invoice callback if you are using recurring payments:
Parameter | Type | Description |
---|---|---|
recurring_payment_id | string |
ID of the recurring payment for this invoice |
Get List of Payments
Getting list of the payments can be done by searching invoices with certain recurring_payment_id and it can be done using List all invoices.
Additional parameters from listing all invoice if you are using recurring payments:
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Parameter | Type | Description |
---|---|---|
recurring_payment_id | string |
ID of the recurring payment for this invoice |
Payouts
Easily send funds to customers with our payouts UI, allowing them to choose their payout destination.
Create Payout
Endpoint: Create Payouts
POST https://api.xendit.co/payouts
Request Parameters
Example Create Payout Request
curl https://api.xendit.co/payouts -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d external_id=demo_2392329329 \
-d amount=23000 \
-d email=demo@xendit.co
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'external_id' => 'demo_2392329329',
'amount' => 23000
];
$createPayout = \Xendit\Payouts::create($params);
var_dump($createPayout);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Payout } = x;
const payoutSpecificOptions = {};
const p = new Payout(payoutSpecificOptions);
const resp = await p.createPayout({
externalID: 'demo_2392329329',
amount: 23000,
email: 'demo@xendit.co'
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("external_id", "demo_2392329329");
params.put("amount", 23000);
params.put("email", "demo@xendit.co");
Payout payout = Payout.createPayout(params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
createData := payout.CreateParams{
ExternalID: "demo_2392329329",
Amount: 23000,
Email: "test@email.com",
}
resp, err := payout.Create(&createData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created payout: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Payout = xendit_instance.Payout
payout = Payout.create(
external_id="payout-1595405117",
amount=50000,
email="test@email.co",
)
print(payout)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
external_id required |
string |
ID of your choice (typically the unique identifier of a payout in your system).Maximum:
|
amount required |
integer positive |
Amount to be paid out. The maximum amount depends on your balance. |
email required |
string |
An email address of the end user you're sending payout to. |
Response Parameters
Example Create Payout Response
{
"id": "67f1b30c-0262-4955-8777-95aa0478c2fc",
"external_id": "demo_2392329329",
"amount": 23000,
"merchant_name": "First Business",
"status": "PENDING",
"expiration_timestamp": "2019-12-12T06:13:21.637Z",
"created": "2019-12-09T06:13:20.363Z",
"payout_url": "https://payout.xendit.co/web/67f1b30c-0262-4955-8777-95aa0478c2fc"
}
Parameter | Type | Description |
---|---|---|
idrequired |
string |
A payout ID generated by Xendit |
external_idrequired |
string |
The payout ID in your server, that can be used to reconcile between you and Xendit. Maximum:
|
amountrequired |
integer positive |
Amount to be paid out. The maximum amount depends on your balance. |
merchant_nameoptional |
string |
The name of your company or website. |
statusrequired |
string |
PENDING The payout has successfully been created and is awaiting the end user’s responseVOIDED The payout has been voided. This issue is raised because the payout has been expired or manually voided by hitting the void endpoint. COMPLETED The payout has completed. FAILED The payout has failed. The list of failures are described in the failure_reason field. |
expiration_timestampoptional |
ISO8601 |
An ISO timestamp that the payout expires. Default is 3 days after creation. Timezone:
|
createdoptional |
ISO8601 |
An ISO timestamp that tracks when the payout was created.Timezone:
|
payout_urloptional |
string |
Public URL for this payout, in case you want to use our UI. |
emailoptional |
string |
An email address of the end user you're sending payout to. |
bank_codeoptional |
string |
Bank code for the relevant bank, learn more here |
account_holder_nameoptional |
string |
Bank account holder name. |
account_numberoptional |
string |
Bank account number. |
disbursement_idoptional |
string |
ID of the disbursement. You can find out here |
failure_reasonoptional |
string |
If the status is FAILED , this describes the failure. |
claimed_timestampoptional |
ISO8601 |
An ISO timestamp that tracks when the payout was claimed. Timezone:
|
completed_timestampoptional |
ISO8601 |
An ISO timestamp that tracks when the payout was completed. Timezone:
|
failed_timestampoptional |
ISO8601 |
An ISO timestamp that tracks when the payout was failed. Timezone:
|
payment_idoptional |
string |
Our internal system’s payment ID that can be used as payment reference. |
Error Codes
Error Code | Description |
---|---|
INSUFFICIENT_BALANCE400 |
The balance in your account is insufficient to make the payout in the desired amount. |
DUPLICATE_PAYOUT_ERROR400 |
The payout with the same external_id has already been made before. |
UNAUTHORIZED_MERCHANT_ERROR403 |
This merchant is not authorized to perform this request. |
Get Payout
Endpoint: Get a Payout
GET https://api.xendit.co/payouts/:id
Request Parameters
Example Get Payout Request
curl https://api.xendit.co/payouts/:id -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '00754a09-ad00-4475-b874-1dd97f83fc24';
$getPayout = \Xendit\Payouts::retrieve($id);
var_dump($getPayout);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Payout } = x;
const payoutSpecificOptions = {};
const p = new Payout(payoutSpecificOptions);
const resp = await p.getPayout({
id: '67f1b30c-0262-4955-8777-95aa0478c2fc',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Payout payout = Payout.getPayout("my_test_id");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
resp, err := payout.Get(&payout.GetParams{
ID: "00754a09-ad00-4475-b874-1dd97f83fc24",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved payout: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Payout = xendit_instance.Payout
payout = Payout.get(
id="a6ee1bf1-ffcd-4bda-a7ab-99c1d5cd0472",
)
print(payout)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string |
ID of the payout to retrieve |
Response Parameters
Example Get Payout Response
{
"id": "00754a09-ad00-4475-b874-1dd97f83fc24",
"external_id": "ext-121313",
"amount": 20000,
"merchant_name": "First Business",
"status": "PENDING",
"expiration_timestamp": "2019-12-12T06:45:30.041Z",
"created": "2019-12-09T06:45:28.628Z",
"payout_url": "https://payout.xendit.co/web/00754a09-ad00-4475-b874-1dd97f83fc24"
}
Parameter | Type | Description |
---|---|---|
idrequired |
string |
A payout ID generated by Xendit |
external_idrequired |