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!
List of Supported Products
- Credit / Debit cards (via Payments API)
- E-Wallets (via Payments API)
- QR Codes (via Payments API)
- Direct Debit (via Payments API)
- Bank Transfer / Virtual Accounts (via Payments API)
- Retail Outlets (via Payments API)
- Invoices
- Payouts
- Customers
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.
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
Installation and Upgrade Guide
Check out our Github source to learn on how to install or upgrade Xendit PHP library
Go
See the source on Github
Go library is a server-side library that helps you to integrate Xendit easily using Go programming language.
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.
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-src
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
Request ID
Each API request has an asssociated request identifier. You can find this value in the response headers, under Request-ID
. You can use Request-ID
to find logs in API Logs in Dashboard. Learn more about Searching API Logs using Request-ID
in API Logs Docs.
If you need to contact us about a specific request, providing the Request ID will ensure the fastest possible resolution.
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 |
Rate Limit
API Rate Limit is a feature that limits the number of requests that a user or account can make to an API within a specific time period. This is often used to prevent excessive or abusive usage of an API, and to ensure that all users have fair access to the resources provided by the API.
Xendit uses the Sliding Window algorithm to implement API Rate Limit. This algorithm divides a specific time period (such as an hour or a day) into smaller windows, and tracks the number of requests made within each window. For example, if the rate limit is 50 requests per second (RPS), and the window size is one minute, the algorithm will allow up to 3000 requests in each one-minute window.
In general, API Rate Limit is set 60 requests per minute (RPM) per endpoint per account in Test mode. In Live mode, the rate limit is set to 6000 requests per minute (RPM) per endpoint per account. The Rate Limit value can be different per endpoint when stated otherwise in each API section in API Reference. We return the following headers in API response to let you check Rate Limit details:
Response Header | Example Value | Description |
---|---|---|
Rate-Limit-Limit | 6000 | Containing the requests quota in the time window |
Rate-Limit-Remaining | 5839 | Containing the remaining requests quota in the current window |
Rate-Limit-Reset | 58.379 | Containing the time remaining in the current window, specified in seconds |
Additionally, the rate limit of each unique IP address of the calling client can make a maximum of 18,000 requests per minute.
If you exceed the rate limit for an endpoint, you will receive an HTTP status code of 429 (Too Many Requests) with the error code RATE_LIMIT_EXCEEDED
. It is important to handle this error and throttle your requests until the rate limit quota replenishes.
Here are some best practices for handling API Rate Limit gracefully as a client:
- Implement rate limiting in your application: As a client, it is important to implement rate limiting in your own application to ensure that you do not exceed the API's rate limits. This can be done by tracking the number of requests made and the time at which they were made, and comparing this to the API's rate limit policies.
- Handle rate limit errors: When you receive an HTTP status code of 429 (Too Many Requests) with the error code
RATE_LIMIT_EXCEEDED
, it is important to handle this error gracefully in your application. One way to do this is to retry the request after a certain amount of time has passed, to give the rate limit quota a chance to replenish. - Use exponential backoff: When retrying a request after a rate limit error, it can be helpful to use exponential backoff. This means that you should increase the amount of time you wait between retries by a factor of two (or some other multiplier) each time you receive a rate limit error. For example, you might retry the request after 1 second, then 2 seconds, then 4 seconds, and so on. This helps to reduce the risk of overwhelming the API with too many retries in a short period of time.
- Use caching: Caching the results of API requests can help to reduce the number of requests made to the API, and can also improve the performance of your application. By storing the results of API requests locally and reusing them until they become stale, you can reduce the need to make frequent requests to the API.
By following these best practices, you can help to ensure that your application handles rate limits gracefully and provides a reliable and consistent experience for your users.
We may reduce limits to prevent abuse, or increase limits to enable high-traffic applications. To increase the rate limit for your account, you can contact us 4 weeks in advance via email api@xendit.co by providing your Business ID. We will review your request and may be able to increase the limit based on the needs of your application and the overall usage of the API.
Overall, it is important to carefully manage your API usage to ensure that you do not exceed the rate limits and disrupt the service for other users. By implementing proper rate limiting and error handling in your application, you can ensure that your users have a reliable and consistent experience when accessing the API.
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 set as headers in Xendit's API. The exact header for idempotency is dependant on the specific API. For example, the idempotency-key
header on the Create Payouts API. 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
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.
Webhook
Xendit uses webhook to notify your application any time an event happens on your account. Set up webhook 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 webhook from us. The webhook notification will be sent over POST request to your webhook URL that you have set. Setup your webhook URL in webhook settings. You can use a tool like ngrok to make your endpoint available for receiving webhook during testing.
Delivery Attempts and Retries
Understand how to view delivery attempts and retry logic when webhook events aren't acknowledged
View events
When viewing information about a specific event through the Dashboard's Webhook 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 webhooks, and the respective HTTP status codes Xendit received.
Retry logic
Xendit attempts to deliver your webhook 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 webhook statistics via email
You can also receive summary of your webhook statistics (number of success and failed webhook) via email every 6 hours. You can enable this feature in Email Recipient settings
Event Handling
Handling webhook events correctly is crucial to making sure your integration's business logic works as expected
Acknowledge events immediately
If your webhook 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 webhook 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
Webhook 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. We provide webhook-id
as a unique identifier in the header parameter of every webhook to help you to implement idempotency. Learn about idempotency.
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 webhook endpoint, Xendit will validate that the connection to your server is secure before sending your webhook 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 webhook 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 webhook token to verify the origin of the webhook |
Before you can verify tokens, you need to retrieve your webhook token from Dashboard's Webhook 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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
BalanceClient balance = xendit.Balance;
BalanceResponse holdingBalance = await balance.Get(BalanceAccountType.Holding);
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 |
currency optional |
string |
Currency filter for customers with multi currency accounts type. This field is only optional if you have only 1 currency. If you have more than 1 currency, please specify your desired currency. sample values: IDR , PHP , USD |
at_timestamp optional |
string |
Datetime format Balance returned in the response will be based on the timestamp provided sample value: 2024-01-01T00:00:00.000Z |
Response Parameters
Example Get Balance Response
{
"balance": 1241231
}
Parameter | Description |
---|---|
balance | The balance remaining in your cash account |
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
The Customer Object is a standard data structure to hold information relating to one of your customers. It has the following major components:
- A Type of customer (Individual or Business)
- Basic descriptive details of that customer
- Addresses of the customer
- Identity accounts and KYC documents to prove the legitimacy of the customer
- Other metadata
When one (or more) customers is returned by endpoints in this section, the response body will contain a Customer Object (or an array of Customer Objects). Each object has the following structure:
Example Customer Object - Individual
{
"id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "demo_1475801962607",
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe",
"nationality": "ID",
"place_of_birth": "Jakarta",
"date_of_birth": "1980-01-01",
"gender": "MALE",
"employment": {
"employer_name": "Xendit",
"nature_of_business": "Payment Gateway",
"role_description": "Test dummy"
}
},
"business_detail": null,
"email": "customer@website.com",
"mobile_number": "+628121234567890",
"phone_number": "+628121234567890",
"hashed_phone_number": null,
"addresses": [{
"street_line1": "Panglima Polim IV",
"street_line2": "Ruko Grand Panglima Polim, Blok E",
"city": "Jakarta Selatan",
"province_state": "DKI Jakarta",
"postal_code": "993448",
"country": "ID",
"category": "HOME",
"is_primary": true
}],
"identity_accounts": [{
"type": "CREDIT_CARD",
"company": "OCBC",
"description": "My account",
"country": "ID",
"properties":{
"token_id": "586f0ba2ab70de5d2b409e0d"
}
}],
"kyc_documents": [{
"type": "IDENTITY_CARD",
"sub_type": "NATIONAL_ID",
"country": "ID",
"document_name": "KTP",
"document_number": "12356789012456",
"expires_at": null,
"holder_name": "John Doe",
"document_images": [
"file-ec700c1c-db17-4496-b1fb-04ebe551b412"
]
}],
"description": "My first customer",
"date_of_registration": "2020-03-30",
"domicile_of_registration": "ID",
"metadata": {
"foo": "bar"
},
"created": "2020-03-30T06:12:47.212Z",
"updated": "2020-03-30T06:12:47.212Z"
}
Example Customer Object - Business
{
"id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "demo_1475801962607",
"type": "BUSINESS",
"individual_detail": null,
"business_detail": {
"business_name": "ACME Corp",
"trading_name": null,
"business_type": "CORPORATION",
"nature_of_business": null,
"business_domicile": null,
"date_of_registration": null
},
"email": "customer@website.com",
"mobile_number": null,
"phone_number": null,
"hashed_phone_number": null,
"addresses": [],
"identity_accounts": [],
"kyc_documents": [],
"description": null,
"metadata": null,
"created": "2020-03-30T06:12:47.212Z",
"updated": "2020-03-30T06:12:47.212Z"
}
Version
You are currently viewing API version 2020-10-31. Click here to view older versions.
Version | Changelog |
---|---|
2020-10-31 (Latest) | Update to support BUSINESS type customers and generic identity accounts |
2020-05-19 | Original version |
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string |
Xendit-generated Customer ID. Will start with cust-... |
||||||||||||||||||||||||||||||||||||||||||||||||
reference_idrequired |
string |
Merchant-provided identifier for the customer | ||||||||||||||||||||||||||||||||||||||||||||||||
typerequired |
string |
Type of customer. Supported values: INDIVIDUAL , BUSINESS |
||||||||||||||||||||||||||||||||||||||||||||||||
individual_detailoptional |
object |
JSON object containing details of the individual. Will be null if type is not INDIVIDUAL
Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
business_detailoptional |
object |
JSON object containing details of the business. Will be null if type is not BUSINESS
Business detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
mobile_numberoptional |
string |
Mobile number of customer in E.164 format
|
||||||||||||||||||||||||||||||||||||||||||||||||
phone_numberoptional |
string |
Additional contact number of customer in E.164 format. May be a landline
|
||||||||||||||||||||||||||||||||||||||||||||||||
hashed_phone_numberoptional |
string |
Hashed phone number
|
||||||||||||||||||||||||||||||||||||||||||||||||
emailoptional |
string |
E-mail address of customer
|
||||||||||||||||||||||||||||||||||||||||||||||||
addressesoptional |
array |
Array of address JSON objects containing the customer's various address information.Addresses child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
identity_accountsrequired |
array |
Array of JSON objects with information relating to financial, social media or other accounts associated with the customer. This array can store details for KYC purposes and can support storing of account details for execution of payments within the Xendit API ecosystem.Identity accounts child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
kyc_documentsrequired |
array |
Array of JSON objects with documents collected for KYC of this customer. KYC documents child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
descriptionoptional |
string |
Merchant-provided description for the customer.
|
||||||||||||||||||||||||||||||||||||||||||||||||
date_of_registrationoptional |
string |
Date of which the account that the shopper had to create/sign up on the merchant’s website
|
||||||||||||||||||||||||||||||||||||||||||||||||
domicile_of_registrationoptional |
string |
Country within which the account that the shopper had to create/sign up on the merchant’s website resides (e.g. accounts created on Shopee SG have SG as the value for this field.
|
||||||||||||||||||||||||||||||||||||||||||||||||
metadataoptional |
object |
Object of additional information as provided in customer creation | ||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired |
string |
Timestamp of customer creation in ISO format | ||||||||||||||||||||||||||||||||||||||||||||||||
updatedrequired |
string |
Timestamp of customer update in ISO format |
Create Customer
Make a POST request to this endpoint to create a customer for later use with a payments endpoint.
Endpoint: Create Customer
POST https://api.xendit.co/customers
Version
You are currently viewing API version 2020-10-31. Click here to view older versions.
Version | Changelog |
---|---|
2020-10-31 (Latest) | Update to support BUSINESS type customers and generic identity accounts |
2020-05-19 | Original version |
Request Parameters
Example Create Customer Request
curl https://api.xendit.co/customers -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json'
--data-raw '{
"reference_id": "demo_1475801962607",
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe"
},
"email": "customer@website.com",
"mobile_number": "+628121234567890"
}'
<?php
$url = "https://api.xendit.co/customers";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$data = [
"reference_id" => "demo_1475801962607",
"type" => "INDIVIDUAL",
"individual_detail" => [
"given_names" => "John",
"surname" => "Doe"
],
"email" => "customer@website.com",
"mobile_number" => "+628121234567890"
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
let url = "https://api.xendit.co/customers";
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
headers.append("Content-Type", "application/json");
var reqBody = JSON.stringify({
"reference_id": "demo_1475801962607",
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe"
},
"email": "customer@website.com",
"mobile_number": "+628121234567890"});
var requestOptions = {
method: 'POST',
headers: headers,
body: reqBody,
redirect: 'follow'
};
fetch(url, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
import requests
import base64
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
url = "https://api.xendit.co/customers"
api_key_bytes = api_key.encode('ascii')
base64_bytes = base64.b64encode(api_key_bytes)
base64_token = base64_bytes.decode('ascii')
payload = {
"reference_id": "demo_1475801962607",
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe"
},
"email": "customer@website.com",
"mobile_number": "+628121234567890"
}
auth_token = 'Basic ' + base64_token
headers = {
'Authorization': auth_token
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
CustomerClient customer = xendit.Customer;
CustomerParameter individualParameter = new CustomerParameter
{
ReferenceId = "demo_11212163",
Type = CustomerType.Individual,
IndividualDetail = new IndividualDetail
{
GivenNames = "John",
Gender = CustomerGender.Male,
},
IdentityAccount = new IdentityAccount[]
{
new IdentityAccount
{
Country = Country.Indonesia,
Type = CustomerIdentityAccountType.BankAccount,
Properties = new IdentityAccountProperties { AccountNumber = "account_number" }
}
},
KycDocuments = new KycDocument[]
{
new KycDocument
{
Country = Country.Indonesia,
Type = CustomerKycDocumentType.IdentityCard,
SubType = CustomerKycDocumentSubType.NationalId,
}
},
};
CustomerResponse individualCustomerVersion20201031 = await customer.Create(individualParameter);
Header Parameter | Type | Description |
---|---|---|
IDEMPOTENCY-KEYoptional |
string |
A unique key to prevent processing duplicate requests. Can be your reference_id or any GUID. Must be unique across development & production environments. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.
|
API-VERSIONoptional |
string |
API version in date semantic (e.g. 2020-10-31). Attach this parameter when calling a specific API version. List of API versions can be found here. |
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 | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
reference_idrequired |
string |
Merchant-provided identifier for the customer. Requests with a duplicate reference_id will return an error. You should PATCH the customer object resource instead.
|
||||||||||||||||||||||||||||||||||||||||||||||||
typerequired |
string |
Type of customer. Supported values: INDIVIDUAL , BUSINESS |
||||||||||||||||||||||||||||||||||||||||||||||||
individual_detailconditionally required |
object |
JSON object containing details of the individual. Required if type is INDIVIDUAL
Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
business_detailconditionally required |
object |
JSON object containing details of the business. Required if type is BUSINESS
Business detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
mobile_numberoptional |
string |
Mobile number of customer in E.164 format
|
||||||||||||||||||||||||||||||||||||||||||||||||
phone_numberoptional |
string |
Additional contact number of customer in E.164 format. May be a landline
|
||||||||||||||||||||||||||||||||||||||||||||||||
hashed_phone_numberoptional |
string |
Hashed phone number
|
||||||||||||||||||||||||||||||||||||||||||||||||
emailoptional |
string |
E-mail address of customer
|
||||||||||||||||||||||||||||||||||||||||||||||||
addressesoptional |
array |
Array of address JSON objects containing the customer's various address information.Addresses child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
identity_accountsoptional |
array |
Array of JSON objects with information relating to financial, social media or other accounts associated with the customer. This array can store details for KYC purposes and can support storing of account details for execution of payments within the Xendit API ecosystem.Identity accounts child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
kyc_documentsoptional |
array |
Array of JSON objects with documents collected for KYC of this customer. KYC documents child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
descriptionoptional |
string |
Merchant-provided description for the customer.
|
||||||||||||||||||||||||||||||||||||||||||||||||
date_of_registrationoptional |
string |
Date of which the account that the shopper had to create/sign up on the merchant’s website
|
||||||||||||||||||||||||||||||||||||||||||||||||
domicile_of_registrationoptional |
string |
Country within which the account that the shopper had to create/sign up on the merchant’s website resides (e.g. accounts created on Shopee SG have SG as the value for this field.
|
||||||||||||||||||||||||||||||||||||||||||||||||
metadataoptional |
object |
Object of additional information related to the customer. Define the JSON properties and values as required to pass information through the APIs. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. This is only for your use and will not be used by Xendit. |
Response Parameters
Success responses will contain a single Customer Object
Error Codes
See other common errors here.
Error Code | Description |
---|---|
DUPLICATE_ERROR409 |
The provided reference_id has been used before. Please enter a unique reference_id . |
IDEMPOTENCY_ERROR409 |
Provided Idempotency-key already exists but the request body provided does not match the original request |
Get Customer
Retrieves a single customer object
Endpoint: Get Customer
GET https://api.xendit.co/customers/:id
Version
You are currently viewing API version 2020-10-31. Click here to view older versions.
Version | Changelog |
---|---|
2020-10-31 (Latest) | Update to support BUSINESS type customers and generic identity accounts |
2020-05-19 | Original version |
Request Parameters
Example Get Customer Request
curl https://api.xendit.co/customers/cust-239c16f4-866d-43e8-9341-7badafbc019f -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
--header 'API-VERSION: 2020-10-31'
<?php
$url = "https://api.xendit.co/customers/cust-239c16f4-866d-43e8-9341-7badafbc019f";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
let url = "https://api.xendit.co/customers/cust-239c16f4-866d-43e8-9341-7badafbc019f";
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
headers.append("Content-Type", "application/json");
headers.append("API-VERSION", "2020-10-31");
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));
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := customer.getCustomer{
id: 'cust-239c16f4-866d-43e8-9341-7badafbc019f'
}
resp, err := customer.getCustomer(&getCustomerByReferenceIDData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved customer: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
Customer[] customers = Customer.getCustomer("cust-239c16f4-866d-43e8-9341-7badafbc019f");
} catch (XenditException e) {
e.printStackTrace();
}
import requests
import base64
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
url = "https://api.xendit.co/customers/239c16f4-866d-43e8-9341-7badafbc019f"
api_key_bytes = api_key.encode('ascii')
base64_bytes = base64.b64encode(api_key_bytes)
base64_token = base64_bytes.decode('ascii')
auth_token = 'Basic ' + base64_token
headers = {
'Authorization': auth_token,
'API-VERSION': '2020-10-31'
}
response = requests.request("GET", url, headers=headers)
print(response.text)
Header Parameter | Type | Description |
---|---|---|
API-VERSIONoptional |
string |
API version in date semantic (e.g. 2020-10-31). Attach this parameter when calling a specific API version. List of API versions can be found here. |
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 |
---|---|---|
id | string |
Xendit-generated Customer ID. Will start with cust-... |
Response Parameters
Success responses will contain a single Customer Object
Error Codes
See other common errors here.
Error Code | Description |
---|---|
DATA_NOT_FOUND404 |
The provided id does not exist. Please review the 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-10-31. Click here to view older versions.
Version | Changelog |
---|---|
2020-10-31 (Latest) | Update to support BUSINESS type customers and generic identity accounts |
2020-05-19 | Original version |
Request Parameters
Example Get Customer by Reference ID Request
curl https://api.xendit.co/customers?reference_id=demo_1475801962607 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
$url = "https://api.xendit.co/customers";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$queryString = "?reference_id=demo_1475801962607";
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url.$queryString);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
let url = "https://api.xendit.co/customers";
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
headers.append("Content-Type", "application/json");
let queryString = "?reference_id=demo_1475801962607";
var requestOptions = {
method: 'GET',
headers: headers,
redirect: 'follow'
};
fetch(url + queryString, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Query Parameter | Type | Description |
---|---|---|
reference_idrequired |
string |
Your identifier for the customer |
Response Parameters
Example Get Customer by Reference ID Success Response
{
"data": [{
"id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "demo_1475801962607",
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe",
"nationality": null,
"place_of_birth": null,
"date_of_birth": null,
"gender": null,
"employment": null
},
"business_detail": null,
"email": "customer@website.com",
"mobile_number": null,
"phone_number": null,
"hashed_phone_number": null,
"addresses": [],
"identity_accounts": [],
"kyc_documents": [],
"description": null,
"metadata": null,
"created": "2020-03-30T06:12:47.212Z",
"updated": "2020-03-30T06:12:47.212Z"
}],
"has_more": false
}
Header Parameter | Type | Description |
---|---|---|
API-VERSIONoptional |
string |
API version in date semantic (e.g. 2020-10-31). Attach this parameter when calling a specific API version. List of API versions can be found here. |
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 |
---|---|---|
data | array |
Array of Customer Objects returned by the query. May be an empty array |
has_more | boolean |
Indicates whether there are more items to be queried with after_id of the last item from current result |
Error Codes
See other common errors here.
Update Customer
Make a PATCH request to this endpoint to update the details on a customer. Only fields present in the request will be updated. Any changes to fields on the customer object will replace that item in its entirety. If you wish to append to an array, your PATCH request should contain the desired end state array (i.e., both the current content and the new array element to append to it). Pass a NULL value to remove the existing content.
Note that the reference_id
and type
on a customer cannot be updated.
Endpoint: Update Customer
PATCH https://api.xendit.co/customers/:id
Version
You are currently viewing API version 2020-10-31. Click here to view older versions.
Version | Changelog |
---|---|
2020-10-31 (Latest) | Update to support BUSINESS type customers and generic identity accounts |
2020-05-19 | Original version |
Request Parameters
Example Update Customer Request
curl https://api.xendit.co/customers/cust-239c16f4-866d-43e8-9341-7badafbc019f -X PATCH \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json'
--data-raw '{
"individual_detail": {
"given_names": "Jane",
"surname": "Doe"
}
}'
<?php
$url = "https://api.xendit.co/customers/cust-239c16f4-866d-43e8-9341-7badafbc019f";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$data = [
"individual_detail" => [
"given_names" => "Jane",
"surname" => "Doe"
]
];
$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, 'PATCH');
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
let url = "https://api.xendit.co/customers/cust-239c16f4-866d-43e8-9341-7badafbc019f";
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
headers.append("Content-Type", "application/json");
var reqBody = JSON.stringify({
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe"
},
"email": "customer@website.com",
"mobile_number": "+628121234567890"});
var requestOptions = {
method: 'PATCH',
headers: headers,
body: reqBody,
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/customers"
api_key_bytes = api_key.encode('ascii')
base64_bytes = base64.b64encode(api_key_bytes)
base64_token = base64_bytes.decode('ascii')
payload = {
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe"
},
"email": "customer@website.com",
"mobile_number": "+628121234567890"
}
auth_token = 'Basic ' + base64_token
headers = {
'Authorization': auth_token
}
response = requests.request("PATCH", url, headers=headers, data=payload)
print(response.text)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
CustomerClient customer = xendit.Customer;
CustomerParameter individualParameter = new CustomerParameter
{
Type = CustomerType.Individual,
IndividualDetail = new IndividualDetail
{
GivenNames = "John",
Gender = CustomerGender.Male,
}
};
CustomerResponse individualCustomerVersion20201031 = await customer.Update(individualParameter);
Header Parameter | Type | Description |
---|---|---|
API-VERSIONoptional |
string |
API version in date semantic (e.g. 2020-10-31). Attach this parameter when calling a specific API version. List of API versions can be found here. |
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 | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
individual_detailoptional |
object |
JSON object containing details of the individual. Will fail API validation if type is not INDIVIDUAL
Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
business_detailoptional |
object |
JSON object containing details of the business. Will fail API validation if type is not BUSINESS
Business detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
mobile_numberoptional |
string |
Mobile number of customer in E.164 format
|
||||||||||||||||||||||||||||||||||||||||||||||||
phone_numberoptional |
string |
Additional contact number of customer in E.164 format. May be a landline
|
||||||||||||||||||||||||||||||||||||||||||||||||
emailoptional |
string |
E-mail address of customer
|
||||||||||||||||||||||||||||||||||||||||||||||||
addressesoptional |
array |
Array of address JSON objects containing the customer's various address information.Addresses child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
identity_accountsoptional |
array |
Array of JSON objects with information relating to financial, social media or other accounts associated with the customer. This array can store details for KYC purposes and can support storing of account details for execution of payments within the Xendit API ecosystem.Identity accounts child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
kyc_documentsoptional |
array |
Array of JSON objects with documents collected for KYC of this customer. KYC documents child parameters
|
||||||||||||||||||||||||||||||||||||||||||||||||
descriptionoptional |
string |
Merchant-provided description for the customer.
|
||||||||||||||||||||||||||||||||||||||||||||||||
date_of_registrationoptional |
string |
Date of which the account that the shopper had to create/sign up on the merchant’s website
|
||||||||||||||||||||||||||||||||||||||||||||||||
domicile_of_registrationoptional |
string |
Country within which the account that the shopper had to create/sign up on the merchant’s website resides (e.g. accounts created on Shopee SG have SG as the value for this field.
|
||||||||||||||||||||||||||||||||||||||||||||||||
metadataoptional |
object |
Object of additional information related to the customer. Define the JSON properties and values as required to pass information through the APIs. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. This is only for your use and will not be used by Xendit. |
Response Parameters
Success responses will contain a single Customer Object with the updated content
Error Codes
See other common errors here.
Error Code | Description |
---|---|
DATA_NOT_FOUND404 |
The provided id does not exist. Please review the id and try again |
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 |
Reports
An API to generate and get report. The available report are Balance and Transaction Report. You can use this endpoint to automate the report generation process. You can use the content of the report to get the detail of transactions and do reconciliation. The report on this API is equivalent to the report that you can download from dashboard.
Report Object
Report Object Example
{
"id": "report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28",
"type": "BALANCE_HISTORY",
"status": "COMPLETED",
"filter": {
"from": "2021-06-23T04:01:55.574Z",
"to": "2021-06-24T04:01:55.574Z"
},
"format": "CSV",
"url": "https://transaction-report-files.s3-us-west-2.amazonaws.com/{report_name}",
"currency": "IDR",
"business_id": "5f34f60535ba7c1c0eed846a",
"created": "2021-06-24T04:01:55.570Z",
"updated": "2021-06-24T04:01:55.570Z"
}
Body Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
id required |
string |
The unique id of report. It will have report_ as prefix. |
||||||||
type required |
string |
The type of report. Available types:
| ||||||||
filter required |
object |
Filtering that are applied to report.Filter Parameter
|
||||||||
format required |
string |
The format of the report. Available format is CSV . |
||||||||
status required |
string |
The status of the report. The status will be PENDING when you hit generate the report and will change after that.
|
||||||||
url optional |
string |
URL to download after report is completed. The file to download will only be accessible for 24 hours. When the url is expired, you will need to send a new request to generate the report. |
||||||||
currency required |
string |
The currency inside the report. See our supported currencies. |
||||||||
business_id required |
string |
The id of business where this transaction belong to. | ||||||||
created required |
string (ISO 8601 |
The time when the report request is created at UTC+0. | ||||||||
updated required |
string (ISO 8601 |
The time when the report is updated at UTC+0. |
Generate Report
Endpoint: Generate Report
POST https://api.xendit.co/reports
Request this endpoint to generate the report. You can specify the type and filter the content of the report. The flow of this endpoint is asynchronous. It means Xendit will send callbacks to you after the report is done. See report callback for more information. Alternatively, you can use the get report endpoint to get the report status and its detail.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to get this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Example Generate Report Request
curl https://api.xendit.co/reports -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d type=BALANCE_HISTORY \
-d currency=IDR
Example Generate Report Response
{
"id": "report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28",
"type": "BALANCE_HISTORY",
"status": "PENDING",
"filter": {
"from": "2021-06-23T04:01:55.574Z",
"to": "2021-06-24T04:01:55.574Z"
},
"format": "CSV",
"currency": "IDR",
"business_id": "5f34f60535ba7c1c0eed846a",
"created": "2021-06-24T04:01:55.570Z",
"updated": "2021-06-24T04:01:55.570Z"
}
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
type required |
string |
The type of report that will be generated. Available types:
| ||||||||||
filter required |
object |
Filtering that are applied to report. Filter Parameter
The combination of from and to must be less than 31 days. |
||||||||||
format optionaldefault:
|
string |
The format of the report. Available format is CSV . |
||||||||||
currency optionaldefault:
|
string |
The currency to filter. See our supported currencies. |
||||||||||
report_version optional |
string |
Report version indicates which version of report you need. This parameter is only applicable to Transaction Report. Default value: VERSION_0 Version value <> changelog: |
Response Parameters
Return Report Object with status code 201
Error Codes
See other common errors here.
Error Code | Description |
---|---|
FEATURE_NOT_AVAILABLE400 |
During this beta, some of customer may encounter this error. Please contact our customer support to enable this feature. |
INVALID_DATE_RANGE400 |
The from and to filter range is too huge. Please reduce the range according to limit on the request parameter. |
Get Report
Endpoint: Get Report
GET https://api.xendit.co/reports/{report_id}
Request this endpoint to get single specific report details by report id. You can use this endpoint as alternative compared to using the report callback.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to get this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Example Get Report
curl https://api.xendit.co/transactions/report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Example Get Report Response
{
"id": "report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28",
"type": "BALANCE_HISTORY",
"status": "COMPLETED",
"filter": {
"from": "2021-06-23T04:01:55.574Z",
"to": "2021-06-24T04:01:55.574Z"
},
"format": "CSV",
"url": "https://transaction-report-files.s3-us-west-2.amazonaws.com/{report_name}",
"currency": "IDR",
"business_id": "5f34f60535ba7c1c0eed846a",
"created": "2021-06-24T04:01:55.570Z",
"updated": "2021-06-24T04:01:55.570Z"
}
Path Parameter | Type | Description |
---|---|---|
report_id required |
string |
The id of report. |
Response Parameters
Return Report Object with status code 200
Error Codes
See other common errors here.
Error Code | Description |
---|---|
TRANSACTION_NOT_FOUND404 |
Report the id is not found. |
FEATURE_NOT_AVAILABLE400 |
During this beta, some of customer may encounter this error. Please contact our customer support to enable this feature. |
Report Webhook
Endpoint: Report Webhook
POST https://yourcompany.com/report_webhook_url
Xendit notifies your system upon the completed or failed report via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Example Report Webhook Request for Successful Report
curl --include \
--request POST \
--header "x-callback-token: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==" \
--header "Content-Type: application/json" \
--data-binary "{
\"id\": \"report_5c1b34a2-6ceb-4c24-aba9-c836bac82b28\",
\"type\": \"BALANCE_HISTORY\",
\"status\": \"PENDING\",
\"filter\": {
\"from\": \"2021-06-23T04:01:55.574Z\",
\"to\": \"2021-06-24T04:01:55.574Z\"
},
\"format\": \"CSV\",
\"currency\": \"IDR\",
\"business_id\": \"5f34f60535ba7c1c0eed846a\",
\"created\": \"2021-06-24T04:01:55.570Z\",
\"updated\": \"2021-06-24T04:01:55.570Z\"
}}" \
'{{your_company_domain}}/{{webhook_url}}'
Header Parameter | Type | Description |
---|---|---|
x-callback-token |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-id |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
event required |
string |
The type of the event. The available types are:
| ||||||
Report Object |
The rest of parameter is the same as report object. |
Balance History Report
Balance history report is report that show the historical list of balance movements from your accounts. This report is equivalent to Balance Tab on dashboard. You can use this report for checking the daily balance or do reconciliation between your transaction data with the balance that are deducted or added into your account. On the report API you can generate this report by using BALANCE_HISTORY
as a type.
Report Columns
Column | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Product Id | Xendit generated ID which will be sent to you via API callback as ‘id’ | ||||||||||||||||||||||||
Transaction Id | Xendit uniquely generated ID for each transactions and this ID help you identify Fee or Reversal for specific transactions. This ID can be used to reconcile between Balance History Report and Transaction Report. | ||||||||||||||||||||||||
Transaction Type | List of available transaction type
|
||||||||||||||||||||||||
Line Type | List of available line type
|
||||||||||||||||||||||||
Payment Channel | The channel to identify the source of the transaction. See channel codes for more information. |
||||||||||||||||||||||||
Reference | Your generated ID which will be sent to Xendit’s system and will also be available on some product callback as ‘external_id’ | ||||||||||||||||||||||||
Currency | Transaction currency. See our supported currencies. |
||||||||||||||||||||||||
Amount | Nominal amount for the transaction. The number of decimal place will be different for each currency according to ISO 4217. |
||||||||||||||||||||||||
Balance | Your account balance on this transaction. | ||||||||||||||||||||||||
Debit or Credit |
|
||||||||||||||||||||||||
Created Date ISO | Date on when the transaction is created using ISO 8601 format. | ||||||||||||||||||||||||
Timezone | Timezone information formatted as “+XXXX UTC”. The timezone will always be +0000 UTC when report is generated via this API. This is different from Dashboart which will use the user timezone. |
||||||||||||||||||||||||
Created Date | Date on when the transaction is created. | ||||||||||||||||||||||||
Payment Date | Date on when payment is received but not yet settled. This is only available for payment transaction. | ||||||||||||||||||||||||
Settlement Date | Date on when payment is settled. This means the fund is already received and added to your balance. This is only available for payment transaction. | ||||||||||||||||||||||||
Completed Date | Date on when fund has been disbursed to the destination bank account. This is only available for disbursement transaction. | ||||||||||||||||||||||||
Bank Code | The bank channel that are used as source or destination of transaction. This is only available for VA_PAYMENT and DISBURSEMENT . |
||||||||||||||||||||||||
Name | The name of the VA or receiver. This is only available for VA_PAYMENT and DISBURSEMENT . |
||||||||||||||||||||||||
Account Number | The account number of VA or receiver. This is only available for VA_PAYMENT and DISBURSEMENT . |
||||||||||||||||||||||||
Description | The description of transaction | ||||||||||||||||||||||||
Invoice ID | The ID of invoice. This is only available for payment that are paid via invoice. | ||||||||||||||||||||||||
Bank Reference | The bank reference that is used only for DISBUSEMENT transaction |
Transactions Report
Transaction reports are the report that shows all transactions that exist whether it is already deduct the balance or not. This report will not show the non-transaction like topup and withdrawal. This report is equivalent to the Transaction Tab on the dashboard. On the report API you can generate this report by using TRANSACTIONS
as a type.
Report Columns
Column | Description | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Status | The corresponding transaction status
|
||||||||||||||
Type | The corresponding transaction type
|
||||||||||||||
Channel | The channel to identify the source of the transaction. The available channel for each type are:
|
||||||||||||||
Channel Name | Channel name will be different for each channel. See channel codes for more information |
||||||||||||||
Account Number | The account number used for the transaction. The definition of this will be different for each channel. For example, on CARD channel this will be masked card number and on BANK channel it will be account number. |
||||||||||||||
Currency | Transaction currency. See our supported currencies. |
||||||||||||||
Amount | Amount of the transaction. The number of decimal place will be different for each currency according to ISO 4217. |
||||||||||||||
Fee Amount | Amount of the fee for this transaction. | ||||||||||||||
VAT Amount | Amount of the VAT for this transaction. | ||||||||||||||
3rd Party WHT | Amount of the 3rd Party Withholding Tax for this transaction if applicable. | ||||||||||||||
Xendit WHT | Amount of the Xendit Withholding Tax for this transaction if applicable. | ||||||||||||||
Net Amount | Net Amount of transaction after fee/VAT/WHT is included. | ||||||||||||||
Reference | The reference of transaction. This is generated from your side and on some product is known as External Id | ||||||||||||||
Transaction Id | The id of the transaction | Invoice Id | The id of the invoice, if this transaction is payment using invoice | Batch Id | Batch settlement id for credit card transaction | Payment Id | Xendit generated payment id which are equivalent to product Id | Payment Date | The date when the payment is received to Xendit | Timestamp - Created | The timestamp when the transaction is recorded | Timestamp - Updated | The timestamp of the latest update occurring for the transaction | Timestamp - Settled | The timestamp when the transaction is settled to the merchant |
Timezone | Timezone information formatted as “+XXXX UTC”. The timezone will always be +0000 UTC when report is generated via this API. This is different from Dashboart which will use the user timezone. |
||||||||||||||
Description | The description of transaction | ||||||||||||||
Channel Reference | The reference that is generated by our channel partner. This can be used to reconcile between the data from your side, Xendit, and our partner. |
Transactions
An API to search and view transactions. The transactions include money in, money out, and transfer that happens within your account. You can use this single endpoint to get the status of a transaction and do reconciliation. This API is equivalent to the transactions tab from dashboard. See our docs of how to use transaction tab for reconciliation.
Transaction Object
Transaction Object Example
{
"id": "txn_13dd178d-41fa-40b7-8fd3-f83675d6f413",
"product_id": "d290f1ee-6c54-4b01-90e6-d701748f0701",
"type": "PAYMENT",
"channel_category": "RETAIL_OUTLET",
"channel_code": "ALFAMART",
"reference_id": "ref23232",
"account_identifier": null,
"currency": "IDR",
"amount": 500000,
"cashflow": "MONEY_IN",
"status": "SUCCESS",
"business_id": "5fc9f5b246f820517e38c84d",
"created": "2021-06-23T02:42:15.601Z",
"updated": "2021-06-23T02:42:15.601Z",
"fee":{
"xendit_fee": 1500,
"value_added_tax": 500,
"xendit_withholding_tax": 0,
"third_party_withholding_tax": 0,
"status": "COMPLETED"
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id required |
string |
The unique id of transaction. It will have txn_ as prefix |
||||||||||||||||||||||
product_id required |
string |
The product_id of transaction. Product id will have different prefix for each different product. You can use this id to match the transaction from this API to each product API. | ||||||||||||||||||||||
type required |
string |
The type of the transactions. Available types:
| ||||||||||||||||||||||
channel_code optional |
string |
The channel of the transaction that is used. See channel codes for the list of available per channel categories. |
reference_id required |
string |
The reference of transaction. On some product, the term reference is the same as external_id . This is the id that you generate that can be used for reconciliation. |
account_identifier optional |
string |
Account identifier of transaction. The format will be different from each channel. For example, on BANK channel it will be account number and on CARD it will be masked card number. |
currency optional |
string (ISO 4217) |
Currency of transaction. See our supported currencies. |
amount required |
number |
The amount of transaction. The number of decimal place will be different for each currency according to ISO 4217. |
net_amount required |
number |
The net amount of transaction after it deducted with fee/vat. | cashflow required |
string |
Representing whether the transaction is money in or money out For transfer, the transfer out side it will shows up as money out and on transfer in side in will shows up as money-in. Available values are MONEY_IN for money in and MONEY_OUT for money out. |
||||
status required |
string |
The status of the transaction. Available status:
| channel_category required |
string |
The channel category of the transaction to identify the source of the transaction. The available channel for each type are:
|
|||||||||||||||||||
business_id required |
string |
The id of business where this transaction belong to | ||||||||||||||||||||||
created required |
string (ISO 8601) |
Transaction created timestamp on UTC+0 | ||||||||||||||||||||||
updated required |
string (ISO 8601) |
Transaction updated timestamp on UTC+0 | ||||||||||||||||||||||
fee required |
object |
| ||||||||||||||||||||||
settlement_status optional |
string |
|
||||||||||||||||||||||
estimated_settlement_time optional |
string (ISO 8601) |
Estimated settlement time will only apply to money-in transactions. For money-out transaction, value will be NULL Estimated settlement time in which transaction amount will be settled to merchant's balance. example: "2022-04-26T08:44:39.566Z" |
Get Transaction
Endpoint: Get Transaction
GET https://api.xendit.co/transactions/{transaction_id}
Request this endpoint to get single specific transaction details by transaction id. If you need to search by other parameters or to get multiple result, see list transactions.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to get this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Example Get Transaction Request
curl https://api.xendit.co/transactions/txn_13dd178d-41fa-40b7-8fd3-f83675d6f413 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Example Get Transaction Response
{
"id": "txn_13dd178d-41fa-40b7-8fd3-f83675d6f413",
"product_id": "d290f1ee-6c54-4b01-90e6-d701748f0701",
"type": "PAYMENT",
"status": "SUCCESS",
"channel_category": "RETAIL_OUTLET",
"channel_code": "ALFAMART",
"reference_id": "ref23232",
"account_identifier": null,
"currency": "IDR",
"amount": 1,
"cashflow": "MONEY_IN",
"business_id": "5fc9f5b246f820517e38c84d",
"created": "2021-06-23T02:42:15.601Z",
"updated": "2021-06-23T02:42:15.601Z"
}
Path Parameter | Type | Description |
---|---|---|
transaction_id required |
string |
The id of transaction. |
Response Parameters
Returns Transaction Object with status code 200
Error Codes
See other common errors here.
Error Code | Description |
---|---|
TRANSACTION_NOT_FOUND404 |
Transaction with the id is not found. |
FEATURE_NOT_AVAILABLE400 |
During this beta, some of customer may encounter this error. Please contact our customer support to enable this feature. |
List Transactions
Endpoint: List Transactions
GET https://api.xendit.co/transactions
Request this endpoint to get all transactions or select specific filter and search parameters. You can filter by date, type, or status. And you can search by reference, product id, or account identifier. The returned result will be paginated and ordered by the created date.
Request Parameters
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to get this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Example List Transactions Request
curl https://api.xendit.co/transactions?types=PAYMENT&statuses=SUCCESS&channel_categories=EWALLET&channel_categories=RETAIL_OUTLET&limit=2 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Query Parameter | Type | Description |
---|---|---|
types optional |
array of strings |
The type of the transactions that will be filtered. If not specified, all transaction type will be returned. Available types: DISBURSEMENT : The disbursement of money-out transaction. PAYMENT : The payment that includes all variation of money-in transaction. REMITTANCE_PAYOUT : The remittance pay-out transaction. TRANSFER : The transfer transaction between xendit account. This can be transfer in or out. REFUND : A refund transaction created to refund amount from money-in Transaction. |
statuses optional |
array of strings |
The status of the transactions that will be filtered. If not specified, all transaction status will be returned. Available status: PENDING : The transaction is still pending to be processed. This refers to money out-transaction when the amount is still on hold. SUCCESS : The transaction is successfully sent for money-out or already arrives on money-in. FAILED : The transaction failed to send/receive. VOIDED : The money-in transaction is voided by customer. REVERSED : The transaction is reversed by Xendit. |
channel_categories optional |
array of strings |
The channel of the transactions that will be filtered. If not specified, all transaction channel will be returned. For DISBURSEMENT and REMITTANCE_PAYOUT type, the available channel categories are BANK and CASH . For PAYMENT type, the available channel categories are CARDS , CARDLESS_CREDIT , DIRECT_DEBIT , EWALLET , PAYLATER , QR_CODE , RETAIL_OUTLET , VIRTUAL_ACCOUNT . For TRANSFER type, the available channel category is XENPLATFORM . |
reference_id optional |
string |
Reference that will be searched. Search by reference is case sensitive and can be partial match. |
product_id optional |
string |
Product_id that will be searched. Product_id search is an exact match and case sensitive. |
account_identifier optional |
string |
Account identifier that will be searched. Account identifier search is exact match case sensitive. |
currency optionaldefault:
|
string (ISO 4217) |
Currency to filter. See our supported currencies. |
amount optional |
number |
Transaction amount to search. This will be exact match. |
created[gte] optional |
string (ISO 8601) |
Start time of transaction by created date. If not specified will list all dates. |
created[lte] optional |
string (ISO 8601) |
End time of transaction by created date. If not specified will list all dates. |
updated[lte] optional |
string (ISO 8601) |
End time of transaction by updated date. If not specified will list all dates. |
updated[gte] optional |
string (ISO 8601) |
Start time of transaction by updated date. If not specified will list all dates. |
limit optionaldefault:
|
number |
A limit on the number of transactions to be returned for each request. Limit can range between 1 and 50. |
after_id optional |
string |
Id of the immediately previous item. Use this with links on the response for pagination. |
before_id optional |
string |
Id of the immediately following item. |
Response Parameters
Example List Transactions Response
{
"has_more": true,
"data": [
{
"id": "txn_13dd178d-41fa-40b7-8fd3-f83675d6f413",
"product_id": "d290f1ee-6c54-4b01-90e6-d701748f0701",
"type": "PAYMENT",
"status": "SUCCESS",
"channel_category": "RETAIL_OUTLET",
"channel_code": "ALFAMART",
"reference_id": "ref23244",
"account_identifier": null,
"currency": "IDR",
"amount": 1,
"cashflow": "MONEY_IN",
"business_id": "5fc9f5b246f820517e38c84d",
"created": "2021-06-23T02:42:15.601Z",
"updated": "2021-06-23T02:42:15.601Z"
},
{
"id": "txn_a765a3f0-34c0-41ee-8686-bca11835ebdc",
"product_id": "d290f1ee-6c54-4b01-90e6-d701748f0700",
"type": "PAYMENT",
"status": "SUCCESS",
"channel_category": "RETAIL_OUTLET",
"channel_code": "ALFAMART",
"reference_id": "ref242424",
"account_identifier": null,
"currency": "IDR",
"amount": 1,
"cashflow": "MONEY_IN",
"business_id": "5fc9f5b246f820517e38c84d",
"created": "2021-06-23T02:39:23.176Z",
"updated": "2021-06-23T02:39:23.176Z"
}
],
"links": [
{
"href": "/transactions?types=PAYMENT&statuses=SUCCESS&channel_categories=EWALLET&channel_categories=RETAIL_OUTLET&limit=2&after_id=txn_a765a3f0-34c0-41ee-8686-bca11835ebdc",
"method": "GET",
"rel": "next"
}
]
}
Body Parameter | Type | Description |
---|---|---|
data required |
array of objects |
Returns an array of Transaction Object. Returns empty array when there is no result. |
has_more required |
bolean |
Indicates whether there are more items to be queried with after_id of the last item from the current result. Use the links to follow to the next result. |
links optional |
object |
The links to the next page based on HATEOAS if there is next result. The HATEOAS format are: href : URI of target, this will be to the next link. rel : The relationship between source and target. The value will be next . method : The HTTP method, the alue will be GET . |
Error Codes
See other common errors here.
Error Code | Description |
---|---|
FEATURE_NOT_AVAILABLE400 |
During this beta, some of customer may encounter this error. Please contact our customer support to enable this feature. |
Payments API
Xendit's Payments API is an enhanced interface that enables merchants to integrate seamlessly with our supported money-in payment channels using a single, unified set of APIs. With these APIs, merchants can utilize a uniform endpoint for various payment methods across all supported markets.
Check out Payments API Reference page ⏩ to explore Payments API. We will cover the following details:
- Payments API Introduction
- Payments API Object
- Payments API Endpoints
- Payments Scenario
- Tokenized Payment Scenario
- Link and Pay Payment Scenario
Download "New Payments API" Postman Collection to explore and test our APIs
Supported Channels
E-wallet 🇮🇩 🇵🇭 🇻🇳 🇲🇾
The following channels are supported for payment method type EWALLET
. For more information about e-wallet channels, you may visit our docs page.
COUNTRY
|
CHANNEL NAME
|
CHANNEL CODE
|
ONE TIME USE
|
MULTIPLE USE
|
REFUND
|
---|---|---|---|---|---|
🇮🇩 ID | DANA | DANA | ✅ | ✅ | ❌ |
🇮🇩 ID | LinkAja | LINKAJA | ✅ | ✅ | ✅ |
🇮🇩 ID | OVO | OVO | ✅ | ✅ | ❌ |
🇮🇩 ID | ASTRAPAY | ASTRAPAY | ✅ | ❌ | ❌ |
🇮🇩 ID | JENIUSPAY | JENIUSPAY | ✅ | ❌ | ✅ |
🇮🇩 ID | ShopeePay | SHOPEEPAY | ✅ | ✅ | ✅ |
🇮🇩 ID | NEXCASH | NEXCASH | ✅ | ❌ | ❌ |
🇵🇭 PH | GrabPay | GRABPAY | ✅ | ✅ | ✅ |
🇵🇭 PH | GCash | GCASH | ✅ | ✅ | ✅ |
🇵🇭 PH | Maya (PayMaya) | PAYMAYA | ✅ | ✅ | ✅ |
🇵🇭 PH | ShopeePay | SHOPEEPAY | ✅ | ✅ | ✅ |
🇻🇳 VN | Appota | APPOTA | ✅ | ❌ | ✅ |
🇻🇳 VN | MOMO | MOMO | ✅ | ❌ | ✅ |
🇻🇳 VN | ZaloPay | ZALOPAY | ✅ | ❌ | ✅ |
🇻🇳 VN | VNPTWALLET | VNPTWALLET | ✅ | ❌ | ✅ |
🇻🇳 VN | ShopeePay | SHOPEEPAY | ✅ | ❌ | ✅ |
🇻🇳 VN | ViettelPay | VIETTELPAY | ✅ | ❌ | ❌ |
🇹🇭 TH | WechatPay | WECHATPAY | ✅ | ❌ | ❌ |
🇹🇭 TH | LINE Pay | LINEPAY | ✅ | ❌ | ❌ |
🇹🇭 TH | ShopeePay | SHOPEEPAY | ✅ | ❌ | ❌ |
🇹🇭 TH | TrueMoney | TRUEMONEY | ✅ | ❌ | ❌ |
🇲🇾 MY | Touch n Go | TOUCHNGO | ✅ | ✅ | ✅ |
🇲🇾 MY | ShopeePay | SHOPEEPAY | ✅ | ✅ | ✅ |
🇲🇾 MY | GrabPay | GRABPAY | ✅ | ✅ | ✅ |
🇲🇾 MY | WechatPay | WECHATPAY | ✅ | ❌ | ✅ |
Direct Debit 🇲🇨 🇵🇭 🇹🇭 🇲🇾
The following channels are supported for payment method type DIRECT_DEBIT
. You may visit our docs page for more information about direct debit channels.
COUNTRY
|
CHANNEL NAME
|
CHANNEL CODE
|
ONE TIME USE
|
MULTIPLE USE
|
REFUND
|
---|---|---|---|---|---|
🇲🇨 ID | BRI | BRI | ✅ | ✅ | ✅ |
🇲🇨 ID | MANDIRI | MANDIRI | ✅ | ✅ | ❌ |
🇵🇭 PH | BPI | BPI | ✅ | ✅ | ✅ |
🇵🇭 PH | RCBC | RCBC | ✅ | ✅ | ✅ |
🇵🇭 PH | Unionbank | UBP | ✅ | ✅ | ✅ |
🇵🇭 PH | Chinabank | CHINABANK | ✅ | ✅ | ✅ |
🇵🇭 PH | BDO EPAY | BDO_EPAY | ✅ | ✅ | ❌ |
🇹🇭 TH | Siam Commercial Bank | SCB | ✅ | ✅ | ❌ |
🇹🇭 TH | Krungthai Bank | KTB | ✅ | ✅ | ❌ |
🇹🇭 TH | Bangkok Bank | BBL | ✅ | ✅ | ❌ |
🇹🇭 TH | Bank of Ayudhya | BAY | ✅ | ✅ | ❌ |
🇹🇭 TH | K-Bank | KBANK_MB | ✅ | ❌ | ❌ |
🇹🇭 TH | Bank of Ayudhya | BAY_MB | ✅ | ❌ | ❌ |
🇹🇭 TH | Krungthai Bank | KTB_MB | ✅ | ❌ | ❌ |
🇹🇭 TH | Siam Commercial Bank | SCB_MB | ✅ | ❌ | ❌ |
🇹🇭 TH | Bangkok Bank | BBL_MB | ✅ | ❌ | ❌ |
🇲🇾 MY | AFFIN | AFFIN_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | AGRO | AGRO_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | ALLIANCE | ALLIANCE_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | AMBANK | AMBANK_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | ISLAM | ISLAM_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | MUAMALAT | MUAMALAT_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | BOC | BOC_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | RAKYAT | RAKYAT_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | BSN | BSN_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | CIMB | CIMB_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | HLB | HLB_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | HSBC | HSBC_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | KFH | KFH_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | MAYB2E | MAYB2E_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | MAYB2U | MAYB2U_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | OCBC | OCBC_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | PUBLIC | PUBLIC_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | RHB | RHB_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | SCH | SCH_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | UOB | UOB_FPX | ✅ | ❌ | ❌ |
🇲🇾 MY | Affin Bank B2B | AFFIN_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | AGRONetBIZ | AGRO_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | Alliance Bank (Business) | ALLIANCE_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | AmBank | AMBANK_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | Bank Islam | ISLAM_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | Bank Muamalat | MUAMALAT_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | BNP Paribas | BNP_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | CIMB Bank | CIMB_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | Citibank Corporate Banking | CITIBANK_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | Deutsche Bank | DEUTSCHE_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | Hong Leong Bank | HLB_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | HSBC Bank | HSBC_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | i-bizRAKYAT | RAKYAT_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | KFH | KFH_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | Maybank2E | MAYB2E_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | OCBC Bank | OCBC_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | Public Bank PB enterprise | PUBLIC_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | RHB Bank | RHB_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | Standard Chartered | SCH_FPX_BUSINESS | ✅ | ❌ | ❌ |
🇲🇾 MY | UOB Regional | UOB_FPX_BUSINESS | ✅ | ❌ | ❌ |
Over-the-Counter/Retail Outlet 🇲🇨 🇵🇭
The following channels are supported for payment method type OVER_THE_COUNTER
. You may visit our docs page for more information about over-the-counter or retail outlet channels.
COUNTRY
|
CHANNEL NAME
|
CHANNEL CODE
|
ONE TIME USE
|
MULTIPLE USE
|
REFUND
|
---|---|---|---|---|---|
🇲🇨 ID | Alfamart | ALFAMART | ✅ | ✅ | ❌ |
🇲🇨 ID | Indomaret | INDOMARET | ✅ | ✅ | ❌ |
🇵🇭 PH | 7-Eleven via 7-Connect Code | 7ELEVEN | ✅ | ❌ | ❌ |
🇵🇭 PH | 7-Eleven via CliQQ | 7ELEVEN_CLIQQ | ✅ | ✅ | ❌ |
🇵🇭 PH | Cebuana Lhuillier | CEBUANA | ✅ | ✅ | ❌ |
🇵🇭 PH | ECPay | ECPAY | ✅ | ✅ | ❌ |
🇵🇭 PH | Palawan Express | PALAWAN | ✅ | ✅ | ❌ |
🇵🇭 PH | MLhuillier | MLHUILLIER | ✅ | ✅ | ❌ |
🇵🇭 PH | ECPay via Dragonloan¹ | ECPAY_DRAGONLOAN | ✅ | ✅ | ❌ |
🇵🇭 PH | LBC | LBC | ✅ | ✅ | ❌ |
🇵🇭 PH | RD_PAWNSHOP | RD_PAWNSHOP | ✅ | ✅ | ❌ |
🇵🇭 PH | CVM | CVM | ✅ | ✅ | ❌ |
🇵🇭 PH | ECPAY_SCHOOL | ECPAY_SCHOOL | ✅ | ✅ | ❌ |
🇵🇭 PH | USSC | USSC | ✅ | ✅ | ❌ |
🇵🇭 PH | SM_BILLS | SM_BILLS | ✅ | ✅ | ❌ |
🇵🇭 PH | ROBINSONS_BILLS | ROBINSONS_BILLS | ✅ | ✅ | ❌ |
Virtual Account 🇲🇨 🇻🇳 🇹🇭 🇵🇭 🇲🇾
The following channels are supported for payment method type VIRTUAL_ACCOUNT
. For more information about virtual accounts, you may visit our docs page.
COUNTRY
|
CHANNEL NAME
|
CHANNEL CODE
|
ONE TIME USE
|
MULTIPLE USE
|
REFUND
|
---|---|---|---|---|---|
🇲🇨 ID | BCA | BCA | ✅ | ✅ | ❌ |
🇲🇨 ID | BJB | BJB | ✅ | ✅ | ❌ |
🇲🇨 ID | BNI | BNI | ✅ | ✅ | ❌ |
🇲🇨 ID | BRI | BRI | ✅ | ✅ | ❌ |
🇲🇨 ID | BSI | BSI | ✅ | ✅ | ❌ |
🇲🇨 ID | BSS (BANK SAHABAT SAMPOERNA) | BSS (BANK SAHABAT SAMPOERNA) | ✅ | ✅ | ❌ |
🇲🇨 ID | CIMB | CIMB | ✅ | ✅ | ❌ |
🇲🇨 ID | MANDIRI | MANDIRI | ✅ | ✅ | ❌ |
🇲🇨 ID | PERMATA | PERMATA | ✅ | ✅ | ❌ |
🇻🇳 VN | PV | PV | ✅ | ✅ | ❌ |
🇻🇳 VN | VIET CAPITAL | VIETCAPITAL | ✅ | ✅ | ❌ |
🇻🇳 VN | WOORI | WOORI | ✅ | ✅ | ❌ |
🇻🇳 VN | MSB | MSB | ✅ | ✅ | ❌ |
🇻🇳 VN | VPB | VPB | ✅ | ✅ | ❌ |
🇻🇳 VN | BIDV | BIDV | ✅ | ✅ | ❌ |
🇹🇭 TH | STANDARD CHARTERED | STANDARD_CHARTERED | ❌ | ✅ | ❌ |
🇵🇭 PH | INSTAPAY / PESONET | BANK_TRANSFER | ❌ | ✅ | ❌ |
🇲🇾 MY | UOB | UOB | ❌ | ✅ | ❌ |
🇲🇾 MY | AMBANK | AMBANK | ❌ | ✅ | ❌ |
QR Code 🇮🇩 🇹🇭
The following channels are supported for payment method type QR_CODE
. You may visit our docs page for more information about QR Code payments.
COUNTRY
|
CHANNEL NAME
|
CHANNEL CODE
|
ONE TIME USE
|
MULTIPLE USE
|
REFUND
|
---|---|---|---|---|---|
🇮🇩 ID | DANA (QRIS) | DANA | ✅ | ✅ | ✅ |
🇮🇩 ID | Linkaja (QRIS) | LINKAJA | ✅ | ✅ | ❌ |
🇹🇭 TH | PromptPay | PROMPTPAY | ✅ | ❌ | ❌ |
🇵🇭 PH | QRPH | QRPH | ✅ | ❌ | ❌ |
Supported Issuers for QR Code Refunds
COUNTRY
|
ISSUER
|
FULL AMOUNT (WITHIN 24 HOURS)
|
FULL AMOUNT (AFTER 24 HOURS)
|
PARTIAL AMOUNT
|
---|---|---|---|---|
🇮🇩 ID | DANA | ✅ | ✅ | ✅ |
🇮🇩 ID | ShopeePay | ✅ | ✅ | ✅ |
🇮🇩 ID | OVO | ✅ | ✅ | ❌ |
🇮🇩 ID | LinkAja | ✅ | ✅ | ❌ |
🇮🇩 ID | Mandiri | ✅ | ❌ | ❌ |
🇮🇩 ID | Permata | ✅ | ✅ | ✅ |
🇮🇩 ID | CIMB | ✅ | ✅ | ❌ |
🇮🇩 ID | Jenius / BTPN | ✅ | ✅ | ✅ |
🇮🇩 ID | BSI | ✅ | ✅ | ✅ |
Card 🇮🇩 🇵🇭
The following channels are supported for payment method type CARD
. You may visit our docs page for more information about Card payments.
Country
|
Currencies
|
ONE TIME USE
|
MULTIPLE USE
|
REFUND
|
---|---|---|---|---|
🇮🇩 ID | Indonesian Rupiah (IDR) | ✅ | ✅ | ✅ |
🇵🇭 PH | Philippines Peso (PHP) United States Dollar (USD) |
✅ | ✅ | ✅ |
BI SNAP
Our BI SNAP API allows you to charge and receive payments compliantly in Indonesia. BI SNAP is used for Indonesian merchants collecting payments from Ewallets, QRIS and Bank payment methods in Indonesia.
Create Account Binding
Endpoint: Create Account Binding Request
POST https://api.xendit.co/snap/v1.0/registration-account-binding
SNAP Account Binding
This API will be used to create a account binding without doing a payment. Account binding returns a token that can be used for subsequent payments.
Request Parameters
Example: Create Account Binding Request
curl https://api.xendit.co//snap/v1.0/registration-account-binding -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"partnerReferenceNo": "371d8a6e-587c-4789-bea5-fac4319b2409",
"phoneNo": "+628123123123",
"additionalData": {
"userId": "fc4c060b-3c41-4707-b7b2-df9c3376edde"
},
"additionalInfo": {
"payMethod": "EWALLET",
"payOption": "OVO",
"reusability": "ONE_TIME_USE",
"metadata": {
"sku": "ABCDEFGH"
}
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
Body Parameter | Type | Description | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
partnerReferenceNooptional |
string |
Transaction identifier on service consumer system | |||||||||||||||||||||||||||||
additionalDataconditionally required |
object |
Channel specific information required for the transaction to be initiated Conditional for BRI
|
|||||||||||||||||||||||||||||
merchantIdoptional |
string |
Xendit-generated identifier for the business that owns the transaction. This field is ignored by Xendit | |||||||||||||||||||||||||||||
phoneNooptional |
string |
Registered mobile number of the end-customer to the channel partner in E.164 Format. Mandatory for: OVO (ONE_TIME_USE) BRI | |||||||||||||||||||||||||||||
additionalInforequired |
object |
Additional information required to complete the transaction Object parameters details
|
Response Parameters
Example: Create Account Binding Request API Success Response
{
"responseCode": "2020700",
"responseMessage": "Request In Progress",
"referenceNo": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"partnerReferenceNo": "371d8a6e-587c-4789-bea5-fac4319b2409",
"additionalInfo": {
"paymentMethod": {
"id": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "EWALLET",
"reusability": "ONE_TIME_USE",
"customerId": "fc4c060b-3c41-4707-b7b2-df9c3376edde",
"businessId": "5f27a14a9bf05c73dd040bc8",
"status": "PENDING",
"country": "ID",
"ewallet": {
"channelCode": "OVO",
"channelProperties": {
"mobileNumber": "+628123123123"
},
"account": {
"accountDetails": null,
"name": null,
"balance": null,
"pointBalance": null
}
},
"referenceId": "371d8a6e-587c-4789-bea5-fac4319b2409",
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "ABCDEFGH"
}
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||||||||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||||||||||||||||||||||||||
referenceNorequired |
string |
Unique identifier for the payment method. This has a prefix of pm- | ||||||||||||||||||||||||||||||||||||||||||||
partnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. | ||||||||||||||||||||||||||||||||||||||||||||
nextActionoptional |
string |
URL to authentication page. | ||||||||||||||||||||||||||||||||||||||||||||
paramsoptional |
object |
Object parameters details
|
||||||||||||||||||||||||||||||||||||||||||||
userInfooptional |
object |
Object parameters details
|
||||||||||||||||||||||||||||||||||||||||||||
additionalInforequired |
object |
Payment method object details
|
Error Codes
Example: Create Binding Request API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4000700 | Generic parsing error |
400 | 4000701 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4000702 | Missing mandatory field or header |
401 | 4010700 | Generic authorization error |
401 | 4010701 | The provided Authorization bearer token is invalid |
403 | 4010701 | The merchant is not allowed to perform this request |
403 | 4010715 | Generic forbidden error |
403 | 4010723 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4090700 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4090701 | An object with the same reference already exists |
Inquire Account Binding Status
Endpoint: Inquire Account Binding Status
POST https://api.xendit.co/snap/v1.0/registration-account-inquiry
Request Parameters
Example: Inquire Account Binding Status
curl https://api.xendit.co/snap/v1.0/registration-account-inquiry -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"partnerReferenceNo": "371d8a6e-587c-4789-bea5-fac4319b2409"
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
Body Parameter | Type | Description |
---|---|---|
partnerReferenceNooptional |
string |
Transaction identifier on service consumer system |
Response Parameters
Example: Inquire Account Binding Status API Success Response
{
"responseCode": "2000800",
"responseMessage": "Successful",
"referenceNo": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"partnerReferenceNo": "371d8a6e-587c-4789-bea5-fac4319b2409",
"accountCurrency": "IDR",
"additionalInfo": {
"paymentMethod": {
"id": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "DIRECT_DEBIT",
"reusability": "MULTIPLE_USE",
"customerId": "fc4c060b-3c41-4707-b7b2-df9c3376edde",
"businessId": "5f27a14a9bf05c73dd040bc8",
"status": "REQUIRES_ACTION",
"country": "ID",
"actions": [
{
"action": "AUTH",
"urlType": "API",
"url": "https://api.xendit.co/payment_methods/d0860b92-a72e-41ff-a758-33850a6f8683/auth",
"method": "POST"
}
],
"directDebit": {
"channelCode": "BRI",
"type": "DEBIT_CARD",
"channelProperties": {
"mobileNumber": "+62818555988",
"cardLastFour": "8888",
"cardExpiry": "06/24",
"email": "test.email@xendit.co"
},
"debitCard": {
"mobileNumber": "+62818555988",
"cardLastFour": "8888",
"cardExpiry": "06/24",
"email": "test.email@xendit.co"
},
"bankAccount": null
},
"referenceId": "371d8a6e-587c-4789-bea5-fac4319b2409",
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "ABCDEFGH"
}
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||||||||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||||||||||||||||||||||||||
referenceNooptional |
string |
Unique identifier for the payment method. This has a prefix of pm- | ||||||||||||||||||||||||||||||||||||||||||||
partnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. | ||||||||||||||||||||||||||||||||||||||||||||
accountCurrencyrequired |
string |
Always set to 'IDR'. | ||||||||||||||||||||||||||||||||||||||||||||
accountNameoptional |
string |
Registered account name. | ||||||||||||||||||||||||||||||||||||||||||||
additionalInforequired |
object |
Payment method object details
|
Error Codes
Example: Inquire Binding Request API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4000800 | Generic parsing error |
400 | 4000801 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4000802 | Missing mandatory field or header |
401 | 4010800 | Generic authorization error |
401 | 4010801 | The provided Authorization bearer token is invalid |
403 | 4010801 | The merchant is not allowed to perform this request |
403 | 4010815 | Generic forbidden error |
403 | 4010823 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4090800 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4090801 | An object with the same reference already exists |
Unbind Account
Endpoint: Unbind Account
POST https://api.xendit.co/snap/v1.0/registration-account-unbinding
Request Parameters
Example: Unbind Account
curl https://api.xendit.co/snap/v1.0/registration-account-inquiry -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"partnerReferenceNo": "371d8a6e-587c-4789-bea5-fac4319b2409"
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
Body Parameter | Type | Description |
---|---|---|
partnerReferenceNooptional |
string |
Transaction identifier on service consumer system |
Response Parameters
Example: Unbind Account API Success Response
{
"responseCode": "2000800",
"responseMessage": "Successful",
"referenceNo": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"partnerReferenceNo": "371d8a6e-587c-4789-bea5-fac4319b2409",
"accountCurrency": "IDR",
"additionalInfo": {
"paymentMethod": {
"id": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "DIRECT_DEBIT",
"reusability": "MULTIPLE_USE",
"customerId": "fc4c060b-3c41-4707-b7b2-df9c3376edde",
"businessId": "5f27a14a9bf05c73dd040bc8",
"status": "INACTIVE",
"country": "ID",
"actions": [
{
"action": "AUTH",
"urlType": "API",
"url": "https://api.xendit.co/payment_methods/d0860b92-a72e-41ff-a758-33850a6f8683/auth",
"method": "POST"
}
],
"directDebit": {
"channelCode": "BRI",
"type": "DEBIT_CARD",
"channelProperties": {
"mobileNumber": "+62818555988",
"cardLastFour": "8888",
"cardExpiry": "06/24",
"email": "test.email@xendit.co"
},
"debitCard": {
"mobileNumber": "+62818555988",
"cardLastFour": "8888",
"cardExpiry": "06/24",
"email": "test.email@xendit.co"
},
"bankAccount": null
},
"referenceId": "371d8a6e-587c-4789-bea5-fac4319b2409",
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "ABCDEFGH"
}
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||||||||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||||||||||||||||||||||||||
referenceNooptional |
string |
Unique identifier for the payment method. This has a prefix of pm- | ||||||||||||||||||||||||||||||||||||||||||||
partnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. | ||||||||||||||||||||||||||||||||||||||||||||
accountCurrencyrequired |
string |
Always set to 'IDR'. | ||||||||||||||||||||||||||||||||||||||||||||
accountNameoptional |
string |
Registered account name. | ||||||||||||||||||||||||||||||||||||||||||||
additionalInforequired |
object |
Payment method object details
|
Error Codes
Example: Cancel Binding Request API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4000800 | Generic parsing error |
400 | 4000801 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4000802 | Missing mandatory field or header |
401 | 4010800 | Generic authorization error |
401 | 4010801 | The provided Authorization bearer token is invalid |
403 | 4010801 | The merchant is not allowed to perform this request |
403 | 4010815 | Generic forbidden error |
403 | 4010823 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4090800 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4090801 | An object with the same reference already exists |
OTP Verify Account Binding
Endpoint: OTP Verify Account Binding
POST https://api.xendit.co/snap/v1.0/otp-verification
Request Parameters
Example: OTP Verify Account Binding
curl https://api.xendit.co/snap/v1.0/registration-account-inquiry -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"originalReferenceNo": "pm-bc9faa22-23e5-486e-bfee-869c46d32cc3",
"otp": "123456",
"type": "binding"
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
Body Parameter | Type | Description |
---|---|---|
originalReferenceNorequired |
string |
Xendit Generated ID for the payment method |
otprequired |
string |
The authorization code or OTP inputted by the end customer |
typerequired |
string |
Must be set to 'binding' |
Response Parameters
Example: Inquire Account Binding Status API Success Response
{
"responseCode": "2000400",
"responseMessage": "Successful",
"originalReferenceNo": "pm-bc9faa22-23e5-486e-bfee-869c46d32cc3",
"originalPartnerReferenceNo": "0f38e017-007f-4134-9e5d-86657ec0cf77"
}
Body Parameter | Type | Description |
---|---|---|
responseCoderequired |
string |
Response code |
responseMessagerequired |
string |
Response description |
originalReferenceNooptional |
string |
Unique identifier for the payment method. Prefix will vary according to the payment method used. |
originalPartnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. Will be extended to the actual payment transactions. |
customerIdoptional |
string |
Xendit-generated identifier for the end-customer. |
Error Codes
Example: Validate Binding Request API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4000400 | Generic parsing error |
400 | 4000401 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4000402 | Missing mandatory field or header |
401 | 4010400 | Generic authorization error |
401 | 4010401 | The provided Authorization bearer token is invalid |
403 | 4010401 | The merchant is not allowed to perform this request |
403 | 4010415 | Generic forbidden error |
403 | 4010423 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4090400 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4090401 | An object with the same reference already exists |
VA - Create
Endpoint: Create VA Request
POST https://api.xendit.co/snap/v1.0/transfer-va/create-va
SNAP Create Virtual Account
This API will be used to create a new Virtual Account (Service code: 27)
Request Parameters
Example: Create Virtual Account Request
curl https://api.xendit.co/snap/v1.0/transfer-va/create-va -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"virtualAccountName": "John Doe",
"trxId": "12349876",
"totalAmount": {
"value": "10000.00",
"currency": "IDR"
},
"freeTexts": [
{
"english": "Please pay for service"
}
],
"expiredDate": "2020-12-31T23:59:59-07:00",
"additionalInfo": {
"channelCode": "MANDIRI",
"reusability": "ONE_TIME_USE"
}
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
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. |
WITH-SPLIT-RULEoptional |
string |
Split Rule ID that you would like to apply to this charge. This header is only used if you are a xenPlatform user. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account. |
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
partnerServiceIdoptional |
string |
This field is ignored by Xendit. | ||||||||||
customerNooptional |
string |
This field is ignored by Xendit. | ||||||||||
virtualAccountNooptional |
string |
You can assign specific Virtual Account number using this parameter. If you do not send one, one will be picked at random. Make sure the number you specify is within your Virtual Account range and don't include the merchant code as prefix. | ||||||||||
virtualAccountNamerequired |
string |
Complete name of the payor. May be used by the channel partner to verify their identity. Characters Only alphabet. For BCA Aggregator, alphabet and number are allowed. Minimum length 1 character, except BCA the minimum length is 3 characters. |
||||||||||
trxIdrequired |
string |
Merchant-provided identifier for this specific transaction. Please note that this field needs to be unique for each Virtual Account. | ||||||||||
totalAmountconditionally required |
object |
Expected amount of the transaction in the actual value in the provided currency. Can be left blank for Open Virtual Account amounts. Conditional for Closed Virtual amounts
|
||||||||||
freeTextsoptional |
array of object |
Xendit will concatenate all text entries in this section to form the Virtual Account description. Free text objects
|
||||||||||
expiredDateoptional |
string |
ISO-8601 Expiration date for Virtual Account. Example: 2023-12-12T23:59:59+07:00. The default expiration date will be 31 years from creation date | ||||||||||
additionalInforequired |
object |
Additional information required to complete the transaction Object parameters details
|
Response Parameters
Example: Create Virtual Account Request API Success Response
{
"responseCode": "2002700",
"responseMessage": "Success",
"virtualAccountData": {
"partnerServiceId": "123459",
"customerNo": "99993701870",
"virtualAccountNo": "1234599993701870",
"virtualAccountName": "John Doe",
"trxId": "12349876",
"expiredDate": "2023-12-31T23:59:59.000Z",
"additionalInfo": {
"id": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"status": "ACTIVE",
"reusability": "MULTIPLE_USE",
"channelCode": "BRI"
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
virtualAccountDataoptional |
object |
Only for successful responses
|
Error Codes
Example: Create Virtual Account Request API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4002700 | Generic parsing error |
400 | 4002701 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4002702 | Missing mandatory field or header |
401 | 4012700 | Generic authorization error |
401 | 4012701 | The provided Authorization bearer token is invalid |
403 | 4012701 | The merchant is not allowed to perform this request |
403 | 4012715 | Generic forbidden error |
403 | 4012723 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4092700 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4092701 | An object with the same reference already exists |
VA - Inquire Status
Endpoint: Inquire VA Request Status
POST https://api.xendit.co/snap/v1.0/transfer-va/inquiry-va
SNAP Inquire Virtual Account Status
Inquire on the status of an existing Virtual Account. (Service code: 30)
Request Parameters
Example: Inquire Virtual Account Request Status
curl https://api.xendit.co/snap/v1.0/transfer-va/inquiry-va -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"trxId": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39"
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
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. |
WITH-SPLIT-RULEoptional |
string |
Split Rule ID that you would like to apply to this charge. This header is only used if you are a xenPlatform user. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account. |
Body Parameter | Type | Description |
---|---|---|
partnerServiceIdoptional |
string |
This field is ignored by Xendit. |
customerNooptional |
string |
This field is ignored by Xendit. |
virtualAccountNooptional |
string |
This field is ignored by Xendit. |
trxIdrequired |
string |
Merchant-provided identifier for this specific transaction. Please note that this field needs to be unique for each Virtual Account. |
Response Parameters
Example: Create Virtual Account Request API Success Response
{
"responseCode": "2002700",
"responseMessage": "Success",
"virtualAccountData": {
"partnerServiceId": "123459",
"customerNo": "99993701870",
"virtualAccountNo": "1234599993701870",
"virtualAccountName": "John Doe",
"trxId": "12349876",
"expiredDate": "2023-12-31T23:59:59.000Z",
"additionalInfo": {
"id": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"status": "ACTIVE",
"reusability": "MULTIPLE_USE",
"channelCode": "BRI"
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
virtualAccountDataoptional |
object |
Only for successful responses
|
Error Codes
Example: Inquire Virtual Account Request API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4003000 | Generic parsing error |
400 | 4003001 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4003002 | Missing mandatory field or header |
401 | 4013000 | Generic authorization error |
401 | 4013001 | The provided Authorization bearer token is invalid |
403 | 4013001 | The merchant is not allowed to perform this request |
403 | 4013015 | Generic forbidden error |
403 | 4013023 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4093000 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4093001 | An object with the same reference already exists |
VA - Update
Endpoint: Update VA Request
POST https://api.xendit.co/snap/v1.0/transfer-va/update-va
SNAP Update Virtual Account
Update an existing Virtual Account. Please also note that closed VAs can not be changed to open VAs and vice versa. (Service code: 28)
Request Parameters
Example: Update Virtual Account Request
curl https://api.xendit.co/snap/v1.0/transfer-va/update-va -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"virtualAccountName": "John Doe",
"totalAmount": {
"value": "10000.00",
"currency": "IDR"
},
"freeTexts": [
{
"english": "Please pay for service"
}
],
"expiredDate": "2020-12-31T23:59:59-07:00"
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
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. |
WITH-SPLIT-RULEoptional |
string |
Split Rule ID that you would like to apply to this charge. This header is only used if you are a xenPlatform user. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account. |
Body Parameter | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
partnerServiceIdoptional |
string |
This field is ignored by Xendit. | ||||||
customerNooptional |
string |
This field is ignored by Xendit. | ||||||
virtualAccountNamerequired |
string |
Complete name of the payor. May be used by the channel partner to verify their identity. Characters Only alphabet. For BCA Aggregator, alphabet and number are allowed. Minimum length 1 character, except BCA the minimum length is 3 characters. |
||||||
totalAmountconditionally required |
object |
Expected amount of the transaction in the actual value in the provided currency. Can be left blank for Open Virtual Account amounts. Conditional for Closed Virtual amounts
|
||||||
freeTextsoptional |
array of object |
Xendit will concatenate all text entries in this section to form the Virtual Account description. Free text objects
|
||||||
expiredDateoptional |
string |
ISO-8601 Expiration date for Virtual Account. Example: 2023-12-12T23:59:59+07:00. The default expiration date will be 31 years from creation date | ||||||
additionalInforequired |
object |
Additional information required to complete the transaction Object parameters details
|
Response Parameters
Example: Update Virtual Account Request API Success Response
{
"responseCode": "2002700",
"responseMessage": "Success",
"virtualAccountData": {
"partnerServiceId": "123459",
"customerNo": "99993701870",
"virtualAccountNo": "1234599993701870",
"virtualAccountName": "John Doe",
"trxId": "12349876",
"expiredDate": "2023-12-31T23:59:59.000Z",
"additionalInfo": {
"id": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"status": "ACTIVE",
"reusability": "MULTIPLE_USE",
"channelCode": "BRI"
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
virtualAccountDataoptional |
object |
Only for successful responses
|
Error Codes
Example: Update Virtual Account Request API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4002800 | Generic parsing error |
400 | 4002801 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4002802 | Missing mandatory field or header |
401 | 4012800 | Generic authorization error |
401 | 4012801 | The provided Authorization bearer token is invalid |
403 | 4012801 | The merchant is not allowed to perform this request |
403 | 4012815 | Generic forbidden error |
403 | 4012823 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4092800 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4092801 | An object with the same reference already exists |
VA - Deactivate
Endpoint: Deactivate VA Request
POST https://api.xendit.co/snap/v1.0/transfer-va/delete-va
SNAP Deactivate Virtual Account
Deactivate an existing Virtual Account. (Service code: 31)
Request Parameters
Example: Inquire Virtual Account Request Status
curl https://api.xendit.co/snap/v1.0/transfer-va/delete-va -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"trxId": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39"
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
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. |
WITH-SPLIT-RULEoptional |
string |
Split Rule ID that you would like to apply to this charge. This header is only used if you are a xenPlatform user. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account. |
Body Parameter | Type | Description |
---|---|---|
partnerServiceIdoptional |
string |
This field is ignored by Xendit. |
customerNooptional |
string |
This field is ignored by Xendit. |
virtualAccountNooptional |
string |
This field is ignored by Xendit. |
trxIdrequired |
string |
Merchant-provided identifier for this specific transaction. Please note that this field needs to be unique for each Virtual Account. |
Response Parameters
Example: Create Virtual Account Request API Success Response
{
"responseCode": "2003100",
"responseMessage": "Success",
"virtualAccountData": {
"partnerServiceId": "123459",
"customerNo": "99993701870",
"virtualAccountNo": "1234599993701870",
"virtualAccountName": "John doe",
"trxId": "12349876",
"expiredDate": "2020-12-31T23:59:59-07:00",
"additionalInfo": {
"channelCode": "BRI",
"id": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"status": "EXPIRED"
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
virtualAccountDataoptional |
object |
Only for successful responses
|
Error Codes
Example: Deactivate Virtual Account Request API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4003100 | Generic parsing error |
400 | 4003101 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4003102 | Missing mandatory field or header |
401 | 4013100 | Generic authorization error |
401 | 4013101 | The provided Authorization bearer token is invalid |
403 | 4013101 | The merchant is not allowed to perform this request |
403 | 4013115 | Generic forbidden error |
403 | 4013123 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4093100 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4093101 | An object with the same reference already exists |
VA - Callback
Xendit notifies your system upon successful payments via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings.
The expected response is a HTTP 200 status. Xendit marks webhook event as failed if there is no response within 30s.
Learn more about Webhook.
Notifications Headers Object
Example: Success Payment Webhook Payload
{
"type": "snap_virtual_account.payment",
"payload": {
"partnerServiceId": "38165",
"customerNo": "9999900674",
"virtualAccountNo": "381659999900674",
"virtualAccountName": "John Doe",
"trxId": "trx-1726657919",
"paymentRequestId": "pm-2803bb6c-f1e1-4d38-ad09-da25d5bdcf4a",
"paidAmount": {
"value": "10000.00",
"currency": "IDR"
},
"trxDateTime": "2024-09-18T11:12:19.000Z",
"referenceNo": "95ee9898-e6f6-4dba-aeb3-3198fcdf3cf9",
"freeTexts": [
{
"english": "Please pay for service"
}
],
"additionalInfo": {
"id": "95ee9898-e6f6-4dba-aeb3-3198fcdf3cf9",
"paymentId": "95ee9898-e6f6-4dba-aeb3-3198fcdf3cf9",
"country": "ID",
"status": "SUCCEEDED",
"created": "2024-09-18T11:12:20.631Z",
"updated": "2024-09-18T11:12:20.631Z",
"virtualAccountInfo": {
"id": "pm-2803bb6c-f1e1-4d38-ad09-da25d5bdcf4a",
"reusability": "MULTIPLE_USE",
"channelCode": "BCA",
"trxId": "trx-1726657919"
}
}
},
"headers": {
"x-partner-id": "64e8508e3a4184dd951c2f29",
"x-external-id": "XENDIT",
"channel-id": "XENDIT"
}
}
Header Object Parameter | Type | Description |
---|---|---|
channel-idrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
x-external-idrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
x-partner-idrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
x-signaturerequired |
string |
Non-repudiation signature for the request. See this article for more info. |
x-timestamprequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
Notifications Payload Object
Payload Object Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
partnerServiceIdrequired |
string |
This field is ignored by Xendit. | ||||||||||||||||||||||||||||||||||||
customerNorequired |
string |
This field is ignored by Xendit. | ||||||||||||||||||||||||||||||||||||
virtualAccountNorequired |
string |
You can assign specific Virtual Account number using this parameter. If you do not send one, one will be picked at random. Make sure the number you specify is within your Virtual Account range and don't include the merchant code as prefix. | ||||||||||||||||||||||||||||||||||||
virtualAccountNamerequired |
string |
Complete name of the payor. May be used by the channel partner to verify their identity. Characters Only alphabet. For BCA Aggregator, alphabet and number are allowed. Minimum length 1 character, except BCA the minimum length is 3 characters. |
||||||||||||||||||||||||||||||||||||
trxIdrequired |
string |
Merchant-provided identifier for this specific transaction. Please note that this field needs to be unique for each Virtual Account. | ||||||||||||||||||||||||||||||||||||
paidAmountrequired |
object |
Actual paid amount Conditional for Closed Virtual amounts
|
||||||||||||||||||||||||||||||||||||
trxDateTimerequired |
string |
Timestamp in ISO 8601 format when the PaymentRequest was created. Example: 2020-08-29T09:12:33.001Z | ||||||||||||||||||||||||||||||||||||
referenceNorequired |
string |
The payment ID that can be used for reconciliation | ||||||||||||||||||||||||||||||||||||
freeTextsoptional |
array of object |
Xendit will concatenate all text entries in this section to form the Virtual Account description. Free text objects
|
||||||||||||||||||||||||||||||||||||
additionalInforequired |
object |
Additional information required to complete the transaction
|
Key | Value | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
paymentIdrequired |
string Internal payment ID in Xendit system |
||||||||||
countryoptional |
string 2-letter ISO 3166-2 country code indicating country of transaction. |
||||||||||
statusrequired |
string Status of the payment. Allowed values: SUCCEEDED , FAILED
|
||||||||||
createdoptional |
string Timestamp in ISO 8601 format when the PaymentRequest was created. |
||||||||||
updatedoptional |
string Timestamp in ISO 8601 format when the PaymentRequest was last updated. Example: 2020-08-29T09:12:33.001Z |
||||||||||
senderNameoptional |
string Name of the end user that paid into the Virtual Account. This field is only supported for BSS VA |
||||||||||
paymentDetailoptional |
Additional information from the bank.
|
Key | Value |
---|---|
remarkoptional |
string A remark that is inputted by the payer when they are about to make a payment, only supported for BSS. |
referenceoptional |
string Reference number from the bank that can be used for reconciliation, only supported for BCA with switcher commercial model. |
optional
object
A free-format JSON for additional information that you may use. required
object
parameters details
Key | Value |
---|---|
idrequired |
string The Virtual Account ID. |
reusabilityrequired |
string The Virtual Account type. Allowed values: ONE_TIME_USE , MULTIPLE_USE
|
channelCodeoptional |
string Identifier for the payment channel partner. Allowed values: BCA , BSI , BJB , CIMB SAHABAT_SAMPOERNA , ARTAJASA , BRI , BNI , MANDIRI , PERMATA
|
trxIdrequired |
string Virtual Account Transaction ID. |
QR - Create
Endpoint: Create QR Request
POST https://api.xendit.co/snap/v1.0/qr/qr-mpm-generate
SNAP QR codes
This API can be used to generate QR Codes. (Service code: 47)
Request Parameters
Example: Create QR Code Request
curl https://api.xendit.co/snap/v1.0/qr/qr-mpm-generate -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"partnerReferenceNo": "0f38e017-007f-4134-9e5d-86657ec0cf7",
"amount": {
"value": "10000.00",
"currency": "IDR"
},
"additionalInfo": {
"reusability": "ONE_TIME_USE"
}
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
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. |
WITH-SPLIT-RULEoptional |
string |
Split Rule ID that you would like to apply to this charge. This header is only used if you are a xenPlatform user. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account. |
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
partnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. Will be extended to the actual payment transactions. | ||||||||||
amountconditionally required |
object |
Amount of the transaction. This is required for ONE_TIME_USE QR and will be ignored for MULTIPLE_USE QR. Conditional for
|
Key | Value |
---|---|
valuerequired |
string For IDR, format should include 2 decimal places. e.g. IDR 10.000, - will be placed with 10000.00 |
currencyrequired |
string ISO 4217 three-letter code of the transaction's currency. Only IDR is allowed. |
required
object
Object parameters details
Key | Value |
---|---|
reusabilityrequired |
string Describes whether or not the QR Code can be reused for only one or multiple payments. Allowed values: ONE_TIME_USE , MULTIPLE_USE
|
paymentMethodReferenceIdoptional |
string Merchant-provided identifier for the created payment method. If not specified, Xendit will generate random unique id for this field. |
metadataoptional |
string Date when the QR will be expired. Format: ISO-8601. |
metadataoptional |
object A free-format JSON for additional information that you may use. |
Response Parameters
Example: Create QR code Request API Success Response
{
"responseCode": "2004700",
"responseMessage": "Successful",
"referenceNo": "2020102900000000000002",
"partnerReferenceNo": "f5e6bb35-2c51-4880-9f19-883856031c30",
"qrContent": "random-qr-string",
"additionalInfo": {
"paymentMethodId": "pm-8c5edad9-32f6-40fa-a24e-0c4e6874c943",
"paymentMethodReferenceId": "620b9df4-fe69-4bfd-b9d4-5cba6861dc7d",
"paymentMethodStatus": "PENDING",
"reusability": "ONE_TIME_USE",
"created": "2023-01-05T13:15:45.265367951Z",
"updated": "2023-01-05T13:15:45.265367951Z"
}
}
Body Parameter | Type | Description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||
referenceNorequired |
string |
Unique identifier for the payment request. Prefix will vary according to the payment method used. | ||||||||||||||||||
partnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. Will be extended to the actual payment transactions. | ||||||||||||||||||
qrContentrequired |
string |
QR string to be rendered for display to end users. | ||||||||||||||||||
additionalInforequired |
object |
Additional information required to complete the transaction Object parameters details
|
Error Codes
Example: Create QR Code API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4004700 | Generic parsing error |
400 | 4004701 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4004702 | Missing mandatory field or header |
401 | 4014700 | Generic authorization error |
401 | 4014701 | The provided Authorization bearer token is invalid |
403 | 4014701 | The merchant is not allowed to perform this request |
403 | 4014715 | Generic forbidden error |
403 | 4014723 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4094700 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4094701 | An object with the same reference already exists |
QR - Inquire Status
Endpoint: Inquire QR Request
POST https://api.xendit.co/snap/v1.0/qr/qr-mpm-query
SNAP QR codes
This API can be used to query the status of specific QR Payment Request. (Service code: 51)
Request Parameters
Example: Inquire QR Code Request
curl https://api.xendit.co/snap/v1.0/qr/qr-mpm-query -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"serviceCode": "47",
"originalPartnerReferenceNo": "0f38e017-007f-4134-9e5d-86657ec0cf77"
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
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. |
Body Parameter | Type | Description |
---|---|---|
originalPartnerReferenceNooptional |
string |
Original transaction identifier on service consumer system. Either originalReferenceNo or originalPartnerReferenceNo must present in the request. |
originalReferenceNooptional |
string |
Xendit Generated ID for the payment request. Either this or referenceNo must be provided. originalPartnerReferenceNo must present in the request. |
serviceCoderequired |
string |
Must be set to '47' |
Response Parameters
Example: Inquire QR code Request API Success Response
{
"responseCode": "2005100",
"responseMessage": "Successful",
"originalReferenceNo": "pr-bc9faa22-23e5-486e-bfee-869c46d32cc3",
"originalPartnerReferenceNo": "0f38e017-007f-4134-9e5d-86657ec0cf77",
"serviceCode": "47",
"latestTransactionStatus": "00",
"transactionStatusDesc": "Success",
"amount": {
"value": "10000.00",
"currency": "IDR"
},
"additionalInfo": {
"paymentMethodId": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"paymentMethodReferenceId": "2020102900000000000001",
"reusability": "ONE_TIME_USE",
"paymentMethodStatus": "INACTIVE",
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "ABCDEFGH"
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||
originalReferenceNooptional |
string |
Unique identifier for the payment request. Prefix will vary according to the payment method used. | ||||||||||||||||||||
originalPartnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. Will be extended to the actual payment transactions. | ||||||||||||||||||||
serviceCoderequired |
string |
Set to '47' | ||||||||||||||||||||
latestTransactionStatusrequired |
string |
Latest transaction status. Allowed values: 00 , 03 , 04 , 06 |
||||||||||||||||||||
transactionStatusDescoptional |
string |
Description status transaction | ||||||||||||||||||||
amountconditionally required |
object |
Amount of the transaction Object information
|
||||||||||||||||||||
additionalInforequired |
object |
Additional information required to complete the transaction Object parameters details
|
Error Codes
Example: Create QR Code API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4005100 | Generic parsing error |
400 | 4005101 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4005102 | Missing mandatory field or header |
401 | 4015100 | Generic authorization error |
401 | 4015101 | The provided Authorization bearer token is invalid |
403 | 4015101 | The merchant is not allowed to perform this request |
403 | 4015115 | Generic forbidden error |
403 | 4015123 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4095100 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4095101 | An object with the same reference already exists |
QR - Callback
Xendit notifies your system upon successful payments via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings.
The expected response is a HTTP 200 status. Xendit marks webhook event as failed if there is no response within 30s.
Learn more about Webhook.
Notifications Headers Object
Example: Success Payment Webhook Payload
{
"type": "snap_qr.payment",
"payload": {
"originalReferenceNo": "pr-bc9faa22-23e5-486e-bfee-869c46d32cc3",
"originalPartnerReferenceNo": "0f38e017-007f-4134-9e5d-86657ec0cf77",
"latestTransactionStatus": "00",
"transactionStatusDesc": "Success",
"amount": {
"value": "10000.00",
"currency": "IDR"
},
"additionalInfo": {
"id": "qrpy-av8faa22-145e5-4766e-bdee-867c46f32cc4",
"paymentMethodId": "pm-0fec5f39-de53-42f0-8443-6bc037138e32",
"paymentMethodReferenceId": "331b2b98-2adf-43b5-8c3f-9b0d76026c9d",
"created": "2023-03-07T12:05:02.894821985Z",
"updated": "2023-03-07T12:05:02.894821985Z"
},
"headers": {
"x-partner-id": "64e8508e3a4184dd951c2f29",
"x-external-id": "XENDIT",
"channel-id": "XENDIT"
}
}
Header Object Parameter | Type | Description |
---|---|---|
channel-idrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
x-external-idrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
x-partner-idrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
x-signaturerequired |
string |
Non-repudiation signature for the request. See this article for more info. |
x-timestamprequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
Notifications Payload Object
Payload Object Parameter | Type | Description | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
originalReferenceNorequired |
string |
Unique identifier for the payment request. Prefix will vary according to the payment method used. | ||||||||||||||
originalPartnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. | ||||||||||||||
latestTransactionStatusrequired |
string |
Latest transaction status of the payment. Allowed values: 00 , 06 |
||||||||||||||
transactionStatusDescrequired |
string |
Description status transaction | ||||||||||||||
amountrequired |
object |
Actual paid amount Object information
|
||||||||||||||
additionalInforequired |
object |
Additional information about the QR payment
|
Key | Value |
---|---|
idrequired |
string Unique identifier for the payment. |
paymentMethodIdrequired |
string Unique identifier for the payment method. |
paymentMethodReferenceIdrequired |
string Merchant-provided identifier for this payment method. If it's not provided, xendit will generate unique identifier for the merchant. |
createdoptional |
string Timestamp in ISO 8601 format when the PaymentRequest was created. |
updatedoptional |
string Timestamp in ISO 8601 format when the PaymentRequest was last updated. Example: 2020-08-29T09:12:33.001Z |
metadataoptional |
object A free-format JSON for additional information that you may use. |
Direct Debit - Create
Endpoint: Create Direct Debit Payment Request
POST https://api.xendit.co/snap/v1.0/debit/payment-host-to-host
SNAP Direct Debit Payment
This API can be used to initiate a one time payment request or a payment request using previously bound account (i.e. a payment method must already exist). Based on the response code an additional action might be required, e.g. to redirect the shopper or to verify the payment with an OTP. This API can be used for all E-Wallet and Direct Debit payment channels. (Service code: 54)
Request Parameters
Example: Create Direct Debit Request
curl https://api.xendit.co/snap/v1.0/debit/payment-host-to-host -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"partnerReferenceNo": "2020102900000000000001",
"amount": {
"value": "10000.00",
"currency": "IDR"
},
"additionalInfo": {
"customerId": "fc4c060b-3c41-4707-b7b2-df9c3376edde",
"paymentMethodId": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"channelProperties": {
"redeemPoints": "REDEEM_ALL"
},
"metadata": {
"sku": "ABCDEFGH"
}
}
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
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. |
WITH-SPLIT-RULEoptional |
string |
Split Rule ID that you would like to apply to this charge. This header is only used if you are a xenPlatform user. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account. |
Body Parameter | Type | Description | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
partnerReferenceNorequired |
string |
Merchant-provided identifier for this specific transaction. Will be extended to the actual payment transactions. | ||||||||||||||||||||||||||
amountconditionally required |
object |
Amount of the transaction. This is required for ONE_TIME_USE QR and will be ignored for MULTIPLE_USE QR. Conditional for
|
Key | Value |
---|---|
valuerequired |
string For IDR, format should include 2 decimal places. e.g. IDR 10.000, - will be placed with 10000.00 |
currencyrequired |
string ISO 4217 three-letter code of the transaction's currency. Only IDR is allowed. |
optional
array
urlParam
with type PAY_RETURN required for: OVO (MULTIPLE_USE), DANA, SHOPEEPAY.urlParam
with type FAILURE_RETURN required for: OVO (MULTIPLE_USE), DANA (MULTIPLE_USE), SHOPEEPAY (MULTIPLE_USE) Object Information for each array item
Key | Value |
---|---|
urlrequired |
string URL where the end-customer is redirected if the authorization is successful (in case of type PAY_RETURN), unsuccessful (in case of type FAILURE_RETURN) or cancellation (in case of CANCEL_RETURN) |
typerequired |
string URL Type. Allowed values: PAY_RETURN , FAILURE_RETURN , CANCEL_RETURN
|
isDeeplinkoptional |
boolean Whether the URL is a deeplink URL or not. Xendit does not support deeplink URL for merchant-provided URLs so this field is ignored. |
conditionally required
array
Object Information for each array item
Key | Value | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
payMethodrequired |
string Type of payment method. Allowed values: EWALLET , DIRECT_DEBIT |
||||||||||||||||||
payOptionrequired |
string Identifier for the payment channel partner. Allowed values for payMethod EWALLET: OVO , DANA , LINKAJA , JENIUSPAY , ASTRAPAY , SHOPEEPAY . Allowed values for payMethod DIRECT_DEBIT: BRI |
||||||||||||||||||
additionalInfoconditionally required |
object Required for OVO one time payment, BRI , JENIUSPAY
Object Information
|
optional
object
Object parameters details
Key | Value | ||||||
---|---|---|---|---|---|---|---|
customerIdrequired |
string Xendit-generated identifier for the end-customer. Will be required for certain payment channels such as Multiple-use e-wallets and direct debit. |
||||||
paymentMethodIdoptional |
string The id of a previously stored PaymentMethod to be used in this transaction. Mandatory if payOptionDetails is not specified. |
||||||
channelPropertiesoptional |
object Additional parameters based on payment channel Object parameters details
|
||||||
descriptionoptional |
string Free-text field for any additional information regarding the payment request. |
||||||
metadataoptional |
object A free-format JSON for additional information that you may use. |
Response Parameters
Example: Create Direct Debit Request API Success Response
{
"responseCode": "2005400",
"responseMessage": "Successful",
"referenceNo": "ewc_6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"partnerReferenceNo": "2020102900000000000001",
"webRedirectUrl": "https://link-web.xendit.co/oauth/lat-4ec01c8d-0326-4a35-bc11-b64c85f7408e/confirm",
"additionalInfo": {
"paymentMethodId": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"actions": [
{
"action": "AUTH",
"method": "GET",
"url": "https://link-web.xendit.co/oauth/lat-4ec01c8d-0326-4a35-bc11-b64c85f7408e/confirm",
"urlType": "WEB"
}
],
"metadata": {
"sku": "ABCDEFGH"
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||||
referenceNooptional |
string |
Unique identifier for the payment request. Prefix will vary according to the payment method used. | ||||||||||||||||||||||
partnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. Will be extended to the actual payment transactions. | ||||||||||||||||||||||
approvalCodeoptional |
string |
If the status of the transaction is FAILED, this describes the reason for failure. Will not be present if the transaction did not fail. | ||||||||||||||||||||||
appRedirectUrloptional |
string |
The provided redirect url utilizes deep linking to the channel partner’s platform. | ||||||||||||||||||||||
webRedirectUrloptional |
string |
The provided redirect url is optimized for desktop or web interface. | ||||||||||||||||||||||
additionalInfooptional |
object |
Additional information for the transaction Object parameters details
|
Error Codes
Example: Create Direct Debit API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4005400 | Generic parsing error |
400 | 4005401 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4005402 | Missing mandatory field or header |
401 | 4015400 | Generic authorization error |
401 | 4015401 | The provided Authorization bearer token is invalid |
403 | 4015401 | The merchant is not allowed to perform this request |
403 | 4015415 | Generic forbidden error |
403 | 4015423 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4095400 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4095401 | An object with the same reference already exists |
Direct Debit - Inquire Status
Endpoint: Create Direct Debit Payment Request
POST https://api.xendit.co/snap/v1.0/debit/status
SNAP Inquire Direct Debit Payment
This API can be used to request the status of a specific Payment request. (Service code: 55)
Request Parameters
Example: Inquire Direct Debit Request
curl https://api.xendit.co/snap/v1.0/debit/status -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"originalPartnerReferenceNo": "0f38e017-007f-4134-9e5d-86657ec0cf77",
"serviceCode": "54"
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
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. |
Body Parameter | Type | Description |
---|---|---|
originalPartnerReferenceNooptional |
string |
Original transaction identifier on service consumer system. Either this field or originalReferenceNo must be provided |
originalReferenceNooptional |
string |
Xendit Generated ID for the payment request. Either this field or originalPartnerReferenceNo must be provided |
serviceCoderequired |
string |
Must be set to ‘54’ |
Response Parameters
Example: Inquire Direct Debit Request API Success Response
{
"responseCode": "2005500",
"responseMessage": "Successful",
"originalReferenceNo": "pr-bc9faa22-23e5-486e-bfee-869c46d32cc3",
"originalPartnerReferenceNo": "0f38e017-007f-4134-9e5d-86657ec0cf77",
"serviceCode": "54",
"latestTransactionStatus": "03",
"transactionStatusDesc": "REQUIRES_ACTION",
"transAmount": {
"value": "10000.00",
"currency": "IDR"
},
"additionalInfo": {
"customerId": "fc4c060b-3c41-4707-b7b2-df9c3376edde",
"paymentMethodId": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"paymentMethodReferenceId": "2020102900000000000001",
"actions": [
{
"action": "RESEND_AUTH",
"method": "POST",
"url": "https://merchant-url/resent-otp",
"urlType": "DEEPLINK"
}
],
"channelProperties": {},
"metadata": {
"sku": "ABCDEFGH"
}
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||||||||||||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||||||||||||||||||||||||||||
originalReferenceNooptional |
string |
Unique identifier for the payment request. Prefix will vary according to the payment method used. | ||||||||||||||||||||||||||||||||||||||||||||
originalPartnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. Will be extended to the actual payment transactions. | ||||||||||||||||||||||||||||||||||||||||||||
serviceCoderequired |
string |
Set to '54' | ||||||||||||||||||||||||||||||||||||||||||||
latestTransactionStatusrequired |
string |
Latest transaction status. Allowed values: 00 , 01 , 02 , 03 , 04 , 05 , 06 , 07 |
||||||||||||||||||||||||||||||||||||||||||||
transactionStatusDescoptional |
string |
Description status transaction | ||||||||||||||||||||||||||||||||||||||||||||
transAmountconditionally required |
object |
Amount of the transaction Object information
|
||||||||||||||||||||||||||||||||||||||||||||
additionalInfooptional |
object |
Additional information for the transaction Object parameters details
|
Error Codes
Example: Inquire Direct Debit Payment API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4005500 | Generic parsing error |
400 | 4005501 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4005502 | Missing mandatory field or header |
401 | 4015500 | Generic authorization error |
401 | 4015501 | The provided Authorization bearer token is invalid |
403 | 4015501 | The merchant is not allowed to perform this request |
403 | 4015515 | Generic forbidden error |
403 | 4015523 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4095500 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4095501 | An object with the same reference already exists |
Direct Debit - Refund
Endpoint: Refund Direct Debit Payment Request
POST https://api.xendit.co/snap/v1.0/debit/refund
SNAP Refund Direct Debit Payment
This API can be used to refund a payment (Service code: 58)
Request Parameters
Example: Refund Direct Debit Request
curl https://api.xendit.co/snap/v1.0/debit/refund -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"originalPartnerReferenceNo": "0f38e017-007f-4134-9e5d-86657ec0cf77",
"partnerRefundNo": "5eea215e-e116-439a-a087-76fc906501e1",
"reason": "FRAUDULENT",
"refundAmount": {
"value": "100000.00",
"currency": "IDR"
}
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
Body Parameter | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
originalPartnerReferenceNooptional |
string |
Original transaction identifier on service consumer system. Either this field or originalReferenceNo must be provided | ||||||
originalReferenceNooptional |
string |
Xendit Generated ID for the payment request. Either this field or originalPartnerReferenceNo must be provided | ||||||
partnerRefundNooptional |
string |
Merchant-provided identifer for the refund request. If none is provided, a unique randomly generated string will be assigned. | ||||||
refundAmountconditionally required |
object |
If refundAmount is not provided, the refund request will default to the maximum possible amount to be refunded from the provided transaction. Conditional for
|
Key | Value |
---|---|
valuerequired |
string For IDR, format should include 2 decimal places. e.g. IDR 10.000, - will be placed with 10000.00 |
currencyrequired |
string ISO 4217 three-letter code of the transaction's currency. Only IDR is allowed. |
optional
string
FRAUDULENT
, DUPLICATE
, REQUESTED_BY_CUSTOMER
, CANCELLATION
, OTHERS
optional
object
Object parameters details
Key | Value |
---|---|
metadataoptional |
object A free-format JSON for additional information that you may use. |
Response Parameters
Example: Inquire Direct Debit Request API Success Response
{
"responseCode": "2005800",
"responseMessage": "Successful",
"originalReferenceNo": "pr-bc9faa22-23e5-486e-bfee-869c46d32cc3",
"refundNo": "rfd-b0abb4fe-4b98-4c07-92d4-3f33fc79aefc",
"partnerRefundNo": "5eea215e-e116-439a-a087-76fc906501e1",
"refundAmount": {
"value": "100000.00",
"currency": "IDR"
},
"additionalInfo": {
"channelCode": "SHOPEEPAY",
"status": "SUCCESS",
"reason": "FRAUDULENT"
}
}
Body Parameter | Type | Description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
responseCoderequired |
string |
Response code | ||||||||||||||||||
responseMessagerequired |
string |
Response description | ||||||||||||||||||
originalReferenceNooptional |
string |
Unique identifier for the payment request. Prefix will vary according to the payment method used. | ||||||||||||||||||
refundNooptional |
string |
Xendit-generated identifier for the refund request | ||||||||||||||||||
partnerRefundNooptional |
string |
Merchant-provided identifer for the refund request. If none is provided, a unique randomly generated string will be assigned. | ||||||||||||||||||
refundAmountconditionally required |
object |
If refundAmount is not provided, the refund request will default to the maximum possible amount to be refunded from the provided transaction. Conditional for
|
Key | Value |
---|---|
valuerequired |
string For IDR, format should include 2 decimal places. e.g. IDR 10.000, - will be placed with 10000.00 |
currencyrequired |
string ISO 4217 three-letter code of the transaction's currency. Only IDR is allowed. |
required
object
Object parameters details
Key | Value |
---|---|
channelCoderequired |
string Identifier for the payment channel partner |
statusrequired |
string Status of the refund. Allowed values: SUCCESS , FAILED , PENDING
|
reasonrequired |
string Reason why the refund request is made. Allowed values: FRAUDULENT , DUPLICATE , REQUESTED_BY_CUSTOMER
|
failureCodeoptional |
string If the status of the transaction is failed, this describes the reason for failure. |
refundFeeAmountoptional |
string If applicable, this is the corresponding additional fee for processing the refund. |
createdoptional |
string Timestamp in ISO 8601 format when the payment request was created |
updated optional |
string Timestamp in ISO 8601 format when the payment request was last updated |
metadataoptional |
object A free-format JSON for additional information that you may use. |
Error Codes
Example: Refund Direct Debit API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4005800 | Generic parsing error |
400 | 4005801 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4005802 | Missing mandatory field or header |
401 | 4015800 | Generic authorization error |
401 | 4015801 | The provided Authorization bearer token is invalid |
403 | 4015801 | The merchant is not allowed to perform this request |
403 | 4015815 | Generic forbidden error |
403 | 4015823 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4095800 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4095801 | An object with the same reference already exists |
Direct Debit - Verify OTP
Endpoint: Verify Direct Debit Payment OTP Request
POST https://api.xendit.co/snap/v1.0/otp-verification
SNAP Verify OTP
This API can be used to verify an OTP if required in the payment process. (Service code: 04)
Request Parameters
Example: Verify Direct Debit OTP Request
curl https://api.xendit.co/snap/v1.0/otp-verification -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'CHANNEL-ID: 123123' \
--header 'Content-Type: application/json' \
--header 'X-EXTERNAL-ID: 123123' \
--header 'X-PARTNER-ID: 123123' \
--header 'X-SIGNATURE: fc4c060b3c414707b7b2df9c3376edde' \
--header 'X-TIMESTAMP: 2020-08-29T09:12:33.001Z' \
--data '{
"originalReferenceNo": "pr-bc9faa22-23e5-486e-bfee-869c46d32cc3",
"otp": "123456",
"type": "payment"
}' \
Header Parameter | Type | Description |
---|---|---|
CHANNEL-IDrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
X-EXTERNAL-IDrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
X-PARTNER-IDrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
X-SIGNATURErequired |
string |
Non-repudiation signature for the request. See this article for more info. |
X-TIMESTAMPrequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
Body Parameter | Type | Description |
---|---|---|
originalReferenceNooptional |
string |
Xendit Generated ID for the payment request. Either this field or originalPartnerReferenceNo must be provided |
otpoptional |
string |
The authorization code or OTP inputted by the end customer |
typeoptional |
string |
Must be set to 'payment'. Allowed value: payment |
Response Parameters
Example: Inquire Direct Debit Request API Success Response
{
"responseCode": "2000400",
"responseMessage": "Successful",
"originalReferenceNo": "pr-bc9faa22-23e5-486e-bfee-869c46d32cc3",
"originalPartnerReferenceNo": "0f38e017-007f-4134-9e5d-86657ec0cf77"
}
Body Parameter | Type | Description |
---|---|---|
responseCoderequired |
string |
Response code |
responseMessagerequired |
string |
Response description |
originalReferenceNooptional |
string |
Unique identifier for the payment request. Prefix will vary according to the payment method used. |
originalPartnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. Will be extended to the actual payment transactions |
customerIdoptional |
string |
Xendit-generated identifier for the end-customer. |
Error Codes
Example: Verify OTP API Error Response
{
"responseCode": "4000000",
"responseMessage": "Bad Request"
}
HTTP error | Response Code | Response Message |
---|---|---|
400 | 4000400 | Generic parsing error |
400 | 4000401 | Invalid field format (i.e. a string is used whereas a number was expected, or an invalid enum value is used, etc.) |
400 | 4000402 | Missing mandatory field or header |
401 | 4010400 | Generic authorization error |
401 | 4010401 | The provided Authorization bearer token is invalid |
403 | 4010401 | The merchant is not allowed to perform this request |
403 | 4010415 | Generic forbidden error |
403 | 4010423 | The amount specified is either smaller or greater than supported by the channel. |
409 | 4090400 | The same X-EXTERNAL-ID token has been used within the last 24 hours |
409 | 4090401 | An object with the same reference already exists |
Direct Debit - Callback
Xendit notifies your system upon successful payments via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings.
The expected response is a HTTP 200 status. Xendit marks webhook event as failed if there is no response within 30s.
Learn more about Webhook.
Notifications Headers Object
Example: Success Payment Webhook Payload
{
"type": "snap.direct_debit.succeeded",
"payload": {
"amount": {
"value": "10000.00",
"currency": "IDR"
},
"createdTime": "2020-08-29T09:12:33.001Z",
"additionalInfo": {
"id": "ddpy-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"updated": "2020-08-29T09:12:33.001Z",
"paymentMethodId": "pm-5f964f11-3a74-4df2-bdc4-0778b3e836d4",
"paymentMethodReferenceId": "c2a6c16f-84b9-4f21-8db3-dc0ddcbbfec7"
},
"originalReferenceNo": "ddpy-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"transactionStatusDesc": "Success",
"latestTransactionStatus": "00",
"originalPartnerReferenceNo": "c2a6c16f-84b9-4f21-8db3-dc0ddcbbfec7"
},
"headers": {
"x-partner-id": "64e8508e3a4184dd951c2f29",
"x-external-id": "XENDIT",
"channel-id": "XENDIT"
}
}
Header Object Parameter | Type | Description |
---|---|---|
channel-idrequired |
string |
Device identification on which the API services is currently being accessed by the end user. If not available, set to 'unknown'. |
Content-Typerequired |
string |
Must be set to application/json |
x-external-idrequired |
string |
Also known as idempotency key. Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer; it expires after 24 hours from the first request.Example: f4d53a90-86aa-46f4-8738-169a4912eff0 |
x-partner-idrequired |
string |
Your Xendit's Client ID. Example: 7049bc78-0600-43b8-a6be-25225bf9344c |
x-signaturerequired |
string |
Non-repudiation signature for the request. See this article for more info. |
x-timestamprequired |
string |
Timestamp for the non-repudiation signature. Format must be yyyy-MM-ddTHH:mm:ssTZD. |
Notifications Payload Object
Payload Object Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
originalReferenceNorequired |
string |
Unique identifier for the payment request. Prefix will vary according to the payment method used. | ||||||||||||||||||||||||
originalPartnerReferenceNooptional |
string |
Merchant-provided identifier for this specific transaction. | ||||||||||||||||||||||||
latestTransactionStatusrequired |
string |
Latest transaction status of the payment. Allowed values: 00 , 06 |
||||||||||||||||||||||||
transactionStatusDescrequired |
string |
Description status transaction | ||||||||||||||||||||||||
createdTimerequired |
string |
Timestamp in ISO 8601 format when the PaymentRequest was created. Example: 2024-08-29T09:12:33.001Z | ||||||||||||||||||||||||
amountrequired |
object |
Actual paid amount Object information
|
||||||||||||||||||||||||
additionalInforequired |
object |
Additional information about the payment.
|
Key | Value | ||||||
---|---|---|---|---|---|---|---|
idrequired |
string Unique identifier for the payment. |
||||||
paymentMethodIdrequired |
string Unique identifier for the payment method. |
||||||
paymentMethodReferenceIdrequired |
string Merchant-provided identifier for this payment method. If it's not provided, xendit will generate unique identifier for the merchant. |
||||||
createdoptional |
string Timestamp in ISO 8601 format when the PaymentRequest was created. |
||||||
updatedoptional |
string Timestamp in ISO 8601 format when the PaymentRequest was last updated. Example: 2020-08-29T09:12:33.001Z |
||||||
descriptionoptional |
string description of the payment request. |
||||||
failureCodeoptional |
string If the status of the transaction is failed, this describes the reason for failure. |
||||||
channelPropertiesoptional |
object Additional information about the channel.
|
Key | Value |
---|---|
successReturnUrlrequired |
string URL where the end-customer is redirected if the authorization is successful. |
failureReturnUrlrequired |
string URL where the end-customer is redirected if the authorization has failed |
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
{
"amount": "10000",
"card_data": {
"account_number": "4456530000001096",
"exp_month": "12",
"exp_year": "2029",
"card_holder_first_name": "John",
"card_holder_last_name": "Doe",
"card_holder_email": "johndoe@gmai.com",
"card_holder_phone_number": "628212223242526"
},
"external_id":"TEST1234",
"card_cvn": "123",
"is_multiple_use": false,
"should_authenticate": true,
"currency": "IDR",
"mid_label": "XBANK_TIDNEX"
}
Example tokenData request for retokenize
{
"amount": "10000",
"credit_card_token_id": "58e2096018b815f555c8a524",
"card_cvn": "123",
"is_multiple_use": false,
"should_authenticate": true,
"external_id": "TEST1234"
}
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.
Retokenize
When performing credit card authorization/charge, sending CVV can help to improve the success rate. Following PCIDSS policy where CVV should not be processed server to server (unless you are a PCIDSS certified company), the retokenize flow can help to collect the CVV from your customer, then pass it to Xendit retokenize function, so that CVV will be passed to the processor when the authorization request is performed.
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_data required |
object |
Customer's card details informations card details child parameters
|
|||||||||||||||||||||||||||||||
external_id optional |
string |
Your reference ID for identifying the created token | |||||||||||||||||||||||||||||||
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 |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. Supported currencies: IDR for Indonesia PHP and USD for Philippines MYR for Malaysia THB for Thailand VND for Vietnam Other currencies are supported only if you are using your own MIDs. If left blank, defaults to currency based on your business country. |
|||||||||||||||||||||||||||||||
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 recommended for increased likelihood of frictionless authentication on 3DS 2.0. billing details child parameters
|
|||||||||||||||||||||||||||||||
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 authentication will proceed using your prioritized MID (first MID on your list)). Note: Only available in the response for switcher merchant |
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",
"network_response": {
"three_ds_trans_status": "Y",
"three_ds_flow": "CHALLENGE"
}
}
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 | ||||||||||
external_id optional |
string |
Your reference ID for identifying the created token | ||||||||||
masked_card_number required |
string |
The first 6 or 8 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
|
||||||||||
network_responseoptional |
object |
These error codes are returned as additional data and insights. Check our card declines and error code documentation for more details. network_response details 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 performed 3DS. Merchant could check the ECI code to ensure the liability shift before proceeding to charge. |
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. Recommendation is to check the input and retry. |
INVALID_JSON_FORMAT400 |
The request body is not valid JSON. Recommendation is to check the input and retry. |
ACCOUNT_NUMBER400 |
Credit card number is invalid. Make sure to input the correct credit card number and retry. |
VALIDATION_ERROR 400 |
Data was passed in an incorrect format. Recommendation is to check the input and retry. |
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. Please retry in a few minutes. |
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",
"external_id": "TEST1234",
"card_data": {
"card_holder_first_name": "John",
"card_holder_last_name": "Doe",
"card_holder_email": "johndoe@gmai.com",
"card_holder_phone_number": "628212223242526"
},
"mid_label": "XBANK_TIDNEX"
}
Example Authentication Response
{
"id": "58e2097218b815f555c8a526",
"external_id": "TEST1234",
"status": "VERIFIED",
"network_response": {
"three_ds_trans_status": "Y",
"three_ds_flow": "CHALLENGE"
}
}
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 optional |
string |
The amount that will be authenticated and processed on charge. Only required for single use tokens with bundled authentication. | ||||||||||
card_data optional |
object |
Additional information of the cardcard data child parameters
|
||||||||||
external_id optional |
string |
Your reference ID for identifying the created token | ||||||||||
token_id optional |
string |
ID of the token that you've created | ||||||||||
currency optional |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. Supported currencies: IDR for Indonesia PHP and USD for Philippines MYR for Malaysia THB for Thailand VND for Vietnam Other currencies are supported only if you are using your own MIDs. If left blank, defaults to currency based on your business country. |
||||||||||
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 authentication will proceed using your prioritized MID (first MID on your list)). Note: Only available in the response for switcher merchant |
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 |
external_id optional |
string |
Your reference ID for identifying the authentication |
payer_authentication_url optional |
string |
If status is IN_REVIEW , this contains the URL for authenticating users with 3DS |
mid_label optional |
string |
MID label used to process the authentication. |
failure_reason optional |
string |
If status is FAILED , this describes the failure. See Tokenization Failure Reasons. |
network_response optional |
string |
These error codes are returned as additional data and insights. Check our card declines and error code documentation for more details. |
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",
"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
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
)
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",
"network_response": {
"card_network_response_code": "65",
"card_network_descriptor": "Exceeds withdrawal count limit",
"network_transaction_id": "123456",
"merchant_advice_code": "28",
"merchant_advice_descriptor": "Retry after 6 days",
"three_ds_trans_status": "Y",
"three_ds_flow": "CHALLENGE"
}
}
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"
}'
<?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
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. Recommendation is to check the input and retry |
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",
"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",
"city": "Jakarta Selatan",
"province_state": "DKI Jakarta",
"postal_code": "993448",
"country": "ID"
}
},
"promotion": {
"reference_id": "BCA_10",
"original_amount": 1000000
},
"installment": {
"count": 3,
"interval": "month"
},
"metadata": {}
}'
<?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,
'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',
descriptor: "My new store",
currency: "IDR",
midLabel: "IDR_MID",
billingDetails: {
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",
city: "Jakarta Selatan",
province_state: "DKI Jakarta",
postal_code: "993448",
country: "ID"
}
},
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
"XDT*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
)
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 |
with-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this card charge in order to split and route payments to multiple accounts. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.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. | |||||||||||||||||||||||||||||||
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 XDT*[MERCHANT_NAME]-DESCRIPTOR For switcher merchant, it will always return [MERCHANT_NAME]-DESCRIPTOR |
|||||||||||||||||||||||||||||||
currency optional |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. Xendit by default supports IDR for Indonesia and PHP for Philippines. Other currencies are supported only if you are using your own MIDs. If left blank, defaults to currency based on your business country. | |||||||||||||||||||||||||||||||
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
|
|||||||||||||||||||||||||||||||
metadataoptional |
object |
A free-format JSON for additional information that you want to provide in the request. | |||||||||||||||||||||||||||||||
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": "XDT*MYBUSINESS-MY NEW STORE",
"id": "598d5dba51e0870d44c61539",
"mid_label": "IDR_MID",
"promotion": {
"reference_id": "BCA_10",
"original_amount": "1000000"
},
"installment": {
"count": 3,
"interval": "month"
},
"network_response": {
"card_network_response_code": "65",
"card_network_descriptor": "Exceeds withdrawal count limit",
"network_transaction_id": "123456",
"merchant_advice_code": "28",
"merchant_advice_descriptor": "Retry after 6 days",
"three_ds_trans_status": "Y",
"three_ds_flow": "CHALLENGE"
}
}
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": "XDT*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:
|
||||||||||||||
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 that is being charged. Can be CREDIT, DEBIT, PREPAID, and UNKNOWN. | ||||||||||||||
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 or 8 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 XDT*[MERCHANT_NAME]-DESCRIPTOR For switcher merchant, it will always return [MERCHANT_NAME]-DESCRIPTOR |
||||||||||||||
currency optional |
string |
Currency which you want to process the transaction in. Use a three-letter ISO currency code. Xendit by default supports IDR for Indonesia and PHP for Philippines. Other currencies are supported only if you are using your own MIDs. If left blank, defaults to currency based on your business country. | ||||||||||||||
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
|
||||||||||||||
network_responseoptional |
object |
These error codes are returned as additional data and insights. Check our card declines and error code documentation for more details. detil objek network_response
|
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 |
---|---|
AUTHENTICATION_FAILED | Payment was declined because transaction is not authenticated yet. Recommend cardholder to to re-authenticate the transaction with 3DS. Alternatively, they can try to use a different card, other form of payment, or contact their card issuing bank to resolve the problem on online transaction. |
DECLINED_BY_ISSUER | Payment was declined by the issuer with no additional information provided to Xendit. Ask your customer to contact issuing bank. Alternatively, they can try using different card or other form of payment |
DECLINED_BY_PROCESSOR | Payment was declined by the processor. Ask your customer to try again. Alternatively, they can try to use a different card or other form of payment. |
EXPIRED_CARD | The card you are trying to capture is expired. Ask your customer for a different card. |
ISSUER_SUSPECT_FRAUD | Payment was declined by the issuer because them suspecting this payment to be fraudulent. Review the cardholder. If you believe the cardholder to be legitimate, recommend them to use a different card or other form of payment. Otherwise, avoid processing transaction from them to prevent chargeback. |
INACTIVE_OR_UNAUTHORIZED_CARD | Payment was declined by the issuer because card is not authorized for online transactions. Recommend cardholder to contact their card issuing bank to resolve the problem on online transaction. Alternatively, they can try to use a different card or other form of payment. |
INSUFFICIENT_BALANCE | The card you are trying to capture does not have enough balance to complete the capture |
INVALID_CARD | Payment was declined by the issuer because incorrect card information being provided. Recommend cardholder to review the card information and try again. Alternatively, they can try to use a different card or other form of payment. |
INVALID_CVV | Payment was declined by the issuer because incorrect card CVN / CVV / CSC being provided. Recommend cardholder to review the card CVV / CVN / CSC (3-4 digit code on the back of the card) and try again. Alternatively, they can try to use a different card or other form of payment. |
ISSUER_UNAVAILABLE | Payment was declined by the processor because card issuer is unreachable. Recommend cardholder to contact their card issuing bank to resolve the problem on online transaction. Alternatively, they can try to use a different card or other form of payment. |
PROCESSOR_ERROR | Payment was declined by the processor because intermittent error on processor side. Recommend cardholder to try again in a few minutes. Alternatively, they can try to use other form of payment. |
STOLEN_CARD | The card you are trying to capture has been marked as stolen. Ask your customer for a different card. |
PROCESSOR_TIMEOUT | We got timeout from our processor when requested the charge which indicated as intermittent connection problem. Advise customer to retry the transaction. |
FRAUD_RISK_BLOCKED | Payment was declined by Xendit risk assessment. Please refer to the Fraud Risk Assessment section for more detail. Review the cardholder, as the payment was blocked by your blocklist. If you believe the cardholder to be legitimate, remove the identifier from the blocklist and ask them to try again. Otherwise, avoid processing transaction from them to prevent chargeback. |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. Recommendation is to check the input and retry. |
INVALID_JSON_FORMAT 400 |
The request body is not valid JSON. Recommendation is to check the input and retry. |
TOKEN_ALREADY_USED_ERROR 400 |
The single-use token ID has already been used in a charge. Recommendation is to create charge with different token_id. |
AUTHENTICATION_ALREADY_USED_ERROR 400 |
The authentication ID has already been used in a charge. Recommendation is to use different authentication_id to proceed charge. |
INVALID_TOKEN_ID_ERROR 400 |
The token ID format is invalid. Recommendation is to check if token_id format is correct and retry. |
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. Recommendation is to check if the CVN is already following the correct format and retry. |
AUTHENTICATION_ID_MISSING_ERROR 400 |
Authentication ID is required for this charge. Recommendation is to include authentication_id in the charge request. |
AMOUNT_GREATER_THAN_AUTHENTICATED_ERROR 400 |
Charge amount was greater than what was authenticated. Ensure the charge amount is the same as what was authenticated and retry. |
INVALID_AUTHENTICATION_ID_ERROR 400 |
The authentication ID format is invalid. Please check if your authentication_id is already following the correct format. |
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. Please check if you already include the correct API key in the request header. For charge, the API key you are using should be secret API key. |
AUTHENTICATION_NOT_FOUND_ERROR 404 |
Authenticated token with given authentication ID is not found. Please check if you already input the existing authentication_id in the request. |
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: |
INCOMPLETE_AUTHENTICATION 400 |
The authentication_id sent cannot be used as authentication could not be completed. This usually happens when there is an issue preventing generation of the 2FA page, if the user did not complete the 3DS process, or something else happened such as a bank timeout. Please attempt the payment again, or exclude authentication_id from the Charge request if optional 3DS has been enabled for you. (If you’d like to skip authentication for optional or dynamic 3DS, please contact us so we can enable this feature for you. Refer to our Authentication documentation for instructions on integration and testing.) |
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) |
Charge with CVV for Multi-Use Token
Example Charge with CVV using Xendit.js
const tokenData = {
token_id: “sample-token-id-6ab4hmu832j8oenx71b”,
card_cvn: “123”,
billing_details: object,
customer: object
};
Example Charge with CVV using Android SDK
final Xendit xendit = new Xendit(getApplicationContext(), <PUBLISHABLE_KEY>, this);
xendit.storeCVN(
<tokenId>,
<cardCVN>,
<billingDetails>,
<customerDetails>,
null,
callback);
Example Charge with CVV using iOS SDK
let storeCVNRequest = XenditStoreCVNRequest.init(tokenId: <tokenId>);
authenticationRequest.cardCvn = <cardCvn>;
Xendit.storeCVN(
fromViewController: self,
storeCVNRequest: storeCVNRequest,
onBehalfOf: nil,
completion: completion)
CVV is part of the requirement that’s included specifically in card transactions, with cardholders providing three or four digit code to authorize the transaction. Why is including CVV important?
- Plays as an additional security precaution to authorize the transactions are coming from the real cardholder
- Increase issuer (bank) confidence to accept the transaction as it indicates the transaction made from the real cardholder
If a merchant would want to perform a transaction with CVN/CVV for multi-use token, please follow along this guide.
What is CVV?
CVV stands for “Card Verification Value,” is a three- or four-digit code on the front or back of the card. CVV is being used by the issuer as an additional layer of security, and thus providing it might increase the success rate and reduce the chance of fraud.
CVV is part of a Sensitive Authentication Data (SAD) and is highly regulated by PCI. According to the PCI rule, the business is not allowed to store the CVN/CVV after the authorization takes place and the system must be following the PCI regulation and processing CVN/CVV must be within the Card Data Environment (CDE) that’s being audited.
How to use
Prepare multiple use token ID that you would want to use to perform charge. Use the token ID by referring to the sample code on the right section.
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",
"network_response": {
"card_network_response_code": "65",
"card_network_descriptor": "Exceeds withdrawal count limit",
"network_transaction_id": "123456",
"merchant_advice_code": "28",
"merchant_advice_descriptor": "Retry after 6 days",
"three_ds_trans_status": "Y",
"three_ds_flow": "CHALLENGE"
}
}
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 |
with-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this card charge in order to split and route payments to multiple accounts. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.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. Recommendation is to check the input and retry. |
INVALID_JSON_FORMAT 400 |
The request body is not valid JSON. Recommendation is to check the input and retry. |
AMOUNT_GREATER_THAN400 |
Capture amount is larger than authorized amount. Ensure the capture amount is the same as what was authorized and retry. |
INVALID_CHARGE400 |
Charge status is not AUTHORIZED. Please authorize the transaction first then retry the capture. |
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 below |
failure_reason optional |
string |
Reason provided if refund request fails. See Refund Failure Reasons below |
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",
"network_response": {
"card_network_response_code": "65",
"card_network_descriptor": "Exceeds withdrawal count limit",
"network_transaction_id": "123456",
"merchant_advice_code": "28",
"merchant_advice_descriptor": "Retry after 6 days",
"three_ds_trans_status": "Y",
"three_ds_flow": "CHALLENGE"
}
}
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. Recommendation is to check the input and retry. |
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 or 8 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 or 8 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. |
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. |
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 or 8 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
API 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.
Version | Changelog |
---|---|
2021-01-25 Latest |
New simple and consistent eWallets API to support top eWallets providers in Indonesia and Philippines You can access the new API easily by calling POST /ewallets/charges |
Create eWallet Charge
Endpoint: Create eWallet Charge Request
POST https://api.xendit.co/ewallets/charges
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);
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
EWalletChargeClient eWalletCharge = xendit.EWalletCharge;
EWalletChargeParameter parameter = new EWalletChargeParameter
{
ReferenceId = "demo-reference-id",
Currency = Currency.IDR,
Amount = 1000,
CheckoutMethod = EWalletEnum.CheckoutMethod.OneTimePayment,
ChannelCode = EWalletEnum.ChannelCode.IdOvo,
ChannelProperties = new EWalletChargeProperties
{
MobileNumber = "+628123123123",
},
};
EWalletChargeResponse eWalletChargeResponse = await eWalletCharge.Create(parameter);
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-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this eWallet charge Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.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) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
currencyrequired |
string |
Currency used for the transaction in ISO4217 format - IDR , PHP , VND , THB , MYR |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
amountrequired |
number |
Transaction amount to be paid Min - 1,000 for ID_JENIUSPAY and 100 IDR for all other eWallets or 1 PHPMax - 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 , ID_ASTRAPAY , ID_JENIUSPAY , ID_SAKUKU , PH_PAYMAYA , PH_GCASH , PH_GRABPAY , PH_SHOPEEPAY , VN_APPOTA , VN_MOMO , VN_SHOPEEPAY , VN_VNPTWALLET , VN_VIETTELPAY , VN_ZALOPAY , TH_WECHATPAY , TH_LINEPAY , TH_TRUEMONEY , TH_SHOPEEPAY , MY_TOUCHNGO , MY_SHOPEEPAY , MY_GRABPAY , MY_WECHATPAY |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
channel_propertiesrequired based on
|
object |
Channel specific information required for the transaction to be initiated OVO - one time payment required fields
JENIUS PAY required fields
OVO - tokenized payment required fields
DANA, LINKAJA - one time payment, SHOPEEPAY (ID, PH & TH), WECHATPAY, LINEPAY, TRUEMONEY, TOUCHNGO - one time payment, SAKUKU required fields
SHOPEEPAY (VN), APPOTA, MOMO, ZALOPAY, VNPTWALLET, VIETTELPAY required fields
SHOPEEPAY (ID, PH & MY) - tokenized payment required fields
GCASH, GRABPAY (PH & MY), ASTRAPAY, LINKAJA, TOUCHNGO - tokenized payment required fields
MAYA (PAYMAYA) required fields
WECHATPAY (MY) required fields
GRABPAY (MY)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
payment_method_idrequired if checkout_method =
|
string |
ID of the payment method. Payment method is being used for tokenized payment to abstract your customer's ewallet as payment method | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer_idoptional |
string |
ID of the customer object to which the payment method will be linked to. Use Create Customer API to create your customer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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,
"refunded_amount": null,
"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",
"void_status": null,
"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 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
statusrequired |
string |
Status of charge request
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
currencyrequired |
string |
Currency used for the transaction in ISO4217 format - IDR , PHP , VND , THB , MYR |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
charge_amountrequired |
number |
Requested charge amount from merchant | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
capture_amountoptional |
number |
Requested capture amount from merchant. At the moment, capture_amount will always be the same as charge_amount |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
refunded_amountoptional |
number |
Total amount refunded by merchant to end user | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 , ID_ASTRAPAY , ID_JENIUSPAY , ID_SAKUKU , PH_PAYMAYA , PH_GCASH , PH_GRABPAY , PH_SHOPEEPAY , VN_APPOTA , VN_MOMO , VN_SHOPEEPAY , VN_VNPTWALLET , VN_VIETTELPAY , VN_ZALOPAY , TH_WECHATPAY , TH_LINEPAY , TH_TRUEMONEY , TH_SHOPEEPAY , MY_TOUCHNGO , MY_SHOPEEPAY , MY_GRABPAY , MY_WECHATPAY |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
channel_propertiesoptional |
object |
Channel specific information required for the transaction to be initiated OVO - one time payment required fields
JENIUS PAY required fields
OVO - tokenized payment required fields
DANA, LINKAJA - one time payment, SHOPEEPAY (ID, PH & TH) - one time payment, WECHATPAY, LINEPAY, TRUEMONEY, TOUCHNGO - one time payment, SAKUKU required fields
SHOPEEPAY (VN), APPOTA, MOMO, ZALOPAY, VNPTWALLET, VIETTELPAY required fields
SHOPEEPAY (ID, PH & MY) - tokenized payment required fields
GCASH, GRABPAY (PH & MY), ASTRAPAY, LINKAJA, TOUCHNGO - tokenized payment required fields
MAYA (PAYMAYA) required fields
WECHATPAY (MY) required fields
GRABPAY (MY)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void_statusoptional |
string |
Status of the void request. Available values: PENDING , FAILED , SUCCEEDED |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 |
---|---|
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_PAYMENT_METHOD_ID400 |
There is a mismatch between the requested channel_code or customer_id against the values used during creation of the specified payment_method_id. Or that the payment_method_id does not exist in this account. Please retry with a valid payment_method_id |
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 |
INVALID_TOKEN401 |
Account linking token for this end user has expired. Please reinitiate account linking before retrying. |
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 |
CHARGE_LIMIT_EXCEEDED429 |
Maximum of 3 request attempts to Jenius Pay per cashtag within a span of 10 minutes has been exceeded. Please wait for 10 minutes before trying to initiate a new request |
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 |
Payment Status Callback
Xendit notifies your system upon successful payments via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard under eWallets paid
.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Example: Success Payment Webhook 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,
"payment_detail": {
"fund_source": "SHOPEEPAY_BALANCE",
"source": null
},
"metadata": {
"branch_code": "tree_branch"
}
}
}
Header Parameter | Type | Description |
---|---|---|
x-callback-token |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-id |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant. ewallet.capture occurs when eWallet provider confirms the payment status of a transaction |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
business_idrequired |
string |
Business ID of the merchant | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for webhook 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 Webhook 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,
"refunded_amount": null,
"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",
"void_status": null,
"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. |
FAILURE_DETAILS_UNAVAILABLE |
Details related to the failed payment request were not provided by the eWallet provider. |
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);
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
EWalletChargeClient eWalletCharge = xendit.EWalletCharge;
EWalletChargeResponse eWalletChargeRepsonse = await eWalletCharge.Get("ewc_bb8c3po-c3po-r2d2-c3po-r2d2c3por2d2");
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,
"refunded_amount": null,
"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",
"void_status": null,
"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 , VND , THB , MYR |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
charge_amountrequired |
number |
Requested charge amount from merchant | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
capture_amountoptional |
number |
Requested capture amount from merchant. At the moment, capture_amount will always be the same as charge_amount |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
refunded_amountoptional |
number |
Total amount refunded by merchant to end user | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 , ID_ASTRAPAY , ID_JENIUSPAY , ID_SAKUKU , PH_PAYMAYA ,PH_GCASH , PH_GRABPAY , PH_SHOPEEPAY , VN_APPOTA , VN_MOMO , VN_SHOPEEPAY , VN_VNPTWALLET , VN_VIETTELPAY , VN_ZALOPAY , TH_WECHATPAY , TH_LINEPAY , TH_TRUEMONEY , TH_SHOPEEPAY , MY_TOUCHNGO , MY_SHOPEEPAY , MY_GRABPAY , MY_WECHATPAY |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
channel_propertiesoptional |
object |
Channel specific information required for the transaction to be initiated OVO - one time payment required fields
JENIUS PAY required fields
OVO - tokenized payment required fields
DANA, LINKAJA - one time payment, SHOPEEPAY (ID, PH & TH), WECHATPAY, LINEPAY, TRUEMONEY, TOUCHNGO - one time payment required fields
SHOPEEPAY (VN), APPOTA, MOMO, ZALOPAY, VNPTWALLET, VIETTELPAY one time payment required fields
SHOPEEPAY (ID, PH & MY) - tokenized payment required fields
GCASH, GRABPAY (PH & MY), ASTRAPAY, LINKAJA, TOUCHNGO - tokenized payment required fields
MAYA (PAYMAYA) required fields
WECHATPAY (MY) required fields
GRABPAY (MY)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void_statusoptional |
string |
Status of the void request. Available values: PENDING , FAILED , SUCCEEDED |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 |
Void eWallet Charge
This Void API allows you to void a successfully completed eWallet payment where 100% of the original amount is returned to the end user
Voiding an eWallet charge is defined as the cancellation of eWallet payments created within the same day and before the cutoff time of 23:50:00 (UTC+07:00 for Indonesia eWallets/ UTC+08:00 for Philippines eWallets). If an eWallet charge is created at 19:00:00 on 1 September 2021, cancelling this transaction by 23:50:00 (UTC+07:00 for Indonesia eWallets/ UTC+08:00 for Philippines eWallets) on 1 September 2021 can be done using this Void API. To cancel eWallet payments after the aforementioned cutoff time, the Refund API should be used
- Void API will only work for charges created via the
/ewallets/charges
API withSUCCEEDED
status - Void API will return
PENDING
void_status
in API response upon execution. A follow-up webhook/webhook will be sent to your system's URL when void has been processed successfully
Indonesia
Value | OVO | DANA | SHOPEEPAY | LINKAJA | ASTRAPAY | JENIUS PAY | SAKUKU |
---|---|---|---|---|---|---|---|
Available at Xendit? |
✓ | ✓ | ✓ | ✓ for One-Time Payment, ✕ for Tokenized Payment | ✕ | ✓ | ✕ |
Validity Period |
Same Day Before 23:50:00 UTC+07:00 | Same Day Before 23:50:00 UTC+07:00 | Same Day Before 23:50:00 UTC+07:00 | Same Day Before 23:50:00 UTC+07:00 | N/A | Same Day Before 23:50:00 UTC+07:00 | N/A |
Transaction Fee Returned? |
✓ | ✓ | ✓ | ✓ | N/A | ✓ | N/A |
Philippines
Value | GCASH | MAYA (PAYMAYA) | GRABPAY | SHOPEEPAY |
---|---|---|---|---|
Available at Xendit? |
✓ | ✓ | ✓ | ✓ |
Validity Period |
Same Day Before 23:50:00 UTC+08:00 | Same Day Before 23:50:00 UTC+08:00 | Same Day Before 23:50:00 UTC+08:00 | Same Day Before 23:50:00 UTC+08:00 |
Transaction Fee Returned? |
✓ | ✓ | ✓ | ✓ |
Vietnam
Value | APPOTA | MOMO | ZALOPAY | SHOPEEPAY | VNPTWALLET | VIETTELPAY |
---|---|---|---|---|---|---|
Available at Xendit? |
✕ | ✕ | ✕ | ✕ | ✕ | ✕ |
Thailand
Value | WECHATPAY | LINEPAY | SHOPEEPAY | TRUEMONEY |
---|---|---|---|---|
Available at Xendit? |
✕ | ✕ | ✕ | ✕ |
Malaysia
Value | TOUCHNGO | SHOPEEPAY | GRABPAY | WECHATPAY |
---|---|---|---|---|
Available at Xendit? |
✕ | x | x | x |
Endpoint: Create eWallet Void
POST https://api.xendit.co/ewallets/charges/{id}/void
Request Parameters
Example: Create eWallet Void - Request
curl https://api.xendit.co/ewallets/charges/ewc_532as23lew2321id/void -X POST \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
-H 'Content-Type: application/json' \
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Unique identifier for the charge request transaction (returned as id in the eWallet Charge request) |
Response Parameters
Example: Create eWallet Void - Response
{
"id" : "ewc_532as23lew2321id",
"business_id" : "5easfnn23aadlmnaa42",
"reference_id" : "test_reference_id",
"status" : "SUCCEEDED",
"currency" : "IDR",
"charge_amount" : 123456,
"capture_amount" : 123456,
"refunded_amount" : null,
"checkout_method" : "ONE_TIME_PAYMENT",
"channel_code" : "ID_DANA",
"channel_properties" :
{
"mobile_number" : "+6287777771111"
},
"actions" : null,
"is_redirect_required" : false,
"callback_url" : "https://webhook.me/gethooked",
"created" : "2020-04-20T16:23:52Z",
"updated" : "2020-04-20T16:23:52Z",
"void_status" : "PENDING",
"voided_at" : null,
"capture_now" : true,
"customer_id" : null,
"payment_method_id" : null,
"failure_code" : null,
"basket" : null,
"metadata" :
{
"branch_code" : "senayan_372"
}
}
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. At the moment, capture_amount will always be the same as charge_amount |
||||||||||||||||||||||||||||||||||||||||
refunded_amountoptional |
number |
Total amount refunded by merchant to end user | ||||||||||||||||||||||||||||||||||||||||
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 , ID_JENIUSPAY , PH_PAYMAYA ,PH_GCASH , PH_GRABPAY , PH_SHOPEEPAY |
||||||||||||||||||||||||||||||||||||||||
channel_propertiesoptional |
object |
Channel specific information required for the transaction to be initiated OVO - one time payment required fields
JENIUS PAY required fields
OVO - tokenized payment required fields
DANA, LINKAJA - one time payment, SHOPEEPAY (ID & PH) - one time payment required fields
SHOPEEPAY (ID & PH) - tokenized payment required fields
GCASH, GRABPAY, ASTRAPAY, LINKAJA - tokenized payment required fields
MAYA (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 |
Webhook 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 | ||||||||||||||||||||||||||||||||||||||||
void_statusoptional |
string |
Status of the void request. Value should be PENDING at this point |
||||||||||||||||||||||||||||||||||||||||
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 webhook 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 Void - Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "Resource not found. Please check your query again."
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is an error with the format submitted to the server. |
VOID_NOT_SUPPORTED400 |
Void feature is not available as the method is not provided by eWallet provider. |
VOID_TEMPORARILY_UNAVAILABLE400 |
Void feature is unavailable between 00:00:00 and 05:00:00 UTC+07:00/UTC+08:00 each day for ShopeePay transactions. Please try again after 05:00:00 UTC+07:00/UTC+08:00. |
INVALID_API_KEY401 |
API key format is invalid. |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request. |
INELIGIBLE_TRANSACTION403 |
Payment has already passed its void validity period (after 23:50:00 UTC+07:00/UTC+08:00) for requested operation or status of charge is not SUCCEEDED . |
INELIGIBLE_MERCHANT403 |
Merchant has a settlement configuration that is not eligible for voiding transactions. Please contact Xendit customer support for resolution. |
DATA_NOT_FOUND404 |
Resource not found. Please check your query again. |
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 Void
To get the status of an eWallet void request, use the Get eWallet Charge Status API where the response includes the void_status
and voided_at
parameters
Void Callback
The void webhook notification will be sent as POST request to the same endpoint used in creating an eWallet charge. 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
Webhook Payload
Example: Success eWallet Void Webhook Payload
{
"event": "ewallet.void",
"business_id": "5abe2389ewpejrt238",
"created": "2020-04-20T16:25:52Z",
"data": {
"id": "ewc_532as23lew2321id",
"reference_id": "test_reference_id",
"status": "VOIDED",
"currency": "IDR",
"checkout_method": "ONE_TIME_PAYMENT",
"charge_amount": 123456,
"capture_amount": 123456,
"refunded_amount": null,
"channel_code": "ID_DANA",
"channel_properties": {
"mobile_number": "+6287777771111"
},
"actions": null,
"is_redirect_required": false,
"callback_url": "https://webhook.me/gethooked",
"created": "2020-04-20T16:23:52Z",
"updated": "2020-04-20T16:23:52Z",
"void_status": "SUCCEEDED",
"voided_at": "2020-04-20T23:24:30Z",
"capture_now": true,
"customer_id": null,
"payment_method_id": null,
"failure_code": null,
"basket": null,
"metadata": {
"branch_code": "senayan_372"
}
}
}
Header Parameter | Type | Description |
---|---|---|
x-callback-token |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-id |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Parameter Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant. ewallet.void occurs when eWallet provider confirms the receipt of a void request |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
Timestamp in ISO 8601 for webhook notification creation. Timezone UTC+0 |
dataoptional |
object |
eWallet Charge object, with business_id abstracted out |
Refund eWallet Charge
This Refund API allows you to fully or partially refund a successfully completed eWallet payment. It is possible to request multiple refunds for a single transaction as long as the aggregate refund amount does not exceed the original transaction amount
Other than the Refund API, the Void API can also be used to cancel an eWallet payment within the same day as the charge creation and before the cutoff time of 23:50:00 (UTC+07:00 for Indonesia eWallets/ UTC+08:00 for Philippines eWallets). Void guarantees that transaction fee and VAT are refunded since the cancellation happens before any real money is moved. Specifically for DANA payments, transaction fee and VAT are refunded in a successful void request but not in a successful refund request
- Refund API will only work for charges created via the
/ewallets/charges
API withSUCCEEDED
orREFUNDED
status for partial refund - Refund API will return
PENDING
status in API response upon execution. A follow-up webhook will be sent to your system's URL when refund has been processed successfully
Indonesia
Value | OVO | DANA | SHOPEEPAY | LINKAJA | ASTRAPAY | JENIUS PAY | SAKUKU |
---|---|---|---|---|---|---|---|
Available at Xendit? |
✕ for One-Time Payment, ✓ for Tokenized Payment | ✓ | ✓ | ✓ for One-Time Payment, ✕ for Tokenized Payment | ✕ | ✓ | ✕ |
Partial Refund Allowed? |
✓ | ✓ | ✓ | ✕ | N/A | ✓ | N/A |
Multiple Refunds Allowed? |
✓ | ✓ | ✓ | ✕ | N/A | ✕ (Only 1 Partial Refund Per Payment Allowed) | N/A |
Validity Period |
14 Days | 30 Days | 365 Days | 30 Days | N/A | Always Valid/No Expiration | N/A |
Transaction Fee Returned? |
✓ | ✕ | ✓ | ✓ | N/A | ✓ for Full Refund, ✕ for Partial Refund | N/A |
Philippines
Value | GCASH | MAYA (PAYMAYA) | GRABPAY | SHOPEEPAY |
---|---|---|---|---|
Available at Xendit? |
✓ | ✓ | ✓ | ✓ |
Partial Refund Allowed? |
✓ | ✓ (Not on Same Day) |
✓ | ✓ |
Multiple Refunds Allowed? |
✓ (Capped at 7) |
✓ | ✓ | ✓ |
Validity Period |
180 Days | 365 Days | 365 Days | 365 Days |
Transaction Fee Returned? |
✓ | ✓ | ✓ | ✓ |
Vietnam
Value | APPOTA | MOMO | ZALOPAY | SHOPEEPAY | VNPTWALLET | VIETTELPAY |
---|---|---|---|---|---|---|
Available at Xendit? |
✓ | ✓ | ✓ | ✓ | ✓ | ✕ |
Partial Refund Allowed? |
✕ | ✓ | ✓ | ✓ | ✕ | N/A |
Multiple Refunds Allowed? |
✕ | ✓ | ✓ | ✓ | ✕ | N/A |
Validity Period |
Always Valid/No Expiration | Always Valid/No Expiration | 180 Days | 90 Days | Always Valid/No Expiration | N/A |
Transaction Fee Returned? |
✓ | ✓ | ✓ | ✓ | ✓ | N/A |
Thailand
Value | WECHATPAY | LINEPAY | SHOPEEPAY | TRUEMONEY |
---|---|---|---|---|
Available at Xendit? |
✕ | ✕ | ✕ | ✕ |
Malaysia
Value | TOUCHNGO | SHOPEEPAY | GRABPAY | WECHATPAY |
---|---|---|---|---|
Available at Xendit? |
✓ | ✓ | ✓ | ✓ |
Partial Refund Allowed? |
✓ | ✓ | ✓ | ✕ |
Multiple Refunds Allowed? |
✓ | ✓ | ✓ | ✕ |
Validity Period |
30 Days | 365 Days | 365 Days | 365 Days |
Transaction Fee Returned? |
✓ | ✓ | ✓ | ✓ |
Endpoint: Create eWallet Refund
POST https://api.xendit.co/ewallets/charges/{id}/refunds
Request Parameters
Example: Create eWallet Refund - Request
curl hhttps://api.xendit.co/ewallets/charges/ewc_532as23lew2321id/refunds -X POST \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
-H 'Content-Type: application/json' \
--data-raw '{
"amount": "1000",
"reason": "REQUESTED_BY_CUSTOMER"
}'
Example: Sample JSON request
{
"amount": 1000,
"reason": "REQUESTED_BY_CUSTOMER"
}
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Unique identifier for charge request transaction (returned as id in the eWallet Charge request) |
Body Parameter | Type | Description |
---|---|---|
amount optional |
number
|
Amount to be refunded to your customer. Cumulative amount refunded must not exceed the original transacted amount. If the amount field is not present in the request body, the remaining unrefunded amount of the charge would be processed |
reason optional |
string
|
Reason for refund, one of the following values can be used. Available values: DUPLICATE , FRAUDULENT , REQUESTED_BY_CUSTOMER , CANCELLATION , OTHERS
|
Response Parameters
Example: Create eWallet Refund - Response
{
"id" : "ewr_532as23lew2321id",
"charge_id" : "5easfnn23aadlmnaa42",
"status" : "PENDING",
"currency" : "IDR",
"channel_code" : "ID_DANA",
"capture_amount" : 123456,
"refund_amount" : 123456,
"reason" : "REQUESTED_BY_CUSTOMER",
"failure_code" : null,
"created" : "2020-04-20T16:23:52Z",
"updated" : "2020-04-20T16:23:52Z"
}
Body Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the refund transaction |
charge_id | string |
Unique identifier for the original charge transaction |
status | string |
Status of the refund request Available values: SUCCEEDED , FAILED , PENDING |
currency | string |
Currency used for the transaction in ISO 4217 formatSupported currency: IDR , PHP , MYR , VND |
capture_amount | number |
Requested capture amount from merchant |
refund_amount | number |
Amount to be refunded |
channel_code | string |
Channel code indicating eWallet provider Supported channels: ID_OVO , ID_DANA , ID_SHOPEEPAY , ID_LINKAJA , ID_JENIUSPAY , PH_PAYMAYA ,PH_GCASH , PH_GRABPAY , PH_SHOPEEPAY , VN_APPOTA , VN_MOMO , VN_SHOPEEPAY , VN_VNPTWALLET , VN_ZALOPAY , MY_TOUCHNGO , MY_SHOPEEPAY , MY_GRABPAY , MY_WECHATPAY |
reason | string |
Reason for refund |
failure_code | string |
Reason for refund transaction failing |
created | string |
Timestamp in ISO 8601 for refund request |
updated | number |
Timestamp in ISO 8601 for refund object update |
Error Codes
Example: Create eWallet Refund - Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "Resource not found. Please check your query again."
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is an error with the format submitted to the server. |
MAXIMUM_REFUND_AMOUNT_REACHED400 |
Requested refund amount cannot exceed remaining unrefunded amount of the successful charge. |
MAXIMUM_REFUND_TRANSACTION_REACHED400 |
You have reached the maximum refund transactions allowed for this charge. Kindly check the refund limitations for all eWallet channels here https://docs.xendit.co/ewallet/payment-flows/void-and-refund#refund-ewallet-charge. |
PARTIAL_REFUND_NOT_SUPPORTED400 |
Partial refund feature is not available as the method is not provided by the eWallet provider. |
REFUND_TEMPORARILY_UNAVAILABLE400 |
Refund feature is unavailable between 23:50:00 and 05:00:00 UTC+07:00/UTC+08:00 each day for ShopeePay transactions. Please try again after 05:00:00 UTC+07:00/UTC+08:00. |
REFUND_TEMPORARILY_UNAVAILABLE400 |
Partial refund feature is not available for Maya (PayMaya) on the day of transaction. Please try again after 23:59:59 of transaction day. |
REFUND_NOT_SUPPORTED400 |
Refund feature is not available as the method is not provided by the eWallet provider. |
REFUND_IN_PROGRESS400 |
Concurrent refund requests to a single eWallet charge is not allowed. Please wait for the pending refund request to be completed before initiating a new one. |
INVALID_API_KEY401 |
API key format is invalid. |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request. |
INELIGIBLE_TRANSACTION403 |
Payment has already passed its refund validity period for the requested operation or the status of the original transaction is FAILED , PENDING , or VOIDED . |
INSUFFICIENT_BALANCE403 |
There is insufficient balance in your account to perform a refund. Please top up your balance with a sufficient amount before retrying the refund. |
DATA_NOT_FOUND404 |
Resource not found. Please check your query again. |
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. |
Refund Callback
The refund webhook notification will be sent as POST request to the same endpoint used in creating an eWallet charge. 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
Webhook Payload
Example: Success eWallet Refund Webhook Payload
{
"event": "ewallet.refund",
"business_id": "5abe2389ewpejrt238",
"created": "2020-04-20T16:25:52Z",
"data": {
"id": "ewr_532as23lew2321id",
"charge_id": "ewc_5easfnn23aadlmnaa42",
"status": "SUCCEEDED",
"currency": "IDR",
"channel_code": "ID_DANA",
"capture_amount": 123456,
"refund_amount": 123456,
"reason": "REQUESTED_BY_CUSTOMER",
"failure_code": null,
"created": "2020-04-20T16:23:52Z",
"updated": "2020-04-20T16:23:52Z"
}
}
Header Parameter | Type | Description |
---|---|---|
x-callback-token |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-id |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Parameter Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant. ewallet.refund occurs when eWallet provider confirms the receipt of a refund request |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
Timestamp in ISO 8601 for webhook notification creation. Timezone UTC+0 |
dataoptional |
object |
eWallet Refund object, with business_id abstracted out |
Failure Codes
Failure Code | Description |
---|---|
INELIGIBLE_TRANSACTION |
Transaction has already passed its validity period for the requested operation or the number of refunds requested has exceeded the allowable number of tries. |
INSUFFICIENT_BALANCE |
Switcher account does not have sufficient balance to perform a refund. Please retry after ensuring there is sufficient balance in the switcher account. |
REFUND_TEMPORARILY_UNAVAILABLE |
Refund is temporarily unavailable because of settlement constraints with the eWallet provider. Please try again later. |
MAXIMUM_USER_BALANCE_EXCEEDED |
Refund could not be processed because the amount returned will cause end user's wallet balance to exceed maximum allowable value. |
INELIGIBLE_PARTIAL_REFUND_TRANSACTION |
Transaction specified is not eligible for partial refund because of eWallet provider's limitations. You can retry refund by doing full refund. GrabPay doesn't allow partial refunds for transactions made under promos or using GrabPay points. |
Get Refund
Get the status and details of a specific eWallet refund by its Refund ID
Endpoint: Get eWallet Refund by Refund ID
GET https://api.xendit.co/ewallets/charges/{charge_id}/refunds/{refund_id}
Request Parameters
Example: GET eWallet Refund by Refund ID - Request
curl https://api.xendit.co/ewallets/charges/ewc_5easfnn23aadlmnaa42/refunds/ewr_532as23lew2321id -X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
charge_id required |
string
|
ID of eWallet Charge |
refund_id required |
string
|
ID of eWallet Refund |
Response Parameters
Example: GET eWallet Refund by Refund ID - Response
{
"id" : "ewr_532as23lew2321id",
"charge_id" : "5easfnn23aadlmnaa42",
"status" : "SUCCEEDED",
"currency" : "IDR",
"channel_code" : "ID_DANA",
"capture_amount" : 123456,
"refund_amount" : 100000,
"reason" : "REQUESTED_BY_CUSTOMER",
"failure_code" : null,
"created" : "2020-04-20T16:23:52Z",
"updated" : "2020-04-20T16:23:52Z"
}
Body Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the refund transaction |
charge_id | string |
Unique identifier for the original charge transaction |
status | string |
Status of the refund request Available values: SUCCEEDED , FAILED , PENDING |
currency | string |
Currency used for the transaction in ISO 4217 formatSupported currency: IDR , PHP , MYR , VND |
capture_amount | number |
Requested capture amount from merchant |
refund_amount | number |
Amount to be refunded |
channel_code | string |
Channel code indicating eWallet provider Supported channels: ID_OVO , ID_DANA , ID_SHOPEEPAY , ID_LINKAJA , ID_JENIUSPAY , PH_PAYMAYA ,PH_GCASH , PH_GRABPAY , PH_SHOPEEPAY , VN_APPOTA , VN_MOMO , VN_SHOPEEPAY , VN_VNPTWALLET , VN_ZALOPAY , MY_TOUCHNGO , MY_SHOPEEPAY , MY_GRABPAY , MY_WECHATPAY |
reason | string |
Reason for refund |
failure_code | string |
Reason for refund transaction failing |
created | string |
Timestamp in ISO 8601 for refund request |
updated | number |
Timestamp in ISO 8601 for refund object update |
Error Codes
Example: GET eWallet Refund by Refund ID - Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "Resource not found. Please check your query again."
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is an error with the format submitted to the server. |
INVALID_API_KEY401 |
API key format is invalid. |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request. |
DATA_NOT_FOUND404 |
Resource not found. Please check your query again. |
SERVER_ERROR500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
List Refunds
Get the details of all eWallet refunds associated with a single eWallet charge transaction by the Charge ID
Endpoint: List eWallet Refunds by Charge ID
GET https://api.xendit.co/ewallets/charges/{id}/refunds
Request Parameters
Example: List eWallet Refunds by Charge ID - Request
curl https://api.xendit.co/ewallets/charges/ewc_532as23lew2321id/refunds -X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Unique identifier for charge request transaction (returned as id in the eWallet Charge request) |
Query Parameter | Type | Description |
---|---|---|
limit optional |
number
|
Maximum number of results to return at one time Default: 10 Minimum: 1 Maximum: 50 |
status optional |
string
|
Refund status to be retrieved Available values: SUCCEEDED , FAILED , PENDING
|
Response Parameters
Example: List eWallet Refunds by Charge ID - Response
{
"data": [
{
"id" : "ewr_532as23lew2321id",
"charge_id" : "ewc_5easfnn23aadlmnaa42",
"status" : "SUCCEEDED",
"currency" : "IDR",
"channel_code" : "ID_DANA",
"capture_amount" : 123456,
"refund_amount" : 100000,
"reason" : "REQUESTED_BY_CUSTOMER",
"failure_code" : null,
"created" : "2020-04-20T16:23:52Z",
"updated" : "2020-04-20T16:23:52Z"
},
{
"id" : "ewr_532as23lew2321id",
"charge_id" : "5easfnn23aadlmnaa42",
"status" : "SUCCEEDED",
"currency" : "IDR",
"channel_code" : "ID_DANA",
"capture_amount" : 123456,
"refund_amount" : 23456,
"reason" : "OTHER",
"failure_code" : null,
"created" : "2020-04-20T16:23:52Z",
"updated" : "2020-04-20T16:23:52Z"
}
],
"has_more": false
}
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
data | array |
Data array of eWallet refund object(s) related to specified Charge ID Refund object parameters
|
||||||||||||||||||||||||
has_more | boolean |
Indicates whether there are more items to be queried based on the query filters from the current result. If result is empty, has_more will be false |
Error Codes
Example: List eWallet Refunds by Charge ID - Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "Resource not found. Please check your query again."
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is an error with the format submitted to the server. |
INVALID_API_KEY401 |
API key format is invalid. |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request. |
DATA_NOT_FOUND404 |
Resource 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 Object
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.
Version | Changelog |
---|---|
Payment methods account linking Latest |
Simplified tokenization and account linking flow is now available; ID - OVO , DANA , LINKAJA , SHOPEEPAY , PH - MAYA , GRABPAY , SHOPEEPAY , and MY - TOUCHNGO , SHOPEEPAY , GRABPAY No API Versioning is required. You can access the new API easily by calling POST .../v2/payment_methods |
LAT account linking flow version with previous account linking flow |
Tokenization and account linking flow is now available |
There are 2 steps required to perform account linking using our tokenization flow - starting with a customer object creation and creating a payment method.
Step 1 - Creation of customer object via /customers endpoint is the required first step before initiating 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. Depending on each payment channel's requirements, there might be required fields for customer objects (e.g. OVO requires name and phone number). In such cases, it is recommended for merchants to build a UI for end users to key in these information themselves. Please refer to the requirements each payment channel below and Customer section to create customer object.
DANA / SHOPEEPAY (ID, PH & MY) / MAYA (PAYMAYA) / GRABPAY (PH & MY) / TOUCHNGO tokenization - required fields in Customer Object
No specific eWallet channel requirements, any customer object fufilling Xendit's API requirements is sufficient
OVO tokenization - required fields in Customer Object
Example Customer Object - OVO tokenization
curl https://api.xendit.co/customers -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--data '{
"reference_id": "demo_1475801962607",
"given_names": "John",
"mobile_number": "+6287774441111",
"email": "customer@website.com"
}' \
Request Body Parameter | Type | Description |
---|---|---|
reference_id required |
string
|
Merchant-provided identifier for the customer (max 255 characters) |
mobile_number required |
string
|
Key identifier used by OVO for account linking. Mobile number of the customer in E.164 international standard must match with OVO's database. Format: +(country code)(subscriber number)
|
given_names required |
string
|
Primary of first name/s of the customer (max 255 characters) |
LINKAJA tokenization - required fields in Customer Object
Example Customer Object - LINKAJA tokenization
curl https://api.xendit.co/customers -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--data '{
"reference_id": "demo_1475801962607",
"mobile_number": "+6287774441111"
}' \
Request Body Parameter | Type | Description |
---|---|---|
reference_id required |
string
|
Merchant-provided identifier for the customer (max 255 characters) |
mobile_number required |
string
|
Key identifier used by LinkAja for account linking. Mobile number of the customer in E.164 international standard must match with LinkAja's database. Format: +(country code)(subscriber number)
|
Create Customer - Errors
See other common errors here
Error Code | Description |
---|---|
DUPLICATE_ERROR409 |
The provided reference_id has been used before. Please enter a unique reference_id |
IDEMPOTENCY_ERROR409 |
Provided Idempotency-key already exists, but the request body provided does not match the original request |
Tokenized - 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 payment method
will be created as a result. End users need to be redirected to the eWallet provider's hosted page to authorize the account linking. Once the account linking is completed by the end user, an account linking notification will be sent to the callback url specified in the Xendit dashboard under payment methods
section.
The table below summarizes key onboarding information of these tokenization payment flow. By default, all tokenization flow requires approval with eWallet partners. Auto debit flows which require special approval will require escalation to the eWallet partners before merchants can access the feature.
Indonesia
Value | OVO | DANA | LINKAJA | SHOPEEPAY |
---|---|---|---|---|
Redirection (PIN required) payment |
Approval required | Approval required | Approval required | Approval required |
Auto debit payment |
Special approval required | Special approval required | ✕ | Special approval required |
Philippines
Value | SHOPEEPAY | MAYA (PAYMAYA) | GRABPAY | GCASH |
---|---|---|---|---|
Auto debit payment |
Approval required | Approval required | Approval required | Approval required |
Malaysia
Value | TOUCHNGO | SHOPEEPAY | GRABPAY |
---|---|---|---|
Auto debit payment |
Approval required | Approval required | Approval required |
Endpoint: Account Linking - Create Payment Method
POST https://api.xendit.co/v2/payment_methods
Account Linking - Create Payment Method Request
Example Account Linking - Create Payment Method Request
curl https://api.xendit.co/v2/payment_methods -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"type": "EWALLET",
"reusability": "MULTIPLE_USE",
"ewallet": {
"channel_code": "OVO",
"channel_properties": {
"success_return_url": "https://your-redirect-website.com/success",
"failure_return_url": "https://your-redirect-website.com/failure"
}
},
"customer_id": "fc4c060b-3c41-4707-b7b2-df9c3376edde"
}' \
{
"type": "EWALLET",
"reusability": "MULTIPLE_USE",
"ewallet": {
"channel_code": "OVO",
"channel_properties": {
"success_return_url": "https://your-redirect-website.com/success",
"failure_return_url": "https://your-redirect-website.com/failure"
}
},
"customer_id": "fc4c060b-3c41-4707-b7b2-df9c3376edde"
}
Request Body Parameter | Type | Description | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
type required |
string
|
Type of payment method - to use EWALLET as value |
||||||||||||||||||||
reusability required |
string
|
Describes whether or not the payment method can be reused for subsequent payments without going through the same linking process again. use MULTIPLE_USE as value for eWallets |
||||||||||||||||||||
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 | ||||||||||||||||||||
country required |
string
|
2-letter ISO 3166-2 country code indicating country of transaction. This is also be used as indicator for channels that are present in multiple markets (e.g. shopeepay). Available values - PH for Philippines, ID for Indonesia, MY for Malaysia |
||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment method. If none is provided, Xendit will randomly generate a unique reference_id
|
||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method | ||||||||||||||||||||
metadata optional |
string
|
A free-format JSON for additional information that you may use | ||||||||||||||||||||
ewallet required |
object
|
For type='EWALLET', this contains the necessary information to describe an ewallet payment method
|
Account Linking - Create Payment Method Response
Example Account Linking - Create Payment Method Success Response
{
"id": "pm-123123123-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "EWALLET",
"country": "ID",
"business_id": "5f27a14a9bf05c73123123123",
"customer_id": "fc4123123-3c41-4707-b7b2-df9c3376edde",
"reference_id": "b63798d3-8240-48c3-af12-3b3c62c0981a",
"reusability": "MULTIPLE_USE",
"status": "REQUIRES_ACTION",
"actions": [
{
"action": "AUTH",
"url": "https://link-web.xendit.co/auth/lat-bcf19cc8-f097-44fb-839c-6e4aed807d00/confirm",
"url_type": "WEB",
"method": "GET"
}
],
"description": null,
"created": "2021-08-18T03:52:56.936277373Z",
"updated": "2021-08-18T03:52:56.936277373Z",
"metadata": {
"sku": "IPHONE20"
},
"ewallet": {
"channel_code": "OVO",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
},
"account": {
"name": null,
"account_details": null,
"balance": null,
"point_balance": null
}
},
"direct_bank_transfer": null,
"direct_debit": null,
"card": null,
"over_the_counter": null,
"qr_code": null,
"virtual_account": null
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for the payment method. This has a prefix of pm-. Example: pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 | ||||||||||||||||||||||||||||||||
typerequired |
string |
Type of payment method - to use EWALLET as value |
||||||||||||||||||||||||||||||||
reusabilityrequired |
string |
Describes whether or not the payment method can be reused for subsequent payments without going through the same linking process again. use MULTIPLE_USE as value for eWallets |
||||||||||||||||||||||||||||||||
customer_idrequired |
string |
ID of the customer object to which the account token will be linked to. Call Tokenized - Create Customer to generate Customer ID | ||||||||||||||||||||||||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||||||||||||||||||||||||
reference_idoptional |
string |
Merchant-provided identifier for this payment method. If none is provided, Xendit will randomly generate a unique reference_id |
||||||||||||||||||||||||||||||||
statusrequired |
string |
Status of the payment method. Allowed values - PENDING , REQUIRES_ACTION , ACTIVE , INACTIVE , EXPIRED REQUIRES_ACTION - The request passed validation but requires additional steps in order to activate the payment method for use. Typical actions are for merchant to trigger OTP validation or redirect your customer to authentication page.ACTIVE - The payment method can be used for payment requests.INACTIVE - Merchant performing unlinking on payment method will trigger this status. This status prevents further transactions from the payment method and is reversible.EXPIRED - The underlying authorization has expired, invalidated, or has been unlinked. This status is not reversible |
||||||||||||||||||||||||||||||||
countryrequired |
string |
2-letter ISO 3166-2 country code indicating country of transaction. This is also be used as indicator for channels that are present in multiple markets (e.g. shopeepay). Available values - PH , ID , MY |
||||||||||||||||||||||||||||||||
actionsrequired |
object |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to activate a payment method
|
||||||||||||||||||||||||||||||||
ewalletrequired |
object |
For type='EWALLET', this contains the necessary information to describe an ewallet payment method
|
||||||||||||||||||||||||||||||||
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 | ||||||||||||||||||||||||||||||||
descriptionoptional |
object |
Free-text field for any additional information regarding the payment method | ||||||||||||||||||||||||||||||||
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 |
Account Linking - Create Payment Method Errors
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 |
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 |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DUPLICATE_ERROR409 |
Xendit code specifying the error encountered: There's an already existing record with the provided details |
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 |
Tokenized - Account Linking Status Callback
Notification when a payment method is successfully activated. This callback is triggered when a particular payment method has been successfully created and can be used for payments. Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings. Once you receive the payment method activation webhook, you are ready to make a payment transaction via our eWallets Charge endpint.
Callback Payload
Example: Payment Method Activation Callback Payload
{
"event": "payment_method.activated",
"business_id": "5f27a14a9bf05c73dd040bc8",
"created": "2020-08-29T09:12:33.001Z",
"data": {
"id": "pm-123123123-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "EWALLET",
"country": "ID",
"business_id": "5f27a14a9bf05c73123123123",
"customer_id": "fc4123123-3c41-4707-b7b2-df9c3376edde",
"reference_id": "b63798d3-8240-48c3-af12-3b3c62c0981a",
"reusability": "MULTIPLE_USE",
"status": "ACTIVE",
"actions": [
{
"action": "AUTH",
"url": "https://link-web.xendit.co/auth/lat-bcf19cc8-f097-44fb-839c-6e4aed807d00/confirm",
"url_type": "WEB",
"method": "GET"
}
],
"description": null,
"created": "2021-08-18T03:52:56.936277373Z",
"updated": "2021-08-18T03:52:56.936277373Z",
"metadata": {
"sku": "IPHONE20"
},
"ewallet": {
"channel_code": "SHOPEEPAY",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
},
"account": {
"name": null,
"account_details": "+62*****3123",
"balance": 10000,
"point_balance": 10000
}
},
"direct_bank_transfer": null,
"direct_debit": null,
"card": null,
"over_the_counter": null,
"qr_code": null,
"virtual_account": null
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.activated |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
business_idrequired |
string |
Business ID of the merchant | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dataoptional |
object |
Payment method object Data fields
|
Tokenized - Get Account Balance/Payment Method Details
Endpoint: Get Account Balance/Payment Method Details
GET https://api.xendit.co/v2/payment_methods/{id}
Get Account Balance/Payment Method Details - Request
Example Get Account Balance by Linked Account Token Request
curl https://api.xendit.co/v2/payment_methods/pm-EM8sad8as56dasdabk -X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
Path Parameter | Type | Description |
---|---|---|
idrequired |
string |
Payment method id received from account linking step. This has the pm- prefix. |
Get Account Balance/ Payment Method Details - Response
This endpoint returns the payment method object:
Example Get Account Balance/ Payment Method Details Response
{
"id": "pm-123123123-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "EWALLET",
"country": "ID",
"business_id": "5f27a14a9bf05c73123123123",
"customer_id": "fc4123123-3c41-4707-b7b2-df9c3376edde",
"reference_id": "b63798d3-8240-48c3-af12-3b3c62c0981a",
"reusability": "MULTIPLE_USE",
"status": "PENDING",
"actions": [
{
"action": "AUTH",
"url": "https://link-web.xendit.co/auth/lat-bcf19cc8-f097-44fb-839c-6e4aed807d00/confirm",
"url_type": "WEB",
"method": "GET"
}
],
"description": null,
"created": "2021-08-18T03:52:56.936277373Z",
"updated": "2021-08-18T03:52:56.936277373Z",
"metadata": {
"sku": "IPHONE20"
},
"ewallet": {
"channel_code": "SHOPEEPAY",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
},
"account": {
"name": null,
"account_details": "+62*****3123",
"balance": 10000,
"point_balance": 10000
}
},
"direct_bank_transfer": null,
"direct_debit": null,
"card": null,
"over_the_counter": null,
"qr_code": null,
"virtual_account": null
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for the payment method. This has a prefix of pm-. Example: pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 | ||||||||||||||||||||||||||||||||
typerequired |
string |
Type of payment method - to use EWALLET as value |
||||||||||||||||||||||||||||||||
reusabilityrequired |
string |
Describes whether or not the payment method can be reused for subsequent payments without going through the same linking process again. use MULTIPLE_USE as value for eWallets |
||||||||||||||||||||||||||||||||
customer_idrequired |
string |
ID of the customer object to which the account token will be linked to. Call Tokenized - Create Customer to generate Customer ID | ||||||||||||||||||||||||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||||||||||||||||||||||||
reference_idoptional |
string |
Merchant-provided identifier for this payment method. If none is provided, Xendit will randomly generate a unique reference_id |
||||||||||||||||||||||||||||||||
statusrequired |
string |
Status of the payment method. Allowed values - PENDING , REQUIRES_ACTION , ACTIVE , INACTIVE , EXPIRED REQUIRES_ACTION - The request passed validation but requires additional steps in order to activate the payment method for use. Typical actions are for merchant to trigger OTP validation or redirect your customer to authentication page.ACTIVE - The payment method can be used for payment requests.INACTIVE - Merchant performing unlinking on payment method will trigger this status. This status prevents further transactions from the payment method and is reversible.EXPIRED - The underlying authorization has expired, invalidated, or has been unlinked. This status is not reversible |
||||||||||||||||||||||||||||||||
countryrequired |
string |
2-letter ISO 3166-2 country code indicating country of transaction. This is also be used as indicator for channels that are present in multiple markets (e.g. shopeepay). Available values - PH , ID , MY |
||||||||||||||||||||||||||||||||
actionsrequired |
object |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to activate a payment method
|
||||||||||||||||||||||||||||||||
ewalletrequired |
object |
For type='EWALLET', this contains the necessary information to describe an ewallet payment method
|
||||||||||||||||||||||||||||||||
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 | ||||||||||||||||||||||||||||||||
descriptionoptional |
object |
Free-text field for any additional information regarding the payment method | ||||||||||||||||||||||||||||||||
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 |
Get Account Balance/Payment Method Details - Errors
See other common errors here
Error Code | Description |
---|---|
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND_ERROR 404 |
Provided payment_method_id is not supported or has not yet activated for this account |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Tokenized - Unlinking
Unlinks a successful linked account token.
Endpoint: Unlink a Payment Method
POST https://api.xendit.co/v2/payment_methods/{id}/expire
Unlink a Payment Method - Request
Example Unlink a Payment Method Request
curl https://api.xendit.co/v2/payment_methods/pm-EM8sad8as56dasdabk/expire -X POST \
-u xnd_development_OSuxk743ma423balls+2fT/7GlCAN3jg==:
Path Parameter | Type | Description |
---|---|---|
idrequired |
string |
Payment method id received from account linking step. This has the pm- prefix |
Unlink a Payment Method - Response
Example Unlink a Payment Method Response
{
"id": "pm-123123123-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "EWALLET",
"country": "ID",
"business_id": "5f27a14a9bf05c73123123123",
"customer_id": "fc4123123-3c41-4707-b7b2-df9c3376edde",
"reference_id": "b63798d3-8240-48c3-af12-3b3c62c0981a",
"reusability": "MULTIPLE_USE",
"status": "PENDING",
"actions": [
{
"action": "AUTH",
"url": "https://link-web.xendit.co/auth/lat-bcf19cc8-f097-44fb-839c-6e4aed807d00/confirm",
"url_type": "WEB",
"method": "GET"
}
],
"description": null,
"created": "2021-08-18T03:52:56.936277373Z",
"updated": "2021-08-18T03:52:56.936277373Z",
"metadata": {
"sku": "IPHONE20"
},
"ewallet": {
"channel_code": "OVO",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
},
"account": {
"name": null,
"account_details": null,
"balance": null,
"point_balance": null
}
},
"direct_bank_transfer": null,
"direct_debit": null,
"card": null,
"over_the_counter": null,
"qr_code": null,
"virtual_account": null
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for the payment method. This has a prefix of pm-. Example: pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 | ||||||||||||||||||||||||||||||||
typerequired |
string |
Type of payment method - to use EWALLET as value |
||||||||||||||||||||||||||||||||
reusabilityrequired |
string |
Describes whether or not the payment method can be reused for subsequent payments without going through the same linking process again use MULTIPLE_USE as value for eWallets |
||||||||||||||||||||||||||||||||
customer_idrequired |
string |
ID of the customer object to which the account token will be linked to. Call Tokenized - Create Customer to generate Customer ID | ||||||||||||||||||||||||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||||||||||||||||||||||||
reference_idoptional |
string |
Merchant-provided identifier for this payment method. If none is provided, Xendit will randomly generate a unique reference_id |
||||||||||||||||||||||||||||||||
statusrequired |
string |
Status of the payment method. Allowed values - PENDING , REQUIRES_ACTION , ACTIVE , INACTIVE , EXPIRED REQUIRES_ACTION - The request passed validation but requires additional steps in order to activate the payment method for use. Typical actions are for merchant to trigger OTP validation or redirect your customer to authentication page.ACTIVE - The payment method can be used for payment requests.INACTIVE - Merchant performing unlinking on payment method will trigger this status. This status prevents further transactions from the payment method and is reversible.EXPIRED - The underlying authorization has expired, invalidated, or has been unlinked. This status is not reversible |
||||||||||||||||||||||||||||||||
countryrequired |
string |
2-letter ISO 3166-2 country code indicating country of transaction. This is also be used as indicator for channels that are present in multiple markets (e.g. shopeepay). Available values - PH , ID , MY |
||||||||||||||||||||||||||||||||
actionsrequired |
object |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to activate a payment method
|
||||||||||||||||||||||||||||||||
ewalletrequired |
object |
For type='EWALLET', this contains the necessary information to describe an ewallet payment method
|
||||||||||||||||||||||||||||||||
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 | ||||||||||||||||||||||||||||||||
descriptionoptional |
object |
Free-text field for any additional information regarding the payment method | ||||||||||||||||||||||||||||||||
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 |
Unlink a Payment Method - Errors
See other common errors here
Error Code | Description |
---|---|
INVALID_PAYMENT_METHOD 400 |
Cannot perform action to payment method due to its status |
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND_ERROR 404 |
Provided payment_method_id is not found or inaccessible for this account |
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 |
Tokenized - Token Expiry Callbacks
Expired Payment Method Callback
This will be sent when a specific payment method has expired or has been invalidated. You may use this to notify your customers to relink. Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Value | OVO | DANA | LINKAJA | SHOPEEPAY (ID & PH) | MAYA (PAYMAYA) | GRABPAY | SHOPEEPAY (MY) | GRABPAY (MY) |
---|---|---|---|---|---|---|---|---|
Token Validity |
Never Expires (Xendit Automatically Refreshes Token at Expiry) | 10 Years | Never Expires | 5 Years | Never Expires | 1 Year | Never Expires | 10 Years |
Example: Expired Payment Method Callback
{
"event": "payment_method.expiry.expired",
"business_id": "5f27a14a9bf05c73dd040bc8",
"created": "2020-08-29T09:12:33.001Z",
"data": {
"id": "pm-123123123-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "EWALLET",
"country": "ID",
"business_id": "5f27a14a9bf05c73123123123",
"customer_id": "fc4123123-3c41-4707-b7b2-df9c3376edde",
"reference_id": "b63798d3-8240-48c3-af12-3b3c62c0981a",
"reusability": "MULTIPLE_USE",
"status": "EXPIRED",
"actions": [
{
"action": "AUTH",
"url": "https://link-web.xendit.co/auth/lat-bcf19cc8-f097-44fb-839c-6e4aed807d00/confirm",
"url_type": "WEB",
"method": "GET"
}
],
"description": null,
"created": "2021-08-18T03:52:56.936277373Z",
"updated": "2021-08-18T03:52:56.936277373Z",
"metadata": {
"sku": "IPHONE20"
},
"ewallet": {
"channel_code": "SHOPEEPAY",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
},
"account": {
"name": null,
"account_details": "+62*****3123",
"balance": 10000,
"point_balance": 10000
}
},
"direct_bank_transfer": null,
"direct_debit": null,
"card": null,
"over_the_counter": null,
"qr_code": null,
"virtual_account": null
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.expiry.expired |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
business_idrequired |
string |
Business ID of the merchant | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dataoptional |
object |
Payment method object Data fields
|
PayLater
With PayLater, you can allow your customers to buy now and pay later in installments. Customers with an active credit line with one of our partner lenders can shop on your store via flexible installment loans.
With one integration, get access to all our available PayLater channels and upcoming PayLater integrations as well.
For full details on each API as well as a comprehensive guide on integration, please refer to our documentation.
Initiate PayLater Plans
Provide your end-customer information on the available PayLater/installment plans.
Endpoint: Initiate PayLater Plans
POST https://api.xendit.co/paylater/plans
Version
You are currently viewing the newest version of our PayLater / Cardless Credit API. In this API version, integrate once to get access to all available and future PayLater providers in Xendit!. Click here to view older versions.
Version | Changelog |
---|---|
2021-06-30 Latest |
New simple and consistent PayLater API to support top PayLater providers in Indonesia and the Philippines. No API Versioning is required. You can access the new API easily by calling POST /paylater/plans |
2019-02-04 will be deprecated by 1st February 2023 |
Cardless credit API with support for Kredivo /cardless-credit |
Request Parameters
Example: Initiate PayLater Plans - Request
curl https://api.xendit.co/paylater/plans -X POST \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
-H 'Content-Type: application/json' \
--data-raw '{
"customer_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"channel_code": "PH_BILLEASE",
"currency": "PHP",
"amount": 3073.68,
"order_items": [{
"type": "PHYSICAL_PRODUCT",
"reference_id": "SKU_123-456-789",
"name": "Dyson Vacuum",
"net_unit_amount": 1234.56,
"quantity": 3,
"url": "https://www.zngmyhome.com/dyson_vacuum",
"category": "Electronics",
"subcategory": "Appliances"
}]
}'
<?php
$url = "https://api.xendit.co/paylater/plans";
$apiKey = "xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:";
$data = [
"customer_id" => "49d056bd-21e5-4997-85f2-2127544c2196",
"channel_code" => "PH_BILLEASE",
"currency" => "PHP",
"amount" => 3073.68,
"order_items" => [
"type" => "PHYSICAL_PRODUCT",
"reference_id" => "SKU_123-456-789",
"name": "Dyson Vacuum",
"net_unit_amount" => 1234.56,
"quantity" => 3,
"url" => "https://www.zngmyhome.com/dyson_vacuum",
"category" => "Electronics",
"subcategory" => "Appliances"
]
];
$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_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman",
});
const { PayLater } = x;
const payLaterSpecificOptions = {};
const plp = new PayLater(payLaterSpecificOptions);
const resp = await plp.initiatePayLaterPlans({
customer_id: '9d056bd-21e5-4997-85f2-2127544c2196',
channel_code: 'PH_BILLEASE',
currency: 'PHP',
amount: 3073.68,
order_items: {
type: 'PHYSICAL_PRODUCT',
reference_id: 'SKU_123-456-789',
name: 'Dyson Vacuum',
net_unit_amount: 1234.56,
quantity: 3,
url: 'https://www.zngmyhome.com/dyson_vacuum',
category: 'Electronics',
subcategory: 'Appliances'
}
});
console.log(resp);
from xendit import PayLater
paylater_plans = PayLater.initiate_paylater_plans(
customer_id="9d056bd-21e5-4997-85f2-2127544c2196",
channel_code="PH_BILLEASE",
currency="PHP",
amount=3073.68,
order_items={
type="PHYSICAL_PRODUCT",
reference_id="SKU_123-456-789",
name="Dyson Vacuum",
net_unit_amount=1234.56,
quantity=3,
url="https://www.zngmyhome.com/dyson_vacuum",
category="Electronics",
subcategory="Appliances"
}
)
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
customer_id required |
string
|
Unique identifier for customer from the Create Customer API POST /customers Required parameters to be set for the customer object
|
||||||||||||||||||||||||
channel_code required |
string
|
Channel code for PayLater provider Supported channels: ID_KREDIVO , ID_AKULAKU , ID_INDODANA , ID_ATOME , PH_ATOME , PH_BILLEASE , PH_CASHALO
|
||||||||||||||||||||||||
currency required |
string
|
ISO 4217 currency code of PayLater transactionSupported currencies: IDR , PHP
|
||||||||||||||||||||||||
amount required |
number
|
Aggregated transaction amount equivalent to the sum of net_unit_amount multiplied by quantity in the order_items arrayTransaction limits per channel
|
||||||||||||||||||||||||
order_items required |
array
|
Array of objects describing the item/s purchased using PayLaterObject parameters
|
Response Parameters
Example: Initiate PayLater Plans - Success Response
{
"id" : "plp_3d88d952-9505-4ed7-84d3-e8639e99e9c4",
"customer_id" : "49d056bd-21e5-4997-85f2-2127544c2196",
"channel_code" : "PH_BILLEASE",
"currency" : "PHP",
"amount" : 2184.56,
"order_items": [{
"type": "PHYSICAL_PRODUCT",
"reference_id": "SKU_123-456-789",
"name": "Dyson Vacuum",
"net_unit_amount": 1234.56,
"quantity": 1,
"url": "https://www.zngmyhome.com/dyson_vacuum",
"category": "Electronics",
"subcategory": "Appliances",
"description": "A very powerful vacuum",
"metadata": null
},
{
"type" : "PHYSICAL_SERVICE",
"reference_id" : "SKU_123-456-790",
"name" : "Home Cleaning Service",
"net_unit_amount" : 1000,
"quantity" : 1,
"url" : "https://www.zngmyhome.com/home_cleaning",
"category" : "Services",
"subcategory" : null,
"description" : "1 hour deep cleaning up to 2 rooms",
"metadata" : null
}],
"options": [{
"downpayment_amount" : 400,
"installment_amount" : 600,
"interest_rate" : 0,
"total_amount" : 1000,
"interval" : "MONTH",
"interval_count" : 1,
"total_recurrence" : 1,
"description" : "Buy Now, Pay Later"
},
{
"downpayment_amount" : 400,
"installment_amount" : 100,
"interest_rate" : 0.025,
"total_amount" : 1015,
"interval" : "MONTH",
"interval_count" : 1,
"total_recurrence" : 6,
"description" : "6 month installment plan"
}],
"created": "2020-11-11T16:23:52Z"
}
Body Parameter | Type | Description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string |
Unique identifier for PayLater Plan Object It will always have the prefix of plp_ , followed by a UUIDv4 |
||||||||||||||||||
customer_id | string |
Unique identifier for customer | ||||||||||||||||||
channel_code | string |
Channel code for PayLater provider Supported channels: ID_KREDIVO , ID_AKULAKU , ID_INDODANA , ID_ATOME , PH_ATOME , PH_BILLEASE , PH_CASHALO |
||||||||||||||||||
currency | string |
ISO 4217 currency code of PayLater transactionSupported currency: IDR , PHP |
||||||||||||||||||
amount | number |
Aggregated transaction amount equivalent to the sum of net_unit_amount multiplied by quantity in the order_items array |
||||||||||||||||||
order_items | array |
Array of objects describing the item/s purchased using PayLater | ||||||||||||||||||
options | array |
Available payment plans users can view to purchase your goods/services. Provided by PayLater providers directly Notes: PH_CASHALO does not provide plans, Xendit will return an empty array.PayLater options details
|
||||||||||||||||||
created | string |
Timestamp in ISO 8601 for creation of plan objectFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
Error Codes
Example: Initiate PayLater Charge Request API - Error Response
{
"error_code": "INVALID_CUSTOMER_ID",
"message": "Missing or invalid parameter(s) in customer_id: given_names, postcode"
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
API_VALIDATION_ERROR400 |
Amount Does Not Tally with Order Items request.body.amount must be equal to the sum of net_unit_amount * quantity in request.body.order_items |
API_VALIDATION_ERROR400 |
Invalid URL url must be a valid URL |
INVALID_CUSTOMER_ID400 |
Missing or invalid parameter(s) in customer_id |
UNSUPPORTED_CURRENCY400 |
The payment currency request is not supported by PayLater partner. Please refer to our API reference or docs for available currencies |
INVALID_API_KEY401 |
API key is not authorized for this API service |
INVALID_MERCHANT_CREDENTIALS401 |
Merchant credentials met with an error with the PayLater partner. Please contact Xendit customer support to resolve this issue. |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
CHANNEL_NOT_ACTIVATED403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
Customer ID is invalid. Please check the ID again or create an ID using Customer API. |
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 PayLater partner will be notified to resolve this issue |
Create PayLater Charges
Create PayLater transaction / generate checkout URL
Version
You are currently viewing the newest version of our PayLater / Cardless Credit API. Click here to view older versions.
Endpoint: Create PayLater Charges
POST https://api.xendit.co/paylater/charges
Request Parameters
Example: Create Payment Request
curl https://api.xendit.co/paylater/charges -X POST \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
-H 'Content-Type: application/json' \
--data-raw '{
"plan_id": "plp_3d88d952-9505-4ed7-84d3-e8639e99e9c4",
"reference_id": "order_id_123",
"checkout_method": "ONE_TIME_PAYMENT",
"success_redirect_url": "https://merchant.com/order/confirm",
"failure_redirect_url": "https://merchant.com/order/fail"
}'
<?php
$url = "https://api.xendit.co/paylater/charges";
$apiKey = "xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:";
$data = [
"plan_id" => "plp_3d88d952-9505-4ed7-84d3-e8639e99e9c4",
"reference_id" => "order_id_123",
"checkout_method" => "ONE_TIME_PAYMENT",
"success_redirect_url" => "https://merchant.com/order/confirm",
"failure_redirect_url" => "https://merchant.com/order/fail"
];
$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_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman",
});
const { PayLater } = x;
const payLaterSpecificOptions = {};
const plc = new PayLater(payLaterSpecificOptions);
const resp = await plc.createPayLaterCharge({
planID: 'plp_3d88d952-9505-4ed7-84d3-e8639e99e9c4',
referenceID: 'order_id_123',
checkoutMethod: 'ONE_TIME_PAYMENT',
successRedirectURL: 'https://merchant.com/order/confirm',
failureRedirectURL: 'https://merchant.com/order/fail'
});
console.log(resp);
from xendit import PayLater
paylater_charge = PayLater.create_paylater_charge(
plan_id="plp_3d88d952-9505-4ed7-84d3-e8639e99e9c4",
reference_id="order_id_123",
checkout_method="ONE_TIME_PAYMENT",
success_redirect_url="https://merchant.com/order/confirm",
failure_redirect_url="https://merchant.com/order/fail"
)
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Body Parameter | Type | Description |
---|---|---|
plan_id required |
string
|
Installment Plan ID retrieved from Initiate PayLater Plans API |
reference_id required |
string
|
Reference ID provided by merchant for the transactionFormat Special and alphanumericMax length 255 characters |
checkout_method required |
string
|
Supported checkout method: ONE_TIME_PAYMENT
|
success_redirect_url required |
string
|
URL where the customer is redirected after completing transaction Must be HTTPS or HTTP |
failure_redirect_url required |
string
|
URL where the end-customer is redirected if the payment has failed Must be HTTPS or HTTP |
payment_method_id optional |
string
|
Payment method ID of end-customer source of funds Required when checkout_method = TOKENIZED_PAYMENT (currently not supported) |
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. This will only be used by the user and not Xendit. |
Response Parameters
Example Create PayLater Charge Success Response
{
"id": "plc_8cb12305-9bcf-4441-a087-ee0d446e297b",
"customer_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"plan_id": "plp_3d88d952-9505-4ed7-84d3-e8639e99e9c4",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "order_id_123",
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "PH_BILLEASE",
"currency": "PHP",
"amount": 1234.56,
"refunded_amount": null,
"order_items": [{
"type": "PRODUCT",
"reference_id": "SKU_123-456-789",
"name": "Dyson Vacuum",
"net_unit_amount": 1234.56,
"quantity": 1,
"url": "https://www.zngmyhome.com/dyson_vacuum",
"category": "Electronics",
"subcategory": "Appliances",
"description": "A very powerful vacuum",
"metadata": null
}],
"success_redirect_url": "https://merchant.com/order/confirm",
"failure_redirect_url": "https://merchant.com/order/fail",
"status": "PENDING",
"created": "2020-11-11T16:23:52Z",
"updated": "2020-11-11T16:23:52Z",
"actions": {
"desktop_web_checkout_url": "https://webcheckout.this/",
"mobile_web_checkout_url": "https://webcheckout.this/",
"mobile_deeplink_checkout_url": "app://deeplinkcheckout.this/"
},
"expires_at": "2020-11-12T16:23:52Z",
"callback_url": "https://webhook.me/gethooked",
"payment_method_id": null,
"voided_at": null,
"refunds": null,
"metadata": null
}
Body Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
id | string |
Unique identifier for the charge request transaction It will always have the prefix of plc_ , followed by a UUIDv4 |
||||||||
customer_id | string |
Unique identifier for customer | ||||||||
plan_id | string |
Unique identifier for PayLater plan created | ||||||||
business_id | string |
Business ID of the merchant | ||||||||
reference_id | string |
Reference ID provided by merchant for the transaction | ||||||||
channel_code | string |
Channel code for PayLater provider Supported channels: ID_KREDIVO , ID_AKULAKU , ID_INDODANA , ID_ATOME , PH_ATOME , PH_BILLEASE , PH_CASHALO |
||||||||
checkout_method | string |
Supported checkout method: ONE_TIME_PAYMENT |
||||||||
currency | string |
ISO 4217 currency code of PayLater transactionSupported currency: IDR , PHP |
||||||||
amount | number |
Aggregated transaction amount equivalent to the sum of net_unit_amount multiplied by quantity in the order_items array |
||||||||
refunded_amount | number |
Total amount that has been successfully refunded to end-user | ||||||||
order_items | array |
Array of objects describing the item/s purchased using PayLater | ||||||||
status | string |
Charge statusPENDING , SUCCEEDED , FAILED Status of charge request
|
||||||||
success_redirect_url | string |
URL where the customer is redirected after completing transaction Must be HTTPS or HTTP |
||||||||
failure_redirect_url | string |
URL where the end-customer is redirected if the payment has failed Must be HTTPS or HTTP |
||||||||
created | string |
Timestamp in ISO 8601 for transaction creationFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||
updated | string |
Timestamp in ISO 8601 latest object updateFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||
actions | object |
PayLater Partner’s checkout URL where end-user will be redirected to complete paymentTypes of redirection URLs
|
||||||||
expires_at | string |
Timestamp in ISO 8601 latest object updateFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||
callback_url | string |
Default to callback URL in dashboard where the charge status will be notified | ||||||||
payment_method_id | string |
Payment method ID of end-customer source of funds Required when checkout_method = TOKENIZED_PAYMENT (currently not supported) |
||||||||
voided_at | string |
Timestamp in ISO 8601 for void of transactionFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||
metadata | 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. |
||||||||
refunds | array |
Array of refund object IDs (only SUCCEEDED refunds will show) |
Error Codes
Example: Create PayLater Charge Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "PayLater partner does not support requested checkout_method."
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
API_VALIDATION_ERROR400 |
Unsupported Checkout Type PayLater partner does not support requested checkout_method |
INVALID_API_KEY401 |
API key is not authorized for this API service |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
PAYLATER_PLAN_DATA_NOT_FOUND404 |
PayLater Plan ID is invalid. Please check the ID again or create an ID using PayLater Plans API |
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 PayLater partner will be notified to resolve this issue |
Payment Status Callback
Xendit notifies your system upon successful payments via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard under Paylater paid
.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
POST webhook-url
Version
You are currently viewing the newest version of our PayLater / Cardless Credit API. Click here to view older versions.
Webhook Payload
This webhook is triggered when a PayLater payment has SUCCEEDED
or FAILED
.
Example: PayLater Success Payment Webhook Payload
{
"event": "paylater.payment",
"business_id": "5f27a14a9bf05c73dd040bc8",
"created": "2020-11-11T16:28:52Z",
"data": {
"id": "plc_8cb12305-9bcf-4441-a087-ee0d446e297b",
"customer_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"plan_id": "plp_3d88d952-9505-4ed7-84d3-e8639e99e9c4",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "order_id_123",
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "PH_BILLEASE",
"currency": "PHP",
"amount": 1234.56,
"refunded_amount": null,
"order_items": [{
"type": "PRODUCT",
"reference_id": "SKU_123-456-789",
"name": "Dyson Vacuum",
"net_unit_amount": 1234.56,
"quantity": 1,
"url": "https://www.zngmyhome.com/dyson_vacuum",
"category": "Electronics",
"subcategory": "Appliances",
"description": "A very powerful vacuum",
"metadata": null
}],
"success_redirect_url": "https://merchant.com/order/confirm",
"failure_redirect_url": "https://merchant.com/order/fail",
"status": "SUCCEEDED",
"created": "2020-11-11T16:23:52Z",
"updated": "2020-11-11T16:23:52Z",
"actions": {
"desktop_web_checkout_url": "https://webcheckout.this/",
"mobile_web_checkout_url": "https://webcheckout.this/",
"mobile_deeplink_checkout_url": "app://deeplinkcheckout.this/"
},
"expires_at": "2020-11-12T16:23:52Z",
"callback_url": "https://webhook.me/gethooked",
"payment_method_id": null,
"voided_at": null,
"refunds": null,
"metadata": null
}
}
Header Parameter | Type | Description |
---|---|---|
x-callback-token |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-id |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
event | string |
Identifies the event triggering a notification to merchant.paylater.payment occurs when PayLater partner confirms the payment status of a transaction |
||||||||||||||||||||||||||||||||||||||||||||||||
business_id | string |
Business ID of the merchant | ||||||||||||||||||||||||||||||||||||||||||||||||
created | string |
ISO 8601 timestamp of the event creation. Timezone is UTC+0 |
||||||||||||||||||||||||||||||||||||||||||||||||
data | object |
PayLater charge object will be nested in this parameter Data fields
|
Get PayLater Charge by ID
Retrieve the details of a PayLater payment by Charge ID
Endpoint: Get PayLater Charge by ID
GET https://api.xendit.co/paylater/charges/{id}
Request Parameters
Example: Check PayLater Charge Status by ID - Request
curl https://api.xendit.co/paylater/charges/plc_8cb12305-9bcf-4441-a087-ee0d446e297b/ -X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman');
$charge_id = 'plc_8cb12305-9bcf-4441-a087-ee0d446e297b';
$getPayLaterChargeStatus = \Xendit\PayLater::getPayLaterChargeStatus($charge_id);
var_dump($getPayLaterChargeStatus);
?>
const x = new require("xendit-node")({
secretKey:
"xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman",
});
const { PayLater } = x;
const paylaterSpecificOptions = {};
const pl = new PayLater(paylaterSpecificOptions);
const resp = await pl.getPayLaterChargeStatus({
chargeID: 'plc_8cb12305-9bcf-4441-a087-ee0d446e297b',
});
console.log(resp);
from xendit import PayLater
paylater_charge = PayLater.get_paylater_charge_status(
charge_id="plc_8cb12305-9bcf-4441-a087-ee0d446e297b",
)
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Unique identifier for charge request transaction (returned as id in the PayLater Charge request) |
Response Parameters
Example: Check PayLater Charge Status by ID - Response
{
"id": "plc_8cb12305-9bcf-4441-a087-ee0d446e297b",
"customer_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"plan_id": "plp_3d88d952-9505-4ed7-84d3-e8639e99e9c4",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "order_id_123",
"checkout_method": "ONE_TIME_PAYMENT",
"channel_code": "PH_BILLEASE",
"currency": "PHP",
"amount": 1234.56,
"refunded_amount": null,
"order_items": [{
"type": "PRODUCT",
"reference_id": "SKU_123-456-789",
"name": "Dyson Vacuum",
"net_unit_amount": 1234.56,
"quantity": 1,
"url": "https://www.zngmyhome.com/dyson_vacuum",
"category": "Electronics",
"subcategory": "Appliances",
"description": "A very powerful vacuum",
"metadata": null
}],
"success_redirect_url": "https://merchant.com/order/confirm",
"failure_redirect_url": "https://merchant.com/order/fail",
"status": "SUCCEEDED",
"created": "2020-11-11T16:23:52Z",
"updated": "2020-11-11T16:23:52Z",
"actions": {
"desktop_web_checkout_url": "https://webcheckout.this/",
"mobile_web_checkout_url": "https://webcheckout.this/",
"mobile_deeplink_checkout_url": "app://deeplinkcheckout.this/"
},
"expires_at": "2020-11-12T16:23:52Z",
"callback_url": "https://webhook.me/gethooked",
"payment_method_id": null,
"voided_at": null,
"refunds": null,
"metadata": null
}
Body Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the charge request transaction It will always have the prefix of plc_ , followed by a UUIDv4 |
customer_id | string |
Unique identifier for customer |
plan_id | string |
Unique identifier for PayLater plan created |
business_id | string |
Business ID of the merchant |
reference_id | string |
Reference ID provided by merchant for the transaction |
checkout_method | string |
Supported checkout method: ONE_TIME_PAYMENT |
channel_code | string |
Channel code for PayLater provider Supported channels: ID_KREDIVO , ID_AKULAKU , ID_INDODANA , ID_ATOME , PH_ATOME , PH_BILLEASE , PH_CASHALO |
currency | string |
ISO 4217 currency code of PayLater transactionSupported currency: IDR , PHP |
amount | number |
Aggregated transaction amount equivalent to the sum of net_unit_amount multiplied by quantity in the order_items array |
refunded_amount | number |
Total amount that has been successfully refunded to end-user |
order_items | array |
Array of objects describing the item/s purchased using PayLater |
success_redirect_url | string |
URL where the customer is redirected after completing transaction |
failure_redirect_url | string |
URL where the end-customer is redirected if the payment has failed |
status | string |
Charge statusPENDING , SUCCEEDED , FAILED |
created | string |
Timestamp in ISO 8601 for transaction creationFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
updated | string |
Timestamp in ISO 8601 latest object updateFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
actions | object |
PayLater Partner’s checkout URL where end-user will be redirected to complete payment |
expires_at | string |
Timestamp in ISO 8601 latest object updateFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
callback_url | string |
Default to callback URL in dashboard where the charge status will be notified HTTPS is required |
payment_method_id | string |
Payment method ID of end-customer source of funds Required when checkout_method = TOKENIZED_PAYMENT (currently not supported) |
voided_at | string |
Timestamp in ISO 8601 for void of transactionFormat: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
metadata | 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.| |refunds|array
|Array of refund object IDs (only SUCCEEDED
refunds will show)|
Error Codes
Example: Check PayLater Charge Status by ID - Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "Charge ID does not match plc_UUID format"
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Charge ID does not match plc_UUID format |
INVALID_API_KEY401 |
API key is not authorized for this API service |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
Charge resource was not found. Please check your query again |
SERVER_ERROR500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
Cancel Paylater Charge
Perform a cancel for a Paylater charge by Charge ID. This endpoint will only work for charges created via the /paylater/charge
endpoint.
A cancellation of a Paylater transaction will make the payments URL inaccessible to the end customer in real time. Xendit does not send callbacks when for the cancellation endpoint
Endpoint: Cancel Paylater Charge
POST https://api.xendit.co/paylater/charges/:id/cancel
Request Parameters
Example: Cancel PayLater Charge - Request
curl https://api.xendit.co/paylater/charges/plc_8cb12305-9bcf-4441-a087-ee0d446e297b/cancel -X POST \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Unique identifier for charge request transaction (returned as id in the PayLater Charge request) |
Response Parameters
Example: Cancel PayLater Charge - Response
{
"id": "plc_5test57-8888-45o8-abb1-123456789abcdefg",
"business_id": "8764829fhgnb74gf63hg74dhg73",
"reference_id": "paylater-mock-ref-12345678",
"customer_id": "cust-9fb4af4e-d98c-40bf-bd87-abcde678901112",
"plan_id": "plp_3d4c8823-0d2a-4c2e-892b-12345abcde1112",
"currency": "IDR",
"amount": 1000,
"channel_code": "ID_KREDIVO",
"checkout_method": "ONE_TIME_PAYMENT",
"status": "CANCELLED",
"actions": {
"mobile_web_checkout_url": "https://pay.kredivo.com/signIn?tk=1234-1234-1234-1234-12345678",
"desktop_web_checkout_url": "https://pay.kredivo.com/signIn?tk=1234-1234-1234-1234-12345678"
},
"expires_at": "2022-11-25T00:00:57.745Z",
"success_redirect_url": "https://www.xendit.co/en/",
"failure_redirect_url": "https://www.google.com/",
"callback_url": "https://webhook.site/12345678",
"created": "2022-11-24T00:00:57.747Z",
"updated": "2022-11-24T00:00:26.441Z",
"order_items": [
{
"type": "DIGITAL_PRODUCT",
"reference_id": "SKU_123-456-789",
"name": "Dyson Vacuum",
"net_unit_amount": 50,
"quantity": 2,
"url": "https://www.xendit.co/en/",
"category": "Electronics",
"subcategory": null,
"description": null,
"metadata": null
},
{
"type": "FEE",
"reference_id": "PLS_FEE_aabcdef0-e4af-4b86-bf12-a31abcdef282",
"name": "Fee",
"net_unit_amount": 900,
"quantity": 1,
"subcategory": null,
"description": null,
"metadata": {
"message": "Xendit generated FEE for amount differences between sum of net unit amount and the amount"
}
}
],
"voided_at": null,
"payment_method_id": null,
"metadata": {
"campaign": "0%_installment"
}
}
Body Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the charge transaction It will always have the prefix of plc_ , followed by a UUIDv4. |
business_id | string |
Business ID of the merchant. |
reference_id | string |
Reference ID provided by merchant for the transaction. |
customer_id | string |
Unique identifier for customer. |
plan_id | string |
Unique identifier for PayLater plan created. |
created | string |
Timestamp in ISO 8601 for transaction creation Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 . |
updated | string |
Timestamp in ISO 8601 latest object update Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 . |
amount | number |
Aggregated transaction amount equivalent to the sum of net_unit_amount multiplied by quantity in the order_items . |
order_items | array |
Array of objects describing the items purchased using PayLater. |
channel_code | string |
Channel code for PayLater provider Supported channels: ID_KREDIVO , ID_AKULAKU , ID_INDODANA , ID_ATOME , PH_ATOME ,PH_BILLEASE ,PH_CASHALO . |
currency | string |
ISO 4217 currency code of PayLater transactionSupported currency: IDR , PHP . |
status | enum |
Status of the charge request. Available values - SUCCEEDED , FAILED , PENDING , CANCELLED . Status will be CANCELLED upon successful cancellation. |
success_redirect_url | string |
URL where the customer is redirected after completing transaction must be HTTPS or HTTP. |
failure_redirect_url | string |
URL where the end-customer is redirected if the payment has failed must be HTTPS or HTTP. |
actions | object |
PayLater Partner’s checkout URL where end-user will be redirected to complete payment. |
expires_at | string |
Timestamp in ISO 8601 latest object update Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 . |
callback_url | string |
Default to callback URL in dashboard where the charge status will be notified. |
metadata | 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. |
Error Codes
Example: Cancel PayLater Charge - Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "Cancel resource was not found. Please check your query again"
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is an error with the format submitted to the server. |
INVALID_API_KEY401 |
API key format is invalid. |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request. |
INELIGIBLE_TRANSACTION403 |
Cancellation requests cannot be processed because the transaction is not in PENDING status. |
DATA_NOT_FOUND404 |
Cancel resource was not found. Please check your query again. |
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. |
Refund Paylater Charge
Perform a refund for a PayLater payment by Charge ID. This endpoint will only work for charges created via the /paylater/charges
endpoint.
A refund of PayLater transaction will return end-customer's credit balance in their PayLater Provider's account in real-time. Xendit will send you a callback upon successful refunds to the same Callback URL you set in the Xendit Dashboard.
Refund Details
PayLater Provider | Refund capabilities | Refund cut-off time |
---|---|---|
Kredivo | Full and partial refunds | 14 days |
Indodana | Full and partial refunds | 30 days |
Atome | Full and partial refunds | N/A Atome will honor refunds as long as Merchant approved end-customer's request |
Akulaku | Full and partial refunds | N/A Akulaku will honor refunds as long as Merchant approved end-customer's request |
Billease | Full Refunds | N/A Billease will honor refunds as long as Merchant approved end-customer's request |
Endpoint: Create Paylater Refund
POST https://api.xendit.co/paylater/charges/{id}/refunds
Request Parameters
Example: Create PayLater Refund - Request
curl https://api.xendit.co/paylater/charges/plc_8cb12305-9bcf-4441-a087-ee0d446e297b/refunds -X POST \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
-H 'Content-Type: application/json' \
--data-raw '{
"amount": "1000",
"reason": "DEFECTIVE_ITEM"
}'
Example: Sample JSON request
{
"amount": 1000,
"reason": "DEFECTIVE_ITEM"
}
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Unique identifier for charge request transaction (returned as id in the PayLater Charge request) |
Body Parameter | Type | Description |
---|---|---|
amount optional |
number
|
Amount to be refunded to the end user. Cumulative amount refunded must not exceed the original transacted amount. Refund will only work for unrefunded amount of the charge. If the amount field is not present in the request body, the remaining unrefunded amount of the charge would be processed. |
reason optional |
enum
|
Reason for refund, one of the following values can be used. Available values - DUPLICATE , FRAUDULENT , CHANGE_OF_MIND , CHANGE_PAYMENT_METHOD , UNFULFILLED_ITEM , DEFECTIVE_ITEM , OTHERS . |
Response Parameters
Example: Create PayLater Refund - Response
{
"id" : "plr_2f2aa47f-2764-4b42-8712-c3fb1270b09e",
"charge_id" : "plc_8cb12305-9bcf-4441-a087-ee0d446e297b",
"channel_code" : "PH_BILLEASE",
"currency" : "PHP",
"amount" : 1234.56,
"reason" : "UNFULFILLED_ITEM",
"status" : "PENDING",
"created" : "2021-04-20T16:23:52Z",
"updated" : null
}
Body Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the refund transaction It will always have the prefix of plr_ , followed by a UUIDv4 |
charge_id | string |
Unique identifier for the original charge transaction It will always have the prefix of plc_ , followed by a UUIDv4 |
channel_code | string |
Channel code for PayLater provider Supported channels: ID_KREDIVO , ID_AKULAKU , ID_INDODANA , ID_ATOME , PH_ATOME |
currency | string |
ISO 4217 currency code of PayLater transactionSupported currency: IDR , PHP |
amount | number |
Amount to be refunded |
reason | string |
Reason for refund |
status | enum |
Status of the refund request, available values - SUCCEEDED , FAILED , PENDING |
created | string |
Timestamp in ISO 8601 for refund request |
updated | number |
Timestamp in ISO 8601 for refund object update |
Error Codes
Example: Create PayLater Refund - Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "Refund resource was not found. Please check your query again"
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is an error with the format submitted to the server. |
REFUND_NOT_SUPPORTED400 |
Refund request failed because refunds are not supported by the PayLater provider. |
PARTIAL_REFUND_NOT_SUPPORTED400 |
Refund request failed because partial refunds are not supported by the PayLater provider. |
INSUFFICIENT_BALANCE400 |
Xendit balance is not enough to perform a refund. Please top up your Xendit balance or wait until other transactions have been settled. |
MAXIMUM_REFUND_AMOUNT_REACHED400 |
Refund request failed because full amount of the PayLater charge has been refunded to end-user. |
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
Refund resource was not found. Please check your query again |
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 PayLater partner will be notified to resolve this issue. |
Get Refund by Refund ID
Get refund status for a PayLater refund. This endpoint will only work for charges created via the /paylater/charges
endpoint
Endpoint: Get PayLater Refund by ID
GET https://api.xendit.co/paylater/charges/{charge_id}/refunds/{refund_id}
Request Parameters
Example: GET PayLater Refund by ID - Request
curl https://api.xendit.co/paylater/charges/plc_8cb12305-9bcf-4441-a087-ee0d446e297b/refunds/plr_2f2aa47f-2764-4b42-8712-c3fb1270b09e -X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
charge_id required |
string
|
ID of Paylater charge |
refund_id required |
string
|
ID of Paylater Refund |
Response Parameters
Example: GET PayLater Refund by ID - Response
{
"id" : "plr_2f2aa47f-2764-4b42-8712-c3fb1270b09e",
"charge_id" : "plc_8cb12305-9bcf-4441-a087-ee0d446e297b",
"channel_code" : "PH_BILLEASE",
"currency" : "PHP",
"amount" : 1234.56,
"reason" : "UNFULFILLED_ITEM",
"status" : "PENDING",
"created" : "2021-04-20T16:23:52Z",
"updated" : null
}
Body Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the refund transaction It will always have the prefix of plr_ , followed by a UUIDv4 |
charge_id | string |
Unique identifier for the original charge transaction It will always have the prefix of plc_ , followed by a UUIDv4 |
channel_code | string |
Channel code for PayLater provider Supported channels: ID_KREDIVO , ID_AKULAKU , ID_INDODANA , ID_ATOME , PH_ATOME |
currency | string |
ISO 4217 currency code of PayLater transactionSupported currency: IDR , PHP |
amount | number |
Amount to be refunded |
reason | string |
Reason for refund |
status | enum |
Status of the refund request, available values - SUCCEEDED , FAILED , PENDING |
created | string |
Timestamp in ISO 8601 for refund request |
updated | number |
Timestamp in ISO 8601 for refund object update |
Error Codes
Example: GET PayLater Refund by ID - Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "Refund resource was not found. Please check your query again"
}
Error Code | Description |
---|---|
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
Refund resource was not found. Please check your query again |
SERVER_ERROR500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
List Paylater Refunds
Get all refunds status made to a PayLater charge transaction. This endpoint will only work for charges created via the /paylater/charges
endpoint
Endpoint: List Paylater Refunds
GET https://api.xendit.co/paylater/charges/{id}/refunds/
Request Parameters
Example: List Paylater Refunds - Request
curl https://api.xendit.co/paylater/charges/plc_8cb12305-9bcf-4441-a087-ee0d446e297b/refunds?limit=10&status=SUCCEEDED -X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
Header | Type | Description |
---|---|---|
for-user-id optional |
string |
The sub-account user-id that you want to make this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Unique identifier for charge request transaction (returned as id in the PayLater Charge request) |
Query Parameter | Type | Description |
---|---|---|
limit optional |
number
|
Maximum number of results to return at one time Default: 10 Minimum: 1 Maximum: 50 |
status optional |
enum
|
Refund status to be retrieved. Available values - SUCCEEDED , FAILED , PENDING
|
Response Parameters
Example: List Paylater Refunds - Response
{
"data": [
{
"id": "plr_2f2aa47f-2764-4b42-8712-c3fb1270b09e",
"charge_id": "plc_8cb12305-9bcf-4441-a087-ee0d446e297b",
"channel_code": "PH_BILLEASE",
"currency": "PHP",
"amount": 1234.56,
"reason": "UNFULFILLED_ITEM",
"status": "SUCCEEDED",
"created": "2021-04-20T16:23:52Z",
"updated": "2021-04-20T16:23:52Z"
},
{
"id": "plr_a351fd9a-90da-459a-b479-9b34e8be6009",
"charge_id": "plc_8cb12305-9bcf-4441-a087-ee0d446e297b",
"channel_code": "PH_BILLEASE",
"currency": "PHP",
"amount": 1000,
"reason": "UNFULFILLED_ITEM",
"status": "SUCCEEDED",
"created": "2021-04-20T16:23:52Z",
"updated": "2021-04-20T16:23:52Z"
}
],
"has_more": false
}
Body Parameter | Type | Description | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
data | array |
Data array of PayLater refund object(s) related to specified charge id Refund object parameters
|
||||||||||||||||||||
has_more | boolean |
Indicates whether there are more items to be queried based on the query filters from the current result. If result is empty, has_more will be false |
Error Codes
Example: List Paylater Refunds - Error Response
{
"error_code": "DATA_NOT_FOUND",
"message": "Refund resource was not found. Please check your query again"
}
Error Code | Description |
---|---|
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
Charge resource was not found. Please check your query again |
SERVER_ERROR500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
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. BCA, Mandiri, OVO, GoPay, DANA.. and more). See full list here.
In Philippines, our merchants can receive payments from any providers connected on QRPh network.
For full details on the features that each QRIS partner provides, please refer to our documentation.
API Version
You are currently viewing the newest version of our QR Codes API. In this API version, the expiry time of a dynamic QRIS code can be customized through the expires_at
parameter.
Version | Changelog |
---|---|
2022-07-31 Latest |
v2 QR Codes API to support customized expiry time of a dynamic QR code |
2020-07-01 Previous version |
v1 QR Codes API without customized expiry time of a dynamic QR code |
QR Code Object
The QR Code Object is returned in the responses of Create QR Code and Get QR Code by QR ID.
Example: QR Code Object
{
"id": "qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2",
"reference_id": "order-id-1666420204",
"business_id": "58cd618ba0464eb64acdb246",
"type": "DYNAMIC",
"currency": "IDR",
"amount": 10000,
"channel_code": "ID_DANA",
"status": "ACTIVE",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"expires_at": "2022-10-23T09:56:43.60445Z",
"created": "2022-10-22T06:30:05.86474Z",
"updated": "2022-10-22T06:30:05.86474Z",
"basket": null,
"metadata": null
}
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string |
Unique identifier for this transaction. Prefix qr_ |
||||||||||||||||||||||||
reference_id | string |
Reference ID provided by merchant (255 characters) | ||||||||||||||||||||||||
business_id | string |
Business ID of merchant | ||||||||||||||||||||||||
type | string |
DYNAMIC or STATIC Note: - Dynamic QR code contains the amount value to be paid upon scanning and can only be paid a single time Static QR code requires end user to input the payment value and can be paid multiple times - STATIC is not available for QRPh at the moment |
||||||||||||||||||||||||
currency | string |
Currency used for the transaction in ISO4217 format Available values: IDR , PHP |
||||||||||||||||||||||||
amount | number |
Amount specified in request Static QR codes require the end user to always input the amount to be paid at the point of scanning Note: - QRIS - min 1 IDR, max 10,000,000 IDR - QRPh - min 1 PHP, max 50,000 PHP |
||||||||||||||||||||||||
channel_code | string |
Code specifying which QR code partner will be used to process the transaction Available values: ID_DANA , ID_LINKAJA , QRPH |
||||||||||||||||||||||||
status | string |
ACTIVE or INACTIVE Note: Inactive or expired QR code can no longer accept payment |
||||||||||||||||||||||||
qr_string | 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) | ||||||||||||||||||||||||
expires_at | string |
ISO 8601 Timestamp for QR code expiry. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ Note: For ID_DANA 's dynamic QR code, default is QR code expires in 48 hours from creation time if expires_at is not specified. For ID_DANA 's static QR code, the QR code never expires, so expires_at value will always be null Custom expiry is not available for QRPh at the moment |
||||||||||||||||||||||||
created | string |
ISO 8601 Timestamp for QR code object creation. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
||||||||||||||||||||||||
updated | string |
ISO 8601 Timestamp for latest QR code object update. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
||||||||||||||||||||||||
basket | object |
Array of objects describing the item(s) purchased
|
||||||||||||||||||||||||
metadata | object |
Object of additional information the merchant may use. Merchant defines the JSON properties and values Merchant can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long |
Create QR Code
This POST endpoint is used to create either a dynamic (fixed amount) or a static (open amount) QR code.
Example: Create QR Code Request
POST https://api.xendit.co/qr_codes
Request Parameters
curl https://api.xendit.co/qr_codes -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'api-version: 2022-07-31'
-H 'Content-Type: application/json' \
--data-raw '{
"reference_id": "order-id-1666420204",
"type": "DYNAMIC",
"currency": "IDR",
"amount": 10000,
"expires_at": "2022-10-23T09:56:43.60445Z"
}'
Header Parameter | Type | Description |
---|---|---|
api-versionrequired |
string |
The version of the API. Use 2022-07-31 for the v2 version of the endpoint |
idempotency-keyoptional |
string |
Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer. It expires after 24 hours from the first request |
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-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this QR code in order to split and route payments to multiple accounts. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.This header is only used if you have access to xenPlatform. See xenPlatform for more information. |
webhook-urloptional |
string |
Callback URL where payment notifications will be sent. Default is the callback URL in your Dashboard for QR code paid |
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
reference_idrequired |
string |
Reference ID provided by merchant. Does not need to be unique (255 characters) | ||||||||||||||||||||||||
typerequired |
string |
DYNAMIC or STATIC Note: - Dynamic QR code contains the amount value to be paid upon scanning and can only be paid a single time Static QR code requires end user to input the payment value and can be paid multiple times - STATIC is not available for QRPh at the moment |
||||||||||||||||||||||||
currencyrequired |
string |
Currency used for the transaction in ISO4217 format Available values: IDR , PHP |
||||||||||||||||||||||||
amountconditionally required |
number |
Amount specified in request Static QR codes require the end user to always input the amount to be paid at the point of scanning Note: - QRIS - min 1 IDR, max 10,000,000 IDR - QRPh - min 1 PHP, max 50,000 PHP |
||||||||||||||||||||||||
channel_codeoptional |
string |
Code specifying which QR code partner will be used to process the transaction Available values: ID_DANA , ID_LINKAJA , QRPH |
||||||||||||||||||||||||
expires_atoptional |
string |
ISO 8601 Timestamp for QR code expiry. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ Note: For ID_DANA 's dynamic QR code, default is QR code expires in 48 hours from creation time if expires_at is not specified. For ID_DANA 's static QR code, the QR code never expires, so expires_at value will always be null Custom expiry is not available for QRPh at the moment. QRPh expiry is fixed at 15 minutes. |
||||||||||||||||||||||||
basketoptional |
object |
Array of objects describing the item(s) purchased
|
||||||||||||||||||||||||
metadataoptional |
object |
Object of additional information the merchant may use. Merchant defines the JSON properties and values Merchant 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 QR Code Success Response (QR Code Object)
{
"id": "qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2",
"reference_id": "order-id-1666420204",
"business_id": "58cd618ba0464eb64acdb246",
"type": "DYNAMIC",
"currency": "IDR",
"amount": 10000,
"channel_code": "ID_DANA",
"status": "ACTIVE",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"expires_at": "2022-10-23T09:56:43.60445Z",
"created": "2022-10-22T06:30:05.86474Z",
"updated": "2022-10-22T06:30:05.86474Z",
"basket": null,
"metadata": null
}
Returns QR Code Object with HTTP status code 200 and ACTIVE
status.
Error Codes
Example: Create QR Code Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is invalid input in one of the required request fields"
}
Error Code | Description |
---|---|
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 QR code acquirer. 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 |
DUPLICATE_ERROR409 |
ID_DANA only allows 1 static QR code for each merchant |
SERVER_ERROR500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
CHANNEL_UNAVAILABLE503 |
The QR partner is currently experiencing unexpected issues. The QR partner will be notified to resolve this issue |
Get QR Code by QR ID
This GET endpoint is used to get the details of a QR code by QR ID (qr_
) returned in the response of Create QR Code.
Example: Get QR Code by QR ID Request
Request Parameters
GET https://api.xendit.co/qr_codes/:id
curl https://api.xendit.co/qr_codes/qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2 -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'api-version: 2022-07-31'
-H 'Content-Type: application/json' \
Header Parameter | Type | Description |
---|---|---|
api-versionrequired |
string |
The version of the API. Use 2022-07-31 for the v2 version of the endpoint |
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 |
Unique identifier for this transaction. QR ID with prefix qr_ returned in the response of Create QR Code |
Response Parameters
Example: Get QR Code by QR ID Success Response (QR Code Object)
{
"id": "qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2",
"reference_id": "order-id-1666420204",
"business_id": "58cd618ba0464eb64acdb246",
"type": "DYNAMIC",
"currency": "IDR",
"amount": 10000,
"channel_code": "ID_DANA",
"status": "ACTIVE",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"expires_at": "2022-10-23T09:56:43.60445Z",
"created": "2022-10-22T06:30:05.86474Z",
"updated": "2022-10-22T06:30:05.86474Z",
"basket": null,
"metadata": null
}
Returns QR Code Object with status code 200 for a valid identifier.
Error Codes
Example: Get QR Code by QR ID Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is invalid input in one of the required request fields"
}
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 |
DATA_NOT_FOUND404 |
QR 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 |
QR Payment Object
The QR Payment Object is returned in the callback of Create QR Code and in the response of List QR Payments by QR ID. For List QR Payments by QR ID, if more than one payment exists for a specific QR code, the response body will contain an array of QR Payment Objects.
Example: QR Payment Object
{
"id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
"business_id": "58cd618ba0464eb64acdb246",
"currency": "IDR",
"amount": 10000,
"status": "SUCCEEDED",
"created": "2022-10-22T06:30:05.86474Z",
"qr_id": "qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"reference_id": "order-id-1666420204",
"type": "DYNAMIC",
"channel_code": "ID_DANA",
"expires_at": "2022-10-23T09:56:43.60445Z",
"basket": null,
"metadata": null,
"payment_detail": {
"receipt_id": "000111666",
"source": "GOPAY",
"name": null,
"account_details": null
}
}
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string |
Unique identifier for this transaction. Prefix qrpy_ |
||||||||||||||||||||||||
business_id | string |
Business ID of merchant | ||||||||||||||||||||||||
currency | string |
Currency used for the transaction in ISO4217 format Available values: IDR . PHP |
||||||||||||||||||||||||
amount | number |
Amount specified in request Static QR codes require the end user to always input the amount to be paid at the point of scanning Note: - QRIS - min 1 IDR, max 10,000,000 IDR - QRPh - min 1 PHP, max 50,000 PHP |
||||||||||||||||||||||||
status | string |
Status of the QR payment Available values: SUCCEEDED |
||||||||||||||||||||||||
created | string |
ISO 8601 Timestamp for QR payment creation. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
||||||||||||||||||||||||
qr_id | string |
Unique identifier for the QR code. Prefix qr_ |
||||||||||||||||||||||||
qr_string | 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) | ||||||||||||||||||||||||
reference_id | string |
Reference ID provided by merchant (255 characters) | ||||||||||||||||||||||||
type | string |
DYNAMIC or STATIC Note: Dynamic QR code contains the amount value to be paid upon scanning and can only be paid a single time Static QR code requires end user to input the payment value and can be paid multiple times |
||||||||||||||||||||||||
channel_code | string |
Code specifying which QR code partner will be used to process the transaction Available values: ID_DANA , ID_LINKAJA |
||||||||||||||||||||||||
expires_at | string |
ISO 8601 Timestamp for QR code expiry. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ Note: For ID_DANA 's dynamic QR code, default is QR code expires in 48 hours from creation time if expires_at is not specified. For ID_DANA 's static QR code, default is QR code never expires (expires_at will be accepted and ignored) Custom expiry is not available for QRPh at the moment |
||||||||||||||||||||||||
basket | object |
Array of objects describing the item(s) purchased
|
||||||||||||||||||||||||
metadata | object |
Object of additional information the merchant may use. Merchant defines the JSON properties and values Merchant can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long |
||||||||||||||||||||||||
payment_detail | object |
Object contains information about the payment that has been shared across the payment network
|
List QR Payments by QR ID
This GET endpoint is used to return a list of payment(s) associated with a single QR code by QR ID (qr_
) from the response of Create QR Code.
Example: List QR Payments by QR ID Request
GET https://api.xendit.co/qr_codes/:qr_id/payments
Request Parameters
curl https://api.xendit.co/qr_codes/qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2/payments -X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
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 |
---|---|---|
qr_idrequired |
string |
Unique identifier for this transaction. QR ID with prefix qr_ returned in the response of Create QR Code |
Query Parameter | Type | Description |
---|---|---|
limitoptional |
number |
Number of payment transactions to be returned in response array Default: 10 |
fromoptional |
string |
Starting timestamp in ISO ISO 8601 format for created . Timestamp must be earlier than to parameter. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
tooptional |
string |
Ending timestamp in ISO ISO 8601 format for created . Timestamp must be later than from parameter. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
Response Parameters
Example: List QR Payments by QR ID Success Response
{
"has_more": false,
"data": [
{
"id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
"business_id": "58cd618ba0464eb64acdb246",
"currency": "IDR",
"amount": 10000,
"status": "SUCCEEDED",
"created": "2022-10-22T06:30:05.86474Z",
"qr_id": "qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"reference_id": "order-id-1666420204",
"type": "DYNAMIC",
"channel_code": "ID_DANA",
"expires_at": "2022-10-23T09:56:43.60445Z",
"basket": null,
"metadata": null,
"payment_detail": {
"receipt_id": "000111666",
"source": "GOPAY",
"name": null,
"account_details": null
}
}
]
}
Body Parameter | Type | Description |
---|---|---|
has_more | boolean |
Indicates whether there are more items to be queried from the current result |
data | array |
Returns array of QR Payment Objects when data found. Returns empty array when data not found. |
Error Codes
Example: List QR Payments by QR ID Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is invalid input in one of the required request fields"
}
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 |
DATA_NOT_FOUND404 |
QR 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 |
QR Payment Callback
Xendit notifies your system upon successful payments via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard under QR Code paid
.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Example: Success Payment Webhook Payload
{
"event": "qr.payment",
"api_version": "2022-07-31",
"business_id": "58cd618ba0464eb64acdb246",
"created": "2022-10-22T06:30:05.86474Z",
"data": {
"id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
"business_id": "58cd618ba0464eb64acdb246",
"currency": "IDR",
"amount": 10000,
"status": "SUCCEEDED",
"created": "2022-10-22T06:30:05.86474Z",
"qr_id": "qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"reference_id": "order-id-1666420204",
"type": "DYNAMIC",
"channel_code": "ID_DANA",
"expires_at": "2022-10-23T09:56:43.60445Z",
"description": "",
"basket": null,
"metadata": null,
"payment_detail": {
"receipt_id": "000111666",
"source": "GOPAY",
"name": null,
"account_details": null
}
}
}
Header Parameter | Type | Description |
---|---|---|
x-callback-token |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-id |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description |
---|---|---|
event | string |
Identifies the event that triggered a notification to the merchant Available values: qr.payment |
api-version | string |
The version of the API. 2022-07-31 is for the v2 version of the endpoint |
business_id | string |
Business ID of merchant |
created | string |
ISO 8601 Timestamp for QR payment creation. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
data | object |
Return QR Payment Object |
Simulate QR Payment
This POST endpoint is used to simulate a QR payment made to a dynamic (fixed amount) or a static (open amount) QR code created in TEST mode.
Example: Create QR Code Request
POST https://api.xendit.co/qr_codes/:id/payments/simulate
Request Parameter
curl https://api.xendit.co/qr_codes/qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2/payments/simulate -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'api-version: 2022-07-31'
-H 'Content-Type: application/json' \
--data-raw '{
"amount": 10000
}'
Header Parameter | Type | Description |
---|---|---|
api-versionrequired |
string |
The version of the API. Use 2022-07-31 for the v2 version of the endpoint |
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 |
Unique identifier for this transaction. QR ID with prefix qr_ returned in the response of Create QR Code |
Body Parameter | Type | Description |
---|---|---|
amountconditionally required |
number |
Amount paid into a static QR code Static QR codes require the end user to always input the amount to be paid at the point of scanning Note: Min amount is 1 IDR Max amount is 10,000,000 IDR |
Response Parameters
Example: Simulate QR Payment Success Response (QR Code Object)
{
"id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
"business_id": "58cd618ba0464eb64acdb246",
"currency": "IDR",
"amount": 10000,
"status": "SUCCEEDED",
"created": "2022-10-22T06:30:05.86474Z",
"qr_id": "qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"reference_id": "order-id-1666420204",
"type": "DYNAMIC",
"channel_code": "ID_DANA",
"expires_at": "2022-10-23T09:56:43.60445Z",
"description": "",
"basket": null,
"metadata": null,
"payment_detail": {
"receipt_id": "000111666",
"source": "GOPAY",
"name": null,
"account_details": null
}
}
Returns QR Payment Object with HTTP status code 200
Callback Payload
Example: Success Payment Callback Payload
{
"event": "qr.payment",
"api_version": "2022-07-31",
"business_id": "58cd618ba0464eb64acdb246",
"created": "2022-10-22T06:30:05.86474Z",
"data": {
"id": "qrpy_8182837te-87st-49ing-8696-1239bd4d759c",
"business_id": "58cd618ba0464eb64acdb246",
"currency": "IDR",
"amount": 10000,
"status": "SUCCEEDED",
"created": "2022-10-22T06:30:05.86474Z",
"qr_id": "qr_61cb3576-3a25-4d35-8d15-0e8e3bdba4f2",
"qr_string": "0002010102##########CO.XENDIT.WWW011893600#######14220002152#####414220010303TTT####015CO.XENDIT.WWW02180000000000000000000TTT52045######ID5911XenditQRIS6007Jakarta6105121606##########3k1mOnF73h11111111#3k1mOnF73h6v53033605401163040BDB",
"reference_id": "order-id-1666420204",
"type": "DYNAMIC",
"channel_code": "ID_DANA",
"expires_at": "2022-10-23T09:56:43.60445Z",
"description": "",
"basket": null,
"metadata": null,
"payment_detail": {
"receipt_id": "000111666",
"source": "GOPAY",
"name": null,
"account_details": null
}
}
}
Merchant will receive a single QR Payment Callback.
Error Codes
Example: Simulate QR Payment Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is invalid input in one of the required request fields"
}
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 |
DATA_NOT_FOUND404 |
QR ID specified was not found. Please check your query again |
INACTIVE_QR_CODE410 |
The specified QR code is inactive and can no longer accept payment |
SERVER_ERROR500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
QR Refund Object
The QR Refund Object is returned in the responses and callback of Refund QR Payment, Get QR Refund by Refund ID, and List QR Refund(s) by QR Payment ID. For List QR Refund(s) by QR Payment ID, if more than one partial refund exists for a specific QR payment, the response body will contain an array of QR Refund Objects.
Example: QR Refund Object
{
"id": "qrrf_52b86306-7464-4fe2-8f98-967ca603f90a",
"qrpy_id": "qrpy_319f4504-867f-45bc-aec4-8ac64fb6be78",
"status": "PENDING",
"currency": "IDR",
"payment_amount": 100000,
"refund_amount": 50000,
"channel_code": "ID_DANA",
"reason": "REQUESTED_BY_CUSTOMER",
"failure_code": null,
"created": "2022-07-15T09:56:43.60445Z",
"updated": "2022-07-15T09:56:43.60445Z",
"refunded_at": null
}
Body Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the QR refund transaction (prefix qrrf_ ) |
qrpy_id | string |
Unique identifier for the original QR payment transaction |
status | string |
Status of the refund request Available values: SUCCEEDED, FAILED, PENDING |
currency | string |
Currency used for the transaction in ISO4217 format Available values: IDR |
payment_amount | number |
Amount of the original QR payment transaction |
refund_amount | number |
Amount to be refunded |
channel_code | string |
Channel code indicating the QR code partner Available values: ID_DANA |
reason | string |
Reason for the refund |
failure_code | string |
Reason for the refund request failing |
created | string |
Timestamp in ISO 8601 for the refund request. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
updated | string |
Timestamp in ISO 8601 for the latest refund object update. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
refunded_at | string |
Timestamp in ISO 8601 for the refund completion from the QR code partner. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
Refund QR Payment
This POST endpoint is used to request a full or partial refund of a QR payment. It is possible to request multiple refunds for a single transaction as long as the aggregate refund amount does not exceed the original transaction amount.
If a refund of the full amount is requested within 24 hours of payment completion, the original payment will be VOIDED
. The original fee and VAT charged will be fully returned.
If a refund of a partial amount is requested or if a refund of any amount is requested after 24 hours of payment completion, the original payment will be REFUNDED
. The original fee and VAT charged will NOT be returned at all.
- This Refund API will only work for successful QR payments.
- This Refund API will return
PENDING
status in API response upon execution. A follow-up webhook/callback will be sent to your system's URL when refund has been processed successfully.
Rules and Limitations
Value | DANA QRIS | LINKAJA QRIS |
---|---|---|
Available at Xendit? |
✓ | ✕ |
Partial Refund Allowed? |
✓ | ✕ |
Multiple Refunds Allowed? |
✓ | ✕ |
Validity Period |
30 days from payment | ✕ |
Transaction Fee Returned? |
✓ if a refund of the full amount is requested within 24 hours of payment completion ✕ if a refund of the partial amount is requested or if a refund of any amount is requested after 24 hours of payment completion |
✕ |
Supported Issuers
Value | Full Amount & Within 24 Hours of Payment Completion | Full Amount & After 24 Hours of Payment Completion | Partial Amount |
---|---|---|---|
DANA |
✓ | ✓ | ✓ |
ShopeePay |
✓ | ✓ | ✓ |
OVO |
✓ | ✓ | ✓ |
LinkAja |
✓ | ✓ | ✕ |
Mandiri |
✓ | ✕ | ✕ |
Permata |
✓ | ✓ | ✓ |
CIMB |
✓ | ✓ | ✕ |
Jenius / BTPN |
✓ | ✓ | ✓ |
BSI |
✓ | ✓ | ✓ |
Example: Refnd QR Code Request
POST https://api.xendit.co/qr_codes/payments/:qrpy_id/refunds
Request Parameters
curl https://api.xendit.co/qr_codes/payments/qrpy_8182837te-87st-49ing-8696-1239bd4d759c/refunds -X POST \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
-H 'Content-Type: application/json' \
--data-raw '{
"amount": "50000",
"reason": "REQUESTED_BY_CUSTOMER"
}'
Header Parameter | Type | Description |
---|---|---|
idempotency-keyoptional |
string |
Provided to prevent duplicate requests. Can be equal to any UUID. Idempotency keys are stored on the request layer. It expires after 24 hours from the first request |
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 |
---|---|---|
qrpy_idrequired |
string |
Unique identifier for the original QR payment transaction (prefix qrpy_ ) returned in the QR payment callback |
Body Parameter | Type | Description |
---|---|---|
amountoptional |
number |
Amount to be refunded to your customer. Cumulative amount refunded must not exceed the original transacted amount If the amount field is not present in the request body, the remaining unrefunded amount of the original transaction will be processed |
reasonoptional |
string |
Reason for the refund, selecting from one of the following values Available values: DUPLICATE, FRAUDULENT, REQUESTED_BY_CUSTOMER, CANCELLATION, OTHERS |
Response Parameters
Example: Refund QR Payment Success Response (QR Refund Object)
{
"id": "qrrf_52b86306-7464-4fe2-8f98-967ca603f90a",
"qrpy_id": "qrpy_319f4504-867f-45bc-aec4-8ac64fb6be78",
"status": "PENDING",
"currency": "IDR",
"payment_amount": 100000,
"refund_amount": 50000,
"channel_code": "ID_DANA",
"reason": "REQUESTED_BY_CUSTOMER",
"failure_code": null,
"created": "2022-07-15T09:56:43.60445Z",
"updated": "2022-07-15T09:56:43.60445Z",
"refunded_at": null
}
Returns QR Refund Object with HTTP status code 200 and PENDING
status.
Error Codes
Example: Refund QR Payment Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server"
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is an error with the format submitted to the server |
MAXIMUM_REFUND_AMOUNT_REACHED400 |
Requested refund amount cannot exceed the remaining unrefunded amount of the original payment |
REFUND_IN_PROGRESS400 |
Concurrent full refund requests to a single QR payment transaction is not allowed. Please wait for the pending full refund request to be completed before initiating a new one |
REFUND_NOT_SUPPORTED400 |
Refund feature is not available as the method is not provided by the QR partner |
PARTIAL_REFUND_NOT_SUPPORTED400 |
Partial refund feature is not available as the method is not supported for this specific issuer |
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
INELIGIBLE_TRANSACTION403 |
Requested refund transaction cannot be processed as the transaction is in “FAILED”, “PENDING”, or “VOIDED” status |
DATA_NOT_FOUND404 |
Resource not found. Please check your query again |
SERVER_ERROR500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
CHANNEL_UNAVAILABLE503 |
The QR partner is currently experiencing unexpected issues. The QR partner will be notified to resolve this issue |
QR Refund Callback
The refund callback notification will be sent as POST request to the same endpoint used in creating an eWallet charge. Please make sure that your callback URL used for receiving QR payment notifications can accept both qr.payment
and qr.refund
events. 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.
Example: Success Refund Callback Payload
{
"event": "qr.refund",
"api_version": null,
"business_id": "58cd618ba0464eb64acdb246",
"created": "2022-10-22T06:30:05.86474Z",
"data": {
"id": "qrrf_52b86306-7464-4fe2-8f98-967ca603f90a",
"qrpy_id": "qrpy_319f4504-867f-45bc-aec4-8ac64fb6be78",
"status": "SUCCEEDED",
"currency": "IDR",
"payment_amount": 100000,
"refund_amount": 50000,
"channel_code": "ID_DANA",
"reason": "REQUESTED_BY_CUSTOMER",
"failure_code": null,
"created": "2022-07-15T09:56:43.60445Z",
"updated": "2022-07-15T09:56:43.60445Z",
"refunded_at": "2022-07-15T09:57:43.60445Z"
}
}
Body Parameter | Type | Description |
---|---|---|
event | string |
Identifies the event that triggered a notification to the merchant Available values: qr.refund |
api_version | string |
The version of the API. Example: 2020-04-22. Default: NULL |
business_id | string |
Business ID of merchant |
created | string |
ISO 8601 Timestamp for notification creation. Timezone UTC+0 Format: YYYY-MM-DDTHH:mm:ssZ |
data | object |
Return QR Refund Object |
Failure Code | Failure Message |
---|---|
INELIGIBLE_TRANSACTION | Transaction has already passed its validity period for the requested operation or the number of refunds requested has exceeded the allowable number of tries |
INSUFFICIENT_BALANCE | There is insufficient balance in your Xendit account to perform a refund. Please top up your Xendit balance with a sufficient amount before retrying the refund |
INSUFFICIENT_BALANCE | Switcher account does not have sufficient balance to perform a refund. Please retry after ensuring there is sufficient balance in the switcher account |
REFUND_TEMPORARILY_UNAVAILABLE | Refund is temporarily unavailable because of settlement constraints with the QR partner. Please try again later |
MAXIMUM_USER_BALANCE_EXCEEDED | Refund could not be processed because the amount returned will cause the end user's account balance to exceed maximum allowable value |
Get QR Refund by Refund ID
This GET endpoint is used to get the details of a QR refund by Refund ID (qrrf_
) returned in the response of Refund QR Payment.
Example: Get QR Refund by Refund ID Request
Request Parameters
GET https://api.xendit.co/qr_codes/payments/:qrpy_id/refunds/:refund_id
curl https://api.xendit.co/qr_codes/payments/qrpy_319f4504-867f-45bc-aec4-8ac64fb6be78/refunds/qrrf_52b86306-7464-4fe2-8f98-967ca603f90a -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==: \
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 |
---|---|---|
qrpy_idrequired |
string |
Unique identifier for the original QR payment transaction (prefix qrpy_ ) returned in the QR payment callback |
refund_idrequired |
string |
Unique identifier for the refund transaction (prefix qrrf_ ) returned in the response of Refund QR Payment |
Response Parameters
Example: Get QR Refund by Refund ID Success Response (QR Refund Object)
{
"id": "qrrf_52b86306-7464-4fe2-8f98-967ca603f90a",
"qrpy_id": "qrpy_319f4504-867f-45bc-aec4-8ac64fb6be78",
"status": "SUCCEEDED",
"currency": "IDR",
"payment_amount": 100000,
"refund_amount": 50000,
"channel_code": "ID_DANA",
"reason": "REQUESTED_BY_CUSTOMER",
"failure_code": null,
"created": "2022-07-15T09:56:43.60445Z",
"updated": "2022-07-15T09:56:43.60445Z",
"refunded_at": "2022-07-15T09:57:43.60445Z"
}
Returns QR Refund Object with status code 200 for a valid identifier.
Error Codes
Example: Get QR Refund by Refund ID Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server"
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is an error with the format submitted to the server |
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
QR 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 |
List QR Refunds by QR Payment ID
This GET endpoint is used to get the details of all refunds associated with a single QR payment ID (qrpy_
) from the QR payment callback.
Example: List QR Refunds by QR Payment ID Request
GET https://api.xendit.co/qr_codes/payments/:qrpy_id/refunds
Request Parameters
curl https://api.xendit.co/qr_codes/payments/qrpy_319f4504-867f-45bc-aec4-8ac64fb6be78/refunds -X GET \
-u xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman:
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 |
---|---|---|
qrpy_idrequired |
string |
Unique identifier for the original QR payment transaction (prefix qrpy_ ) returned in the QR payment callback |
Query Parameter | Type | Description |
---|---|---|
limitoptional |
number |
Number of payment transactions to be returned in response array Default: 10 Min: 1 Max: 50 |
statusoptional |
string |
Refund status to be retrieved Available values: SUCCEEDED, FAILED, PENDING |
Response Parameters
Example: List QR Refunds by QR Payment ID Success Response
{
"has_more": false,
"data": [
{
"id": "qrrf_52b86306-7464-4fe2-8f98-967ca603f90a",
"qrpy_id": "qrpy_319f4504-867f-45bc-aec4-8ac64fb6be78",
"status": "SUCCEEDED",
"currency": "IDR",
"payment_amount": 100000,
"refund_amount": 50000,
"channel_code": "ID_DANA",
"reason": "REQUESTED_BY_CUSTOMER",
"failure_code": null,
"created": "2022-07-15T09:56:43.60445Z",
"updated": "2022-07-15T09:56:43.60445Z",
"refunded_at": "2022-07-15T09:57:43.60445Z"
}
]
}
Body Parameter | Type | Description |
---|---|---|
has_more | boolean |
Indicates whether there are more items to be queried from the current result. If result is empty, has_more will be false |
data | array |
Returns array of QR Refund Objects when data found. Returns empty array when data not found |
Error Codes
Example: List QR Refunds by QR Payment ID Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server"
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is an error with the format submitted to the server |
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
Resource not found. Please check your query again |
SERVER_ERROR500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$linkedAccountTokenizationParams = [
'customer_id' => '4b7b6050-0830-440a-903b-37d527dbbaa9',
'channel_code' => 'DC_BRI',
'properties' => [
'account_mobile_number' => '+62818555988',
'card_last_four' => '8888',
'card_expiry' => '06/24',
'account_email' => 'test.email@xendit.co'
],
'metadata' => [
'meta' => 'data'
]
];
$initializeTokenization = \Xendit\DirectDebit::initializeLinkedAccountTokenization(
$linkedAccountTokenizationParams
);
var_dump($initializeTokenization);
?>
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);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
properties := map[string]interface{}{
"account_mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"account_email": "test.email@xendit.co",
}
metadata := map[string]interface{}{
"meta": "data",
}
data := linkedaccount.InitializeLinkedAccountTokenizationParams{
CustomerID: "791ac956-397a-400f-9fda-4958894e61b5",
ChannelCode: xendit.DC_BRI,
Properties: properties,
Metadata: metadata,
}
resp, err := linkedaccount.InitializeLinkedAccountTokenization(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("initialized linked account tokenization: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
Map<String, Object> properties = new HashMap<>();
properties.put("account_mobile_number", "+62818555988");
properties.put("card_last_four", "8888");
properties.put("card_expiry", "06/24");
properties.put("account_email", "test.email@xendit.co");
Map<String, Object> metadata = new HashMap<>();
metadata.put("tes", "123");
Map<String, Object> params = new HashMap<>();
params.put("customer_id", "791ac956-397a-400f-9fda-4958894e61b5");
params.put("channel_code", "DC_BRI");
params.put("properties", properties);
params.put("metadata", metadata);
InitializedLinkedAccount linkedAccount = InitializedLinkedAccount.initializeLinkedAccountTokenization(params);
} catch (XenditException e) {
e.printStackTrace();
}
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
LinkedAccountTokenClient linkedAccountToken = xendit.LinkedAccountToken;
InitializedLinkedAccountTokenParameter parameter = new InitializedLinkedAccountTokenParameter
{
CustomerId = "customer-id",
ChannelCode = LinkedAccountEnum.ChannelCode.DcBri,
Properties = new LinkedAccountProperties
{
AccountMobileNumber = "+62818555988",
CardLastFour = "4444",
CardExpiry = "06/24",
AccountEmail = "test@email.com",
},
Metadata = new Dictionary<string, object>()
{
{ "example-metadata", "here is the example" },
},
};
InitializedLinkedAccountToken initializedLinkedAccountToken = await linkedAccountToken.Initialize(parameter);
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 BRI Debit Card Linking:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$validateOTPForLinkedAccountParams = [
'otp_code' => '333000'
];
$validateOTPForLinkedAccount = \Xendit\DirectDebit::validateOTPForLinkedAccount(
'lat-a08fba1b-100c-445b-b788-aaeaf8215e8f',
$validateOTPForLinkedAccountParams
);
var_dump($validateOTPForLinkedAccount);
?>
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);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := linkedaccount.ValidateOTPForLinkedAccountParams{
LinkedAccountTokenID: "lat-f9dc34e7-153a-444e-b337-cd2599e7f670",
OTPCode: "333000",
}
resp, err := linkedaccount.ValidateOTPForLinkedAccount(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("validated linked account: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
Map<String, Object> params = new HashMap<>();
params.put("otp_code", "333000");
String tokenId = "lat-ba3c5645-f134-432a-b4f4-f8972685aa03";
ValidatedLinkedAccount linkedAccount = ValidatedLinkedAccount.validateOTP(tokenId, params);
} catch (XenditException e) {
e.printStackTrace();
}
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
LinkedAccountTokenClient linkedAccountToken = xendit.LinkedAccountToken;
string otpCode = "333000";
string linkedAccountTokenId = "lat-f325b757-0aae-4c24-92c5-3661e299e154";
ValidatedLinkedAccountToken validatedLinkedAccountToken = await linkedAccountToken.ValidateOtp(otpCode, linkedAccountTokenId);
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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$retrieveLinkedAccounts = \Xendit\DirectDebit::retrieveAccessibleLinkedAccounts(
'lat-a08fba1b-100c-445b-b788-aaeaf8215e8f'
);
var_dump($retrieveLinkedAccounts);
?>
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);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := linkedaccount.RetrieveAccessibleLinkedAccountParams{
LinkedAccountTokenID: "lat-f9dc34e7-153a-444e-b337-cd2599e7f670",
}
resp, err := linkedaccount.RetrieveAccessibleLinkedAccounts(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved accessible linked accounts: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
AccessibleLinkedAccount[] linkedAccounts = AccessibleLinkedAccount.retrieveAccessibleLinkedAccounts(
"lat-960e709c-bdd6-4b4a-a361-243186379c45");
System.out.println(Arrays.toString(linkedAccounts));
} catch (XenditException e) {
e.printStackTrace();
}
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_accounts_by_token(
linked_account_token_id="lat-f325b757-0aae-4c24-92c5-3661e299e154",
)
print(accessible_accounts)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
LinkedAccountTokenClient linkedAccountToken = xendit.LinkedAccountToken;
string linkedAccountTokenId = "lat-f325b757-0aae-4c24-92c5-3661e299e154";
AccessibleLinkedAccountToken[] accessibleLinkedAccountTokens = await linkedAccountToken.Get(linkedAccountTokenId);
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 (BRI, BCA OneKlik) or BANK_ACCOUNT (BPI, UBP) |
||||||||||||||||||||||||||||||||||
properties |
object
|
Object containing information regarding the account. The values inside properties change based on the type of account: For type BRI DEBIT_CARD :
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}
Endpoint: Unbind a KTB Linked Account Token
DELETE https://api.xendit.co/linked_account_tokens/{linked_account_token_id}?success_redirect_url=https://success.yourcompany.com&failure_redirect_url=https://failure.yourcompany.com
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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$unbindLinkedAccountToken = \Xendit\DirectDebit::unbindLinkedAccountToken(
'lat-a08fba1b-100c-445b-b788-aaeaf8215e8f'
);
var_dump($unbindLinkedAccountToken);
?>
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));
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := linkedaccount.UnbindLinkedAccountTokenParams{
LinkedAccountTokenID: "lat-f9dc34e7-153a-444e-b337-cd2599e7f670",
}
resp, err := linkedaccount.UnbindLinkedAccountToken(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("unbinded linked account: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
UnbindedLinkedAccount linkedAccount = UnbindedLinkedAccount.unbindLinkedAccountToken ("lat-a08fba1b-100c-445b-b788-aaeaf8215e8f");
} catch (XenditException e) {
e.printStackTrace();
}
string apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==";
XenditClient xendit = new XenditClient(apiKey);
LinkedAccountTokenClient linkedAccountToken = xendit.LinkedAccountToken;
string linkedAccountTokenId = "lat-f325b757-0aae-4c24-92c5-3661e299e154";
UnbindedLinkedAccountToken unbindedLinkedAccountToken = await linkedAccountToken.Unbind(linkedAccountTokenId);
Path Parameter | Type | Description |
---|---|---|
linked_account_token_id required |
string |
Linked account token id received from Initialize Account Authorization. This has the lat- prefix. |
Query Parameter | Type | Description |
---|---|---|
success_redirect_url | string |
URL where the end customer is redirected if the unlinking authorization is successful. Required if the payment method is direct debit and the channel is KTB. |
failure_redirect_url | string |
URL where the end customer is redirected if the unlinking authorization is failed. Required if the payment method is direct debit and the channel is KTB. |
Unbind a Linked Account Token - Response
Example Unbind a Linked Account Token Success Response
{
"id": "lat-aa620619-124f-41db-995b-66a52abe036a",
"is_deleted": true
}
Example Unbind a KTB Linked Account Token Success Response
{
"id": "lat-aa620619-124f-41db-995b-66a52abe036a",
"is_deleted": false,
"authorizer_url": "https://link-web.xendit.co/oauth/lat-aa620619-124f-41db-995b-66a52abe036a/confirm_unlink"
}
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 |
authorizer_url optional |
string |
Direct debit issuer generated URL for redirecting user to authorize account unlinking. It only shown for KTB linked account token. |
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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$createPaymentMethodParams = [
'customer_id' => '4b7b6050-0830-440a-903b-37d527dbbaa9',
'type' => 'DEBIT_CARD',
'properties' => [
'id' => 'la-052d3e2d-bc4d-4c98-8072-8d232a552299'
],
'metadata' => [
'meta' => 'data'
]
];
$createPaymentMethod = \Xendit\DirectDebit::createPaymentMethod(
$createPaymentMethodParams
);
var_dump($createPaymentMethod);
?>
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);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
properties := map[string]interface{}{
"id": "la-55048b41-a7ab-4799-9f33-6ec5cc078db0",
}
metadata := map[string]interface{}{
"meta": "data",
}
data := paymentmethod.CreatePaymentMethodParams{
CustomerID: "4b7b6050-0830-440a-903b-37d527dbbaa9",
Type: xendit.DEBIT_CARD,
Properties: properties,
Metadata: metadata,
}
resp, err := paymentmethod.CreatePaymentMethod(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created payment method: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
Map<String, Object> properties = new HashMap<>();
properties.put("id", "la-052d3e2d-bc4d-4c98-8072-8d232a552299");
Map<String, Object> metadata = new HashMap<>();
metadata.put("halo", "hello");
metadata.put("tes", "123");
Map<String, Object> params = new HashMap<>();
params.put("customer_id", "4b7b6050-0830-440a-903b-37d527dbbaa9");
params.put("type", "DEBIT_CARD");
params.put("properties", properties);
params.put("metadata", metadata);
PaymentMethod paymentMethod = PaymentMethod.createPaymentMethod(params);
} catch (XenditException e) {
e.printStackTrace();
}
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
PaymentMethodClient paymentMethod = xendit.PaymentMethod;
PaymentMethodParameter parameter = new PaymentMethodParameter
{
Type = PaymentMethodEnum.AccountType.DebitCard,
Properties = new PaymentMethodProperties
{
Id = "la-052d3e2d-bc4d-4c98-8072-8d232a552299",
ChannelCode = PaymentMethodEnum.ChannelCode.DcBri,
Currency = Currency.IDR,
CardLastFour = "1234",
CardExpiry = "06/24",
Description = "Payment Debit Card",
},
CustomerId = "4b7b6050-0830-440a-903b-37d527dbbaa9",
};
PaymentMethodResponse paymentMethodResponse = await paymentMethod.Create(parameter);
Request Body Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
customer_id conditional |
string
|
ID of the customer object to which the account token will be linked to. Required for all channels except for BCA KlikPay. |
||||||||
type required |
string
|
Type of payment method For BRI, BCA OneKlik: DEBIT_CARD For BCA KlikPay: BANK_REDIRECT For BPI, Unionbank, BBL, Krungsri, KTB, SCB: BANK_ACCOUNT |
||||||||
properties required |
object
|
JSON that contains information that identifies the payment method: For BRI, BCA OneKlik, BPI, Unionbank, BBL, Krungsri, KTB, and SCB:
|
||||||||
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. For BRI, BCA OneKlik: DEBIT_CARD For BCA KlikPay: BANK_REDIRECT For BPI, Unionbank, BBL, Krungsri, KTB, SCB: BANK_ACCOUNT |
||||||||||||||||||||||||||||||||||||||||||||
properties |
object
|
Object containing information regarding the account. The values inside properties change based on the type of account: For BRI:
|
||||||||||||||||||||||||||||||||||||||||||||
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 |
---|---|
CHANNEL_CODE_NOT_SUPPORTED_ERROR 400 |
Provided channel_code does not exist |
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 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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$createDirectDebitPaymentParams = [
'reference_id' => 'test-direct-debit-ref',
'payment_method_id' => 'pm-ebb1c863-c7b5-4f20-b116-b3071b1d3aef',
'currency' => 'IDR',
'amount' => 15000,
'callback_url' => 'http://webhook.site/',
'enable_otp' => true,
'description' => 'test description',
'basket' => [
[
'reference_id' => 'basket-product-ref-id',
'name' => 'product name',
'category' => 'mechanics',
'market' => 'ID',
'price' => 50000,
'quantity' => 5,
'type' => 'product type',
'sub_category' => 'product sub category',
'description' => 'product description',
'url' => 'https://product.url'
]
],
'device' => [
'id' => 'device_id',
'ip_address' => '0.0.0.0',
'ad_id' => 'ad-id',
'imei' => '123a456b789c'
],
'success_redirect_url' => 'https://success-redirect.url',
'failure_redirect_url' => 'https://failure-redirect.url',
'metadata' => [
'meta' => 'data'
],
'Idempotency-key' => '' . time()
];
$createDirectDebitPayment = \Xendit\DirectDebit::createDirectDebitPayment(
$createDirectDebitPaymentParams
);
var_dump($createDirectDebitPayment);
?>
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);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
metadata := map[string]interface{}{
"meta": "data",
}
data := directdebitpayment.CreateDirectDebitPaymentParams{
ReferenceID: "test-direct-debit-ref-0100",
PaymentMethodID: "pm-ebb1c863-c7b5-4f20-b116-b3071b1d3aef",
Currency: "IDR",
Amount: 15000,
CallbackURL: "http://webhook.site/",
EnableOTP: true,
Description: "test description",
Basket: []xendit.DirectDebitBasketItem{
{
ReferenceID: "basket-product-ref-id",
Name: "product-name",
Category: "mechanics",
Market: "ID",
Price: 50000,
Quantity: 5,
Type: "product type",
SubCategory: "product sub category",
Description: "product description",
URL: "https://product.url",
},
},
Device: xendit.DirectDebitDevice{
ID: "device-id",
IPAddress: "0.0.0.0",
UserAgent: "user-agent",
ADID: "ad-id",
Imei: "123a456b789c",
},
SuccessRedirectURL: "https://success-redirect.url",
FailureRedirectURL: "https://failure-redirect.url",
Metadata: metadata,
IdempotencyKey: time.Now().String(),
}
resp, err := directdebitpayment.CreateDirectDebitPayment(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created direct debit payment: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
DirectDebitBasketItem basketItem = DirectDebitBasketItem.builder()
.referenceId("basket-product-ref-id")
.name("product-name")
.category("mechanics")
.market("ID")
.price(50000)
.quantity(5)
.type("product type")
.subCategory("product sub category")
.description("product description")
.url("https://product.url")
.build();
DirectDebitBasketItem[] basketItemArray = new DirectDebitBasketItem[]{basketItem};
DirectDebitDevice device = DirectDebitDevice.builder()
.id("device-id")
.ipAddress("0.0.0.0")
.userAgent("user-agent")
.adId("ad-id")
.imei("123a456b789c")
.build();
Map<String, Object> metadata = new HashMap<>();
metadata.put("halo", "hello");
metadata.put("tes", "123");
Map<String, Object> params = new HashMap<>();
params.put("reference_id", "test-direct-debit-ref-4");
params.put("payment_method_id", "pm-ebb1c863-c7b5-4f20-b116-b3071b1d3aef");
params.put("currency", "IDR");
params.put("amount", 15000);
params.put("callback_url", "http://webhook.site/");
params.put("enable_otp", true);
params.put("description", "test description");
params.put("basket", basketItemArray);
params.put("success_redirect_url", "https://success-redirect.url");
params.put("failure_redirect_url", "https://failure-redirect.url");
params.put("device", device);
params.put("metadata", metadata);
String idempotencyKey = "idempotency-key-4";
DirectDebitPayment directDebitPayment = DirectDebitPayment.createDirectDebitPayment(params, idempotencyKey);
} catch (XenditException e) {
e.printStackTrace();
}
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
DirectDebitPaymentClient directDebitPayment = xendit.DirectDebitPayment;
DirectDebitPaymentParameter directDebitPaymentParameter = new DirectDebitPaymentParameter
{
ReferenceId = "reference-id",
PaymentMethodId = "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
Currency = Currency.IDR,
Amount = 10000,
CallbackUrl = "https://callback-url.com/",
EnableOtp = true,
Description = "Example Description",
SuccessRedirectUrl = "https://success-url.com/",
FailureRedirectUrl = "https://failure-url.com/",
Device = new LinkedAccountDevice
{
Id = "device-id",
IpAddress = "255.255.255.255",
UserAgent = "App",
Imei = "imei-example",
AdId = "ad-id",
},
Metadata = null,
Basket = new BasketItem[]
{
new BasketItem { Name = "Black shoes", Type = "goods", Price = 2000, Quantity = 1 },
new BasketItem { Name = "Blue shirt", Type = "apparel", Price = 2000, Quantity = 1 },
},
};
string idempotencyKey = "fa9b53a1-f81a-47ff-8fde-b2eec3546b66";
DirectDebitPaymentResponse directDebitPaymentResponse = await directDebitPayment.Create(directDebitPaymentParameter, idempotencyKey);
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 |
with-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this direct debit payment in order to split and route payments to multiple accounts. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.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 . Not supported for BA_BPI , BA_UBP , and BCA_KLIKPAY . Note for BCA OneKlik: If set to true , the transaction will require an OTP to be validated regardless of the device object.If not provided, it will follow the device object validation logic set by BCA. |
||||||||||||||||||||||||
description optional |
string
|
Description for the direct debit transaction. | ||||||||||||||||||||||||
device conditional |
object
|
Required for BCA OneKlik Object that contains the end-customer's device fingerprint information. This is used for fraud detection.
|
||||||||||||||||||||||||
basket optional |
array
|
Array of objects describing the item/s purchased using direct debit
|
||||||||||||||||||||||||
success_redirect_url conditional |
string
|
Required for BCA OneKlik and BCA KlikPay The end-customer gets redirected to this URL on successful transaction. If OTP is not required and the transaction was successful, the end-customer gets redirected to this immediately. |
||||||||||||||||||||||||
failure_redirect_url conditional |
string
|
Required for BCA OneKlik and BCA KlikPay The end-customer gets redirected to this URL on failed or cancelled transaction. If OTP is not required and the transaction fails, the end-customer gets redirected to this after displaying the error message. |
||||||||||||||||||||||||
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,
"required_action": "VALIDATE_OTP",
"checkout_url": null,
"success_redirect_url": null,
"failure_redirect_url": null,
"refunded_amount": null,
"refunds": 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 | string |
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. | ||||||||
required_action | string |
Describes the required action in order to complete the linking. If VALIDATE_ON_REDIRECT , the end-customer must be redirected to the provided checkout_url to complete the direct debit payment.If VALIDATE_OTP , an OTP will be sent to the end-customer and must be validated through the /direct_debits/:id/validate_otp endpoint to complete the direct debit payment.If null , the capture is already in progress. |
||||||||
checkout_url | string |
If required_action is VALIDATE_ON_REDIRECT , the end-customer must be redirected to this URL in order to complete the payment.For BCA OneKlik, this will be the page wherein the end-customer will select their mobile number and input the OTP. The URL will be sent out asynchronously via the Payment Initialized Callback. |
||||||||
success_redirect_url | string |
Only applicable for BCA OneKlik, BCA KlikPay The end-customer gets redirected to this URL on successful transaction. |
||||||||
failure_redirect_url | string |
Only for BCA OneKlik, BCA KlikPay The end-customer gets redirected to this URL on failed transactions. The failure_redirect_url will have a failure-code as part of the query string. This describes the reason why the transaction failed. You may use this to dynamically update your failure_redirect_url page based on the failure-code. |
||||||||
refunded_amount | number |
Amount that was successfully refunded from the transaction. | ||||||||
refunds | object |
When refunds are made, this will contain information about the refunds done to the transaction. The will have the following properties:
|
||||||||
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. |
PAYMENT_STATUS_FAILED400 |
The bank partner was unable to process the transaction successfully due to a timeout or an unexpected error on the bank partner’s end. |
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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$validateOTPForDirectDebitPaymentParams = [
'otp_code' => '222000'
];
$validateOTPForDirectDebitPayment = \Xendit\DirectDebit::validateOTPForDirectDebitPayment(
'ddpy-7e61b0a7-92f9-4762-a994-c2936306f44c',
$validateOTPForDirectDebitPaymentParams
);
var_dump($validateOTPForDirectDebitPayment);
?>
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);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := directdebitpayment.ValidateOTPForDirectDebitPaymentParams{
DirectDebitID: "ddpy-7e61b0a7-92f9-4762-a994-c2936306f44c",
OTPCode: "222000",
}
resp, err := directdebitpayment.ValidateOTPForDirectDebitPayment(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("validated direct debit payment: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
Map<String, Object> params = new HashMap<>();
params.put("otp_code", "222000");
String directDebitPaymentId = "ddpy-b150da90-2121-44a6-a836-5eebf0d7ab55";
DirectDebitPayment directDebitPayment = DirectDebitPayment.validateOTP(directDebitPaymentId, params);
} catch (XenditException e) {
e.printStackTrace();
}
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
DirectDebitPaymentClient directDebitPayment = xendit.DirectDebitPayment;
string otpCode = "123456";
DirectDebitPaymentResponse directDebitPaymentResponse = await directDebitPayment.ValidateOtp(otpCode, "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14");
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. |
List Payment Methods
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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$getPaymentMethods = \Xendit\DirectDebit::getPaymentMethodsByCustomerID('4b7b6050-0830-440a-903b-37d527dbbaa9');
var_dump($getPaymentMethods);
?>
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);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := paymentmethod.GetPaymentMethodsByCustomerIDParams{
CustomerID: "4b7b6050-0830-440a-903b-37d527dbbaa9",
}
resp, err := paymentmethod.CreatePaymentMethod(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved payment method: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
PaymentMethod[] paymentMethods = PaymentMethod.getPaymentMethodsByCustomerId("4b7b6050-0830-440a-903b-37d527dbbaa9");
System.out.println(Arrays.toString(paymentMethods));
} catch (XenditException e) {
e.printStackTrace();
}
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
PaymentMethodClient paymentMethod = xendit.PaymentMethod;
PaymentMethodResponse[] paymentMethodResponses = await paymentMethod.Get("ed20b5db-df04-41fc-8018-8ea4ac4d1030");
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. For BRI, BCA OneKlik: DEBIT_CARD For BCA KlikPay: BANK_REDIRECT For BPI, Unionbank: BANK_ACCOUNT |
||||||||||||||||||||||||||||||||||||||||||||
properties |
object
|
Object containing information regarding the account. The values inside properties change based on the type of account: For BRI:
|
||||||||||||||||||||||||||||||||||||||||||||
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. |
Get Payment Methods by Customer ID - Errors
See other common errors here.
Get Payment 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
GET 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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$getDirectDebitPaymentByID = \Xendit\DirectDebit::getDirectDebitPaymentByID(
'ddpy-7e61b0a7-92f9-4762-a994-c2936306f44c'
);
var_dump($getDirectDebitPaymentByID);
?>
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);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := directdebitpayment.GetDirectDebitPaymentStatusByIDParams{
ID: "ddpy-7e61b0a7-92f9-4762-a994-c2936306f44c",
}
resp, err := directdebitpayment.GetDirectDebitPaymentStatusByIDParams(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved direct debit payment: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
DirectDebitPayment directDebitPayment = DirectDebitPayment.getDirectDebitPaymentStatusById("ddpy-7e61b0a7-92f9-4762-a994-c2936306f44c");
} catch (XenditException e) {
e.printStackTrace();
}
`
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
DirectDebitPaymentClient directDebitPayment = xendit.DirectDebitPayment;
DirectDebitPaymentResponse directDebitPaymentResponse = await directDebitPayment.GetById("ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14");
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 Payment 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
GET 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
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$getDirectDebitPaymentByReferenceID = \Xendit\DirectDebit::getDirectDebitPaymentByReferenceID(
'test-direct-debit-ref'
);
var_dump($getDirectDebitPaymentByReferenceID);
?>
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);
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := directdebitpayment.GetDirectDebitPaymentStatusByReferenceIDParams{
ReferenceID: "direct-debit-ref-id",
}
resp, err := directdebitpayment.GetDirectDebitPaymentStatusByReferenceIDParams(&data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved direct debit payments: %+v\n", resp)
try {
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
DirectDebitPayment[] directDebitPayments = DirectDebitPayment.getDirectDebitPaymentStatusByReferenceId("test-direct-debit-ref-4");
System.out.println(Arrays.toString(directDebitPayments));
} catch (XenditException e) {
e.printStackTrace();
}
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
DirectDebitPaymentClient directDebitPayment = xendit.DirectDebitPayment;
DirectDebitPaymentResponse[] directDebitPayments = await directDebitPayment.GetById("direct-debit-ref-1594717458");
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 |
Refund Object
Refund API allows you to fully or partially refund a successfully completed direct debit payment. It is possible to do multiple refunds for a single transaction as long as the amount does not exceed the original transaction amount.
A callback will be sent when a refund has been determined to have succeeded or failed.
Note: Transaction fees will not be refunded.
Example Refund a Direct Debit Payment Success Response
{
"id": "ddrfd-c3970211-f73a-49c4-a3e5-7e93ea49b85f",
"direct_debit_id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
"channel_code": "DC_BRI",
"currency": "IDR",
"amount": "1500",
"status": "PENDING",
"reason": "REQUESTED_BY_CUSTOMER",
"failure_code": null,
"created": "2020-03-26T05:44:26+0800",
"updated": null,
"metadata": null
}
Parameter | Type | Description |
---|---|---|
id | string |
Unique identifier for the refund. Starts with ddrfd- |
direct_debit_id | string |
ID of the original payment transaction. |
channel_code | string |
Code identifier for the channel |
currency | string |
Currency of the refund in ISO4217 format |
amount | string |
Amount to be refunded |
status | string |
Status of the refund - PENDING , COMPLETED , FAILED |
reason | string |
Reason why refund was made Possible values:
|
failure_code | string |
Contains an error code if refund fails. null by default. See possible failure codes here. |
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 |
metadata | object |
Metadata provided by merchant |
Refund a Direct Debit Payment - Failure Codes
Failure Code | Description |
---|---|
REFUND_FAILED |
The bank was unable to process the refund successfully |
ACCOUNT_ACCESS_BLOCKED |
Access to the bank account has been blocked by the bank. The bank account may be frozen, closed, or blocked. |
ACCOUNT_NOT_FOUND |
Refund failed because bank account find the bank account |
INSUFFICIENT_BALANCE |
Source bank account does not have enough balance to perform a refund. |
Create Refund
This API will allow you to refund BRI Direct Debit transactions in Indonesia through Xendit. Currently, only full refunds are allowed.
It will accept information such as direct_debit_id
and an optional reason
for refunds, and will produce PENDING
status in the response. PENDING
status represents that the refunds is being processed by the bank.
A webhook or callback will be sent to your system after the payment has SUCCEEDED
or FAILED
.
Endpoint: Refund a Direct Debit Payment
POST https://api.xendit.co/direct_debits/:direct_debit_id/refunds
Request Parameters
Example Refund a Direct Debit Payment Request
curl https://api.xendit.co/direct_debits/ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14/refunds -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
-H 'Idempotency-key: Test_Idempotent_Key'\
--data-raw '{
"currency": "IDR",
"amount": 1500,
"reason": "REQUESTED_BY_CUSTOMER"
}'
<?php
$url = "https://api.xendit.co/direct_debits/ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14/refunds";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = $headers = [
"Content-Type: application/json",
"Idempotency-key: Test_Idempotent_Key",
];
$data = [
"currency" => "IDR",
"amount" => 1500,
"reason" => "REQUESTED_BY_CUSTOMER",
];
$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;
Path Parameter | Type | Description |
---|---|---|
direct_debit_idrequired |
string |
Xendit identifier for specified direct debit transaction |
Header Parameter | 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 |
---|---|---|
reason required |
string
|
Reason why refund is made Accepted values:
|
amount optional |
number
|
Amount to be refunded If none is provided, it will default to the maximum possible amount to be refunded |
currency optional |
string
|
Currency of the refund. Should be in ISO4217 format. If none is provided, it will follow the currency of the direct debit transaction. Only supports IDR |
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 |
Response Parameters
Returns Refund Object with status code 200
Errors
Example Refund a Direct Debit Payment Error Response
{
"error_code" : "IDEMPOTENCY_ERROR",
"message" : "Idempotency key has been used before. Use a unique idempotency key and try again"
}
Error Code | Description |
---|---|
IDEMPOTENCY_ERROR409 |
Provided Idempotency-key already exists but the request body provided does not match the original request |
DATA_NOT_FOUND404 |
We couldn’t find a valid payment matching the payment id given. |
MAXIMUM_REFUND_AMOUNT_REACHED400 |
The refund amount you have entered is greater than the refundable amount. |
REFUND_NOT_SUPPORTED400 |
Refund request failed because refunds are not supported by the channel. |
INELIGIBLE_TRANSACTION400 |
Refund request failed because the original transaction was not completed successfully or the refund period has passed. |
PARTIAL_REFUND_NOT_SUPPORTED400 |
Refund request failed because partial refunds are not supported by the channel |
INSUFFICIENT_BALANCE400 |
Xendit balance is not enough to perform a refund |
Get Refund by ID
You may use this endpoint to retrieve information regarding a specific refund request by its refund ID.
Endpoint: Get Direct Debit Refund by ID
GET https://api.xendit.co/direct_debits/:direct_debit_id/refunds/:refund_id
Request Parameters
Example Get Direct Debit Refund by ID Request
curl https://api.xendit.co/direct_debits/ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14/refunds/ddrfd-c3970211-f73a-49c4-a3e5-7e93ea49b85f -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
}'
<?php
$direct_debit_id = "ddpy-623dca10-5dad-4916-test";
$refund_id = "ddrfd-c3970211-f73a-49c4-a3e5-7e93ea49b85f";
$url = "https://api.xendit.co/direct_debits/" . $direct_debit_id . "/refunds" . $refund_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;
Path Parameter | Type | Description |
---|---|---|
direct_debit_idrequired |
string |
Xendit identifier for specified direct debit transaction. Starts with ddpy- . |
refund_idrequired |
string |
Unique identifier for the refund generated by Xendit. Starts with ddrfd- . |
Response Parameters
Returns Refund Object with status code 200
Errors
Example Get Direct Debit Refund by ID Error Response
{
"error_code" : "DATA_NOT_FOUND",
"message" : "We couldn’t find a valid payment matching the payment id given."
}
Error Code | Description |
---|---|
DATA_NOT_FOUND404 |
We couldn’t find a valid payment matching the payment id given. |
List Refunds
You may use this endpoint to retrieve all associated refund requests for a specific direct debit payment.
Endpoint: List Refunds by Direct Debit ID
GET https://api.xendit.co/direct_debits/:direct_debit_id/refunds
Request Parameters
Example List Refunds by Direct Debit ID Request
curl https://api.xendit.co/direct_debits/ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14/refunds -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 . "/refunds";
$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;
Path Parameter | Type | Description |
---|---|---|
direct_debit_idrequired |
string |
Xendit identifier for specified direct debit transaction. Starts with ddpy- . |
List Refunds by Direct Debit ID - Response
Example List Refunds by Direct Debit ID Success Response
[
{
"data": [
{
"id": "ddrfd-c3970211-f73a-49c4-a3e5-7e93ea49b85f",
"direct_debit_id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
"channel_code": "DC_BRI",
"currency": "IDR",
"amount": "1500",
"status": "PENDING",
"failure_code": null,
"reason": "REQUESTED_BY_CUSTOMER",
"created": "2020-03-26T05:44:26+0800",
"updated": null,
"metadata": null
}
],
"has_more": false,
"links": null
}
]
Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
data | array |
Array containing refund object that matches the query provided | ||||||||
has_more | boolean |
Indicates whether there are more items to be queried with last_id of the last item from the current result. | ||||||||
links | object |
Array of objects containing target links to access the rest of the data. Will be null if there is no further data available.Each object will have the following properties:
|
List Refunds by Direct Debit ID - Errors
Example List Refunds by Direct Debit ID Error Response
{
"error_code" : "DATA_NOT_FOUND",
"message" : "We couldn’t find a valid payment matching the payment id given."
}
Error Code | Description |
---|---|
DATA_NOT_FOUND404 |
We couldn’t find a valid payment matching the payment id given. |
Callback Notifications
Xendit notifies your system during Linked Account Tokenization and Direct Debit Payment process via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Header Parameter | Type | Description |
---|---|---|
x-callback-token |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-id |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Linked Account Tokenization Webhook
Linked Account Tokenization webhook is only supported for BPI, Unionbank, and BCA OneKlik. Merchants can skip this flow if they are only integrating for BRI Direct Debit.
Example: Linked Account Tokenization Webhook Payload (BCA OneKlik)
{
"event": "linked_account_token.successful",
"timestamp": "2020-03-19T05:34:55+0800",
"id": "lat-aa620619-4177-476e-b097-2ad5ae4d3e55",
"channel_code": "BCA_ONEKLIK",
"type": "DEBIT_CARD",
"accounts": [
{
"id": "la-aa620619-124f-41db-995b-66a52abe036a",
"card_last_four": "1234",
"card_expiry": "06/24",
"account_mobile_number": "+62818555988",
"currency": "IDR",
"description": null
}
]
}
Example: Linked Account Tokenization Webhook Payload (BPI)
{
"event": "linked_account_token.successful",
"timestamp": "2020-03-27T05:45:06+0800",
"id": "lat-aa620619-124f-41db-995b-66a52abe036a",
"channel_code": "BA_BPI",
"type": "BANK_ACCOUNT",
"accounts": [
{
"id": "la-7f2bc3ad-8049-42ff-8b57-6578088e9641",
"account_details": "XXXXXXX123",
"account_hash": "5789fb5c4b051701928af5ac268c8178",
"currency": "PHP",
"account_type": "SAVINGS",
"description": null
}
]
}
Parameter | Type | 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 | ||||||||||||||||||||||||||||
type |
string
|
Payment method type. Possible values: DEBIT_CARD , BANK_ACCOUNT
|
||||||||||||||||||||||||||||
accounts |
array
|
An array of objects containing bank account informations linked to the authorization. For BCA OneKlik:
|
Expiring Payment Method Webhook
This webhook will be sent if the currently linked payment method object is discovered to be invalidated in 7 days. When received, you may notify your user to relink. This is only supported for BPI and Unionbank.
Example: Expiring Payment Method Webhook
{
"event": "payment_method.expiry.expiring",
"timestamp": "2020-03-26T05:44:26+0800",
"id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"channel_code": "BA_BPI",
"customer_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
"expiration_timestamp": "2021-03-26T05:44:26+0800",
"business_id": "5f21361959ef2b788cbbe97f"
}
Parameter | Type | Description |
---|---|---|
event |
string
|
Identifier of the event - payment_method.expiry.expiring
|
timestamp |
string
|
ISO 8601 timestamp of the event. Timezone is UTC+0 |
id |
string
|
Unique identifier for the transaction. Will have pm- as prefix. |
channel_code |
string
|
Code identifier for the channel |
expiration_timestamp |
string
|
ISO 8601 timestamp of when the payment method will be expired. |
customer_id |
string
|
ID of the customer object that owns the payment method object |
business_id |
string
|
Xendit-internal business ID identifying the merchant |
Expired Payment Method Webhook
This will be sent when a specific payment method has expired or has been invalidated. You may use this to notify your customers to relink. This feature is only supported for BPI and Unionbank.
Example: Expired Payment Method Webhook
{
"event": "payment_method.expiry.expired",
"timestamp": "2020-03-26T05:44:26+0800",
"id": "pm-c30d4800-afe4-4e58-ad5f-cc006d169139",
"customer_id": "e17a0ac8-6fed-11ea-bc55-0242ac130003",
"business_id": "5f21361959ef2b788cbbe97f"
}
Parameter | Type | Description |
---|---|---|
event |
string
|
Identifier of the event - payment_method.expiry.expired
|
timestamp |
string
|
ISO 8601 timestamp of the event. Timezone is UTC+0 |
id |
string
|
Unique identifier for the transaction. Will have pm- as prefix. |
customer_id |
string
|
ID of the customer object that owns the payment method object |
business_id |
string
|
Xendit-internal business ID identifying the merchant |
Direct Debit Payment Webhook
Example: Direct Debit Payment Webhook
{
"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 | Type | 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 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 Webhook
{
"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 |
Direct Debit Refund Webhook
Example: Direct Debit Refund Webhook
{
"event": "“direct_debit.refund",
"created": "2020-03-26T05:44:26+0800",
"business_id": "5f21361959ef2b788cbbe97f",
"data": {
"id": "ddrfd-c3970211-f73a-49c4-a3e5-7e93ea49b85f",
"direct_debit_id": "ddpy-623dca10-5dad-4916-b14d-81aaa76b5d14",
"channel_code": "DC_BRI",
"currency": "IDR",
"amount": "1500",
"status": "COMPLETED",
"failure_code": null,
"reason": "REQUESTED_BY_CUSTOMER",
"created": "2020-03-26T05:44:26+0800",
"updated": null,
"metadata": null
}
}
Parameter | Type | Description |
---|---|---|
event | string |
Identifier of the event - "direct_debit.refund" |
created | string |
ISO 8601 timestamp of when the event was created. Timezone is UTC+0 |
busines_id | string |
Xendit-internal business ID identifying the merchant |
data | object |
Returns Refund Object with status COMPLETED or FAILED |
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.
You have 2 environments to try and use Virtual Account APIs: TEST
mode and LIVE
mode. In TEST
mode, Virtual Account is ready and available for you to integrate. For LIVE
mode, activate Virtual Account in Dashboard to start using your preferred Virtual Account. Read more about virtual accounts.
Looking for your virtual accounts to be tied to a transaction rather than a user? Use our invoices API.
Create Virtual Account
Endpoint: Create Virtual Account
POST https://api.xendit.co/callback_virtual_accounts
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='Michael Chen'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
"external_id" => "va-1475804036622",
"bank_code" => "BNI",
"name" => "Michael Chen"
];
$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: 'va-1475804036622',
bankCode: 'BNI',
name: 'Michael Chen',
});
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", "Michael Chen");
//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: "va-1475804036622",
BankCode: "BNI",
Name: "Michael Chen",
}
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="va-1475804036622",
bank_code="BNI",
name="Michael Chen",
)
print(virtual_account)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
VirtualAccountClient virtualAccount = xendit.VirtualAccount;
CreateVirtualAccountParameter parameter = new CreateVirtualAccountParameter
{
ExternalId = "va-1475804036622",
BankCode = VirtualAccountEnum.BankCode.Bni,
Name = "John Doe",
ExpectedAmount = 200000,
};
VirtualAccountResponse virtualAccountResponse = await virtualAccount.Create(parameter);
Example Request of BNI Open VA
{
"external_id": "va-1475804036622",
"bank_code": "BNI",
"name": "Michael Chen"
}
Example Request of BRI Closed VA
{
"external_id": "va-1475804036622",
"bank_code": "BRI",
"name": "Michael Chen",
"is_closed": true,
"expected_amount": 50000,
"expiration_date": "2021-09-27T17:00:00.000Z"
}
Example Request of VPB Single Use, Closed VA with QR_STRING alternative display type
{
"external_id": "va-1329804723",
"bank_code": "VPB",
"name": "Michael Chen",
"country": "VN",
"currency": "VND",
"is_single_use": true,
"is_closed": true,
"expected_amount": 10000,
"alternative_display_types": [
"QR_STRING"
]
}
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-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this Virtual Account in order to split and route payments to multiple accounts. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.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.
|
bank_coderequired |
string |
Bank code of the virtual account you want to create.Available bank codes for Indonesia: |
namerequired |
string |
Name of user/virtual account, - this will be displayed in the bank's user interface, e.g. ATM confirmation screens.Note: |
virtual_account_numberoptional. default:
|
string |
You can assign specific Virtual Account number using this parameter. If you do not send one, one will be picked at random. Make sure the number you specify is within your Virtual Account range. Check your Virtual Account range in Virtual Account Settings. API will throw error if you include merchant code (first 4 or 5 digits of your VA range, ie 26215 for BRI). Example: If your BRI Virtual Account range: 26215 9999000001 - 26215 9999999999 , request virtual_account_number : 9999100101 will be accepted as the value is within VA range, while virtual_account_number : 262159999100101 will throw VIRTUAL_ACCOUNT_NUMBER_OUTSIDE_RANGE Note: Your VA range in TEST and LIVE mode might be different. When going live, double check and adjust your request to follow the respective VA range |
countryoptional. default:
|
string |
The country in which the virtual account operates.Available countries:
|
currencyoptional. default:
|
string |
The currency of payment in which the virtual account can accept.Available currencies for Indonesia: |
is_single_useoptional. default:
|
boolean |
There are 2 types of Virtual Account: is_single_use : true ) can only be paid once. Used VA number can be recreated for other customer/invoice/transactionis_single_use : false ) allows your customer to pay to the same Virtual Account continuously |
is_closedoptional. default:
|
boolean |
There are 2 types of Virtual Account amount: open or closed amount expected_amount parameter below |
expected_amountoptional |
number |
Required amount to be paid by your customer for closed Virtual Account. For BNI ,BJB ,BRI ,BSI , BNC , MANDIRI , and SAHABAT_SAMPOERNA : For PERMATA : For BCA : For CIMB : For DBS : For WOORI and VIETCAPITAL : |
min_amountoptional |
integer positive |
Minimum amount to be paid by your customer for open Virtual Account, it should use an amount above the minimum amount from the bank. Available banks:
|
max_amountoptional |
integer positive |
Maximum amount to be paid by your customer for open Virtual Account, it should use an amount below the maximum amount from the bank. Available banks:
|
suggested_amountoptional |
number |
The suggested amount you want to assign. Available banks: |
expiration_dateoptional. default:
|
string |
ISO8601 timestamp of Virtual Account expiration timeTimezone: |
descriptionoptional |
string |
Description for the Virtual Account. Available for BRI and BSI .
|
alternative_display_typesoptional |
array of strings |
Alternative display types for Virtual Account. Note:This value is currently only applicable to Vietnam virtual accounts. Allowed value: |
Response Parameters
Example of BNI Open VA Response
{
"id": "57f6fbf26b9f064272622aa6",
"external_id": "va-1475804036622",
"owner_id": "57b4e5181473eeb61c11f9b9",
"bank_code": "BNI",
"merchant_code": "8808",
"account_number": "8808999939380502",
"name": "Michael Chen",
"is_single_use": false,
"is_closed": false,
"expiration_date": "2051-09-27T17:00:00.000Z",
"status": "PENDING",
"currency": "IDR",
"country": "ID"
}
Example of BRI Single Use Close VA Response
{
"id": "57f6fbf26b9f064272622aa6",
"external_id": "va-1475804036622",
"owner_id": "57b4e5181473eeb61c11f9b9",
"bank_code": "BRI",
"merchant_code": "26215",
"account_number": "262159939380502",
"name": "Michael Chen",
"is_single_use": true,
"is_closed": true,
"expected_amount": 50000,
"suggested_amount": 50000,
"expiration_date": "2021-09-27T17:00:00.000Z",
"description": "Utensils Payment 27 September 2021",
"status": "PENDING",
"currency": "IDR",
"country": "ID"
}
Example of VPB Single Use Close VA Response with QR_STRING alternative display type
{
"id": "fc1a1fbc-1876-4dc6-b2d1-564f756312f5",
"owner_id": "62ea3c344b29b4f5d58f634c",
"external_id": "va-234982374",
"account_number": "0024600000028492",
"bank_code": "VPB",
"merchant_code": "0024",
"name": "Michael Chen",
"is_closed": true,
"expected_amount": 10000,
"expiration_date": "2055-04-24T10:14:05.651Z",
"is_single_use": true,
"status": "PENDING",
"currency": "VND",
"country": "VN",
"alternative_displays": [
{
"type": "QR_STRING",
"data": "00020101021238600010A00000072701300006970432011600246000000284920208QRIBFTTA53037045802VN5405100006304EDF0"
}
]
}
Returns Virtual Account Object with status 200
Error Codes
Example of Error Message
{
"error_code": "BANK_NOT_SUPPORTED_ERROR",
"message": "That bank code is not currently supported. Use Get Virtual Account Banks API to check available banks"
}
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. Change your body format to JSON to proceed. |
VIRTUAL_ACCOUNT400 |
The virtual account number you want is outside your range. Check your VA range in Virtual Accounts Settings and make sure the account_number is within your VA range |
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 for Closed Virtual Account (is_closed : true ). Specify required amount to proceed. |
CLOSED_VA_NOT400 |
The closed option for this virtual account is not currently supported. |
DUPLICATE_CALLBACK400 |
The Virtual Account number already exist. Check your Virtual Account in Virtual Account tab in Dashboard or Get Virtual Account API. Expire existing Virtual Account first if persists to proceed. |
MINIMUM_EXPECTED400 |
The expected amount is below the maximum limit. |
MAXIMUM_EXPECTED400 |
The expected amount is above the maximum limit. |
CALLBACK_VIRTUAL_ACCOUNT_NAME_NOT_ALLOWED400 |
The name cannot contain bank or institution name. Use non-bank and non-institutions name to proceed. |
DESCRIPTION_NOT400 |
The requested Virtual Account bank doesn't support description feature. |
MINIMUM_AMOUNT_ERROR400 |
Parameter min_amount should be above minimum amount allowed by the bank |
MAXIMUM_AMOUNT_ERROR400 |
Parameter max_amount should be below maximum amount allowed by the bank |
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 |
FEATURE_NOT_SUPPORTED403 |
Minimum and maximum amount feature is not supported by the selected bank. Check Docs/API Reference to see list of banks who support minimum and maximum amount feature. |
CHANNEL_UNAVAILABLE503 |
The payment channel requested is currently experiencing unexpected issues. The Virtual Account provider will be notified to resolve this issue. |
Update Virtual Account
Endpoint: Update Virtual Account (VA)
PATCH https://api.xendit.co/callback_virtual_accounts/:id
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=150000
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = 'VA-id';
$updateParams = ["suggested_amount" => 150000];
$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: 150000,
})
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: "57f6fbf26b9f064272622aa6",
ExpirationDate: &expirationDate,
ExpectedAmount: 150000,
}
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="57f6fbf26b9f064272622aa6",
is_single_use=True,
)
print(virtual_account)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
VirtualAccountClient virtualAccount = xendit.VirtualAccount;
UpdateVirtualAccountParameter parameter = new UpdateVirtualAccountParameter
{
IsSingleUse = true,
ExpectedAmount = 20000,
};
VirtualAccountResponse virtualAccountResponse = await virtualAccount.Update(parameter, "57f6fbf26b9f064272622aa6");
Update Virtual Account API allows you to update Virtual Account type and information according to your business need. You can update VA when the VA status is ACTIVE
. API will throw error when you update INACTIVE
VA.
Request Parameters
Example Update Virtual Accounts Request
{
"expiration_date": "2021-09-27T17:00:00.000Z",
"expected_amount": 150000
}
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 the Virtual Account object |
Body Parameter | Type | Description |
---|---|---|
is_single_useoptional. default:
|
boolean |
When set to true , the virtual account status will be inactive after it is paid |
expected_amountoptional |
number |
The amount that the virtual account will expect if is_closed is set to true |
min_amountoptional |
string |
Minimum amount to be paid by your customer for open Virtual Account, it should use an amount above the minimum amount from the bank. |
max_amountoptional |
string |
Maximum amount to be paid by your customer for open Virtual Account, it should use an amount below the maximum amount from the bank. |
suggested_amountoptional |
number |
Suggested amount you want to assign |
expiration_dateoptional. default:
|
string |
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:
|
descriptionoptional |
string |
Virtual account description shown to end user during payment.
|
external_idoptional |
string |
An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID Characters : Special and alphanumeric Minimum Character : 1 character Maximum Characters : 950 Characters |
Response Parameters
Example Update Virtual Account Response
{
"id": "57f6fbf26b9f064272622aa6",
"external_id": "va-1475804036622",
"owner_id": "57b4e5181473eeb61c11f9b9",
"bank_code": "BRI",
"merchant_code": "26215",
"account_number": "262159939380502",
"name": "Michael Chen",
"country": "ID",
"currency": "IDR",
"is_single_use": true,
"is_closed": true,
"expected_amount": 150000,
"expiration_date": "2021-09-27T17:00:00.000Z",
"description": "Utensils Payment 27 September 2021",
"status": "PENDING"
}
Returns Virtual Account Object with status 200
Error Codes
Example of Error Message
{
"error_code": "BANK_NOT_SUPPORTED_ERROR",
"message": "That bank code is not currently supported. Use Get Virtual Account Banks API to check available banks"
}
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. Change your body format to JSON to proceed. |
VIRTUAL_ACCOUNT400 |
The virtual account number you want is outside your range. Check your VA range in Virtual Accounts Settings and make sure the account_number is within your VA range |
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 for Closed Virtual Account (is_closed : true ). Specify required amount to proceed. |
INACTIVE_VIRTUAL_ACCOUNT_ERROR400 |
Account number that you want to update is inactive. |
MINIMUM_EXPECTED400 |
The expected amount below the minimum limit. |
MAXIMUM_EXPECTED400 |
The expected amount above the maximum limit. |
DESCRIPTION_NOT400 |
The requested Virtual Account bank doesn't support description feature. |
MINIMUM_AMOUNT_ERROR400 |
Parameter min_amount should be above minimum amount allowed by the bank |
MAXIMUM_AMOUNT_ERROR400 |
Parameter max_amount should be below maximum amount allowed by the bank |
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 |
FEATURE_NOT_SUPPORTED403 |
Minimum and maximum amount feature is not supported by the selected bank. Check Docs/API Reference to see list of banks who support minimum and maximum amount feature. |
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==:
<?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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
VirtualAccountClient virtualAccount = xendit.VirtualAccount;
VirtualAccountResponse virtualAccountResponse = await virtualAccount.Get("5eec3a3e8dd9ea2fc97d6728");
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.
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. |
Path Parameter | Type | Description |
---|---|---|
idrequired |
string |
ID of the Virtual Account object |
Response Parameters
Example Get Virtual Account Response
{
"id": "57f6fbf26b9f064272622aa6",
"external_id": "va-1475804036622",
"owner_id": "57b4e5181473eeb61c11f9b9",
"bank_code": "BNI",
"merchant_code": "8808",
"account_number": "8808999939380502",
"name": "Michael Chen",
"currency": "IDR",
"country" : "ID",
"is_single_use": false,
"is_closed": false,
"expiration_date": "2051-09-27T17:00:00.000Z",
"status": "PENDING"
}
Returns Virtual Account Object with status 200
Error Codes
Example of Error Message
{
"error_code": "CALLBACK_VIRTUAL_ACCOUNT_NOT_FOUND_ERROR",
"message": "Callback virtual account not found"
}
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. |
Virtual Account Object
Example of Virtual Account Object
{
"id": "57f6fbf26b9f064272622aa6",
"external_id": "va-1475804036622",
"owner_id": "57b4e5181473eeb61c11f9b9",
"bank_code": "BRI",
"merchant_code": "26215",
"account_number": "262159939380502",
"name": "Michael Chen",
"currency": "IDR",
"is_single_use": true,
"is_closed": true,
"expected_amount": 50000,
"suggested_amount": 50000,
"expiration_date": "2021-09-27T17:00:00.000Z",
"description": "Utensils Payment 27 September 2021",
"status": "PENDING",
"alternative_displays": [
{
"type": "QR_STRING",
"data": "00020101021238600010A00000072701300006970432011600246000000284920208QRIBFTTA53037045802VN5405100006304EDF0"
}
]
}
Parameter | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique Xendit ID for the Virtual Account. Use this ID for support escalation and reconciliation. Can be used to link VA to Invoice using create Invoices API. | ||||||
external_idrequired |
string |
An ID of your choice which you provided upon request. | ||||||
owner_idrequired |
string |
Your Xendit Business ID. | ||||||
bank_coderequired |
string |
Bank code of the virtual account you want to create. | ||||||
merchant_coderequired |
string |
Prefix for the Virtual Account. For the aggregator model, this is Xendit's merchant code. For the switcher model, this is the merchant code that you received from the bank. Learn more about Virtual Account models here. | ||||||
account_numberrequired |
string |
Complete Virtual Account number (including merchant code as prefix). This is what a user will use to pay Virtual Account. | ||||||
namerequired |
string |
Name for the Virtual Account. | ||||||
countryrequired |
string |
The country in which the virtual account operates. | ||||||
currencyrequired |
string |
The currency of payment in which the virtual account can accept, available for API version 2018-12-21 . |
||||||
is_single_userequired |
boolean |
There are 2 types of Virtual Account: is_single_use : false ) remain active upon successful payment and can continue to receive payments using the same Virtual Account |
||||||
is_closedrequired |
boolean |
There are 2 types of Virtual Account amount: expected_amount parameter below |
||||||
expected_amountoptional |
number |
Required amount to be paid by your customer for closed Virtual Account. | ||||||
min_amountoptional |
string |
Minimum amount to be paid by your customer for open Virtual Account, it should use an amount above the minimum amount from the bank. | ||||||
max_amountoptional |
string |
Maximum amount to be paid by your customer for open Virtual Account, it should use an amount below the maximum amount from the bank. | ||||||
suggested_amountoptional |
number |
Suggested amount for the Virtual Account. | ||||||
expiration_date optional |
string |
ISO8601 timestamp of Virtual Account expiration time. Timezone UTC+0. | ||||||
descriptionoptional |
string |
Description of the Virtual Account that will be displayed in payment interface. | ||||||
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 |
||||||
alternative_displaysoptional |
object |
Alternative Display for the virtual account. Note: This field is only applicable to Vietnam virtual accounts.Data fields
|
Simulate Payment
Simulate Virtual Account Payment API allows you to mimic your customer behavior to pay to your Virtual Account in TEST
mode. This is similar to your customers paying your Virtual Account using ATM/internet banking/mobile banking in LIVE
mode. A callback will be sent to your callback URL upon payment completion. See our testing page here for further guideline.
Endpoint: Simulate VA Payment
POST https://api.xendit.co/callback_virtual_accounts/external_id={external_id}/simulate_payment
Request Parameters
Simulation Example
{
"amount": 50000
}
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to simulate this transaction for. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
external_idrequired |
string |
External ID of the Virtual Account |
Response Parameters
Simulation Response
{
"status": "COMPLETED",
"message": "Payment for the Fixed VA with external id {{$external_id}} is currently being processed. Please ensure that you have set a callback URL for VA payments via Dashboard Settings and contact us if you do not receive a VA payment callback within the next 5 mins."
}
Parameters | Type | Description |
---|---|---|
statusrequired |
string |
Status of the payment simulation |
messagerequired |
string |
Additional information regarding the payment simulation process |
Virtual Account Callback
Endpoint: Virtual Account Webhook
POST https://yourcompany.com/virtual_account_paid_webhook_url
Xendit notifies your system upon successful payments via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Example Virtual Account Payment Webhook Payload
{
"id": "598d91b1191029596846047f",
"payment_id": "5f218745736e619164dc8608",
"callback_virtual_account_id": "598d5f71bf64853820c49a18",
"owner_id": "57b4e5181473eeb61c11f9b9",
"external_id": "demo-1502437214715",
"account_number": "999939380502",
"bank_code": "BNC",
"transaction_timestamp": "2021-07-24T05:22:55.115Z",
"amount": 50000,
"merchant_code": "90100010",
"currency": "IDR",
"country" : "ID",
"sender_name": "Michael Chen",
"payment_detail": {
"payment_interface": "MOBILE_BANKING",
"remark": "Sent by Michael for my package",
"reference": "66143641700",
"sender_account_number": "12345678912345",
"sender_channel_code": "BNC",
"sender_name": "Michael Chen",
"transfer_method": "INHOUSE"
}
}
Returns Virtual Account Payment Object with additional parameters:
Body Parameter | Type | Description |
---|---|---|
createdrequired |
string |
ISO8601 timestamp of when the Virtual Account payment was created. Timezone UTC+0 |
updatedrequired |
string |
ISO8601 timestamp of the Virtual Account payment last updated. Timezone UTC+0 |
owner_idrequired |
string |
Owner of the payment with the value of your Xendit business ID |
Creation / Update Webhook Payload
Example of Virtual Account Active Webhook Payload
{
"id": "57f6fbf26b9f064272622aa6",
"external_id": "va-1475804036622",
"owner_id": "57b4e5181473eeb61c11f9b9",
"bank_code": "BNI",
"merchant_code": "8808",
"account_number": "8808999939380502",
"name": "Michael Chen",
"currency": "IDR",
"country" : "ID",
"is_single_use": false,
"is_closed": false,
"expiration_date": "2051-09-27T17:00:00.000Z",
"status": "ACTIVE"
}
Returns Virtual Account Object with additional parameters:
Body Parameter | Type | Description |
---|---|---|
createdrequired |
string |
ISO8601 timestamp of when the Virtual Account was created. Timezone UTC+0 |
updatedrequired |
string |
ISO8601 timestamp of the Virtual Account last updated. Timezone UTC+0 |
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
VirtualAccountPaymentClient virtualAccountPayment = xendit.VirtualAccountPayment;
VirtualAccountPaymentResponse virtualAccountPaymentResponse = await virtualAccountPayment.Get("5ef18efca7d10d1b4d61fb52");
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. |
Path Parameter | Type | Description |
---|---|---|
payment_idrequired |
string |
ID of the payment retrieved from Virtual Account Payment object. |
Response Parameters
Example Get Virtual Account Payment Response
{
"id": "598d91b1191029596846047f",
"payment_id": "5f218745736e619164dc8608",
"callback_virtual_account_id": "598d5f71bf64853820c49a18",
"owner_id": "57b4e5181473eeb61c11f9b9",
"external_id": "demo-1502437214715",
"bank_code": "BNC",
"merchant_code": "90100010",
"account_number": "999939380502",
"amount": 50000,
"currency" : "IDR",
"transaction_timestamp": "2021-07-24T05:22:55.115Z",
"sender_name": "Michael Chen",
"payment_detail": {
"payment_interface": "MOBILE_BANKING",
"remark": "Sent by Michael for my package",
"reference": "66143641700",
"sender_account_number": "12345678912345",
"sender_channel_code": "BNC",
"sender_name": "Michael Chen",
"transfer_method": "INHOUSE"
}
}
Returns Virtual Account Payment object with status 200
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. |
Virtual Account Payment Object
Example Virtual Account Payment Object
{
"id": "598d91b1191029596846047f",
"payment_id": "5f218745736e619164dc8608",
"callback_virtual_account_id": "598d5f71bf64853820c49a18",
"owner_id": "57b4e5181473eeb61c11f9b9",
"external_id": "demo-1502437214715",
"account_number": "999939380502",
"bank_code": "BNC",
"transaction_timestamp": "2021-07-24T05:22:55.115Z",
"amount": 50000,
"merchant_code": "90100010",
"currency": "IDR",
"country": "ID",
"sender_name": "Michael Chen",
"payment_detail": {
"payment_interface": "MOBILE_BANKING",
"remark": "Sent by Michael for my package",
"reference": "66143641700",
"sender_account_number": "12345678912345",
"sender_channel_code": "BNC",
"sender_name": "Michael Chen",
"transfer_method": "INHOUSE"
}
}
Body Parameter | Type | Description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
ID of the Virtual Account Payment. Use this ID for support escalation and reconciliation. | ||||||||||||||||||
payment_idrequired |
string |
Our internal system’s payment ID. | ||||||||||||||||||
callback_virtual_account_idrequired |
string |
ID of the Virtual Account that was paid. | ||||||||||||||||||
external_idrequired |
string |
External ID of the Virtual Account. | ||||||||||||||||||
bank_coderequired |
string |
Bank code of the Virtual Account. | ||||||||||||||||||
merchant_coderequired |
string |
Virtual Account merchant code identified via the first 4-5 digits of Virtual Account number. | ||||||||||||||||||
account_numberrequired |
string |
Virtual Account number exclude the prefix (merchant code). | ||||||||||||||||||
currencyrequired |
string |
The currency of payment in which the virtual account can accept, if it's not specified, it will be using IDR by default. | ||||||||||||||||||
countryrequired |
string |
The country in which the virtual account operate, if it's not specified, it will be using ID by default. | ||||||||||||||||||
amountrequired |
integer positive |
Amount that was paid to the Virtual Account. | ||||||||||||||||||
transaction_timestamprequired |
string |
Date time of the Virtual Account transaction. | ||||||||||||||||||
sender_nameoptional |
string |
Name of the end user that paid into the Virtual Account. Available for BNC , DBS , and SAHABAT_SAMPOERNA . |
||||||||||||||||||
payment_detailoptional |
object |
Additional information from the bank. Data fields
|
Get Virtual Account Banks
Endpoint: Get Virtual Account Available Banks
GET https://api.xendit.co/available_virtual_account_banks
Example Get Virtual Account Banks Request
curl https://api.xendit.co/available_virtual_account_banks -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$getVABanks = \Xendit\VirtualAccounts::getVABanks();
var_dump($getVABanks);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { VirtualAcc } = x;
const vaSpecificOptions = {};
const va = new VirtualAcc(vaSpecificOptions);
const resp = await va.getVABanks();
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
AvailableBank[] availableBanks = FixedVirtualAccount.getAvailableBanks();
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
availableBanks, err := virtualaccount.GetAvailableBanks()
if err != nil {
log.Fatal(err)
}
fmt.Printf("available va banks: %+v\n", availableBanks)
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
VirtualAccountClient virtualAccount = xendit.VirtualAccount;
AvailableBank[] availableBanks = await virtualAccount.GetAvailableBanks();
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. |
Response Parameters
Example Get Virtual Account Banks Response for Indonesia
[
{
"name": "Bank Central Asia",
"code": "BCA",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "Bank Negara Indonesia",
"code": "BNI",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "Bank Mandiri",
"code": "MANDIRI",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "Bank Permata",
"code": "PERMATA",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "Bank Sahabat Sampoerna",
"code": "SAHABAT_SAMPOERNA",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "Bank Rakyat Indonesia",
"code": "BRI",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "Bank Neo Commerce",
"code": "BNC",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "Bank CIMB Niaga",
"code": "CIMB",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "Bank Syariah Indonesia",
"code": "BSI",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "Bank Jabar Banten",
"code": "BJB",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "The Development Bank of Singapore",
"code": "DBS",
"country": "ID",
"currency": "IDR",
"is_activated": false
},
{
"name": "The Development Bank of Singapore",
"code": "DBS",
"country": "ID",
"currency": "USD",
"is_activated": false
}
]
Example Get Virtual Account Banks Response for Vietnam
[
{
"name": "PV Bank",
"code": "PV",
"country": "VN",
"currency": "VND",
"is_activated": false
},
{
"name": "Vietcapital Bank",
"code": "VIETCAPITAL",
"country": "VN",
"currency": "VND",
"is_activated": false
},
{
"name": "Woori Bank",
"code": "WOORI",
"country": "VN",
"currency": "VND",
"is_activated": false
}
]
Returns array of the following object:
Parameter | Type | Description |
---|---|---|
namerequired |
string |
Full name of the bank. |
coderequired |
string |
Code of the bank, relevant during creation of virtual accounts. |
countryrequired |
string |
The country in which the virtual account operates. |
currencyrequired |
string |
The currency of payment in which the virtual account can accept. |
is_activatedrequired |
boolean |
Activation status of the bank, relevant during creation of virtual accounts. |
Retail Outlets (OTC) - ID
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 webhook 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 |
with-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this OTC payment code in order to split and route payments to multiple accounts. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.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 |
You can assign specific fixed payment code using this parameter e.g 12345 . If you do not send one, one will be picked at randomMake sure when you want to create payment code, you do not include the prefix on this field. For example: your prefix is PSTEST and you want to create payment code PSTEST12345 , you can only fill 12345 on this fieldYou can check your prefix information on Retail Outlet details 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 system. |
statusrequired |
string |
Status of fixed payment code that defines if it’s ACTIVE , INACTIVE , or EXPIRED . ACTIVE if fixed payment code has not paid or has not expired yet.INACTIVE if fixed payment code is already paid.EXPIRED if fixed payment code that has expiration date and been updated to the date less than now. |
typerequired |
string |
To define that this is user generated payment code |
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 system. |
statusrequired |
string |
Status of fixed payment code that defines if it’s ACTIVE , INACTIVE , or EXPIRED . ACTIVE if fixed payment code has not paid or has not expired yet.INACTIVE if fixed payment code is already paid.EXPIRED if fixed payment code that has expiration date and been updated to the date less than now. |
typerequired |
string |
To define that this is user generated payment code |
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. |
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 |
Path 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 |
statusrequired |
string |
Status of fixed payment code that defines if it’s ACTIVE , INACTIVE , or EXPIRED . ACTIVE if fixed payment code has not paid or has not expired yet.INACTIVE if fixed payment code is already paid.EXPIRED if fixed payment code that has expiration date and been updated to the date less than now. |
typerequired |
string |
To define that this is user generated payment code |
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 system. |
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 Webhook
POST https://yourcompany.com/fixed_payment_code_paid_webhook_url
Xendit notifies your system upon successful payments via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Example Fixed Payment Code Payment Webhook Request
curl --include \
--request POST \
--url https://yourcompany.com/fixed_payment_code_paid_webhook_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
SETTLING means that transaction already PAID but still waiting for settlement time COMPLETED means that transaction already PAID and SETTLED |
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 |
Get Payments By Fixed Payment Code ID
Endpoint: Get Payments By Fixed Payment Code ID(FPC)
GET https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id}/payments
Sometimes, you need to know the payments made for your fixed payment code. This endpoint can be used to retrieve all payments that were made into a particular fixed payment code.
Request Parameters
Example Get Payments by Fixed Payment Code ID Request
curl https://api.xendit.co/fixed_payment_code/{fixed_payment_code_id}/payments -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
To be developed
To be developed
To be developed
To be developed
To be developed
Example Get Payments by Fixed Payment Code ID Response
{
"data": [
{
"status": "COMPLETED",
"fixed_payment_code_payment_id": "61c53c4fdc1b825d9a58ff54",
"fixed_payment_code_id": "61c53c3727c7a679826dd90a",
"amount": 2500000,
"name": "JOHN DOE",
"prefix": "TEST",
"payment_code": "TEST892185",
"payment_id": "1640315983260",
"external_id": "FPC-1640315959",
"retail_outlet_name": "ALFAMART",
"transaction_timestamp": "2021-12-24T03:19:43.260Z",
"id": "61c53c4f6cc577e4038ab099",
"owner_id": "60ca10b83ffd534ece8aa856"
}
],
"has_more": true,
"links": {
"href": "https://api.xendit.co/fixed_payment_code/61c53c3727c7a679826dd90a/payments?limit=1&after_id=61c53c4f6cc577e4038ab099",
"rel": "next",
"method": "GET"
}
}
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 |
---|---|---|
fixed_payment_code_id required |
string |
ID of the fixed payment code to retrieve |
Query Parameter | Type | Description |
---|---|---|
limit optionaldefault:
|
number |
A limit on the number of invoice objects to be returned. Limit can range between 1 and 100. |
after_id optional |
string |
Id of the immediately previous item. Use this with links on the response for pagination. |
Response Parameters
Parameter | Type | Description |
---|---|---|
data required |
array of objects |
Returns an array of Payment Object. Returns empty array when there is no result. |
has_more required |
bolean |
Indicates whether there are more items to be queried with after_id of the last item from the current result. Use the links to follow to the next result. |
links optional |
object |
The links to the next page based on HATEOAS if there is next result. The HATEOAS format are: href : URI of target, this will be to the next link. rel : The relationship between source and target. The value will be next . method : The HTTP method, the value will be GET . |
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 |
DATA_NOT_FOUND404 |
Could not find fixed payment code. |
Retail Outlets (OTC) - PH
Retail Outlets (OTC) is a payment method allowing your end customer to make payments through one of our retail outlet partners throughout Philippines.
End customers can visit any of our partners and inform the cashier of the merchant they are paying to, quote the unique payment code for the transaction, and make a payment in cash.
Create Payment Code
Endpoint: Create Payment Code
POST https://api.xendit.co/payment_codes
Payment code allows your customers to make a payment through the branches of our partners.
Provide the payment code to your customer, and receive a webhook once the payment has been made.
Request Parameters
Example Create Payment Code Request
curl https://api.xendit.co/payment_codes -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d reference_id=demo_payment_code_123 \
-d channel_code=7ELEVEN \
-d customer_name='Rika Sutanto' \
-d amount=50
-d currency=PHP
-d market=PH
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'reference_id' => 'demo_payment_code_123',
'channel_code' => '7ELEVEN',
'customer_name' => 'Rika Sutanto',
'amount' => 50
'currency' => 'PHP'
'market' => 'PH'
];
$createFPC = \Xendit\RegionalRetailOutlet::create($params);
var_dump($createFPC);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RegionalRetailOutlet } = x;
const retailOutletSpecificOptions = {};
const ro = new RegionalRetailOutlet(retailOutletSpecificOptions);
const resp = await ro.createPaymentCode({
referenceId: 'demo_payment_code_123',
channelCode: '7ELEVEN',
customerName: 'Rika Sutanto',
amount: 50,
currency: 'PHP',
market: 'PH'
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("reference_id", "demo_payment_code_123");
params.put("channel_code", "7ELEVEN");
params.put("customer_name", "Rika Sutanto");
params.put("amount", 50);
params.put("currency", "PHP");
params.put("market", "PH");
FixedPaymentCode fpc = RegionalRetailOutlet.createPaymentCode(params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
data := regionalRetailoutlet.CreatePaymentCodeParams{
ReferenceId: "demo_payment_code_123",
ChannelCode: xendit.RetailOutletName7eleven,
CustomerName: "Rika Sutanto",
Amount: 50,
Currency: "PHP",
Market: "PH"
}
resp, err := regionalRetailoutlet.CreatePaymentCode(&data)
if err != nil {
log.Fatal(err.ErrorCode)
}
fmt.Printf("created retail outlet payment code: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RegionalRetailOutlet = xendit_instance.RegionalRetailOutlet
regional_retail_outlet = RegionalRetailOutlet.create_payment_code(
reference_id="demo_fixed_payment_code_123",
channel_code="7ELEVEN",
customer_name="Rika Sutanto",
amount=50,
currency="PHP",
market="PH"
)
print(regional_retail_outlet)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
RetailOutletClient retailOutlet = xendit.RetailOutlet;
CreateFixedPaymentCodeParameter parameter = new CreateFixedPaymentCodeParameter
{
ReferenceId = "demo_payment_code_id",
ChannelCode = RetailOutletEnum.ChannelCode.SevenEleven,
CustomerName = "Rika Sutanto",
Amount = 50,
Currency = Currency.PHP,
Market = Country.Philippines,
PaymentCode = "12345678",
Description = "Example payment code",
};
FixedPaymentCode fixedPaymentCode = await retailOutlet.CreatePaymentCode(parameter);
JSON
{
"reference_id": "123",
"channel_code": "7ELEVEN",
"customer_name": "Rika Sutanto",
"amount": 50,
"currency": "PHP",
"market": "PH"
}
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-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this OTC payment code in order to split and route payments to multiple accounts. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.This header is only used if you have access to xenPlatform. See xenPlatform for more information. |
Body Parameter | Type | Description |
---|---|---|
reference_idrequired |
string |
An ID of your choice. Often it is unique identifier like a phone number, email or transaction ID.
|
channel_coderequired |
string |
Channel code of selected payment method.Available Channel Codes: |
amountoptional |
number |
The amount that is expected to be paid by end customer7ELEVEN 7ELEVEN_CLIQQ CEBUANA ECPAY LBC Integration via DragonPay DP_PALAWAN DP_MLHUILLIER DP_ECPAY_LOAN DP_RD_PAWNSHOP DP_CVM DP_ECPAY_SCHOOL DP_USSC Note: amount is required if you want to create closed type payment codeamount field can be empty or null
|
currencyrequired |
string |
ISO 4217 Currency codeSupported currency code:
|
customer_namerequired |
string |
Name of user - this might be used by the Retail Outlets cashier to validate the end user.
|
marketrequired |
string |
2-letter ISO 3166-2 country code indicating country of transaction.Supported market:
|
payment_codeoptional |
string |
The payment code that you want to assign, e.g 12345. If you do not send one, one will be picked at random. You do not need to include prefix to create a payment code. For example: You want to create payment code PSTEST12345A and your prefix is PSTEST , you can only fill 12345A in this field. Lower case value will be automatically converted to upper case in the API responseNote: 7ELEVEN does not support custom payment_code, you cannot use this parameter for 7ELEVEN default: |
expires_atoptional |
ISO 8601 Date |
The time when the payment code will be expired.7ELEVEN timezone:
|
is_single_useoptional |
boolean |
When set to false , the payment code will be a multiple use payment code and active after it is paid.Channel code that supports multiple use:7ELEVEN_CLIQQ CEBUANA ECPAY LBC DP_ECPAY_LOAN DP_RD_PAWNSHOP DP_CVM DP_ECPAY_SCHOOL DP_USSC default: true
|
descriptionoptional |
string |
Description of the payment code.
|
metadataoptional |
object |
Object of additional key-value pairs that the merchants may use like internal system parameters (business ID, shopping cart). 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. Otherwise NULL |
Response Parameters
Example Create Payment Code Response
{
"id": "pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1",
"business_id": "5f21361959ef2b788cbbe97f",
"reference_id": "demo_payment_code_123",
"customer_name": "Rika Sutanto",
"payment_code": "TESTABCD1234",
"currency": "PHP",
"amount": 50,
"channel_code": "7ELEVEN_CLIQQ",
"description": "Test payment code",
"is_single_use": true,
"market": "PH",
"status": "ACTIVE",
"metadata": null,
"created_at": "2021-01-01T02:38:01Z",
"updated_at": "2021-01-01T02:38:01Z",
"expires_at": "2021-05-30T02:38:01Z"
}
Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique ID for the payment code that generated randomly by system. |
business_idrequired |
string |
Your Xendit business ID. |
reference_idrequired |
string |
An ID of your choice which you provided upon request. |
customer_namerequired |
string |
Name of customer. |
payment_coderequired |
string |
Complete payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. |
currencyrequired |
string |
ISO 4217 Currency codeSupported currency code:
|
amountoptional |
number |
The amount that is expected to be paid by end customer7ELEVEN 7ELEVEN_CLIQQ CEBUANA ECPAY LBC Integration via DragonPay DP_PALAWAN DP_MLHUILLIER DP_ECPAY_LOAN DP_RD_PAWNSHOP DP_CVM DP_ECPAY_SCHOOL DP_USSC |
descriptionrequired |
string |
Description of the payment code. |
is_single_userequired |
boolean |
Value that determines whether a payment code will be inactive after it is paid or not. |
marketrequired |
string |
2-letter ISO 3166-2 country code indicating country of transaction.Supported market:
|
statusrequired |
string |
Status of the payment code.Possible values:ACTIVE INACTIVE |
metadatarequired |
object |
Object of additional key-value pairs that the merchants may use like internal system parameters (business ID, shopping cart). 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. Otherwise NULL |
created_atrequired |
ISO 8601 Date |
The time when the payment code was created.timezone:
|
updated_atrequired |
ISO 8601 Date |
The time when the payment code was updated.timezone:
|
expires_atrequired |
ISO 8601 Date |
The time when the payment code will be expired.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. |
CHANNEL_CODE_NOT_400 |
The Retail Outlets is not currently supported. Please contact Xendit customer support to resolve this issue |
DUPLICATE_ERROR400 |
The payment code that you want to create already exist. Please use a different payment code. |
EXPIRATION_DATE_INVALID_400 |
Invalid custom expiration date because it's earlier than current time. Update expires_at value, must be a date in the future. |
DATA_NOT_FOUND_ERROR404 |
Retail outlet merchant not found. Please contact Xendit customer support to resolve this issue |
GENERATION_ERROR503 |
Error occurred while generating payment code. This can be caused by an unspecified error by the channel - but not due to channel downtime. |
Update Payment Code
Endpoint: Update Payment Code
PATCH https://api.xendit.co/payment_codes/{payment_code_id}
Payment Code is so adaptable, and it's all based on your needs. Therefore, we provide you this endpoint to easily update your payment code as you like.
Request Parameters
Example Update Payment Code Request
curl https://api.xendit.co/payment_codes/{payment_code_id} -X PATCH \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d amount=100
-d currency=PHP
-d customer_name='Lorem Ipsum'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = 'pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1';
$updateParams = [
'amount' => 100,
'currency' => 'PHP',
'customer_name' => 'Lorem Ipsum'
];
$updatedPaymentCode = \Xendit\RegionalRetailoutlet::update($id, $updateParams);
var_dump($updatedPaymentCode);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RegionalRetailOutlet } = x;
const retailOutletSpecificOptions = {};
const ro = new RegionalRetailOutlet(retailOutletSpecificOptions);
const resp = await ro.updatePaymentCode({
id: 'pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1',
customer_name: 'Lorem Ipsum',
amount: 100,
currency: 'PHP',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("customer_name", "Lorem Ipsum");
FixedPaymentCode fpc = RegionalRetailOutlet.updatePaymentCode("EXAMPLE_ID", params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
expirationDate := time.Now().AddDate(0, 0, 1)
updatePaymentCodeData := regionalretailoutlet.UpdatePaymentCodeParams{
PaymentCodeID: "pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1",
CustomerName: "Lorem Ipsum",
ExpectedAmount: 50,
Currency: "PHP"
}
resp, err := regionalretailoutlet.PaymentCode(&updatePaymentCodeData)
if err != nil {
log.Fatal(err.ErrorCode)
}
fmt.Printf("updated retail outlet payment code: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RegionalRetailOutlet = xendit_instance.RegionalRetailOutlet
retail_outlet = RegionalRetailOutlet.update_payment_code(
payment_code_id="pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1",
customer_name="Lorem Ipsum",
amount=100,
currency="PHP"
)
print(retail_outlet)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
RetailOutletClient retailOutlet = xendit.RetailOutlet;
UpdateFixedPaymentCodeParameter parameter = new UpdateFixedPaymentCodeParameter
{
CustomerName = "Rika Sutanto",
Amount = 100,
Currency = Currency.PHP,
Description = "Example updated payment code",
};
FixedPaymentCode fixedPaymentCode = await retailOutlet.UpdatePaymentCode(parameter, "pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1");
JSON
{
"amount": 100,
"currency": "PHP",
"customer_name": "Lorem Ipsum"
}
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 |
---|---|---|
customer_nameoptional |
string |
Name of user - this might be used by the Retail Outlets cashier to validate the end user.
|
amountoptional |
number |
The amount that is expected to be paid by end customer7ELEVEN 7ELEVEN_CLIQQ CEBUANA ECPAY LBC Integration via DragonPay DP_PALAWAN DP_MLHUILLIER DP_ECPAY_LOAN DP_RD_PAWNSHOP DP_CVM DP_ECPAY_SCHOOL DP_USSC |
currencyoptional |
string |
ISO 4217 Currency codeSupported currency code:
|
expires_atoptional |
ISO 8601 Date |
The time when the payment code will be expired. You can set it to be days in the past to expire payment code immediately updating of expiration days is not allowed for 7ELEVEN Timezone:
|
descriptionoptional |
string |
Description of the payment code.
|
Response Parameters
Example Update Payment Code Response
{
"id": "pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1",
"business_id": "5f21361959ef2b788cbbe97f",
"reference_id": "demo_payment_code_123",
"customer_name": "Rika Sutanto",
"payment_code": "TEST906558",
"currency": "PHP",
"amount": 50,
"channel_code": "7ELEVEN",
"description": "Test payment code",
"is_single_use": true,
"market": "PH",
"status": "ACTIVE",
"metadata": null,
"created_at": "2021-01-01T02:38:01Z",
"updated_at": "2021-01-01T02:38:01Z",
"expires_at": "2021-05-30T02:38:01Z"
}
Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique ID for the payment code that generated randomly by system. |
business_idrequired |
string |
Your Xendit business ID. |
reference_idrequired |
string |
An ID of your choice which you provided upon request. |
customer_namerequired |
string |
Name of customer. |
payment_coderequired |
string |
Complete payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. |
currencyrequired |
string |
ISO 4217 Currency codeSupported currency code:
|
amountoptional |
number |
The amount that is expected to be paid by end customer7ELEVEN 7ELEVEN_CLIQQ CEBUANA ECPAY LBC Integration via DragonPay DP_PALAWAN DP_MLHUILLIER DP_ECPAY_LOAN DP_RD_PAWNSHOP DP_CVM DP_ECPAY_SCHOOL DP_USSC |
channel_coderequired |
string |
Name of the Retail Outlets. e.g. 7ELEVEN , 7ELEVEN_CLIQQ , CEBUANA , ECPAY , LBC , DP_PALAWAN , DP_MLHUILLIER , DP_ECPAY_LOAN , DP_RD_PAWNSHOP , DP_CVM , DP_ECPAY_SCHOOL , and DP_USSC |
descriptionrequired |
string |
Description of the payment code. |
is_single_userequired |
boolean |
Value that determines whether a payment code will be inactive after it is paid or not. |
marketrequired |
string |
2-letter ISO 3166-2 country code indicating country of transaction.Supported market:
|
statusrequired |
string |
Status of the payment code.Possible values: |
metadatarequired |
object |
Object of additional key-value pairs that the merchants may use like internal system parameters (business ID, shopping cart). 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. Otherwise NULL |
created_atrequired |
ISO 8601 Date |
The time when the payment code was created.timezone:
|
updated_atrequired |
ISO 8601 Date |
The time when the payment code was updated.timezone:
|
expires_atrequired |
ISO 8601 Date |
The time when the payment code will be expired.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. |
DATA_NOT_FOUND_ERROR404 |
Provided payment code id does not exist |
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 Payment Code
Endpoint: Get Payment Code
GET https://api.xendit.co/payment_codes/{payment_code_id}
Example Get Payment Code Request
curl https://api.xendit.co/payment_codes/{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 { RegionalRetailOutlet } = x;
const retailOutletSpecificOptions = {};
const ro = new RegionalRetailOutlet(retailOutletSpecificOptions);
const resp = await ro.getPaymentCode({
id: 'pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
PaymentCode fpc = RegionalRetailOutlet.getPaymentCode("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
getPaymentCodeData := regionalretailoutlet.GetPaymentCodeParams{
PaymentCodeID: "pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1",
}
resp, err := regionalretailoutlet.GetPaymentCode(&getPaymentCodeData)
if err != nil {
log.Fatal(err.ErrorCode)
}
fmt.Printf("retrieved retail outlet payment code: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RegionalRetailOutlet = xendit_instance.RegionalRetailOutlet
retail_outlet = RegionalRetailOutlet.get_payment_code(
payment_code_id="5ef2f0f8e7f5c14077275493",
)
print(retail_outlet)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
RetailOutletClient retailOutlet = xendit.RetailOutlet;
FixedPaymentCode fixedPaymentCode = await retailOutlet.GetPaymentCode("5ef2f0f8e7f5c14077275493");
Sometimes, you need to know the detail for your payment code. This endpoint can be used to get the latest details from your 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 |
Path Parameter | Type | Description |
---|---|---|
payment_code_id required |
string |
ID of the payment code to retrieve |
Response Parameters
Example Get Payment Code Response
{
"id": "pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1",
"business_id": "5f21361959ef2b788cbbe97f",
"reference_id": "demo_payment_code_123",
"customer_name": "Rika Sutanto",
"payment_code": "TEST906558",
"currency": "PHP",
"amount": 50,
"channel_code": "7ELEVEN",
"description": "Test payment code",
"is_single_use": true,
"market": "PH",
"status": "ACTIVE",
"metadata": null,
"created_at": "2021-01-01T02:38:01Z",
"updated_at": "2021-01-01T02:38:01Z",
"expires_at": "2021-05-30T02:38:01Z"
}
Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique ID for the payment code that generated randomly by system. |
business_idrequired |
string |
Your Xendit business ID. |
reference_idrequired |
string |
An ID of your choice which you provided upon request. |
customer_namerequired |
string |
Name of customer. |
payment_coderequired |
string |
Complete payment code (including prefix). This is what a user will need to tell Retail Outlets cashier or show via barcode page. |
currencyoptional |
string |
ISO 4217 Currency codeSupported currency code:
|
amountoptional |
number |
The amount that is expected to be paid by end customer7ELEVEN 7ELEVEN_CLIQQ CEBUANA ECPAY LBC Integration via DragonPay DP_PALAWAN DP_MLHUILLIER DP_ECPAY_LOAN DP_RD_PAWNSHOP DP_CVM DP_ECPAY_SCHOOL DP_USSC |
descriptionrequired |
string |
Description of the payment code. |
is_single_userequired |
boolean |
Value that determines whether a payment code will be inactive after it is paid or not. |
marketrequired |
string |
2-letter ISO 3166-2 country code indicating country of transaction.Supported market:
|
statusrequired |
string |
Status of the payment code.Possible values: |
metadatarequired |
object |
Object of additional key-value pairs that the merchants may use like internal system parameters (business ID, shopping cart). 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. Otherwise NULL |
created_atrequired |
ISO 8601 Date |
The time when the payment code was created.timezone:
|
updated_atrequired |
ISO 8601 Date |
The time when the payment code was updated.timezone:
|
expires_atrequired |
ISO 8601 Date |
The time when the payment code will be expired.timezone:
|
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 |
DATA_NOT_FOUND_ERROR404 |
Could not find payment code. |
Get Payments By Payment Code ID
Endpoint: Get Payments By Payment Code ID
GET https://api.xendit.co/payment_codes/{payment_code_id}/payments
Example Get Payments By Payment Code ID Request
curl https://api.xendit.co/payment_codes/{payment_code_id}/payments -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\RegionalRetailOutlet::retrievePayments($id);
var_dump($getFPC);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { RetailOutlet } = x;
const retailOutletSpecificOptions = {};
const ro = new RegionalRetailOutlet(retailOutletSpecificOptions);
const resp = await ro.getPayments({
id: 'pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1',
});
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=="
getPaymentsData := regionalretailoutlet.GetPaymentsParams{
PaymentCodeID: "pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1",
}
resp, err := retailoutlet.GetPayments(&getPaymentsData)
if err != nil {
log.Fatal(err.ErrorCode)
}
fmt.Printf("retrieved retail outlet payments: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
RegionalRetailOutlet = xendit_instance.RegionalRetailOutlet
retail_outlet = RegionalRetailOutlet.get_payments(
payment_code_id="pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1",
)
print(retail_outlet)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
RetailOutletClient retailOutlet = xendit.RetailOutlet;
FixedPaymentCode[] fixedPaymentCodes = await retailOutlet.GetPaymentCode("pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1");
Sometimes, you need to know the payments made for your payment code. This endpoint can be used to retrieve all payments that were made into a particular 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 |
Path Parameter | Type | Description |
---|---|---|
payment_code_id required |
string |
ID of the payment code to retrieve payments made |
Response Parameters
Example Get Payments By Payment Code ID Response
This endpoint returns an array of objects with the following properties:
{
"id": "pymt-24f45c63-8cba-4aa8-a18c-1d6954c7fed2",
"payment_code_id": "pcode-559bb2df-6ae7-4fb8-bc05-f17aa07aeae1",
"payment_code": "TEST906558",
"channel_code": "7ELEVEN",
"currency": "PHP",
"amount": 50,
"status": "COMPLETED",
"remarks": "payment simulation",
"created": "2021-01-01T02:38:01Z",
"updated": "2021-01-01T02:38:01Z",
}
Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique ID for the payment that generated randomly by system. |
payment_code_idrequired |
string |
Unique ID for the payment code that generated randomly by system |
payment_coderequired |
string |
The code given to end-customer for making payments |
channel_coderequired |
string |
The name of the Retail Outlets e.g. 7ELEVEN , 7ELEVEN_CLIQQ , CEBUANA , ECPAY , LBC , DP_PALAWAN , DP_MLHUILLIER , DP_ECPAY_LOAN , DP_RD_PAWNSHOP , DP_CVM , DP_ECPAY_SCHOOL , and DP_USSC |
currencyrequired |
string |
ISO 4217 Currency codeSupported currency code:
|
amountoptional |
number |
The amount that is paid by end customer |
statusrequired |
string |
Status of the payment.Possible values:COMPLETED |
remarksrequired |
string |
Note from channel during payment |
createdrequired |
ISO 8601 Date |
The time when the payment code was createdtimezone:
|
updatedrequired |
ISO 8601 Date |
The time when the payment code was updatedtimezone:
|
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 |
DATA_NOT_FOUND_ERROR404 |
Could not find payment code. |
Payment Code Callback
Endpoint: Payment Code Webhook
POST https://yourcompany.com/fixed_payment_code_paid_webhook_url
Xendit notifies your system upon successful payments via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Example Payment Code Payment webhook Request
curl --include \
--request POST \
--url https://yourcompany.com/payment_code_paid_webhook_url \
--header 'content-type: application/json' \
--header 'x-callback-token: MuaJALKJSDK12LASHD123kSAKSDHzjahwUWjkasJSDSA12KSNAK21n==' \
--data '{
"id": "pymt-6858d71e-4bd3-4bcb-9cc4-200b34bcc86c",
"amount": 50,
"business_id": "5fce6c32b596a10b19aeebe2"
"channel_code": "7ELEVEN",
"country_code": "PH",
"currency": "PHP",
"event": "payment_code.payment",
"created": "2021-05-27T11:50:37Z",
"payment_code": "TEST123",
"reference_id": "payment-code-14876410",
"remarks": " ",
"payment_code_id": "pcode-da9a68dd-d8eb-4cd3-ad30-87eade685c7f",
"status": "COMPLETED"
}'
JSON
{
"event": "payment_code.payment",
"id": "pymt-6858d71e-4bd3-4bcb-9cc4-200b34bcc86c",
"reference_id": "payment-code-14876410",
"business_id": "5fce6c32b596a10b19aeebe2",
"payment_code_id": "pcode-da9a68dd-d8eb-4cd3-ad30-87eade685c7f",
"channel_code": "7ELEVEN",
"payment_code": "TEST123",
"country_code": "PH",
"currency": "PHP",
"amount": 50,
"status": "COMPLETED",
"created": "2021-05-27T11:50:37Z",
"remarks": " "
}
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Event that was made for the payment codePossible values:
|
idrequired |
string |
Unique identifier for this transaction |
reference_idrequired |
string |
An ID of your choice which you provided upon payment code creation |
business_idrequired |
string |
Your Xendit business ID |
payment_code_idrequired |
string |
Unique ID for the payment code |
channel_coderequired |
string |
Name for the relevant Retail Outlets. e.g. 7ELEVEN , 7ELEVEN_CLIQQ , CEBUANA , ECPAY , LBC , DP_PALAWAN , DP_MLHUILLIER , DP_ECPAY_LOAN , DP_RD_PAWNSHOP , DP_CVM , DP_ECPAY_SCHOOL , and DP_USSC |
payment_coderequired |
string |
Complete payment code (including prefix) |
country_coderequired |
string |
2-letter ISO 3166-2 country code indicating country of transaction.Supported country code: |
currencyrequired |
string |
ISO 4217 Currency codeSupported currency code:
|
amountoptional |
integer positive |
Nominal amount that is paid |
statusrequired |
string |
Status of payment. Possible value(s): COMPLETED |
createdrequired |
ISO 8601 Date |
Date time when transaction was createdtimezone:
|
remarksrequired |
string |
Note from channel during payment |
Payouts
This Payouts API is an updated version of the existing Disbursements API product where users can send money at scale to all bank accounts & eWallets in Indonesia, Philippines, Thailand, Malaysia and Vietnam by using just a single endpoint.
Users of the new Payouts API should be able to enjoy the existing disbursement services and any new channels or regions made available in the future without needing to do another integration.
Payout Object
Example of Payout Object
{
"id": "disb-1475459775872",
"amount": 100,
"channel_code": "ID_BCA",
"currency": "IDR",
"description": "Lotto Winner #12",
"reference_id": "lotto-1482928194",
"status": "ACCEPTED",
"created": "2022-01-05T05:37:48.108Z",
"updated": "2022-01-05T05:37:48.108Z",
"estimated_arrival_time": "2022-01-05T05:52:48.106Z",
"business_id": "5785e6334d7b410667d355c4",
"channel_properties": {
"account_number": "0000000000",
"account_holder_name": "Michael Chen"
},
"receipt_notification": {
"email_to": [
"chen@example.co",
"somebodyexample.co"
],
"email_cc": [
"somebodyexample.co",
"somebodyexample.co"
],
"email_bcc": [
"somebodyexample.co",
"somebodyexample.co"
]
}
}
Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Xendit-generated unique identifier for each payout Prefix: disb_ |
||||||||
amountrequired |
number |
Amount to be sent to the destination account. Should be a multiple of the minimum increment for the selected channel. For IDR currency, number should be integer For PHP currency, number can be up to 2 decimal placesFor VND currency, number should be integer For MYR currency, number can be up to 2 decimal placesFor THB currency, number can be up to 2 decimal places |
||||||||
channel_coderequired |
string |
Channel code of selected destination bank, e-wallet or OTC channel. | ||||||||
currencyrequired |
string |
ISO 4217 Currency Code. | ||||||||
descriptionoptional |
string |
Description to send with the payout. The recipient may see this e.g., in their bank statement (if supported) or in email receipts we send on your behalf.Characters Special and alphanumericMaximum length 100 charactersMinimum length 1 character |
||||||||
reference_idrequired |
string |
A client defined payout identifier. This is the ID assigned to the payout on your system, such as a transaction or order ID. Does not need to be unique.Characters Special and alphanumericMaximum length 255 charactersMinimum length 1 character |
||||||||
statusrequired |
string |
Status of payout. The status in the response will always be ACCEPTED; meaning transfer is initiated but not yet completed by bank or e-wallet. The final status will be given in a callback. |
||||||||
createdrequired |
ISO8601 |
Timestamp when the payout request was made (in ISO 8601 format) Timezone UTC+0 |
||||||||
updatedrequired |
ISO8601 |
Timestamp when the payout status was updated (in ISO 8601 format) Timezone UTC+0 |
||||||||
estimated_arrival_timeoptional |
ISO8601 |
Estimated time of arrival of funds in destination account (in ISO 8601 format) For OTC payouts: Estimated time that funds will be available for pick-up Timezone UTC+0 |
||||||||
failure_codeoptional |
string |
If the Payout failed, we include a failure code for more details on the failure. | ||||||||
business_idrequired |
string |
Your Xendit Business ID | ||||||||
channel_propertiesrequired |
object |
A container for properties associated with the chosen channel_code For digital channels (bank or e-wallet account) Individual detail child parameters
|
||||||||
receipt_notificationoptional |
JSON |
Object containing email addresses to receive payout details upon successful payout. Maximum of three email addresses each.
|
||||||||
metadataoptional |
Object |
Object of additional information you may use |
Create Payout
Endpoint: Create Payout
POST https://api.xendit.co/v2/payouts
Request Parameters
Example Create Payout Request
Create payout request
curl https://api.xendit.co/v2/payouts -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
--header 'Idempotency-key: some-unique-ref-for-request'
--data-raw '{
"reference_id": "lotto-1482928194",
"channel_code": "ID_BCA",
"channel_properties": {
"account_number": "000000000099",
"account_holder_name": "Michael Chen"
},
"amount": 1000,
"description": "Lotto Winner #12",
"currency": "IDR",
"receipt_notification": {
"email_to": [
"chen@example.co",
"somebody@example.co"
],
"email_cc": [
"somebody@example.co",
"somebody@example.co"
],
"email_bcc": [
"somebody@example.co",
"somebody@example.co"
]
},
"metadata": {
"lotto_outlet": 24
}
}'
Header Parameter | Type | Description |
---|---|---|
Idempotency-keyrequired |
string |
A unique key to prevent processing duplicate requests. Can be your reference_id or any GUID. Must be unique across development & production environments.
|
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 of Create Payout Request to Bank
{
"reference_id": "sample-successful-create-idr-payout",
"channel_code": "ID_BCA",
"channel_properties": {
"account_holder_name": "Test",
"account_number": "0000000000"
},
"amount": 1000,
"description": "Sample Successful Create IDR Payout",
"currency": "IDR",
"receipt_notification" : {
"email_to": ["somebody@xendit.co"],
"email_cc": ["somebody@xendit.co"]
}
}
Example of Create Payout Request to eWallet
{
"reference_id": "sample-successful-create-php-payout",
"channel_code": "PH_GCASH",
"channel_properties": {
"account_holder_name": "Test",
"account_number": "0000000000"
},
"amount": 1.11,
"description": "Sample Successful Create PHP Payout",
"currency": "PHP",
"receipt_notification" : {
"email_to": ["somebody@xendit.co"],
"email_cc": ["somebody@xendit.co"]
}
}
Example of Create Payout Request with currency THB to a mobile number
{
"reference_id": "sample-successful-create-thb-payout",
"channel_code": "TH_BAY",
"channel_properties": {
"account_holder_name": "Test",
"account_number": "6612345678",
"account_type": "MOBILE_NO"
},
"amount": 1.11,
"description": "Sample Successful Create THB Payout",
"currency": "THB",
"receipt_notification" : {
"email_to": ["somebody@xendit.co"],
"email_cc": ["somebody@xendit.co"]
}
}
Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
reference_idrequired |
string |
A client defined payout identifier. This is the ID assigned to the payout on your system, such as a transaction or order ID. Does not need to be unique.Characters Special and alphanumericMaximum length 255 charactersMinimum length 1 character |
||||||||
channel_coderequired |
string |
Channel code of destination bank, e-wallet or OTC channel. List of supported channels can be found here | ||||||||
channel_propertiesrequired |
object |
A container for properties associated with the chosen channel_code Inputs for digital channels (bank or e-wallet account) Individual detail child parameters
|
||||||||
amountrequired |
number |
Amount to be sent to the destination account. Should be a multiple of the minimum increment for the selected channel. For IDR currency, number should be integerFor PHP currency, number can be up to 2 decimal placesFor VND currency, number should be integerFor MYR currency, number can be up to 2 decimal placesFor THB currency, number can be up to 2 decimal places |
||||||||
descriptionoptional |
string |
Description to send with the payout. The recipient may see this e.g., in their bank statement (if supported) or in email receipts we send on your behalf.Characters Special and alphanumericMaximum length 100 charactersMinimum length 1 character |
||||||||
currencyrequired |
string |
ISO 4217 Currency Code. | ||||||||
receipt_notificationoptional |
array of object |
Object containing email addresses to receive payout details upon successful payout. Maximum of three email addresses each.
|
||||||||
metadataoptional |
object |
Object of additional information you may use |
Response Parameters
Example of Create Payout Response
{
"id": "disb-1475459775872",
"amount": 1.11,
"channel_code": "PH_GCASH",
"currency": "PHP",
"description": "Sample Successful Create PHP Payout",
"reference_id": "sample-successful-create-php-payout",
"status": "ACCEPTED",
"created": "2022-01-05T05:37:48.108Z",
"updated": "2022-01-05T05:37:48.108Z",
"estimated_arrival_time": "2022-01-05T05:52:48.106Z",
"business_id": "6018306aa16ad90cb3c43ba7",
"channel_properties": {
"account_number": "0000000000",
"account_holder_name": "Test"
},
"receipt_notification": {
"email_to": [
"somebody@xendit.co"
],
"email_cc": [
"somebody@xendit.co"
]
}
}
Returns Payout object with status 200
Error Codes
Example of payout error
{
"error_code": "DUPLICATE_ERROR",
"message": "A payout with this idempotency key already exists. If you meant to execute a different request, please use another idempotency key."
}
Error Code | Error Message |
---|---|
DUPLICATE_ERROR 400 |
A payout with this idempotency key already exists. If you meant to execute a different request, please use another idempotency key. |
API_VALIDATION_ERROR 400 |
Should have required property “xxx” |
API_VALIDATION_ERROR 400 |
"amount” should have 2 decimal places or less |
API_VALIDATION_ERROR 400 |
“expires_at” should be at least 2 days from now and not exceeding 90 days |
CHANNEL_CODE_NOT_SUPPORTED 400 |
“channel_code” is not supported. See list of supported channel codes at the URL below. |
MINIMUM_TRANSFER_LIMIT_ERROR 400 |
"amount” is under the minimum amount supported for the channel. See amount limitations at the URL below. |
MAXIMUM_TRANSFER_LIMIT_ERROR 400 |
“amount” is more than the maximum amount supported for the channel. See amount limitations at the URL below. |
AMOUNT_INCREMENT_NOT_SUPPORTED 400 |
“amount” needs to be a multiple of the minimum increment supported by the channel. |
INVALID_API_KEY 401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR 403 |
The API key is forbidden to perform this request |
SERVER_ERROR 500 |
Something unexpected, our devs have been notified to troubleshoot the issue |
Get Payout by ID
Endpoint: Get Payout by id
GET https://api.xendit.co/v2/payouts/:id
This endpoint queries the current status of a payout. This is often used for checking the status of a transaction using the id from the Payout Object.
Request Parameters
Example Get Payout Request
Get Payout by ID
curl https://api.xendit.co/v2/payouts/disb-b57fff2d-9699-470b-9978-ac509c5b266c -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
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 |
Xendit Payout ID generated by [POST] /payouts/ Prefix: disb- |
Response Parameters
Example Get Payout Response
{
"id": "disb-1475459775872",
"amount": 100,
"channel_code": "ID_BCA",
"currency": "IDR",
"description": "Sample Failed Create Payout",
"estimated_arrival_time": "2022-01-05T06:09:23.667Z",
"failure_code": "TEMPORARY_TRANSFER_ERROR",
"reference_id": "sample-failed-create-payout",
"status": "FAILED",
"created": "2022-01-05T05:54:23.670Z",
"updated": "2022-01-05T05:54:35.680Z",
"business_id": "5785e6334d7b410667d355c4",
"channel_properties": {
"account_number": "123456",
"account_holder_name": "Test"
}
}
Returns Payout object with status 200
Error Codes
Error Code | Error Message |
---|---|
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. |
DATA_NOT_FOUND404 |
Could not find payout with the corresponding ID. Please try again with a valid ID. |
INVALID_API_KEY401 |
API Key is invalid. |
Get Payouts by Reference ID
Endpoint: Get Payouts by Reference ID
GET https://api.xendit.co/v2/payouts?reference_id=:reference_id
Retrieve all matching payouts with reference ID. Returns an array of matching Payout Object if a valid reference_id was provided. Returns an empty array if there is no payout corresponding to the reference_id.
Request Parameters
Example Get Payout Request
Get Payout by Reference ID
curl https://api.xendit.co/v2/payouts?reference_id=lotto-1482928194&limit=10&after_id=disb-cc7cd9c0-1971-4414-9b54-be545948a33d&before_id=disb-69d8e2ba-20f9-41af-bd04-e299237fd7ec -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
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 |
---|---|---|
reference_id required |
string |
The reference_id you provided in the Create Payout request |
limit optional |
number |
A limit on the number of objects that will be returnedDefault 10Min 1Max 100 |
after_id optional |
UUID |
ID of the immediately previous item |
before_id optional |
UUID |
ID of the immediately following item |
Response Parameters
Example Get Payout Response
[
{
"id": "disb-1475459775872",
"amount": 100,
"channel_code": "ID_BCA",
"currency": "IDR",
"description": "Sample Failed Create Payout",
"estimated_arrival_time": "2022-01-05T06:09:23.667Z",
"failure_code": "TEMPORARY_TRANSFER_ERROR",
"reference_id": "sample-failed-create-payout",
"status": "FAILED",
"created": "2022-01-05T05:54:23.670Z",
"updated": "2022-01-05T05:54:35.680Z",
"business_id": "5785e6334d7b410667d355c4",
"channel_properties": {
"account_number": "123456",
"account_holder_name": "Test"
}
},
{
"id": "disb-567845975142",
"amount": 200,
"channel_code": "ID_BCA",
"currency": "IDR",
"description": "Sample Failed Create Payout2",
"estimated_arrival_time": "2022-01-05T06:14:23.667Z",
"failure_code": "TEMPORARY_TRANSFER_ERROR",
"reference_id": "sample-failed-create-payout2",
"status": "FAILED",
"created": "2022-01-05T05:58:23.670Z",
"updated": "2022-01-05T05:58:35.680Z",
"business_id": "5785e6334d7b410667d355c4",
"channel_properties": {
"account_number": "123456",
"account_holder_name": "Test"
}
}
]
Returns array of Payout object sorted by created time in descending order with HTTP status code 200. “data” will be an empty array and “has_more” equal to false when there are no match data
Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
data required |
array |
Array of Payout object that match the reference_id. Will be sorted by created time in descending order. | ||||||||
has_more required |
boolean |
Indicates whether there are more items to be queried with after_id of the last item from current result | ||||||||
links optional |
array |
HATEOAS implementation on after_id field
|
Error Codes
Error Code | Message |
---|---|
REQUEST_FORBIDDEN_ERROR 403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. |
Cancel Payout
Endpoint: Cancel Payout
GET https://api.xendit.co/v2/payouts/:id/cancel
This endpoint allows cancellation of requested payouts that have not yet been sent to partner banks and e-wallets.
Note: Cancellation is possible if the payout has not been sent out via our partner
Bank and e-wallet payouts: Cancellation is only allowed when status is ACCEPTED
Request Parameters
Example Cancel Payout Request
Cancel Payout
curl https://api.xendit.co/v2/payouts/disb-b57fff2d-9699-470b-9978-ac509c5b266c/cancel -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
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 |
Xendit Payout ID generated by [POST] /payouts/ Prefix: disb- |
Response Parameters
Example Cancel Payout Response
{
"id": "disb-1475459775872",
"amount": 250000,
"channel_code": "PH_CITI",
"currency": "PHP",
"description": "rewards",
"reference_id": "test-rewards-001",
"status": "CANCELLED",
"created": "2022-01-16T12:11:22.233Z",
"updated": "2022-01-16T12:21:31.373Z",
"estimated_arrival_time": "2022-01-16T12:26:22.155Z",
"business_id": "5785e6334d7b410667d355c4",
"channel_properties": {
"payout_code": "002912362381009082189137",
"recipient_given_names": "Michael",
"recipient_surname": "Chen",
"expires_at": "2022-01-23T12:11:22.156Z"
}
}
Returns Payout object with status 200 and status CANCELLED.
Error Codes
Error Code | Error Message |
---|---|
CANCELLATION_NOT_ALLOWED400 |
Payout cannot be canceled because it has already been processed by Xendit. |
DATA_NOT_FOUND404 |
Could not find payout with the corresponding ID. Please try again with a valid ID. |
Payout Webhook
Endpoint: Payout Webhook
POST https://yourcompany.com/payout_webhook_url
Xendit notifies your system upon failed and successful payouts via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Example of Success Payout Webhook
{
"id":"disb-1b950430-kkk-44f0-q485-641bc450c59c",
"amount":1.23,
"status":"SUCCEEDED",
"created":"2022-01-11T01:39:15.465Z",
"updated":"2022-01-11T01:39:18.773Z",
"currency":"PHP",
"description":"V2 Regional Payout",
"channel_code":"PH_GCASH",
"reference_id":"Webhook-Automation-test-49a294eb-d664-423f-9ea5-476d8201c9d8",
"account_number":"09991231877",
"idempotency_key":"a029fc31-02ef-4c8b-b21d-af32ceed7321",
"channel_category":"EWALLET",
"account_holder_name":"Michael Chen",
"connector_reference":"SIMULATED_PARTNER_REFERENCE_1665452357445_241",
"receipt_notification":{
"email_cc":[
"mikechen@xendit.co"
]
},
"estimated_arrival_time":"2022-01-11T01:54:15.464Z"
}
Example of Failed Payout Webhook
{
"id":"disb-31ff90a0-d0fe-444c-9653-44d01cbf2a0e",
"amount":1,
"status":"FAILED",
"created":"2022-01-11T01:39:21.074Z",
"updated":"2022-01-11T01:39:24.139Z",
"currency":"PHP",
"description":"V2 Regional Payout",
"channel_code":"PH_UBP",
"failure_code":"INVALID_DESTINATION",
"reference_id":"Webhook-Test-ab2cd787-05ab-4a2f-8a89-f3604384b9ea",
"account_number":"121212",
"idempotency_key":"01d6d000-bc20-4630-9e3f-68312ac2272e",
"channel_category":"BANK",
"account_holder_name":"Michael Chen",
"estimated_arrival_time":"2022-01-11T01:54:21.073Z"
}
Payouts Failed/Completed
Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Type of the event. Possible events: payout.succeeded - A payout’s status has already succeeded and partner bank has credited the funds to the beneficiary payout.failed - A payout’s status has already failed and the partner bank rejected the transaction or there was an issue processing the transaction. payout.reversed - A payout that was originally in succeeded status received a bounceback or reversal of funds from the partner bank. Funds have been refunded back to the merchant’s available balance. |
business_id required |
string |
Xendit's unique business ID |
created required |
string |
ISO8601 timestamp of the event created time Timezone UTC+0 Format: YYYY-MM-DDThh:mm:ssZ |
data required |
object |
Return Payout object with a specific status based on the payout processing result and the following event field |
Failure Codes
Error Message | Description | Should you retry? |
---|---|---|
INSUFFICIENT_BALANCE | Client has insufficient balance for the payout amount | Yes, retry the payout after ensuring that you have sufficient balance in your account. |
INVALID_DESTINATION | Destination account does not exist/is invalid. | You are unlikely to succeed if you retry the payout request. Please confirm with the beneficiary whether the destination account is correct |
REJECTED_BY_CHANNEL | Payout failed due to an error from the destination channel. This is usually because of network issues associated with the destination bank or issues crediting funds into the destination bank account | Yes, retry the payout after validating that the destination bank account number is active and can receive funds in your chosen currency. |
TEMPORARY_TRANSFER_ERROR | The channel networks are experiencing a temporary error. Retry the payout in 1-3 hours. | Yes, retry the payout in 1-3 hours. |
TRANSFER_ERROR | We’ve encountered a fatal error while processing this payout. Normally, this means that certain API fields in your request are invalid. | It is unlikely that the same disbursement request will succeed if you retry. |
UNKNOWN_BANK_NETWORK_ERROR | The bank has delivered an error they have not documented. By definition, this means the bank does not know the issue. | Unfortunately, we are unable to predict whether the disbursement will succeed should you retry the same disbursement request. You may however choose to retry the same disbursement request at least one hour after receiving our webhook at your own discretion. |
Get Payouts Channels
Endpoint: Get Payouts Channels
GET https://api.xendit.co/payouts_channels
Example Get Payouts Channels Request
curl https://api.xendit.co/payouts_channels?currency=PHP&channel_category=BANK -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
This API endpoint will provide you the current list of banks and e-wallets we support for payouts for both regions. If you would like us to support payment to a specific destination, please contact us at support@xendit.co.
Request Parameters
Parameter | Type | Description |
---|---|---|
currency optional |
string |
Filter by currency Values: IDR, PHP |
channel_category optional |
string |
Filter by channel_category Values: BANK, EWALLET, OTC |
channel_code optional |
string |
Filter by channel_code ie: ID_BSI, PH_AUB |
Response Parameters
Get Payouts Channels (Banks) Response
[
{
"channel_code": "ID_BSI",
"channel_category": "BANK",
"currency": "IDR",
"channel_name": "Bank Syariah Indonesia",
"amount_limits": {
"minimum": 10000,
"maximum": 1999999999999,
"minimum_increment": 1
}
},
{
"channel_code": "PH_AUB",
"channel_category": "BANK",
"currency": "PHP",
"channel_name": "Asia United Bank",
"amount_limits": {
"minimum": 1,
"maximum": 100000000,
"minimum_increment": 1
}
}
]
Returns array of Payout Channel objects sorted by alphabetical order by channel_code with HTTP status code 200. Return empty array when not found.
If query parameters are defined, returns a filtered list of Payout Channel objects matching the query parameter.
Parameter | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
channel_name | string |
Name of payout channel | ||||||
channel_category | string |
Type of payout destination Values: BANK, EWALLET, OTC |
||||||
channel_code | string |
Channel code of destination bank, e-wallet or OTC channel. List of supported channels can be found here | ||||||
currency | string |
Default currency of payout channel Currency Format: ISO 4217 |
||||||
amount_limits | object |
Object containing amount limitations imposed by the channel. Individual detail child parameters
|
Disbursements
Send money at scale to all bank accounts & eWallets in Indonesia using Xendit’s Disbursements. We currently support disbursements to 140+ local banks, virtual accounts of the biggest banks (BRI, BNI, Mandiri, CIMB Niaga, Permata, BTN, and NOBU Bank) and eWallets (e.g. Gopay, OVO, DANA, LinkAja & Shopee Pay). View all supported destination here.
Disbursement Object
Example of Disbursement Object
{
"id": "57f1ce05bb1a631a65eee662",
"external_id": "disb-1475459775872",
"user_id": "5785e6334d7b410667d355c4",
"bank_code": "BCA",
"account_holder_name": "MICHAEL CHEN",
"amount": 90000,
"disbursement_description": "Reimbursement for shoes",
"status": "PENDING",
"email_to": [
"somebody@email.com"
],
"email_cc": [
"somebody.else@gmail.com"
],
"email_bcc": [
"someone@mail.co"
]
}
Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique Xendit disbursement ID. Use this ID for support escalation and reconciliation |
external_idrequired |
string |
Custom ID of your choice to identify the transaction. Our customers often use a phone number, email address, or transaction/order ID |
user_idrequired |
string |
Your Xendit Business ID |
bank_coderequired |
string |
Destination bank or e-wallet. View all bank and e-wallet codes here |
account_holder_namerequired |
string |
Name of account holder as per the bank's or e-wallet’s records. Used for verification and error/customer support scenarios |
amountrequired |
number |
Amount to disburse |
disbursement_descriptionrequired |
string |
Description to send with the disbursement |
statusrequired |
string |
Status of the disbursement - PENDING Transfer is initiated but not yet completed by bank. - COMPLETED Bank has confirmed transmission of funds.- FAILED Disbursement failed because of failure code |
failure_code optional |
string |
INSUFFICIENT_BALANCE The balance in your account is insufficient to make the disbursement in the desired amountUNKNOWN_BANK_NETWORK_ERROR The bank networks have returned an unknown error to us. We are unable to predict whether the disbursement will succeed should you retry the same disbursement request.TEMPORARY_BANK_NETWORK_ERROR The bank networks are experiencing a temporary error. Please retry the disbursement in 1-3 hoursINVALID_DESTINATION The banks have reported that the destination account is unregistered or blocked. If unsure about this, please retry again or contact the destination bank directly regarding the status of the destination accountSWITCHING_NETWORK_ERROR At least one of the switching networks is encountering an issue. Please retry the disbursement in 1-3 hoursREJECTED_BY_BANK The bank has rejected this transaction for unclear reasons. We are unable to predict whether the disbursement will succeed should you retry the same disbursement request.TRANSFER_ERROR We’ve encountered a fatal error while processing this disbursement. Certain API fields in your request may be invalid. Please contact our customer support team for more informationTEMPORARY_TRANSFER_ERROR We’ve encountered a temporary issue while processing this disbursement. Please retry the disbursement in 1-2 hoursFor detailed information regarding the different error codes above, please see Common Errors in Disbursements. |
email_tooptional |
array of string |
Email addresses that get notified of disbursement details after the disbursement is completed. This response parameter is only returned if this field is filled. |
email_ccoptional |
array of string |
Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed. This response parameter is only returned if this field is filled. |
email_bccoptional |
array of string |
Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed. This response parameter is only returned if this field is filled. |
Create Disbursement
Endpoint: Create Disbursement
POST https://api.xendit.co/disbursements
Request Parameters
Example Create Disbursement Request
curl https://api.xendit.co/disbursements -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d external_id=disb-1475459775872 \
-d amount=90000 \
-d bank_code=BCA \
-d account_holder_name='MICHAEL CHEN' \
-d account_number=1234567890 \
-d description='Reimbursement for shoes'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'external_id' => '12345',
'amount' => 90000,
'bank_code' => 'BCA',
'account_holder_name' => 'MICHAEL CHEN',
'account_number' => '1234567890',
'description' => 'Disbursement from Example',
'X-IDEMPOTENCY-KEY' => 'unique-id'
];
$createDisbursements = \Xendit\Disbursements::create($params);
var_dump($createDisbursements);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Disbursement } = x;
const disbursementSpecificOptions = {};
const d = new Disbursement(disbursementSpecificOptions);
const resp = await d.create({
externalID: 'disb-1475459775872',
amount: 90000,
bankCode: 'BCA',
accountHolderName: 'MICHAEL CHEN',
accountNumber: '1234567890',
description: 'Reimbursement for shoes',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Map<String, Object> params = new HashMap<>();
params.put("external_id", "disb-1475459775872");
params.put("bank_code", "BCA");
params.put("account_holder_name", "MICHAEL CHEN");
params.put("account_number", "1234567890");
params.put("description", "Reimbursement for shoes");
params.put("amount", "90000");
Disbursement disbursement = Disbursement.create(params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
createData := disbursement.CreateParams{
IdempotencyKey: "disbursement" + time.Now().String(),
ExternalID: "12345",
BankCode: "BCA",
AccountHolderName: "MICHAEL CHEN",
AccountNumber: "1234567890",
Description: "Disbursement from Go",
Amount: 90000,
}
resp, err := disbursement.Create(&createData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created disbursement: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Disbursement = xendit_instance.Disbursement
disbursement = Disbursement.create(
external_id="disb-1475459775872",
bank_code="BCA",
account_holder_name="MICHAEL CHEN",
account_number="1234567890",
description="Reimbursement for shoes",
amount=90000,
)
print(disbursement)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
DisbursementClient disbursement = xendit.Disbursement;
DisbursementParameter parameter = new DisbursementParameter
{
ExternalId = "disb-1475459775872",
BankCode = DisbursementChannelCode.Bca,
AccountHolderName = "MICHAEL CHEN",
AccountNumber = "1234567890",
Description = "Reimbursement for shoes",
Amount = 1000,
};
DisbursementResponse disbursementResponse = await disbursement.Create(parameter);
Header Parameter | Type | Description |
---|---|---|
X-IDEMPOTENCY-KEYoptional |
string |
A unique key to prevent processing duplicate requests. Can be your external_id or any GUID. Must be unique across development & production environments.
|
for-user-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 of Create Disbursement Request to Bank
{
"external_id": "disb-{{$timestamp}}",
"amount": 90000,
"bank_code": "BCA",
"account_holder_name": "MICHAEL CHEN",
"account_number": "1234567890",
"description":"Reimbursement for shoes"
}
Example of Create Disbursement Request to eWallet
{
"external_id": "disb-{{$timestamp}}",
"amount": 90000,
"bank_code": "OVO",
"account_holder_name": "MICHAEL CHEN",
"account_number": "081228271026",
"description":"Reimbursement for shoes"
}
Body Parameter | Type | Description |
---|---|---|
external_idrequired |
string |
ID of the disbursement in your system, used to reconcile disbursements after they have been completed.
|
bank_coderequired |
string |
Destination bank or e-wallet. View all bank and e-wallet codes here. |
account_holder_namerequired |
string |
Name of account holder as per the bank's or e-wallet's records. Used for verification and error/customer support scenarios.
|
account_numberrequired |
string |
Destination bank or e-wallet account number. If disbursing to an e-wallet, phone number registered with the e-wallet account. We support disbursements to virtual accounts of major banks (BRI, BNI, Mandiri, CIMB Niaga, Permata, BTN, and NOBU Bank). |
descriptionrequired |
string |
Description to send with the disbursement
|
amountrequired |
number |
Amount to disburse. See maximum and minimum amount for each destination channel
|
email_tooptional |
array of string |
Email addresses that get notified of disbursement details after the disbursement is completed. Maximum 3 email addresses accepted. |
email_ccoptional |
array of string |
Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed. Maximum 3 email addresses accepted. Only allowed if email_to provided. |
email_bccoptional |
array of string |
Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed. Maximum 3 email addresses accepted. Only allowed if email_to provided. |
Response Parameters
Example of Create Disbursement Response
{
"id": "57f1ce05bb1a631a65eee662",
"external_id": "disb-1475459775872",
"user_id": "5785e6334d7b410667d355c4",
"bank_code": "BCA",
"account_holder_name": "MICHAEL CHEN",
"amount": 90000,
"disbursement_description": "Reimbursement for shoes",
"status": "PENDING",
"email_to": [
"somebody@email.com"
],
"email_cc": [
"somebody.else@gmail.com"
],
"email_bcc": [
"someone@mail.co"
]
}
Returns Disbursement object with status 200
Error Codes
Example of disbursement error
{
"error_code": "BANK_CODE_NOT_SUPPORTED",
"message": "Destination bank code is not supported. See https://docs.xendit.co/xendisburse/channel-codes for all supported channel 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. |
DISBURSEMENT400 |
Disbursement description is not set in Disbursement Settings in Xendit Dashboard. Add a default description before retrying. |
DIRECT_DISBURSEMENT400 |
Not enough balance to disburse. Add more balance before retrying. |
DUPLICATE_TRANSACTION400 |
Idempotency key has been used before. Use a unique idempotency key and try again. |
BANK_CODE_NOT400 |
Destination bank code is not supported. See all supported channel codes |
RECIPIENT400 |
For transfers to BCA, account_number input needs to be 10 digits. Check the account number length before retrying. |
RECIPIENT400 |
The transfer amount requested is lower than the prescribed minimum for the chosen destination bank. Amend the transfer amount before retrying. See maximum and minimum amount for each destination channel |
MAXIMUM400 |
The transfer amount requested is higher than the prescribed maximum for the chosen destination bank. Amend the transfer amount before retrying. See maximum and minimum amount for each destination channel |
INVALID400 |
The account number is unable to processed. Use different account number to retry. |
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 |
SERVER_ERROR500 |
Error connecting to our server. Use Get Disbursement API to check whether the disbursement has already been created. Retry safely using X-IDEMPOTENCY-KEY header |
Get Disbursement by ID
Endpoint: Get Disbursement by id
GET https://api.xendit.co/disbursements/{disbursement_id}
This endpoint queries the current status of a disbursement. This is often used for checking the status of a transaction.
Request Parameters
Example Get Disbursement Request
curl https://api.xendit.co/disbursements/57c9010f5ef9e7077bcb96b6 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '57c9010f5ef9e7077bcb96b6';
$getDisbursements = \Xendit\Disbursements::retrieve($id);
var_dump($getDisbursements);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Disbursement } = x;
const disbursementSpecificOptions = {};
const d = new Disbursement(disbursementSpecificOptions);
const resp = await d.getByID({ disbursementID: '587cc7ea77535fb94bb4e8eb' });
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Disbursement disbursement = Disbursement.getById("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
getByIDData := disbursement.GetByIDParams{
DisbursementID: "57c9010f5ef9e7077bcb96b6",
}
resp, err := disbursement.GetByID(&getByIDData)
if err != nil {
log.Fatal(err.ErrorCode, err.Message, err.GetStatus())
}
fmt.Printf("retrieved disbursement: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Disbursement = xendit_instance.Disbursement
disbursement = Disbursement.get(
id="5ef1befeecb16100179e1d05",
)
print(disbursement)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
DisbursementClient disbursement = xendit.Disbursement;
DisbursementResponse disbursementResponse = await disbursement.GetById("5ef1befeecb16100179e1d05");
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 |
---|---|---|
disbursement_idrequired |
string |
ID of the disbursement to retrieve The disbursement_id must match the unique disbursement ID provided in our success response at disbursement creation precisely |
Response Parameters
Example Get Disbursement Response
{
"id": "57f1ce05bb1a631a65eee662",
"external_id": "disb-1475459775872",
"user_id": "5785e6334d7b410667d355c4",
"bank_code": "BCA",
"account_holder_name": "MICHAEL CHEN",
"amount": 90000,
"disbursement_description": "Reimbursement for shoes",
"status": "PENDING",
"email_to": [
"somebody@email.com"
],
"email_cc": [
"somebody.else@gmail.com"
],
"email_bcc": [
"someone@mail.co"
]
}
Returns Disbursement object with status 200
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 |
DIRECT_DISBURSEMENT404 |
Could not find direct disbursement. |
Get Disbursements by External ID
Endpoint: Get Disbursements by External ID
GET https://api.xendit.co/disbursements?external_id={external_id}
This endpoint queries the current status of all disbursements with requested external_id. This is often used to check the status of a transaction with external_id.
Request Parameters
Example Get Disbursement Request
curl https://api.xendit.co/disbursements?external_id=72655 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$external_id = 'disbursements-ext-id';
$getDisbursementsByExt = \Xendit\Disbursements::retrieveExternal($external_id);
var_dump($getDisbursementsByExt);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Disbursement } = x;
const disbursementSpecificOptions = {};
const d = new Disbursement(disbursementSpecificOptions);
const resp = await d.getByExtID({ externalID: 'disbursement_12345' });
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Disbursement[] disbursement = Disbursement.getByExternalId("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
getByExternalIDData := disbursement.GetByExternalIDParams{
ExternalID: "disbursement_12345",
}
resps, err := disbursement.GetByExternalID(&getByExternalIDData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("retrieved disbursements: %+v\n", resps)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Disbursement = xendit_instance.Disbursement
disbursement_list = Disbursement.get_by_ext_id(
external_id="demo_1475459775872",
)
print(disbursement_list)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
DisbursementClient disbursement = xendit.Disbursement;
DisbursementResponse[] disbursementResponses = await disbursement.GetByExternalId("demo_1475459775872");
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 |
---|---|---|
external_idrequired |
string |
Custom ID of the disbursement set by the customer at disbursement creation The external_id must match the external_id used at disbursement creation precisely |
Response Parameters
Example Get Disbursement Response
[
{
"id": "57f1ce05bb1a631a65eee662",
"external_id": "disb-1475459775872",
"user_id": "5785e6334d7b410667d355c4",
"bank_code": "BCA",
"account_holder_name": "MICHAEL CHEN",
"amount": 90000,
"disbursement_description": "Refunds for shoes",
"status": "COMPLETED",
"email_to": [
"somebody@email.com"
],
"email_cc": [
"somebody.else@gmail.com"
],
"email_bcc": [
"someone@mail.co"
]
},
{
"id": "57f12e1afb1a721a65efe715",
"external_id": "disb-1475459775872",
"user_id": "5785e6334d7b410667d355c4",
"bank_code": "BCA",
"account_holder_name": "MICHAEL CHEN",
"amount": 90000,
"disbursement_description": "Refunds for shoes",
"status": "FAILED",
"failure_code": "REJECTED_BY_BANK",
"email_to": [
"somebody@email.com"
],
"email_cc": [
"somebody.else@gmail.com"
],
"email_bcc": [
"someone@mail.co"
]
}
]
Returns array of Disbursement object with status 200
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 |
DIRECT_DISBURSEMENT404 |
Could not find direct disbursement. |
Disbursement Callback
Endpoint: Disbursement Webhook
POST https://yourcompany.com/disbursement_webhook_url
Xendit notifies your system upon failed and successful disbursements via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Example of Success Disbursement Webhook
{
"id": "57e214ba82b034c325e84d6e",
"created": "2021-07-10T08:15:03.404Z",
"updated": "2021-07-10T08:15:03.404Z",
"external_id": "disbursement_123124123",
"user_id": "57c5aa7a36e3b6a709b6e148",
"amount": 150000,
"bank_code": "BCA",
"account_holder_name": "MICHAEL CHEN",
"disbursement_description": "Refund for shoes",
"status": "COMPLETED",
"is_instant": true
}
Example of Failed Disbursement Webhook
{
"id": "57e214ba82b034c325e84d6e",
"created": "2021-07-10T08:15:03.404Z",
"updated": "2021-07-10T08:15:03.404Z",
"external_id": "disbursement_123124123",
"user_id": "57c5aa7a36e3b6a709b6e148",
"amount": 150000,
"bank_code": "BCA",
"account_holder_name": "MICHAEL CHEN",
"disbursement_description": "Refund for shoes",
"status": "FAILED",
"failure_code": "INVALID_DESTINATION",
"is_instant": true
}
Body Parameter | Type | Description |
---|---|---|
id | string |
Unique Xendit disbursement ID. Use this ID for support escalation and reconciliation |
created | string |
ISO 8601 timestamp of the disbursement creation. Timezone UTC+0 |
updated | string |
ISO 8601 timestamp of the last updated of the disbursement object. Timezone UTC+0 |
external_id | string |
Custom ID set at disbursement creation. Our customers often use a phone number, email address, or transaction/order ID |
user_id | string |
Your Xendit Business ID |
bank_code | string |
Destination bank or e-wallet. See bank codes |
account_number | string |
Destination bank or e-wallet account number |
account_holder_name | string |
Name of account holder as per the bank's or e-wallet's records. |
amount | number |
Amount to disburse |
disbursement_description | string |
Description to send with the disbursement |
status | string |
COMPLETED Bank has confirmed transmission of funds.FAILED Disbursement failed because of failure code |
failure_code |
string |
INSUFFICIENT_BALANCE The balance in your account is insufficient to make the disbursement in the desired amountUNKNOWN_BANK_NETWORK_ERROR The bank networks have returned an unknown error to us. We are unable to predict whether the disbursement will succeed should you retry the same disbursement request.TEMPORARY_BANK_NETWORK_ERROR The bank networks are experiencing a temporary error. Please retry the disbursement in 1-3 hoursINVALID_DESTINATION The banks have reported that the destination account is unregistered or blocked. If unsure about this, please retry again or contact the destination bank directly regarding the status of the destination accountSWITCHING_NETWORK_ERROR At least one of the switching networks is encountering an issue. Please retry the disbursement in 1-3 hoursREJECTED_BY_BANK The bank has rejected this transaction for unclear reasons. We are unable to predict whether the disbursement will succeed should you retry the same disbursement request.TRANSFER_ERROR We’ve encountered a fatal error while processing this disbursement. Certain API fields in your request may be invalid. Please contact our customer support team for more informationTEMPORARY_TRANSFER_ERROR We’ve encountered a temporary issue while processing this disbursement. Please retry the disbursement in 1-2 hoursFor detailed information regarding the different error codes above, please see Common Errors in Disbursements. |
is_instant | boolean |
Indicates whether the disbursement is being disbursed instantly |
Get Available Banks
Endpoint: Get Available Disbursement Banks
GET https://api.xendit.co/available_disbursements_banks
Example Get Available Disbursement Banks Request
curl https://api.xendit.co/available_disbursements_banks -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$getDisbursementsBanks = \Xendit\Disbursements::getAvailableBanks();
var_dump($getDisbursementsBanks);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Disbursement } = x;
const disbursementSpecificOptions = {};
const d = new Disbursement(disbursementSpecificOptions);
const resp = await d.getBanks();
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
AvailableBank[] banks = Disbursement.getAvailableBanks();
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
availableBanks, err := disbursement.GetAvailableBanks()
if err != nil {
log.Fatal(err)
}
fmt.Printf("available disbursement banks: %+v\n", availableBanks)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Disbursement = xendit_instance.Disbursement
disbursement_banks = Disbursement.get_available_banks()
print(disbursement_banks)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
DisbursementClient disbursement = xendit.Disbursement;
AvailableBank[] availableBanks = await disbursement.GetAvailableBanks();
This API endpoint will provide you the current list of banks and e-wallets we support for disbursements. We support transfers to 140+ banks in Indonesia, including some BPDs and BPRs, and virtual accounts of major banks (BRI, BNI, Mandiri, CIMB Niaga, Permata, BTN, and NOBU Bank). We also support disbursements to major e-wallets (GoPay, OVO, Dana, Linkaja, and Shopeepay). If you would like us to support payment to a specific destination, please contact us at support@xendit.co.
Response Parameters
Get Available Disbursement Banks Response
[
{
"name": "Bank Mandiri",
"code": "MANDIRI",
"can_disburse": true,
"can_name_validate": true
},
{
"name": "Bank Rakyat Indonesia (BRI)",
"code": "BRI",
"can_disburse": true,
"can_name_validate": true
},
{
"name": "Bank Central Asia (BCA)",
"code": "BCA",
"can_disburse": true,
"can_name_validate": true
}
]
Parameter | Type | Description |
---|---|---|
name | string |
Full name of the bank or e-wallet |
code | string |
Code of the bank or e-wallet you would like to disburse to |
Batch Disbursement
Batch disbursements (beta) are a set of instructions containing multiple commands to disburse funds to any banks in Indonesia.
Note: Idempotency can be achieved by sending a header with the key X-IDEMPOTENCY-KEY.
Create Batch Disbursement
With this API endpoint you can create multiple disbursements at the same time.
Endpoint: Create Batch Disbursement
POST https://api.xendit.co/batch_disbursements
Request Parameters (Money-out write permission)
Example Create Batch Disbursement Request
curl https://api.xendit.co/batch_disbursements -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H "Content-Type: application/json" \
-d '{
"reference": "demo_123",
"disbursements": [
{
"external_id": "demo_123_1",
"bank_code": "BCA",
"bank_account_name": "Stanley Nguyen",
"bank_account_number": "12345678",
"description": "Reimbursement for pair of shoes (1)",
"amount": 20000
}
]
}'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$batch_params = [
'reference' => 'qwerty1234',
'disbursements' => [
[
'amount' => 20000,
'bank_code' => 'BCA',
'bank_account_name' => 'Fadlan',
'bank_account_number' => '1234567890',
'description' => 'Batch Disbursement',
'external_id' => 'disbursement-1'
],
[
'amount' => 10000,
'bank_code' => 'MANDIRI',
'bank_account_name' => 'Lutfi',
'bank_account_number' => '1234567891',
'description' => 'Batch Disbursement with email notifications',
'external_id' => 'disbursement-2',
'email_to' => ['test+to@xendit.co'],
'email_cc' => ['test+cc@xendit.co'],
'email_bcc' => ['test+bcc1@xendit.co', 'test+bcc2@xendit.co']
]
]
];
$createBatchDisbursements = \Xendit\Disbursements::createBatch($batch_params);
var_dump($createBatchDisbursements);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Disbursement } = x;
const disbursementSpecificOptions = {};
const d = new Disbursement(disbursementSpecificOptions);
const resp = await d.createBatch({
reference: 'demo_123',
disbursements: [
{
externalID: 'demo_123_1',
bankCode: 'BCA',
accountHolderName: 'Stanley Nguyen',
accountNumber: '12345678',
description: 'Reimbursement for pair of shoes (1)',
amount: 20000,
}
]
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
String emailTo[] = new String[1];
emailTo[0] = "test@email.com";
String emailCC[] = new String[1];
emailCC[0] = "test@email.com";
String emailBcc[] = new String[1];
emailBcc[0] = "test@email.com";
BatchDisbursementItem items[] = new BatchDisbursementItem[1];
BatchDisbursementItem item =
BatchDisbursementItem.builder()
.amount(10000)
.bankCode("ABC")
.bankAccountName("Lorem Ipsum")
.bankAccountNumber("1234567890")
.description("Lorem ipsum dolor sit amet")
.externalId("test_id")
.emailTo(emailTo)
.emailCC(emailCC)
.emailBcc(emailBcc)
.build();
items[0] = item;
BatchDisbursement.create(
"reference", //reference
items //BatchDisbursementItem []
);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
createBatchData := disbursement.CreateBatchParams{
Reference: "batch_disbursement" + time.Now().String(),
Disbursements: []disbursement.DisbursementItem{
{
Amount: 200000,
BankCode: "BNI",
BankAccountName: "Michael Jackson",
BankAccountNumber: "1234567890",
Description: "Batch disbursement from Go",
},
{
Amount: 100000,
BankCode: "BRI",
BankAccountName: "Michael Jackson",
BankAccountNumber: "1234567890",
Description: "Batch disbursement from Go 2",
},
},
}
batchDisbursementResp, err := disbursement.CreateBatch(&createBatchData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("created batch disbursement: %+v\n", batchDisbursementResp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
BatchDisbursement = xendit_instance.BatchDisbursement
batch_disbursement_items = []
batch_disbursement_items.append(
BatchDisbursement.helper_create_batch_item(
amount=10000,
bank_code="BCA",
bank_account_name="Adyaksa W",
bank_account_number="12345678",
description="Sample Batch Disbursement",
external_id=f"batch-disbursement-item-12345"
)
)
batch_disbursement = BatchDisbursement.create(
reference="batch_disbursement-1595326225",
disbursements=batch_disbursement_items,
)
print(batch_disbursement)
Header Parameter | Type | Description |
---|---|---|
X-IDEMPOTENCY-KEYoptional |
string |
A unique key to prevent processing duplicate requests. Can be your external_id or any GUID. Must be unique across development & production environments. |
for-user-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 |
---|---|---|
referencerequired |
string |
ID of the batch disbursement in your system, used to reconcile disbursements after they have been completed |
disbursementsrequired |
Disbursement Item[] |
List of disbursements in the batch |
Disbursement Item
Parameter | Type | Description |
---|---|---|
amountrequired |
number |
Amount to disburse |
bank_coderequired |
string |
Code of the receiving bank |
bank_account_namerequired |
string |
Receiving bank account holder name |
bank_account_numberrequired |
string |
Receiving bank account number |
descriptionrequired |
string |
Description to accompany the disbursement |
external_idoptional |
string |
ID of disbursement in your system |
email_tooptional |
string[] |
Email addresses that get notified of disbursement details after the disbursement is completed |
email_ccoptional |
string[] |
Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed |
email_bccoptional |
string[] |
Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed |
Response Parameters
Example Create Batch Disbursement Response
{
"created": "2017-03-30T06:12:47.212Z",
"reference": "qwerty1234",
"total_uploaded_amount": 30000,
"total_uploaded_count": 2,
"status": "UPLOADING",
"id": "58dca1dffee4228917d37336"
}
Parameter | Type | Description |
---|---|---|
createdrequired |
string |
Timestamp of batch disbursement creation in ISO format |
referencerequired |
string |
ID of the batch disbursement in your system, used to reconcile disbursements after they have been completed |
total_uploaded_countrequired |
number |
The count of all disbursements in the batch |
total_uploaded_amountrequired |
number |
Total amount of all disbursements in the batch |
statusrequired |
string |
UPLOADING Batch disbursement request is received and pending for items details to be populated and verified |
idrequired |
string |
Unique ID of batch disbursement in our system |
Error Codes
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
Inputs has failed in validation. The errors field in the response will contain details about which fields are violating validation. |
INVALID_JSON_FORMAT400 |
The request body is not a valid JSON format. |
DUPLICATE_TRANSACTION400 |
Request failed because idempotency key has been seen before. |
INVALID_API_KEY401 |
Wrong API key is being used. |
BATCH_DISBURSEMENT400 |
Request failed because the disbursements contain more than 1000 items. |
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 |
Batch Disbursement Callback
Endpoint: Disbursement Webhook
POST https://yourcompany.com/disbursement_webhook_url
Xendit notifies your system upon failed and successful payouts via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
After creating a batch disbursement via API, to receive a webhook, you must log into your Dashboard and do the following steps:
- Approve the batch disbursements
- Confirm name mismatches, if required
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Example of Batch Disbursements webhook payload
{
"id": "5a64e8217c077f576d926038",
"created": "2021-01-21T19:21:05.982Z",
"updated": "2021-01-21T19:21:42.297Z",
"reference": "Test webhook BD",
"user_id": "5a64e81d70dd16331f65cd61",
"total_uploaded_count": 1,
"total_uploaded_amount": 10000,
"approved_at": "2021-01-21T19:21:16.853Z",
"approver_id": "5a64e82070dd16331f65cd6d",
"status": "COMPLETED",
"total_disbursed_count": 1,
"total_disbursed_amount": 10000,
"total_error_count": 0,
"total_error_amount": 0,
"disbursements": [
{
"id": "5a64e8227c077f576d926039",
"created": "2021-01-21T19:21:06.066Z",
"updated": "2021-01-21T19:21:33.569Z",
"external_id": "1",
"amount": 10000,
"bank_code": "PANIN",
"bank_account_number": "8888888888",
"bank_account_name": "Albert Chen Fadlan",
"description": "Test webhook BD",
"email_to": "disbursement_test_example@xendit.co",
"status": "COMPLETED",
"valid_name": "Albert Chen Fadlan",
"bank_reference": "123456"
}
]
}
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Parameter | Type | Description |
---|---|---|
id | string |
Unique ID of batch disbursement in our system |
created | string |
Timestamp of batch disbursement creation in ISO format |
updated | string |
Timestamp of the latest batch disbursement status change in ISO format |
reference | string |
ID of the batch disbursement in your system, used to reconcile disbursements after they have been completed |
user_id | string |
Your Xendit Business ID |
total_uploaded_count | number |
The count of all disbursements in the batch that you requested |
total_uploaded_amount | number |
Total amount of all disbursements in the batch that you requested |
approved_at | string |
Timestamp of batch disbursement approved in ISO format |
approver_id | string |
User ID of the person who approves the batch disbursement |
status | string |
COMPLETED All disbursements are successfully paid CHECK Some disbursements are successfully paid DELETED Batch disbursement has been deletedFAILED All disbursements are not successfully paid |
total_disbursed_count | number |
The count of all disbursements in the batch that are succesfully paid |
total_disbursed_amount | number |
Total amount of all disbursements in the batch that are succesfully paid |
total_error_count | number |
The count of all disbursements in the batch that are not successfully paid |
total_error_amount | number |
Total amount of all disbursements in the batch that are not successfully paid |
disbursements | array of Disbursement object |
Details of each disbursement in the batch, explained below |
Disbursement
Parameter | Type | Description |
---|---|---|
id | string |
Unique ID of the batch disbursement item in our system |
created | string |
Timestamp of batch disbursement item creation in ISO format |
updated | string |
Timestamp of latest batch disbursement status update in ISO format |
external_id | string |
ID of disbursement from your system |
amount | number |
Amount to disburse |
bank_code | string |
Receiving bank code. See bank codes |
bank_account_number | string |
Receiving bank account number |
bank_account_name | string |
Receiving bank account holder name |
description | string |
Description to accompany the disbursement |
email_to | string |
Email addresses that get notified of disbursement details after the disbursement is completed |
email_cc | string |
Email addresses that get notified as carbon copy receiver of disbursement details after the disbursement is completed |
email_bcc | string |
Email addresses that get notified as blind carbon copy receiver of disbursement details after the disbursement is completed |
status | string |
COMPLETED Disbursement is successfully paid FAILED Disbursement is not successfully paid |
valid_name | string |
Valid receiving account holder name according to receiving bank |
bank_reference | string |
Transaction reference number from the bank |
failure_code | string |
The error code associated with the failure of disbursement |
failure_message | string |
The error message associated with the failure of disbursement |
Get Available Banks
Endpoint: Get Available Disbursement Banks
GET https://api.xendit.co/available_disbursements_banks
Example Get Available Disbursement Banks Request
curl https://api.xendit.co/available_disbursements_banks -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
require 'vendor/autoload.php';
$options['secret_api_key'] = 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==';
$xenditPHPClient = new XenditClient\XenditPHPClient($options);
$response = $xenditPHPClient->getAvailableDisbursementBanks();
print_r($response);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Disbursement } = x;
const disbursementSpecificOptions = {};
const d = new Disbursement(disbursementSpecificOptions);
const resp = await d.getBanks();
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
AvailableBank[] banks = BatchDisbursement.getAvailableBanks();
} catch (XenditException e) {
e.printStackTrace();
}
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Disbursement = xendit_instance.Disbursement
disbursement_banks = Disbursement.get_available_banks()
print(disbursement_banks)
This API endpoint will provide you the current list of banks we support for disbursements. The current list of supported banks is >140 just for Indonesia, including some BPDs and BPRs.
Response Parameters
Get Available Disbursement Banks Response
[
{
"name": "Bank Central Asia (BCA)",
"code": "BCA"
},
{
"name": "Bank Mandiri",
"code": "MANDIRI"
},
{
"name": "Bank Rakyat Indonesia (BRI)",
"code": "BRI"
}
]
Parameter | Type | Description |
---|---|---|
name | string |
Full name of the bank |
code | string |
Code of the bank, relevant during creation of virtual accounts |
Payout Links
Previously called Payouts. Easily send funds to customers with our payouts links UI, allowing them to choose their payout destination.
Create Payout Link
Endpoint: Create Payout Link
POST https://api.xendit.co/payouts
Request Parameters
Example Create Payout Link 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. Minimum:
|
email required |
string |
An email address of the end user you're sending the payout link to. |
Response Parameters
Example Create Payout Link 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 link ID generated by Xendit |
external_idrequired |
string |
The payout link ID in your server, that can be used to reconcile between you and Xendit. Maximum:
|
amountrequired |
integer positive |
Amount to be paid out. Minimum:
|
merchant_nameoptional |
string |
The name of your company or website. |
statusrequired |
string |
PENDING The payout link has successfully been created and is awaiting the end user’s responseVOIDED The payout link has been voided. This issue is raised because the payout link 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. EXPIRED The payout has expired. |
expiration_timestampoptional |
ISO8601 |
An ISO timestamp that the payout link expires. Default is 3 days after creation. Timezone:
|
createdoptional |
ISO8601 |
An ISO timestamp that tracks when the payout link 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 the payout link 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 |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INSUFFICIENT_BALANCE400 |
The balance in your account is insufficient to make the payout in the desired amount. |
DUPLICATE_PAYOUT_ERROR400 |
The payout link with the same external_id has already been made before. |
UNAUTHORIZED_MERCHANT_ERROR403 |
This merchant is not authorized to perform this request. |
Get Payout Link
Endpoint: Get a Payout Link
GET https://api.xendit.co/payouts/:id
Request Parameters
Example Get Payout Link 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 link to retrieve |
Response Parameters
Example Get Payout Link 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 link ID generated by Xendit |
external_idrequired |
string |
The payout link ID in your server, that can be used to reconcile between you and Xendit. Maximum:
|
amountrequired |
integer positive |
Amount to be paid out. Minimum:
|
merchant_nameoptional |
string |
The name of your company or website. |
statusrequired |
string |
PENDING The payout link has successfully been created and is awaiting the end user’s responseVOIDED The payout link has been voided. This issue is raised because the payout link 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. EXPIRED The payout link has expired. |
expiration_timestampoptional |
ISO8601 |
An ISO timestamp that the payout link expires. Default is 3 days after creation.Timezone:
|
createdoptional |
ISO8601 |
An ISO timestamp that tracks when the payout link 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 the payout link 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. |
</tr>
Error Codes
Error Code | Description |
---|---|
PAYOUT_NOT_FOUND_ERROR404 |
The payout was not found in the system. |
UNAUTHORIZED_MERCHANT_ERROR403 |
This merchant is not authorized to perform this request. |
Void a Payout Link
Endpoint: Void a Payout Link
POST https://api.xendit.co/payouts/:id/void
You can cancel a pending payout by voiding it using this endpoint.
Request Parameters
Example Void Payout Link Request
curl https://api.xendit.co/payouts/:id/void -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$id = '00754a09-ad00-4475-b874-1dd97f83fc24';
$voidPayout = \Xendit\Payouts::void($id);
var_dump($voidPayout);
?>
const x = new require('xendit-node')({ secretKey: 'xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==' });
const { Payout } = x;
const payoutSpecificOptions = {};
const p = new Payout(payoutSpecificOptions);
const resp = await p.voidPayout({
id: '67f1b30c-0262-4955-8777-95aa0478c2fc',
});
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
Payout payout = Payout.voidPayout("EXAMPLE_ID");
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
resp, err := payout.Void(&payout.VoidParams{
ID: "00754a09-ad00-4475-b874-1dd97f83fc24",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("voided payout: %+v\n", resp)
from xendit import Xendit
api_key = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
xendit_instance = Xendit(api_key=api_key)
Payout = xendit_instance.Payout
payout = Payout.void(
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 link to retrieve |
Void Payout Link Response
Example Void Payout Link Response
{
"id": "00754a09-ad00-4475-b874-1dd97f83fc24",
"external_id": "ext-121312",
"amount": 20000,
"merchant_name": "First Business",
"status": "VOIDED",
"expiration_timestamp": "2019-12-12T06:45:30.041Z",
"created": "2019-12-09T06:45:28.628Z"
}
Parameter | Type | Description |
---|---|---|
idrequired |
string |
A payout link ID generated by Xendit |
external_idrequired |
string |
The payout link ID in your server, that can be used to reconcile between you and Xendit.Maximum:
|
amountrequired |
integer positive |
Amount to be paid out. Minimum:
|
merchant_nameoptional |
string |
The name of your company or website. |
statusrequired |
string |
PENDING The payout link has successfully been created and is awaiting the end user’s responseVOIDED The payout link has been voided. This issue is raised because the payout link 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. EXPIRED The payout link has expired. |
expiration_timestampoptional |
ISO8601 |
An ISO timestamp that the payout link expires. Default is 3 days after creation.Timezone:
|
createdoptional |
ISO8601 |
An ISO timestamp that tracks when the payout link 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 the payout link 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. |
Void Payout Link Failure Reason
Error Code | Description |
---|---|
CLAIMED_PAYOUT_ERROR400 |
The payout is already claimed. You are stopped from voiding the payout because the payout is already claimed by your customer. |
PAYOUT_NOT_FOUND_ERROR404 |
The payout link was not found in the system. |
UNAUTHORIZED_MERCHANT_ERROR403 |
This merchant is not authorized to perform this request. |
Cross-border Payouts
Xendit's Multi Currency Cross-border Payout (Remittance Payout) services include sending funds to Indonesia and Philippines.
We currently support remittances to various fund transfer channels globally, including to 200+ banks and e-wallets in Indonesia and Philippines.
Learn more about Cross-border Payout here
Cross-border Payout Object
This is a Cross-border Payout object, which will be returned in API response and webhook request.
Example of Cross-border Payout Object
{
"id": "rpo_cde3dcb8-37d7-4ea1-a275-8f54af81feb0",
"created": "2024-05-01T07:15:22Z",
"updated": "2024-05-01T07:15:22Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"destination_currency": "PHP",
"destination_amount": 35,
"sender_customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recipient_customer_id": "cust-f71ffaa8-95a2-47ba-b486-cfe9e2c075d7",
"status": "ACCEPTED",
"description": "This is a sample Cross-border Payout transaction",
"source_of_fund": "OTHER",
"origin_currency": "IDR",
"origin_amount": "10000",
"purpose_code": "OTHER",
"relationship": "CUSTOMER",
"failure_code": "string",
"metadata": {}
}
Parameter | Data Type | Description |
---|---|---|
id required |
string |
Unique Cross-border Payout ID (with prefix rpo_, example: rpo_12345432432131 ) |
created required |
string |
Timestamp when the Cross-border Payout request was made in ISO8601 format. Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
updated required |
string |
Timestamp when the Cross-border Payout request was last updated in ISO8601 format. Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
business_id required |
string |
Merchant Business ID provided by Xendit |
reference_id required |
string |
ID provided by merchant to identify Cross-border Payout request |
destination_currency required |
string |
Currency Code in ISO4217 format. Available Currency: IDR , PHP , SGD , THB , VND |
destination_amount required |
number |
Transfer Amount. Minimum and maximum amount can be referred to Docs |
sender_customer_id required |
string |
The ID of the sender customer (as returned by Xendit’s Create Customer endpoint) The following fields are required in the sender customer object: customer_type and addresses - For INDIVIDUAL customer_type , then the following parameters are also required: given_names , nationality , and date_of_birth in customer_type.individual_detail object - For BUSINESS customer_type , then the following parameters are also required: business_name in customer_type.business_detail object. - For addresses object, the following fields are also required: addresses.country , addresses.city , addresses.street_line1 Reference: Customer Object |
recipient_customer_id required |
string |
The ID of the recipient customer (as returned by Xendit’s Create Customer endpoint) The following fields are required in the recipient customer object: customer_type , addresses , identity_accounts , and one of phone_number or mobile_number (mobile_number is a mandatory field for PH_GCASH channel destination). - For INDIVIDUAL customer_type , then the following parameters are also required: given_names , nationality , and date_of_birth in customer_type.individual_detail object - For BUSINESS customer_type , then the following parameters are also required: business_name in customer_type.business_detail object. - For addresses object, the following fields are also required: addresses.country , addresses.city , addresses.street_line1 - For identity_accounts object, the following fields are also required: type , country , company (put channel code value), and properties Reference: Customer Object |
status required |
string |
Status of the Cross-border Payout. Default is ACCEPTED : Request is being processed and assessed in the risk scoring system. See Cross-border Payout Statuses |
description required |
string |
Description to send with the Cross-border Payout. The recipient may see this e.g., in their bank statement (if supported) or in email receipts we send on your behalf. Alphanumber Min length: 1 character Max length: 100 characters. |
source_of_fund optionalDefault:
|
string | Source of fund. Refer to our list of Source of Funds section |
origin_currency required |
string |
Origin currency of the Cross-border Payout. Cross-border Payout from SGD to IDR will have origin_currency as SGD |
origin_amount required |
number |
Origin amount of the Cross-border Payout. Cross-border Payout from 100 SGD to IDR will have origin_amount as 100 |
purpose_code optionalDefault:
|
string |
Purpose of the Cross-border Payout. Refer to our list of Purpose Codes section |
relationship optionalRequired for |
string |
Relationship between sender and recipient. Refer to our list of Relationships section |
failure_code optional |
string |
Failure Code for failed Cross-border Payout. You can refer the full list in Failure Reason section |
metadata object |
object |
Object of additional information the merchant may use. Users define the JSON properties and values. This will only be used by the merchant and not Xendit |
Create Cross-border Payout
Our Create Remittance Payout APIs allow you to send remittances from your Xendit Account on behalf of a sender to your designated recipient.
Endpoint: Create Cross-border Payout
POST https://api.xendit.co/remittance_payouts
Request Parameters
Example Create Cross-border Payout Request
curl --request POST \
--url https://api.xendit.co/remittance_payouts \
--header 'Authorization: {{base_64_of_your_secret_api_key}}' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'IDEMPOTENCY-KEY: ' \
--data '{
"reference_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"destination_currency": "PHP",
"destination_amount": "35",
"sender_customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recipient_customer_id": "cust-f71ffaa8-95a2-47ba-b486-cfe9e2c075d7",
"origin_currency": "IDR",
"origin_amount": "10000",
"source_of_fund": "OTHER",
"purpose_code": "OTHER",
"relationship": "CUSTOMER",
"description": "This is a sample remittance transaction",
"metadata": {}
}'
Create Cross-border Payout Request
Header Parameter | Type | Description |
---|---|---|
Idempotency-keyrequired |
string |
A unique key to prevent processing duplicate requests. Can be your reference_id or any GUID. Must be unique across development & production environments.
|
Example of Create Cross-border Payout Request
{
"reference_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"destination_currency": "PHP",
"destination_amount": "35",
"sender_customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recipient_customer_id": "cust-f71ffaa8-95a2-47ba-b486-cfe9e2c075d7",
"origin_currency": "IDR",
"origin_amount": "10000",
"source_of_fund": "OTHER",
"purpose_code": "OTHER",
"relationship": "CUSTOMER",
"description": "This is a sample Cross-border Payout transaction",
"metadata": {}
}
Parameter | Data Type | Description |
---|---|---|
reference_id required |
string |
ID provided by merchant to identify Cross-border Payout request |
destination_currency required |
string |
Currency Code in ISO4217 format. Available Currency: IDR , PHP , SGD , THB , VND |
destination_amount required |
number |
Transfer Amount. Minimum and maximum amount can be referred to Docs |
sender_customer_id required |
string |
The ID of the sender customer (as returned by Xendit’s Create Customer endpoint) The following fields are required in the sender customer object: customer_type and addresses - For INDIVIDUAL customer_type , then the following parameters are also required: given_names , nationality , and date_of_birth in customer_type.individual_detail object - For BUSINESS customer_type , then the following parameters are also required: business_name in customer_type.business_detail object. - For addresses object, the following fields are also required: addresses.country , addresses.city , addresses.street_line1 Reference: Customer Object |
recipient_customer_id required |
string |
The ID of the recipient customer (as returned by Xendit’s Create Customer endpoint) The following fields are required in the recipient customer object: customer_type , addresses , identity_accounts , and one of phone_number or mobile_number (mobile_number is a mandatory field for PH_GCASH channel destination). - For INDIVIDUAL customer_type , then the following parameters are also required: given_names , nationality , and date_of_birth in customer_type.individual_detail object - For BUSINESS customer_type , then the following parameters are also required: business_name in customer_type.business_detail object. - For addresses object, the following fields are also required: addresses.country , addresses.city , addresses.street_line1 - For identity_accounts object, the following fields are also required: type , country , company (put channel code value), and properties Reference: Customer Object |
origin_currency required |
string |
Origin currency of the Cross-border Payout. Cross-border Payout from SGD to IDR will have origin_currency as SGD |
origin_amount required |
number |
Origin amount of the Cross-border Payout. Cross-border Payout from 100 SGD to IDR will have origin_amount as 100 |
source_of_fund optionalDefault:
|
string | Source of fund. Refer to our list of Source of Funds section |
purpose_code optionalDefault:
|
string |
Purpose of the Cross-border Payout. Refer to our list of Purpose Codes section |
relationship optionalRequired for |
string |
Relationship between sender and recipient. Refer to our list of Relationships section |
description required |
string |
Description to send with the Cross-border Payout. The recipient may see this e.g., in their bank statement (if supported) or in email receipts we send on your behalf. Alphanumber Min length: 1 character Max length: 100 characters. |
metadata object |
object |
Object of additional information the merchant may use. Users define the JSON properties and values. This will only be used by the merchant and not Xendit |
Response Parameters
Example of Create Cross-border Payout Response
{
"id": "rpo_cde3dcb8-37d7-4ea1-a275-8f54af81feb0",
"created": "2024-05-01T07:15:22Z",
"updated": "2024-05-01T07:15:22Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"destination_currency": "PHP",
"destination_amount": 35,
"sender_customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recipient_customer_id": "cust-f71ffaa8-95a2-47ba-b486-cfe9e2c075d7",
"status": "ACCEPTED",
"description": "This is a sample Cross-border Payout transaction",
"source_of_fund": "OTHER",
"origin_currency": "IDR",
"origin_amount": "10000",
"purpose_code": "OTHER",
"relationship": "CUSTOMER",
"failure_code": "string",
"metadata": {}
}
Returns Cross-border Payout object with HTTP status code 201
Error Codes
Example of Cross-border Payout error
{
"error_code": "IDEMPOTENCY_ERROR",
"message": "Keys for idempotent requests can only be used for the same endpoint they were first used for. Try using a key if you meant to execute a different request."
}
Error Code | Error Message |
---|---|
API_VALIDATION_ERROR 400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation |
INVALID_JSON_FORMAT 400 |
The request body is not a valid JSON format. |
DESTINATION_CURRENCY_NOT_SUPPORTED 400 |
Destination currency is not supported. Check that the currency is supported for your chosen channel before retrying. |
AMOUNT_FORMAT_ERROR 400 |
Given amount should contain less than or equal to 2 decimal places |
MINIMUM_TRANSFER_LIMIT_ERROR 400 |
The transfer amount requested is lower than the prescribed minimum for the recipient bank. Amend the transfer amount before retrying. |
MAXIMUM_TRANSFER_LIMIT_ERROR 400 |
The transfer amount requested is higher than the prescribed maximum for the recipient bank. Amend the transfer amount before retrying. |
AMOUNT_INCREMENT_NOT_SUPPORTED 400 |
Amount is not supported for the chosen channel. Check the Cross-border Payout amount matches the minimum increment for the chosen channel. |
ACCOUNT_BLACKLISTED_ERROR 400 |
The provided recipient bank account is blacklisted. |
PAYMENT_CHANNEL_DETAIL_ERROR 400 |
The provided recipient account type is invalid. Please use the valid values (BANK_ACCOUNT or EWALLET ). |
DUPLICATE_ERROR 400 |
A payout with this idempotency key already exists. If you meant to execute a different request, please use another idempotency key. |
CUSTOMER_DATA_NOT_FOUND 404 |
Could not find any customer object with given sender_customer_id or recipient_customer_id . Try again using a valid Customer ID. |
IDEMPOTENCY_ERROR 409 |
Keys for idempotent requests can only be used for the same endpoint they were first used for. Try using a key if you meant to execute a different request. |
STILL_PROCESSING_ERROR 409 |
Similar request with similar idempotency key is still processing. |
REQUEST_FORBIDDEN403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. Learn more <a href="https://docs.xendit.co/ |
SERVER_ERROR500 |
Error connecting to our server. Use Get Cross-border Payout API to check whether the payout has already been created. Retry safely using IDEMPOTENCY-KEY header when available |
Get Cross-border Payout by ID
Endpoint: Get Cross-border Payout by ID
GET https://api.xendit.co/remittance_payouts/:cross_border_payout_id
This endpoint queries the current status of a Cross-border payout. This is often used for checking the status of a transaction.
Request Parameters
Path Parameter | Type | Description |
---|---|---|
cross_border_payout_idrequired |
string |
ID of the Cross-border Payout |
Response Parameters
Example Get Cross-border Payout by ID Response
{
"id": "rpo_cde3dcb8-37d7-4ea1-a275-8f54af81feb0",
"created": "2024-05-01T07:15:22Z",
"updated": "2024-05-01T07:15:22Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"destination_currency": "PHP",
"destination_amount": 35,
"sender_customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recipient_customer_id": "cust-f71ffaa8-95a2-47ba-b486-cfe9e2c075d7",
"status": "FAILED",
"description": "This is a sample Cross-border Payout transaction",
"source_of_fund": "OTHER",
"origin_currency": "IDR",
"origin_amount": "10000",
"purpose_code": "OTHER",
"relationship": "CUSTOMER",
"failure_code": "INVALID_DESTINATION",
"metadata": {}
}
Returns Cross-border Payout object with HTTP status code 200
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 |
REMITTANCE_PAYOUT404 |
Could not find Cross-border Payout. Try again with a valid ID. |
Cancel Cross-border Payout
Endpoint: Cancel Cross-border Payout
POST https://api.xendit.co/remittance_payouts/:cross_border_payout_id/cancel
Cross-border Payout can only be cancelled while in the following status :
ACCEPTED
PENDING_COMPLIANCE_ASSESSMENT
Request Parameters
Path Parameter | Type | Description |
---|---|---|
cross_border_payout_idrequired |
string |
ID of the Cross-border Payout |
Response Parameters
Example Cancel Cross-border Payout by ID Response
{
"id": "rpo_cde3dcb8-37d7-4ea1-a275-8f54af81feb0",
"created": "2024-05-01T07:15:22Z",
"updated": "2024-05-01T07:15:22Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"destination_currency": "PHP",
"destination_amount": 35,
"sender_customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recipient_customer_id": "cust-f71ffaa8-95a2-47ba-b486-cfe9e2c075d7",
"status": "CANCELLED",
"description": "This is a sample Cross-border Payout transaction",
"source_of_fund": "OTHER",
"origin_currency": "IDR",
"origin_amount": "10000",
"purpose_code": "OTHER",
"relationship": "CUSTOMER",
"failure_code": null,
"metadata": {}
}
Returns Cross-border Payout object with HTTP status code 200
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 |
CANCELLATION_NOT_ALLOWED404 |
Cross-border Payout cannot be canceled because it has already been processed by Xendit. |
REMITTANCE_PAYOUT404 |
Could not find Cross-border Payout. Try again with a valid ID. |
SERVER_ERROR500 |
Error connecting to our server. Use Get Cross-border Payout API to check whether the payout has already been created. Retry safely using IDEMPOTENCY-KEY header when available |
Webhooks for Cross-border Payout
Endpoint: Cross-border Payout Webhook
POST https://yourcompany.com/cross_border_payout_webhook_url
Xendit notifies your system upon failed and successful disbursements via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
We send a webhook when there’s a change of your Cross-border Payout status to:
- Compliance Verification
- Compliance Rejected
- Cross-border Payout Failed
- Cross-border Payout Succeeded
- Cross-border Payout Ready
- Cross-border Payout Updated
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Example of Pending Compliance Assessment Event
{
"event": "remittance_payout.pending_compliance_assessment",
"id": "rpo_cde3dcb8-37d7-4ea1-a275-8f54af81feb0",
"created": "2024-05-01T07:15:22Z",
"updated": "2024-05-01T07:15:22Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"destination_currency": "PHP",
"destination_amount": 35,
"sender_customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recipient_customer_id": "cust-f71ffaa8-95a2-47ba-b486-cfe9e2c075d7",
"status": "PENDING_COMPLIANCE_ASSESSMENT",
"description": "This is a sample Cross-border Payout transaction",
"source_of_fund": "OTHER",
"origin_currency": "IDR",
"origin_amount": "10000",
"purpose_code": "OTHER",
"relationship": "CUSTOMER",
"metadata": {}
}
Example of Cross-Border Payout Succeeded Event
{
"event": "remittance_payout.succeeded",
"id": "rpo_cde3dcb8-37d7-4ea1-a275-8f54af81feb0",
"created": "2024-05-01T07:15:22Z",
"updated": "2024-05-01T07:15:22Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"destination_currency": "PHP",
"destination_amount": 35,
"sender_customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recipient_customer_id": "cust-f71ffaa8-95a2-47ba-b486-cfe9e2c075d7",
"status": "SUCCEEDED",
"description": "This is a sample Cross-border Payout transaction",
"source_of_fund": "OTHER",
"origin_currency": "IDR",
"origin_amount": "10000",
"purpose_code": "OTHER",
"relationship": "CUSTOMER",
"metadata": {}
}
Example of Cross-Border Payout Failed Event
{
"event": "remittance_payout.succeeded",
"id": "rpo_cde3dcb8-37d7-4ea1-a275-8f54af81feb0",
"created": "2024-05-01T07:15:22Z",
"updated": "2024-05-01T07:15:22Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"reference_id": "49d056bd-21e5-4997-85f2-2127544c2196",
"destination_currency": "PHP",
"destination_amount": 35,
"sender_customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recipient_customer_id": "cust-f71ffaa8-95a2-47ba-b486-cfe9e2c075d7",
"status": "FAILED",
"description": "This is a sample Cross-border Payout transaction",
"source_of_fund": "OTHER",
"origin_currency": "IDR",
"origin_amount": "10000",
"purpose_code": "OTHER",
"relationship": "CUSTOMER",
"failure_code": "INVALID_DESTINATION",
"metadata": {}
}
Pending Compliance Assessment Event
We will send a webhook event with Cross-border Payout Object and additional field(s) as follow:
Body Parameter | Type | Description |
---|---|---|
event | string |
Type of the event. Event value: remittance_payout.pending_compliance_assessment |
Compliance Rejected Event
We will send a webhook event with Cross-border Payout Object and additional field(s) as follow:
Body Parameter | Type | Description |
---|---|---|
event | string |
Type of the event. Event value: remittance_payout.compliance_rejected |
Cross-border Payout Failed
We will send a webhook event with Cross-border Payout Object and additional field(s) as follow:
Body Parameter | Type | Description |
---|---|---|
event | string |
Type of the event. Event value: remittance_payout.failed |
failure_code | string |
Failure code for the failed Cross-border Payout. Please find the detail and description in Failure Code section |
Cross-border Payout Succeeded
We will send a webhook event with Cross-border Payout Object and additional field(s) as follow:
Body Parameter | Type | Description |
---|---|---|
event | string |
Type of the event. Event value: remittance_payout.succeeded |
Cross-border Payout Ready
We will send a webhook event with Cross-border Payout Object and additional field(s) as follow:
Body Parameter | Type | Description |
---|---|---|
event | string |
Type of the event. Event value: remittance_payout.ready |
disbursement_code | string |
Code to be presented by the beneficiary for cash pick-up. Please share this with the beneficiary. Example: XENDIT-12341 Characters: Special and alphanumeric Minimum length: 1 character Maximum length: 100 characters |
Cross-border Payout Updated
We will send a webhook event with Cross-border Payout Object and additional field(s) as follow:
Body Parameter | Type | Description |
---|---|---|
event | string |
Type of the event. Event value: remittance_payout.locked or remittance_payout.expired |
Statuses for Cross-border Payouts
Status | Description |
---|---|
ACCEPTED | Request is being processed and assessed in the risk scoring system |
PENDING_COMPLIANCE_ASSESSMENT | Request is considered medium or high risk, and is being reviewed by our compliance team. Our team will contact you via email for extra information for enhanced due diligence |
REQUESTED | Request has been approved and the Cross-border Payout is queued to be transferred to the recipient |
COMPLIANCE_REJECTED | Request is rejected by compliance |
READY | The disbursement has been sent to the channel. For cash Cross-border Payout Only: funds are ready for pick-up |
LOCKED | For cash Cross-border Payout only. Cash pick-up in progress. Cancellation is not allowed. |
EXPIRED | For cash Cross-border Payout only. Disbursement has expired. |
SUCCEEDED | The sending bank has confirmed transmission of the Cross-border Payout |
FAILED | Cross-border Payout could not be transferred to the recipient due to certain errors. See Cross-border Payouts Failure Codes |
REFUNDED | Only valid for SKN/RTGS and cash cahnnel use case |
CANCELLED | Cancel transactions |
Failure Codes for Cross-border Payouts
Failure Code | Description | Should you retry? |
---|---|---|
INSUFFICIENT_BALANCE | Client has insufficient balance for the Cross-border Payout amount. | Yes, retry the Cross-border Payout after ensuring that you have sufficient balance in your account. |
REJECTED_BY_CHANNEL | Cross-border Payout failed due to error from destination channel. This is usually because of network issues associated with the destination bank or issues crediting funds into the destination bank account | Yes, retry the Cross-border Payout after validating that the destination bank account number exists. |
TEMPORARY_TRANSFER_ERROR | Cross-border Payout failed due to a known temporary internal error | Yes, retry the Cross-border Payout in 1-3 hours. |
INVALID_DESTINATION | Destination account does not exist/is invalid. | You are unlikely to succeed if you retry the same Cross-border Payout request. Please confirm with the beneficiary whether the destination account is correct |
TRANSFER_ERROR | We’ve encountered a fatal error while processing this Cross-border Payout. Normally, this means that certain fields in your requests are invalid. | It is unlikely that the same request will succeed if you retry |
UNKNOWN_BANK_NETWORK_ERROR | The bank has delivered an error they have not documented. By definition, this means the bank does not known the issue | Unfortunately, we are unable to predict whether the disbursement will succeed should you retry the same Cross-border Payout request.You may however choose to retry the same Cross-border Payout request at least one hour after receiving our callback at your own discretion. |
Purpose Codes for Cross-border Payouts
Key | Description |
---|---|
SELF | Transfer to own account |
FAMILY | Family Maintenance |
EDUCATION | Education-related student expenses |
MEDICAL | Medical Treatment |
HOTEL | Hotel Accomodation |
TRAVEL | Travel |
UTILITIES | Utility Bills |
LOAN_REPAYMENT | Repayment of Loans |
TAX_PAYMENT | Tax Payment |
RESIDENCE_PURCHASE | Purchase of Residential Property |
RESIDENCE_RENT | Payment of Property Rental |
INSURANCE | Insurance |
MUTUAL_FUND | Mutual Fund Investment |
SHARES_INVESTMENT | Investment in Shares |
DONATIONS | Donations |
ADVERTISING | Advertising & Public relations-related expenses |
ROYALTY_FEES | Royalty fees, trademark fees, patent fees, and copyright fees |
BROKER_FEES | Fees for brokers, front end fee, commitment fee, guarantee fee and custodian fee |
ADVISORS | Fees for advisors, technical assistance, and academic purpose, including remuneration for specialists |
OFFICE | Representative office expenses |
CONSTRUCTION | Construction costs / expenses |
SHIPMENT | Transportation fees for goods |
EXPORT | For payment of exported goods |
DELIVERY | Delivery fees for goods |
TRADES | General Goods Trades - Offline trade |
SALARY | Salary |
REFUND | Refund |
LOAN_REPAYMENT | Loan |
OTHER | Other |
Source of Funds for Cross-border Payouts
Key | Description |
---|---|
INVESTMENT | Bonds, fixed deposits, preference shares, business ownership/equity or property ownership |
PERSONAL_SAVINGS | Funds kept in an account in a bank or a similar organization |
BUSINESS_REVENUE | Income from a business or a company |
LEGACY | Inherited money from a will |
BUSINESS_ARRANGEMENT | Any understanding, procedure, course of dealing, or arrangement between a creditor and a seller |
LOAN | A sum of money that is borrowed |
SALARY | A fixed regular payment made by an employer |
OTHER | Other |
Relationships for Cross-border Payouts
Key | Description |
---|---|
BRANCH_REPRESENTATIVE_OFFICE | Branch/Representative Office |
BUSINESS_PARTNER | Business Partner |
CHILDREN | Children |
CREDITOR | Creditor |
CUSTOMER | Customer |
DEBTOR | Debtor |
EMPLOYEE | Employee |
EX_SPOUSE | Ex-spouse |
FRANCHISEE_FRANCHISOR | Franchisee/Franchisor |
GRANDPARENTS | Grandparents |
HOLDING_COMPANY | Holding Company |
MAID | Maid |
OWNSELF | Ownself |
PARENTS | Parents |
RELATIVE | Relative (uncle/aunt/cousin) |
SIBLING | Sibling / Brother / Sister |
SPOUSE | Spouse |
SUBSIDIARY_COMPANY | Subsdiary company |
SUPPLIER | Supplier |
FRIEND | Friend |
GOVERNMENT_BODY | Government Body |
EDUCATION_INSTITUTION | Education Instituion |
NON_GOVERNMENT_BODY | Non-government Body |
OTHER | Other |
Test Scenarios for Cross-border Payout
Positive Scenarios
Scenario | Criteria | Expected Result |
---|---|---|
Successful Cross-border Payout to Indonesia Channel | First, create new customers representing the sender and recipient. Use the following values for the recipient customer: Option 1 - identity_accounts.company : ID_PANIN - identity_accounts.properties.account_holder_name : Maria Wenger - identity_accounts.properties.account_number : 818181 Option 2 - identity_accounts.company : ID_OVO - identity_accounts.properties.account_holder_name : Ari Fernandes - identity_accounts.properties.account_number : 081234567890 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will complete Cross-border Payout and send a callback to your callback URL with status: SUCCEEDED |
Successful Cross-border Payout to Philippine Channel | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : PH_BDO - identity_accounts.properties.account_holder_name : Kal Stones - identity_accounts.properties.account_number : 828282 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will complete Cross-border Payout and send a callback to your callback URL with status: SUCCEEDED |
Successful Cross-border Payout to Singapore Channel | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : SG_BOC - identity_accounts.properties.account_holder_name : Ruth Langmore - identity_accounts.properties.account_number : 838383 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will complete Cross-border Payout and send a callback to your callback URL with status: SUCCEEDED |
Successful Cross-border Payout to Thailand Channel | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : TH_SCB - identity_accounts.properties.account_holder_name : Justin Morph - identity_accounts.properties.account_number : 267267 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will complete Cross-border Payout and send a callback to your callback URL with status: SUCCEEDED |
Cross-border Payout has been assessed to be medium or high risk and requires compliance verification. Cross-border Payout is eventually approved by compliance and succeeds | First, create customers representing the sender and recipient. Use the following values for the recipient customer: Option 1 - identity_accounts.company : ID_MANDIRI - identity_accounts.properties.account_holder_name : Evan Dimas - identity_accounts.properties.account_number : 808080 Option 2 - identity_accounts.company : {{anything}} - identity_accounts.properties.account_holder_name : {{anything}} - identity_accounts.properties.account_number : 87778798 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with status: PENDING_COMPLIANCE_ASSESSMENT . Then, will send a second callback to your callback URL with status: SUCCEEDED |
Cross-border Payout transaction is stuck in compliance assessment | First, create customers representing the sender and recipient. Use the following values for the recipient customer: Option 1 - identity_accounts.company : ID_MANDIRI - identity_accounts.properties.account_holder_name : Shawn - identity_accounts.properties.account_number : 898989 Option 2 - identity_accounts.company : {{anything}} - identity_accounts.properties.account_holder_name : {{anything}} - identity_accounts.properties.account_number : 4455445544 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with status: PENDING_COMPLIANCE_ASSESSMENT |
Successful Cross-border Payout to Indonesia Cash Channel | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : ID_ALFAMART - identity_accounts.properties.payment_code : 898900 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with disbursement_code and status: READY . Then, will send a callback to your callback URL with status: LOCKED . Then,will complete Cross-border Payout and send a callback to your callback URL with status: SUCCEEDED |
Simulate an online Cross-border Payout cancellation flow | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : ID_MANDIRI - identity_accounts.properties.account_holder_name : Gustafo Vring - identity_accounts.properties.account_number : 10101010 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Cross-border Payout status will remain on ACCEPTED . You can then try a Cancel Cross-border Payout request |
Cash Cross-border Payout ready to pick up | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : ID_ALFAMART - identity_accounts.properties.payment_code : 898911 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with disbursement_code and status: READY . Cross-border Payout status will remain on READY. |
Simulate a cash Cross-border Payout cancellation flow | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : ID_ALFAMART - identity_accounts.properties.payment_code : 898911 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Cross-border Payout status will remain on READY. You can then try a Cancel Cross-border Payout request |
Successful Cross-border Payout to Singapore Channel | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : SG_DBS - identity_accounts.properties.payment_code : 818181 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will complete Cross-border Payout and send a callback to your callback URL with status: SUCCEEDED |
Negative Scenarios
Scenario | Criteria | Expected Result |
---|---|---|
Cross-border Payout has been assessed to be medium or high risk and requires compliance verification. Cross-border Payout is eventually rejected by compliance | First, create customers representing the sender and recipient. Use the following values for the recipient customer: Option 1 - identity_accounts.company : ID_MANDIRI - identity_accounts.properties.account_holder_name : Cynthia Rodriguez - identity_accounts.properties.account_number : 909090 Option 2 - identity_accounts.company : {{anything}} - identity_accounts.properties.account_holder_name : {{anything}} - identity_accounts.properties.account_number : 987654321 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with status: PENDING_COMPLIANCE_ASSESSMENT . Then, we will send a second callback to your callback URL with status: COMPLIANCE_REJECTED |
Destination account does not exist/is invalid. | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : ID_MANDIRI - identity_accounts.properties.account_holder_name : Teo Alcantara - identity_accounts.properties.account_number : 4567890 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with status: FAILED and failure_code: INVALID_DESTINATION |
Transaction has been rejected by the destination channel without a clear error reason | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : ID_CIMB - identity_accounts.properties.account_holder_name : Ichwan De Bryune - identity_accounts.properties.account_number : 8787878 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with status: FAILED and failure_code: REJECTED_BY_CHANNEL |
Transaction failed because of a known temporary issue | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.channel_code : PH_OMNI - identity_accounts.properties.account_holder_name : Ayrton Da Silva - identity_accounts.properties.account_number : 868686 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with status: FAILED and failure_code: TEMPORARY_TRANSFER_ERROR |
Insufficient Balance | First, create customers representing the sender and recipient (which field detail is different with above specifications). Then, Create Cross-border Payout request with amount greater than the balance you have |
Will send a callback to your callback URL with status: FAILED and failure_code: INSUFFICIENT_BALANCE |
Cash Cross-border Payout expired | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : ID_ALFAMART - properties.payment_code : 898922 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with disbursement_code and status: READY . Then,will send a callback to your callback URL with status: EXPIRED |
Singapore bank networks have rejected the transaction due to maintenance or unknown reason | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.channel_code : SG_DBS - properties.account_number : 999999 |
Payout will be FAILED with failure_code = REJECTED_BY_CHANNEL |
Destination account does not exist/is invalid for Singapore channel | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : SG_BOC - properties.account_holder_name : Darlene Snell - properties.account_number : 733810 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with status: FAILED and failure_code: INVALID_DESTINATION |
Destination account does not exist/is invalid for Thailand channel | First, create customers representing the sender and recipient. Use the following values for the recipient customer: - identity_accounts.company : TH_SCB - properties.account_holder_name : Harry Johnson - properties.account_number : 588372 Then create a Cross-border Payout using required params (refer to Create Cross-border Payout) and the above sender and recipient customer ids |
Will send a callback to your callback URL with status: FAILED and failure_code: INVALID_DESTINATION |
Invoices
Xendit Hosted Checkout (Invoice) is a free pre-built payment page that provides a seamless payment experience to you and your customers. Xendit Checkout can be paid via debit/credit cards, banks, retail outlets, eWallets and direct debit. It automatically detects payments for real-time status updates on your dashboard.
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 -H 'Content-Type: application/json' -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d '{
"external_id": "payment-link-example",
"amount": 510000,
"description": "Invoice Demo #123",
"invoice_duration": 86400,
"customer": {
"given_names": "John",
"surname": "Doe",
"email": "johndoe@example.com",
"mobile_number": "+6287774441111",
"addresses": [
{
"city": "Jakarta Selatan",
"country": "Indonesia",
"postal_code": "12345",
"state": "Daerah Khusus Ibukota Jakarta",
"street_line1": "Jalan Makan",
"street_line2": "Kecamatan Kebayoran Baru"
}
]
},
"customer_notification_preference": {
"invoice_created": [
"whatsapp",
"email",
"viber"
],
"invoice_reminder": [
"whatsapp",
"email",
"viber"
],
"invoice_paid": [
"whatsapp",
"email",
"viber"
]
},
"success_redirect_url": "https://www.google.com",
"failure_redirect_url": "https://www.google.com",
"currency": "IDR",
"items": [
{
"name": "Air Conditioner",
"quantity": 1,
"price": 100000,
"category": "Electronic",
"url": "https://yourcompany.com/example_item"
}
],
"fees": [
{
"type": "ADMIN",
"value": 5000
}
],
"payment_methods": [
"CREDIT_CARD"
],
"channel_properties": {
"cards": {
"allowed_bins": [
"400000",
"52000000"
],
"installment_configuration": {
"allow_installment": true,
"allow_full_payment": false,
"allowed_terms": [
{
"issuer": "BCA",
"terms": [
3,
6,
12
]
},
{
"issuer": "BNI",
"terms": [
3,
6
]
},
{
"issuer": "MANDIRI",
"terms": [
6
]
}
]
}
}
},
"metadata": {
"store_branch": "Jakarta"
}
}'
<?php
use Xendit\Xendit;
require 'vendor/autoload.php';
Xendit::setApiKey('xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==');
$params = [
'external_id' => 'demo_1475801962607',
'amount' => 510000,
'description' => 'Invoice Demo #123',
'invoice_duration' => 86400,
'customer' => [
'given_names' => 'John',
'surname' => 'Doe',
'email' => 'johndoe@example.com',
'mobile_number' => '+6287774441111',
'addresses' => [
[
'city' => 'Jakarta Selatan',
'country' => 'Indonesia',
'postal_code' => '12345',
'state' => 'Daerah Khusus Ibukota Jakarta',
'street_line1' => 'Jalan Makan',
'street_line2' => 'Kecamatan Kebayoran Baru'
]
]
],
'customer_notification_preference' => [
'invoice_created' => [
'whatsapp',
'email',
'viber'
],
'invoice_reminder' => [
'whatsapp',
'email',
'viber'
],
'invoice_paid' => [
'whatsapp',
'email',
'viber'
]
],
'success_redirect_url' => 'https=>//www.google.com',
'failure_redirect_url' => 'https=>//www.google.com',
'currency' => 'IDR',
'items' => [
[
'name' => 'Air Conditioner',
'quantity' => 1,
'price' => 510000,
'category' => 'Electronic',
'url' => 'https=>//yourcompany.com/example_item'
]
],
'fees' => [
[
'type' => 'ADMIN',
'value' => 5000
]
],
'payment_methods' => ['CREDIT_CARD'],
'channel_properties' => [
'cards' => [
'allowed_bins' => [
'400000',
'52000000'
],
'installment_configuration' => [
'allow_installment' => true,
'allow_full_payment' => false,
'allowed_terms' => [
[
'issuer' => 'BCA'
'terms' => [3,6,12]
],
[
'issuer' => 'BNI'
'terms' => [3,6]
],
[
'issuer' => 'MANDIRI'
'terms' => [6]
]
]
]
]
],
'metadata' => [
'store_branch' => 'Jakarta'
]
];
$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(
'external_id': 'payment-link-example',
'amount': 510000,
'description': 'Invoice Demo #123',
'invoice_duration': 86400,
'customer': {
'given_names': 'John',
'surname': 'Doe',
'email': 'johndoe@example.com',
'mobile_number': '+6287774441111',
'addresses': [
{
'city': 'Jakarta Selatan',
'country': 'Indonesia',
'postal_code': '12345',
'state': 'Daerah Khusus Ibukota Jakarta',
'street_line1': 'Jalan Makan',
'street_line2': 'Kecamatan Kebayoran Baru'
}
]
},
'customer_notification_preference': {
'invoice_created': [
'whatsapp',
'email',
'viber'
],
'invoice_reminder': [
'whatsapp',
'email',
'viber'
],
'invoice_paid': [
'whatsapp',
'email',
'viber'
]
},
'success_redirect_url': 'https://www.google.com',
'failure_redirect_url': 'https://www.google.com',
'currency': 'IDR',
'items': [
{
'name': 'Air Conditioner',
'quantity': 1,
'price': 510000,
'category': 'Electronic',
'url': 'https://yourcompany.com/example_item'
}
],
'fees': [
{
'type': 'ADMIN',
'value': 5000
}
],
'payment_methods': ['CREDIT_CARD'],
'channel_properties': {
'cards': {
'allowed_bins': [
'400000',
'52000000'
],
'installment_configuration': {
'allow_installment': true,
'allow_full_payment': false,
'allowed_terms': [
{
'issuer': 'BCA',
'terms': [3,6,12]
},
{
'issuer': 'BNI',
'terms': [3,6]
},
{
'issuer': 'MANDIRI',
'terms': [6]
}
]
}
}
},
"metadata": {
"store_branch": "Jakarta"
}
);
console.log(resp);
Xendit.apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
try {
ArrayList<Map<String, Object>> customerAddresses = new ArrayList<Map<String, Object>>();
Map<String, Object> customerAddress1 = new HashMap<>();
customerAddress1.put("city", "Jakarta Selatan");
customerAddress1.put("state", "Daerah Khusus Ibukota Jakarta");
customerAddress1.put("country", "Indonesia");
customerAddress1.put("postal_code", "12345");
customerAddress1.put("street_line1", "Jalan Makan");
customerAddress1.put("street_line2", "Kecamatan Kebayoran Baru");
customerAddresses.add(customerAddress1);
Map<String, Object> customerAddress2 = new HashMap<>();
customerAddress2.put("city", "Jakarta Selatan");
customerAddress2.put("state", "Daerah Khusus Ibukota Jakarta");
customerAddress2.put("country", "Indonesia");
customerAddress2.put("postal_code", "12345");
customerAddress2.put("street_line1", "Jalan Satu");
customerAddress2.put("street_line2", "Kecamatan Kebayoran Baru");
Map<String, Object> customerObject = new HashMap<>();
customerObject.put("given_names", "John");
customerObject.put("surname", "Doe");
customerObject.put("email", "johndoe@example.com");
customerObject.put("mobile_number", "+6287774441111");
customerObject.put("addresses", customerAddresses);
Map<String, Object> customerNotificationPreference = new HashMap<>();
customerNotificationPreference.put("invoice_created", notifications);
customerNotificationPreference.put("invoice_reminder", notifications);
customerNotificationPreference.put("invoice_paid", notifications);
ArrayList<Map<String, Object>> items = new ArrayList<Map<String, Object>>();
Map<String, Object> item1 = new HashMap<>();
item1.put("name": "Air Conditioner");
item1.put("quantity": 1);
item1.put("price": 510000);
item1.put("category": "Electronic");
item1.put("url": "https://yourcompany.com/example_item");
items.add(item1);
ArrayList<Map<String, Object>> fees = new ArrayList<Map<String, Object>>();
Map<String, Object> fee1 = new HashMap<>();
fees.add(fee1);
Map<String, Object> params = new HashMap<>();
params.put("external_id", "demo_1475801962607");
params.put("amount", 50000);
params.put("description", "Invoice Demo #123");
params.put("invoice_duration", 86400);
params.put("customer", customerObject);
params.put("customer_notification_preference", customerNotificationPreference);
params.put("success_redirect_url", "https://www.google.com");
params.put("failure_redirect_url", "https://www.google.com");
params.put("currency", "IDR");
params.put("items", items);
params.put("fees", fees);
Invoice invoice = Invoice.create(params);
} catch (XenditException e) {
e.printStackTrace();
}
xendit.Opt.SecretKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw=="
customerAddress := xendit.CustomerAddress{
Country: "Indonesia",
StreetLine1: "Jalan Makan",
StreetLine2: "Kecamatan Kebayoran Baru",
City: "Jakarta Selatan",
State: "Daerah Khusus Ibukota Jakarta",
PostalCode: "12345",
}
customer := xendit.Customer{
GivenNames: "John",
Surname: "Doe",
Email: "johndoe@example.com",
MobileNumber: "+6287774441111"
Addresses: []xendit.CustomerAddress{customerAddress},
}
item := xendit.Item{
Name: "Air Conditioner",
Quantity: 1,
Price: 510000,
Category: "Electronic",
Url: "https://yourcompany.com/example_item"
}
items := xendit.Items{
item: []xendit.item{item}
}
fee := xendit.fee{
Type: "ADMIN",
Value: 5000,
}
fees := xendit.Fees{
fee: []xendit.fee{fee}
}
NotificationType := [3]string{"whatsapp", "email"}
customerNotificationPreference := xendit.CustomerNotificationPreference{
InvoiceCreated: NotificationType,
InvoiceReminder: NotificationType,
InvoicePaid: NotificationType,
}
data := invoice.CreateParams{
ExternalID: "demo_1475801962607",
Amount: 50000,
Description: "Invoice Demo #123",
InvoiceDuration: 86400,
Customer: customer,
CustomerNotificationPreference: customerNotificationPreference,
SuccessRedirectUrl: "https://www.google.com",
FailureRedirectUrl: "https://www.google.com",
Currency: "IDR",
Items: items,
Fees: fees
}
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
addresses = []
address = {
city: "Jakarta Selatan",
country: "Indonesia",
postal_code: "12345",
state: "Daerah Khusus Ibukota Jakarta",
street_line1: "Jalan Makan",
street_line2: "Kecamatan Kebayoran Baru"
}
addresses.append(address)
customer = {
given_names: "John",
surname: "Doe",
email: "johndoe@example.com",
mobile_number: "+6287774441111",
address: addresses
}
NotificationType = {
"whatsapp",
"email",
"viber"
}
customerNotificationPreference = {
invoice_created: NotificationType
invoice_reminder: NotificationType
invoice_paid: NotificationType
}
items = []
item = {
name: "Phone Case",
price: 510000,
quantity: 1
category: "Electronic",
url: "https://yourcompany.com/example_item"
}
items.append(item)
fees = []
fee = {
Type: "ADMIN",
Value: 5000,
}
fees.append(fee)
allowedTerms = []
allowedTerm = {
issuer: 'BNI',
terms: [3,6,12]
}
allowedTerms.append(allowedTerm)
installmentConfiguration = {
allow_installment: true,
allow_full_payment: false,
allowed_terms: allowedTerms
}
cardChannelProperties = {
allowed_bins: ['400000', '520000'],
installment_configuration: installmentConfiguration
}
paymentMethods = ["CREDIT_CARD"]
channelProperties = {
card: cardChannelProperties
}
invoice = Invoice.create(
external_id = "invoice-1593684000",
amount = 20000,
description =" Invoice Demo #123",
invoice_duration = 86400,
customer = customer,
customer_notification_preference = customerNotificationPreference,
SuccessRedirectUrl = "https://www.google.com",
FailureRedirectUrl = "https://www.google.com"
Currency = "IDR",
items = items,
fees = fees,
payment_methods = paymentMethods,
channel_properties = channelProperties
)
print(invoice)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
InvoiceClient invoice = xendit.Invoice;
Address addresses = new Address
{
Country = Country.Indonesia,
StreetLine1 = "Jalan Makan",
StreetLine2 = "Kecamatan Kebayoran Baru",
State = "Daerah Khusus Ibukota Jakarta",
City = "Jakarta Selatan",
Province = "Daerah Khusus Ibukota Jakarta",
PostalCode = "12345",
};
CustomerResponse customer = new CustomerResponse
{
GivenNames = "John",
Surname = "Doen",
Email = "johndoe@example.com",
MobileNumber = "+6287774441111",
Addresses = new Address[] { addresses },
};
NotificationPreference preference = new NotificationPreference
{
InvoicePaid = new NotificationType[] { NotificationType.Email, NotificationType.Whatapp }
InvoiceCreated = new NotificationType[] { NotificationType.Email, NotificationType.Whatapp }
InvoiceReminder = new NotificationType[] { NotificationType.Email, NotificationType.Whatapp }
};
ItemInvoice item = new ItemInvoice
{
Name = "shoes",
Quantity = 1,
Price = 100,
Category = "Electronic",
Url = "https://yourcompany.com/example_item"
};
FeeInvoice fee = new FeeInvoice
{
Type = "ADMIN",
Value = 200,
};
InvoiceParameter parameter = new InvoiceParameter
{
ExternalId = "external-id",
Amount = 1000,
Description = "Invoice Demo #123",
InvoiceDuration = 86400,
Customer = customer,
NotificationPreference = preference,
SuccessRedirectUrl = "https://www.google.com",
FailureRedirectUrl = "https://www.google.com"
Currency = Currency.IDR,
Items = new ItemInvoice[] { item },
Fees = new FeeInvoice[] { fee },
};
InvoiceResponse invoiceResponse = await invoice.Create(parameter);
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-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this card charge in order to split and route payments to multiple accounts. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.This header is only used if you have access to xenPlatform. See xenPlatform for more information. |
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
external_idrequired |
string |
ID of your choice (typically the unique identifier of an invoice in your system). Min character: 1 Max characters: 255 characters |
||||||||||||||||||||||||
amount required |
number |
Amount on the invoice. Min and max amounts are stated here. The amount should be inclusive of any fees and or items that you may choose to include. If there is a difference between this amount and the sum of the price in the items parameters and or fees parameter, Xendit will refer to this amount parameter to create invoice. Do take note: if the currency or default currency is IDR and the amount includes decimals (e.g IDR 4550.50), the amount will be truncated to IDR 4550. |
||||||||||||||||||||||||
descriptionoptional |
string |
Description of invoice - you can use this field to list what items are being paid for, or anything else of your choice that describes the function of the invoice. Min character: 1 Max characters: unlimited |
||||||||||||||||||||||||
customeroptional |
object |
Object containing your end customer’s details. Please always include your customer’s email & mobile number if you wish to send email/WhatsApp notifications to them. customer child parameters
|
||||||||||||||||||||||||
customer_notification_preference optional |
object |
Object containing notification preferences for this invoice. If you wish to send notifications and reminders to your end customer, please populate the values in this object. You can also configure your notifications in your Invoice Settings (in your Xendit Dashboard). If you don’t set notification preferences via API, we will refer to the configurations in your Invoice Settings. customer_notification_preference child parameters
|
||||||||||||||||||||||||
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). Min number: 1 second Max number: 31536000 seconds (1 year) |
||||||||||||||||||||||||
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 . Min character: 1 Max characters: 255 characters |
||||||||||||||||||||||||
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 . Min character: 1 Max characters: 255 characters |
||||||||||||||||||||||||
payment_methods optional |
array of strings |
Specify the payment channels that you wish to be available on your Invoice / Checkout UI. Leave this field empty if you would like all payment channels to be available on this particular invoice, or if you want to use the defaults set in your Xendit Dashboard Settings. Possible values for Indonesia: ["CREDIT_CARD", "BCA", "BNI", BSI, "BRI", "MANDIRI", "PERMATA", "SAHABAT_SAMPOERNA", "BNC", "ALFAMART", "INDOMARET", "OVO", "DANA", "SHOPEEPAY", "LINKAJA", "JENIUSPAY", "DD_BRI", "DD_BCA_KLIKPAY", "KREDIVO", "AKULAKU", "ATOME", "QRIS"]
Possible values for Philippines: ["CREDIT_CARD", "7ELEVEN", "CEBUANA", "DD_BPI", "DD_UBP", "DD_RCBC", "DD_BDO_EPAY", "DP_MLHUILLIER", "DP_PALAWAN", "DP_ECPAY_LOAN", "PAYMAYA", "GRABPAY", "GCASH", "SHOPEEPAY", "BILLEASE", "CASHALO", "BDO_ONLINE_BANKING", "BPI_ONLINE_BANKING", "UNIONBANK_ONILNE_BANKING", "BOC_ONLINE_BANKING", "CHINABANK_ONLINE_BANKING", "INSTAPAY_ONLINE_BANKING", "LANDBANK_ONLINE_BANKING", "MAYBANK_ONLINE_BANKING", "METROBANK_ONLINE_BANKING", "PNB_ONLINE_BANKING", "PSBANK_ONLINE_BANKING", "PESONET_ONLINE_BANKING", "RCBC_ONLINE_BANKING", "ROBINSONS_BANK_ONLINE_BANKING", "SECURITY_BANK_ONLINE_BANKING", "QRPH"]
Possible values for Thailand: ["CREDIT_CARD", "PROMPTPAY", "LINEPAY", "WECHATPAY", "TRUEMONEY", "SHOPEEPAY", "DD_SCB_MB", "DD_BBL_MB", "DD_KTB_MB", "DD_BAY_MB", "DD_KBANK_MB"]
Possible values for Vietnam: ["CREDIT_CARD", "APPOTA", "ZALOPAY", "VNPTWALLET", "VIETTELPAY", "SHOPEEPAY", "WOORI", "VIETCAPITAL", "VPB", "BIDV"]
Possible values for Malaysia: ["CREDIT_CARD", "TOUCHNGO", "WECHATPAY", "DD_UOB_FPX", "DD_PUBLIC_FPX", "DD_AFFIN_FPX", "DD_AGRO_FPX", "DD_ALLIANCE_FPX", "DD_AMBANK_FPX", "DD_ISLAM_FPX", "DD_MUAMALAT_FPX", "DD_BOC_FPX", "DD_RAKYAT_FPX", "DD_BSN_FPX", "DD_CIMB_FPX", "DD_HLB_FPX", "DD_HSBC_FPX", "DD_KFH_FPX", "DD_MAYB2U_FPX", "DD_OCBC_FPX", "DD_RHB_FPX", "DD_SCH_FPX", "AFFIN_FPX_BUSINESS", "AGRO_FPX_BUSINESS", "ALLIANCE_FPX_BUSINESS", "AMBANK_FPX_BUSINESS", "ISLAM_FPX_BUSINESS", "MUAMALAT_FPX_BUSINESS", "BNP_FPX_BUSINESS", "CIMB_FPX_BUSINESS", "CITIBANK_FPX_BUSINESS", "DEUTSCHE_FPX_BUSINESS", "HLB_FPX_BUSINESS", "HSBC_FPX_BUSINESS", "RAKYAT_FPX_BUSINESS", "KFH_FPX_BUSINESS", "MAYB2E_FPX_BUSINESS", "OCBC_FPX_BUSINESS", "PUBLIC_FPX_BUSINESS", "RHB_FPX_BUSINESS", "SCH_FPX_BUSINESS", "UOB_FPX_BUSINESS"]
For more info on each payment method, see here |
||||||||||||||||||||||||
currency optional |
string |
Currency of the amount that you created Possible values : IDR , PHP , THB , VND , MYR
|
||||||||||||||||||||||||
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
|
||||||||||||||||||||||||
mid_label optional |
string |
MID label when you have an acquiring bank, and are using credit cards. | ||||||||||||||||||||||||
reminder_time_unit optionaldefault:
|
string |
Signifies the unit for reminder_time field. The value can be either days or hours
|
||||||||||||||||||||||||
reminder_time optional |
integer positive |
Signifies when a reminder notification will be sent before the invoice expires. When reminder_time_unit is days , allowed values are between 1 and 30. When reminder_time_unit is hours , allowed values are between 1 and 24. |
||||||||||||||||||||||||
locale optional |
string |
The default language to display. Currently supporting : en or id You can also configure your default language in Invoice Settings in Xendit Dashboard. If you do not set the locale, we will refer to the configurations in your Invoice Settings. |
||||||||||||||||||||||||
items optional*mandatory for PayLater payment method |
array |
Array of items JSON objects describing the item(s) purchased. Max array size: 75. Mandatory for PayLater payment method. Items child parameters
|
||||||||||||||||||||||||
fees optional |
array |
Array of items JSON objects describing the fee(s) that you charge to your end customer. This can be an admin fee, logistics fee, etc. This amount will be included in the total invoice amount and will be transferred to your balance when the transaction settles. Max array size: 10. Fees child parameters
|
||||||||||||||||||||||||
should_authenticate_credit_card optional |
boolean |
Specify whether you want this checkout transaction to go through 3DS (credit card authentication). Please make sure "Optional 3DS" is enabled in your Credit Card Settings. If Optional 3DS is disabled, all checkout transactions paid via card will go through 3DS, regardless of the value of this parameter. | ||||||||||||||||||||||||
channel_properties optional |
object |
Specify the configuration of each payment method or payment channel that will be used for this payment link creation Cards channel child parameters
|
||||||||||||||||||||||||
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 |
Response Parameters
Example Create Invoice Response
{
"id": "65fc7522ff846905c2fc1c8d",
"external_id": "payment-link-example",
"user_id": "65e95b2b3e4690f17fab20ad",
"status": "PENDING",
"merchant_name": "Honey Badger Business",
"merchant_profile_picture_url": "https://du8nwjtfkinx.cloudfront.net/xendit.png",
"amount": 510000,
"description": "Checkout Demo #123",
"expiry_date": "2024-03-22T17:57:54.578Z",
"invoice_url": "https://checkout-staging.xendit.co/v2/65fc7522ff846905c2fc1c8d",
"available_banks": [
{
"bank_code": "MANDIRI",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
},
{
"bank_code": "BRI",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
},
{
"bank_code": "BNI",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
},
{
"bank_code": "PERMATA",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
},
{
"bank_code": "BCA",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
},
{
"bank_code": "SAHABAT_SAMPOERNA",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
},
{
"bank_code": "CIMB",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
},
{
"bank_code": "BSI",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
},
{
"bank_code": "BJB",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
},
{
"bank_code": "BNC",
"collection_type": "POOL",
"transfer_amount": 510000,
"bank_branch": "Virtual Account",
"account_holder_name": "CARDS AUTOMATION TEST",
"identity_amount": 0
}
],
"available_retail_outlets": [
{
"retail_outlet_name": "ALFAMART"
},
{
"retail_outlet_name": "INDOMARET"
}
],
"available_ewallets": [
{
"ewallet_type": "SHOPEEPAY"
},
{
"ewallet_type": "ASTRAPAY"
},
{
"ewallet_type": "JENIUSPAY"
},
{
"ewallet_type": "DANA"
},
{
"ewallet_type": "LINKAJA"
},
{
"ewallet_type": "OVO"
},
{
"ewallet_type": "NEXCASH"
}
],
"available_qr_codes": [
{
"qr_code_type": "QRIS"
}
],
"available_direct_debits": [
{
"direct_debit_type": "DD_BRI"
},
{
"direct_debit_type": "DD_MANDIRI"
}
],
"available_paylaters": [
{
"paylater_type": "KREDIVO"
},
{
"paylater_type": "AKULAKU"
},
{
"paylater_type": "ATOME"
}
],
"should_exclude_credit_card": false,
"should_send_email": false,
"success_redirect_url": "https://www.google.com",
"failure_redirect_url": "https://www.google.com",
"created": "2024-03-21T17:57:55.128Z",
"updated": "2024-03-21T17:57:55.128Z",
"currency": "IDR",
"items": [
{
"name": "Air Conditioner",
"quantity": 1,
"price": 510000,
"category": "Electronic",
"url": "https://yourcompany.com/example_item"
}
],
"fees": [
{
"type": "ADMIN",
"value": 5000
}
],
"customer": {
"given_names": "John",
"surname": "Doe",
"email": "johndoe@example.com",
"mobile_number": "+6287774441111",
"addresses": [
{
"city": "Jakarta Selatan",
"country": "Indonesia",
"postal_code": "12345",
"state": "Daerah Khusus Ibukota Jakarta",
"street_line1": "Jalan Makan",
"street_line2": "Kecamatan Kebayoran Baru"
}
]
},
"customer_notification_preference": {
"invoice_created": [
"whatsapp",
"email",
"viber"
],
"invoice_reminder": [
"whatsapp",
"email",
"viber"
],
"invoice_paid": [
"whatsapp",
"email",
"viber"
]
},
"channel_properties": {
"cards": {
"allowed_bins": [
"400000",
"52000000"
],
"installment_configuration": {
"allow_installment": true,
"allow_full_payment": false,
"allowed_terms": [
{
"issuer": "BRI",
"terms": [
3,
6,
12
]
},
{
"issuer": "BNI",
"terms": [
3,
6
]
}
]
}
}
},
"metadata": {
"store_branch": "Jakarta"
}
}
Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string |
An invoice ID generated by Xendit | ||||||||||||||||||||||||
external_id | string |
The invoice ID in your server, that can be used to reconcile between you and Xendit | ||||||||||||||||||||||||
user_id | string |
Your Xendit Business ID | ||||||||||||||||||||||||
status | string |
Status showing whether the invoice has been paid Possible values: PENDING , PAID , EXPIRED PENDING means the invoice has been successfully created but yet to be paid PAID means the invoice has been paid EXPIRED means the invoice expired before your customer paid |
||||||||||||||||||||||||
merchant_name | string |
The name of your company or website | ||||||||||||||||||||||||
merchant_profile_picture_url | string |
The URL to profile picture of your company | ||||||||||||||||||||||||
amount | number |
Nominal amount for the invoice | ||||||||||||||||||||||||
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 | ||||||||||||||||||||||||
expiry_date | string |
ISO date and time that the invoice expires. Default is 24 hours. | ||||||||||||||||||||||||
invoice_url | string |
Public URL for this invoice - your customer can click this link to access the Checkout UI for this invoice | ||||||||||||||||||||||||
customer | object |
Object containing your end customer’s details. Please always include your customer’s email & mobile number if you wish to send email/WhatsApp notifications to them.
|
||||||||||||||||||||||||
customer_notification_preference | object |
Object containing notification preferences for this invoice. If you wish to send notifications and reminders to your end customer, please populate the values in this object. You can also configure your notifications in your Invoice Settings (in your Xendit Dashboard). If you don’t set notification preferences via API, we will refer to the configurations in your Invoice Settings.
|
||||||||||||||||||||||||
available_banks | object |
Available bank transfer (virtual account) channels available, as per your configuration
|
||||||||||||||||||||||||
available_retail_outlets | object |
Available retail outlets as per your configuration
|
||||||||||||||||||||||||
available_ewallets | object |
Available e-ewallet channels available, as per your configuration
|
||||||||||||||||||||||||
available_qr_codes | object |
Available QR payment channels, as per your configuration
|
||||||||||||||||||||||||
reminder_date optional |
string |
ISO8601 An ISO timestamp that the customer will be sent an invoice reminder email (when they send reminder_time for invoice creation). Timezone:
|
||||||||||||||||||||||||
fixed_va | boolean |
WILL BE DEPRECATED SOON. A flag showing whether you have chosen to bind a fixed VA to this invoice (either TRUE or FALSE ) |
||||||||||||||||||||||||
mid_label | string |
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 | ||||||||||||||||||||||||
should_exclude_credit_card | boolean |
A flag showing if credit card should be excluded in invoice UI or not | ||||||||||||||||||||||||
should_send_email | boolean |
Shows whether you will send email notifications for this invoice WILL BE DEPRECATED SOON. If you wish to send email notifications to your end users, please provide values in the customer_notification_preference object
| ||||||||||||||||||||||||
created | string |
An ISO timestamp that tracks when the invoice was created (UTC GMT+0) | ||||||||||||||||||||||||
updated | string |
An ISO timestamp that tracks when the invoice was updated (UTC GMT+0) | ||||||||||||||||||||||||
currency | string |
Currency of the amount that you created. You will get this response when you add this parameter when create invoice through API | ||||||||||||||||||||||||
items optional |
array |
Array of items JSON objects describing the item(s) purchased
|
||||||||||||||||||||||||
fees optional |
array |
Array of fees JSON objects describing the fee(s) that you charge to your end customer
|
||||||||||||||||||||||||
should_authenticate_credit_card optional |
boolean |
Specify whether you want this checkout transaction to go through 3DS (credit card authentication). Please make sure "Optional 3DS" is enabled in your Credit Card Settings. If Optional 3DS is disabled, all checkout transactions paid via card will go through 3DS, regardless of the value of this parameter. | ||||||||||||||||||||||||
channel_properties optional |
object |
Specify the configuration of each payment method or payment channel that will be used for this payment link creation Cards channel child parameters
|
||||||||||||||||||||||||
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
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. |
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. |
INSTALLMENT_CONFIGURATION_NOT_AVAILABLE400 |
The installment bank_code (ABC) configuration is not available for your business. Please contact our CS to enable it |
INSTALLMENT_NOT_ENABLED400 |
The installment option is not available for your business. Please contact our CS to enable it |
AMOUNT_BELOW_MINIMUM_LIMIT400 |
Requested amount 51000 is lower than installment minimum limit |
Get Invoice
Endpoint: Get an Invoice
GET https://api.xendit.co/v2/invoices/{invoice_id}
Request Parameters
Example Get Invoice Request by External ID
curl https://api.xendit.co/v2/invoices/?external_id={external_id} -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Example Get Invoice Request by Invoice ID (Default)
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
InvoiceClient invoice = xendit.Invoice;
InvoiceResponse invoiceResponse = await invoice.GetById("5efda8a20425db620ec35f43");
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
}
],
"available_paylaters": [
{
"paylater_type": "AKULAKU"
}
],
"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,
"locale": "en"
}
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 | ||||||||||||||||||||||||
customer | Object containing your end customer’s details.
|
||||||||||||||||||||||||
customer_notification_preference | Object containing notification preferences for this invoice.
|
||||||||||||||||||||||||
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", "BSI", "BNC", "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 | WILL BE DEPRECATED SOON. Input this parameter as true to enable one VA number for Your end customers. |
||||||||||||||||||||||||
locale | Bahasa default yang dikonfigurasi ke faktur. | ||||||||||||||||||||||||
items optional |
Array of items JSON objects describing the item(s) purchased
|
||||||||||||||||||||||||
fees optional |
Array of fees JSON objects describing the fee(s) that you charge to your end customer
|
||||||||||||||||||||||||
payment_details optional |
Object containing payment details. Currently supporting QRIS payment only.
|
||||||||||||||||||||||||
should_authenticate_credit_card optional |
Specify whether you want this checkout transaction to go through 3DS (credit card authentication). Please make sure "Optional 3DS" is enabled in your Credit Card Settings. If Optional 3DS is disabled, all checkout transactions paid via card will go through 3DS, regardless of the value of this parameter. | ||||||||||||||||||||||||
channel_properties optional |
object Specify the configuration of each payment method or payment channel that will be used for this payment link creation Cards channel child parameters
|
||||||||||||||||||||||||
metadataoptional |
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
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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
InvoiceClient invoice = xendit.Invoice;
InvoiceResponse invoiceResponse = await invoice.Expire("5efda8a20425db620ec35f43");
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 | ||||||||||||
customer | Object containing your end customer’s details.
|
||||||||||||
customer_notification_preference | Object containing notification preferences for this invoice.
|
||||||||||||
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 |
||||||||||||
items optional |
Array of items JSON objects describing the item(s) purchased
|
||||||||||||
fees optional |
Array of fees JSON objects describing the fee(s) that you charge to your end customer
|
||||||||||||
should_authenticate_credit_card optional |
Specify whether you want this checkout transaction to go through 3DS (credit card authentication). Please make sure "Optional 3DS" is enabled in your Credit Card Settings. If Optional 3DS is disabled, all checkout transactions paid via card will go through 3DS, regardless of the value of this parameter. | ||||||||||||
metadataoptional |
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
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&external_id=627&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)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
InvoiceClient invoice = xendit.Invoice;
// Invoke GetAll without specifying parameter
InvoiceResponse[] invoicesWithoutParams = await invoice.GetAll(null);
// specify parameter using ListInvoiceParameter
ListInvoiceParameter parameter = new ListInvoiceParameter
{
Limit = 1,
ClientTypes = new InvoiceClientType[] { InvoiceClientType.ApiGateway, InvoiceClientType.Dashboard },
};
InvoiceResponse[] invoices = await invoice.GetAll(parameter);
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": [],
"available_paylaters": [],
"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": "627",
"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": [],
"available_paylaters": [],
"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 |
---|---|---|
external_id optional |
string |
The external id used during generation of invoice. Given that external_id is non-unique, by including external_id, it will return all invoices with that specific external_id. |
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 Webhook
POST https://yourcompany.com/invoice_webhook_url
Xendit notifies your system upon successful and expired invoices via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Example Invoice Webhook Request for Payment Through Bank
{
"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 webhook test",
"created": "2020-01-13T02:32:49.827Z",
"updated": "2020-01-13T02:32:50.912Z",
"currency": "IDR",
"payment_channel": "MANDIRI",
"payment_destination": "8458478548758748"
}
Example Invoice Webhook Request for Payment Through Retail Outlet
{
"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 webhook test",
"created": "2020-01-13T02:32:49.827Z",
"updated": "2020-01-13T02:32:50.912Z",
"currency": "IDR",
"payment_channel": "ALFAMART",
"payment_destination": "TEST815"
}
Example Invoice Webhook Request for Expired invoices (Unpaid invoice)
{
"id": "621887f17d9cdaa199d6e787",
"user_id": "61d3c21692594a88b0dad56b",
"external_id": "yumin-invoice-1645774832",
"is_high": false,
"status": "EXPIRED",
"merchant_name": "fintech",
"amount": 1000,
"created": "2022-02-25T07:40:33.922Z",
"updated": "2022-02-25T07:42:43.872Z",
"description": "Invoice Demo #123",
"currency": "PHP",
"success_redirect_url": "https://www.google.com",
"failure_redirect_url": "https://www.google.com",
}
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string |
An invoice ID generated by Xendit | ||||||||||||
external_id | string |
The invoice ID in your server, that can be used to reconcile between you and Xendit | ||||||||||||
user_id | string |
Your Xendit Business ID | ||||||||||||
is_high | boolean |
Should unique numbers go above or below the amount. | ||||||||||||
status | string |
Status showing whether the invoice has been paid PAID means the invoice has been paid EXPIRED means the invoice expired before your customer paid Expired invoice webhooks are not enabled by default. In special cases when a payment is made after the invoice has expired (such as due to delayed bank webhooks for paid transactions), you can receive paid webhooks by enabling this on your Xendit Dashboard. |
||||||||||||
merchant_name | string |
The name of your company or website | ||||||||||||
amount | number |
Nominal amount for the invoice | ||||||||||||
payer_email optional |
string |
Email of the payer, we get this information from your API call | ||||||||||||
description optional |
string |
Description for the invoice, we get this information from your API call | ||||||||||||
paid_amount optional |
number |
Total amount paid for the invoice | ||||||||||||
updated | string |
An ISO timestamp that tracks when the invoice was updated (UTC GMT+0) | ||||||||||||
created | string |
An ISO timestamp that tracks when the invoice was created (UTC GMT+0) | ||||||||||||
currency | string |
Currency of the amount that you created. You will get this response when you add this parameter when create invoice through API | ||||||||||||
paid_at optional |
string |
Date time data when your customer pay the invoice. You will get this response when your invoice is paid | ||||||||||||
payment_method optional |
string |
Payment method that is used when a customer pays the invoice. You will get this response when your invoice is paid Possible values: BANK_TRANSFER , CREDIT_CARD , RETAIL_OUTLET , EWALLET , DIRECT_DEBIT , PAYLATER , QR_CODE |
||||||||||||
payment_channel optional |
string |
The specific payment channel used to pay the invoice. | ||||||||||||
payment_destination optional |
string |
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 | ||||||||||||
payment_details optional |
object |
Object containing payment details. Currently supporting QRIS payment only. Object parameters
|
||||||||||||
payment_id | string |
Payment unique identifier. Currently this object will only be returned when payment method that payer use are eWallets, PayLater, and QR code. You can use the value of this parameter to initiate ewallet and PayLater refunds using the eWallets and Paylater refund endpoints. | ||||||||||||
success_redirect_url | string |
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 | string |
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 | ||||||||||||
credit_card_charge_id optional |
string |
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 | ||||||||||||
items optional |
array |
Array of items JSON objects describing the item(s) purchased. Items child parameters
|
||||||||||||
fees optional |
array |
Array of fees JSON objects describing the fee(s) that you charge to your end customer. Fees child parameters
|
||||||||||||
should_authenticate_credit_card optional |
boolean |
Specify whether you want this checkout transaction to go through 3DS (credit card authentication). Please make sure "Optional 3DS" is enabled in your Credit Card Settings. If Optional 3DS is disabled, all checkout transactions paid via card will go through 3DS, regardless of the value of this parameter. | ||||||||||||
bank_code optional |
string |
Code of the bank used to receive invoice payment, only if payment method is BANK_TRANSFER |
||||||||||||
ewallet_type optional |
string |
Code of the ewallet used to receive invoice payment, only if payment method is EWALLET |
||||||||||||
on_demand_link optional |
string |
Link to the on demand invoice (multiple payment link). Only for on demand invoices. | ||||||||||||
recurring_payment_id optional |
string |
ID of recurring invoice. Only for recurring invoices. | ||||||||||||
fees_paid_amount only if payment_channel is non switching Bank Partner and all of Retail Outlet. |
number |
Xendit fee paid from this transaction. DEPRECATED SINCE 18th MAY 2022. If you need this information go to Xendit Dashboard > Balance Tab |
||||||||||||
adjusted_received_amount only if payment_channel is non switching Bank Partner andall of Retail Outlet. |
number |
Amount attributable to you net of our fees. DEPRECATED SINCE 18th MAY 2022. If you need this information go to Xendit Dashboard > Balance Tab |
Subscriptions (formerly called Recurring)
Our Subscriptions API offers our merchants the ability to collect subscription payments flexibly and seamlessly via auto debit/ merchant initiated payment methods (end users does not perform OTP/ PIN after initial account linking/ binding). Xendit’s Subscriptions delivers more than automated payments scheduling; we focus on providing the best end user experience and maximum payment success rates for our merchants.
Supported Use Cases
- Fixed subscription payments (e.g. Content streaming subscription, recurring donation contributions)
- Usage based subscription payments/ Metered billing (e.g. Utilities bill, data roaming charges)
Supported Autodebit Payment Methods in Indonesia (subject to payment method provider's approval)
- Credit Cards
- BRI DD
- OVO
- SHOPEEPAY
Supported Autodebit Payment Methods in Philippines (subject to payment method provider's approval)
- Credit Cards
- SHOPEEPAY
- GRABPAY
- MAYA
- GCASH
- UBP
- BPI
For full details on each API as well as help on integration, please refer to our documentation
API Version
You are currently viewing the newest version of our Subscriptions API. Integrate once to get access to all available Subscriptions features and future Subscriptions features in Xendit!
Version | Changelog |
---|---|
2022-10-01 Latest |
New Subscriptions endpoint that supports auto debit payments natively with configurable retry mechanisms. Supports cards, eWallets and direct debit payment methods |
2022-07-15 Previous version |
Recurring endpoint powered by Xendit payment links |
Plan Object
The key data object that will orchestrate the merchant's subscription payment flows. Subscriptions plan object will take in the customer object, schedule object (optional) to set up the subscription payments behaviour for a particular end user. Merchant will tie the end user's payment details to a Subscriptions plan using this plan object (either using the payment_method_id from the account linking process or Subscriptions's account linking UI). The Subscriptions plan also takes in other parameters from the merchant to configure how the subscription plan should behave when certain scenarios happen. The Subscriptions plan object will generate multiple Subscriptions cycle objects to orchestrate each instances of payment.
Refer to subscriptions concepts for an overview on subscription objects and relationships.
Example Plan Object
{
"id": "repl-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"recurring_cycle_count": 0,
"currency": "IDR",
"amount": 13579,
"status": "PENDING",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"payment_methods": [
{
"payment_method_id": "pm-239c16f4-866d-43e8-9341-7badafbc019f",
"rank": 1,
"type": "EWALLET"
}
],
"schedule_id": "resc-239c16f4-866d-43e8-9341-7badafbc019f",
"schedule": {
"reference_id": "test_reference_id",
"interval": "MONTH",
"interval_count": 1,
"created": "2022-02-15T16:23:52Z",
"updated": "2022-02-15T16:23:52Z",
"total_recurrence": 12,
"anchor_date": "2022-02-15T16:23:52Z",
"retry_interval": "DAY",
"retry_interval_count": 5,
"total_retry": 5,
"failed_attempt_notifications": [
2,
4
]
},
"immediate_action_type": "FULL_AMOUNT",
"notification_config": {
"recurring_created": [
"WHATSAPP",
"EMAIL"
],
"recurring_succeeded": [
"WHATSAPP",
"EMAIL"
],
"recurring_failed": [
"WHATSAPP",
"EMAIL"
],
"locale": "en"
},
"failed_cycle_action": "STOP",
"metadata": {
"meta_metadata": "meta_meta_metadata"
},
"description": "Video Game Subscription",
"items": [
{
"type": "DIGITAL_PRODUCT",
"name": "Cine Mraft",
"net_unit_amount": 13579,
"quantity": 1
}
],
"actions": [
{
"action": "AUTH",
"url": "https://linking-dev.xendit.co/pali_e53e1ca6-3c09-4026-be2e-95ed3d4bb25b",
"url_type": "WEB",
"method": "GET"
}
],
"success_return_url": "https://www.xendit.co/successisthesumoffailures",
"failure_return_url": "https://www.xendit.co/failureisthemotherofsuccess"
}
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Xendit-generated Subscriptions plan ID, with prefix repl-xxx | ||||||||||||||||||||||||
reference_idrequired |
string |
Merchant-provided identifier for the Subscriptions plan Min - 1 character Max - 64 characters |
||||||||||||||||||||||||
customer_idrequired |
string |
Xendit-generated customer ID, with prefix cust-xxx | ||||||||||||||||||||||||
recurring_actionrequired |
enum |
The type of Subscriptions action requested. Supported values - PAYMENT | ||||||||||||||||||||||||
recurring_cycle_countrequired |
number |
Total number of cycles the Subscriptions plan has executed. Immediate charge cycle also counts as 1 cycle count | ||||||||||||||||||||||||
currencyrequired |
enum |
ISO 4217 currency code of Subscriptions plan. Supported currency - IDR, PHP | ||||||||||||||||||||||||
amountrequired |
number |
Amount that Subscriptions plan will charge to end users. Subscriptions cycles will be generated based on this value. If items param is used, amount should be equivalent to the sum of net_unit_amount multiplied by quantity in the items array Min - Rp 1000 (Indonesia) or PHP 50 (Philippines) Max - Dependent on individual payment providers |
||||||||||||||||||||||||
statusrequired |
enum |
Status of Subscriptions plan: ACTIVE - Subscriptions plan is ongoing INACTIVE - Subscriptions plan will not trigger any more actions PENDING - awaiting for the plan to be completed REQUIRES_ACTION - The request passed validation but requires additional steps for completion |
||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for Subscriptions plan creation. Timezone UTC+0. Example value: "2020-04-20T16:23:52Z" | ||||||||||||||||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest plan object update. Timezone UTC+0. Example value: "2020-04-20T16:23:52Z" | ||||||||||||||||||||||||
payment_methodsoptional |
array |
Array of payment_method_id that the Subscriptions plan will attempt to make payments with (attempts will be made according to the rank of each object in the array). Only one successful payment will be made If this parameter is not passed in, a URL to perform payment account linking will be generated for end users
|
||||||||||||||||||||||||
schedule_idoptional |
string |
Xendit-generated Subscriptions schedule ID. | ||||||||||||||||||||||||
schedulerequired |
object |
Data object containing the configurations of how Subscriptions cycles will be scheduled.
|
||||||||||||||||||||||||
immediate_action_typeoptional |
enum |
The type of action the Subscriptions plan takes upon creation. If the action fails, the Subscriptions plan would be inactivated and an inactivated webhook will be sent. Supported values - FULL_AMOUNT - a full charge will be attempted upon Subscriptions plan creation | ||||||||||||||||||||||||
notification_configoptional |
Object |
Object containing notification preferences for the Subscriptions plan
|
||||||||||||||||||||||||
payment_link_for_failed_attemptoptional |
boolean |
Default = false . Indicates whether the plan should generate a payment link to be sent to the end customer when the first attempt of the cycle fails. The schedule object of the plan must have a minimum total_retry of 1. The plan's notification_config.recurring_failed determines the channel for which the end customer will receive the notification with the payment link URL. You will also receive the payment link URL in the recurring.cycle.retrying callback. For more information about payment links, please see this section |
||||||||||||||||||||||||
failed_cycle_actionoptional |
enum |
Default = RESUME. Indicate the behaviour the Subscriptions plan should take when Subscriptions cycles fail. RESUME will ignore failure and continue on with the next Subscriptions cycle. STOP will inactivate the Subscriptions plan and there will be no active Subscriptions cycles. Supported values - RESUME, STOP | ||||||||||||||||||||||||
metadataoptional |
object |
Object of additional information the merchants 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 | ||||||||||||||||||||||||
descriptionoptional |
string |
Description of Subscriptions plan - you can use this field to list what items are being paid for, or anything else of your choice that describes the function of the Subscriptions plan. This field will be displayed to end users for UI, email or whatsapp. Min - 1 character Max - 1000 characters |
||||||||||||||||||||||||
itemsoptional |
array |
Array of objects describing the item/s
|
||||||||||||||||||||||||
actionsoptional |
array |
Array of objects that contain URLs for end users to complete their Subscriptions plan
|
||||||||||||||||||||||||
success_return_urloptional |
string |
URL where the end user is redirected after account linking has been successful. Must be HTTPS or HTTP | ||||||||||||||||||||||||
failure_return_urloptional |
string |
URL where the end-customer is redirected if the account linking has failed. Must be HTTPS or HTTP |
Schedule Object
The data object used to define how the recurring cycles are supposed to happen. The object contains information about how frequent events should happen and the intervals (day/ month/ year) between each event. The recurring plan object will read off the recurring schedule object to generate each recurring cycle.
Refer to recurring concepts for an overview on recurring objects and relationships.
Example Schedule Object
{
"id" : "resc-239c16f4-866d-43e8-9341-7badafbc019f",
"business_id" : "5f27a14a9bf05c73dd040bc8",
"reference_id": "test_reference_id",
"interval": "MONTH",
"interval_count": 1,
"created": "2022-02-15T16:23:52Z",
"updated": "2022-02-15T16:23:52Z",
"total_recurrence": 12,
"anchor_date": "2022-02-15T16:23:52Z",
"retry_interval": "DAY",
"retry_interval_count": 5,
"total_retry": 5,
"failed_attempt_notifications": [
2,
4
]
}
Body Parameter | Type | Description |
---|---|---|
idrequired |
string |
Xendit-generated recurring schedule ID, with prefix resc-xxx |
reference_idrequired |
string |
Merchant-provided identifier for the recurring schedule Min - 1 character Max - n/a |
business_idrequired |
string |
Xendit-generated identifier for the business |
intervalrequired |
enum |
The type of interval between consecutive recurring cycles. Supported values - DAY, WEEK, MONTH WEEK - the day of the week which anchor_date lands on (e.g. anchor_date lands on Wed, subsequent cycles will be on Wed) MONTH - the date of the month which anchor_date lands on (anchor_date lands on the 25th, subsequent cycles will be on the 25th) |
interval_countrequired |
number |
The number of units of interval between consecutive recurring cycles (e.g. interval = MONTH, interval_count = 3, then recurring cycle happens every 3 month) |
createdrequired |
string |
ISO 8601 Timestamp for recurring schedule creation. Timezone UTC+0. Example value: "2020-04-20T16:23:52Z" |
updatedrequired |
string |
ISO 8601 Timestamp for latest schedule object update. Timezone UTC+0. Example value: "2020-04-20T16:23:52Z" |
total_recurrenceoptional |
number |
Default = NULL The total number of times the end user will be charged. The immediate charge instance does not count to total_recurrence . If the parameter is not used, recurring plan will run on indefinitely |
anchor_dateoptional |
string |
Default = the date of schedule creation (same day action). Timestamp in ISO 8601 ("2020-11-20T16:23:52+07:00"). A timestamp used to determine when a recurring plan starts. The date, day of week or date of month will be used to initialize the recurring cycle (back dated timestamps still works). If a timezone passed in, the recurring event will be executed based on the timezone, else UTC 0 wil be used Supported values - Timestamps between 1st to 28th of a month If no anchor_date value is passed and date of schedule creation falls on 29/30/31, anchor date will be defaulted to 1st of next month |
retry_intervaloptional |
enum |
The type of interval between failed attempt and retries. Supported values - DAY |
retry_interval_countoptional |
number |
The number of units of retry_interval between consecutive retries (e.g. retry_interval = DAY, retry_interval_count = 3, then recurring cycle retries 3 days after a failed attempt) |
total_retryoptional |
number |
The number of times you will retry a failed recurring cycle. If no value is passed into total_retry , it will be null by default and no retries will be triggered Min - 1 Max - 10 |
failed_attempt_notificationsoptional |
string |
Specify which retry attempts will have failed recurring notifications to the end user. Array values count should not be greater than total_retry number or duplicated. 1 in this param refers to the first retry attempt. |
Cycle Object
A recurring cycle refers to one specific instance of the recurring plan's action - for e.g. a specific month's billing cycle. The recurring cycle object is generated from the recurring plan object where the recurring behaviour is defined. If changes to a particular month's billing cycle is required, this object can be updated without affecting the original recurring plan. This object is especially useful for usage based billing.
Refer to recurring concepts for an overview on recurring objects and relationships.
Example Cycle Object
{
"id": "recy-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"type": "SCHEDULED",
"cycle_number": 2,
"attempt_count": 2,
"attempt_details": [
{
"attempt_number": 1,
"created": "2020-04-21T16:23:52Z",
"action_id": "ewc-239c16f4-866d-43e8-9341-7badafbc019f",
"status": "SUCCEEDED",
"Failure_code": null,
"next_retry_timestamp": null
},
{
"attempt_number": 1,
"created": "2020-04-20T16:23:52Z",
"action_id": "ewc-239c16f4-866d-43e8-9341-7badafbc019f",
"status": "FAILTED",
"failure_code": "INSUFFICIENT_BALANCE",
"next_retry_timestamp": "2020-04-20T16:23:52Z"
}
],
"status": "SUCCEEDED",
"scheduled_timestamp": "2020-12-20T16:23:52Z",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"currency": "IDR",
"amount": 13579
}
Body Parameter | Type | Description | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Xendit-generated recurring cycle ID, with prefix recy-xxx | ||||||||||||||
plan_idrequired |
string |
Xendit-generated recurring plan ID, with prefix repl-xxx | ||||||||||||||
reference_idrequired |
string |
Merchant-provided identifier, inherited from the recurring plan object Min - 1 character Max - 64 characters |
||||||||||||||
customer_idrequired |
string |
Xendit-generated customer ID, inherited from the recurring plan object, with prefix cust-xxx | ||||||||||||||
recurring_actionrequired |
enum |
The type of recurring action requested, inherited from the recurring plan object. Supported values - PAYMENT | ||||||||||||||
typerequired |
enum |
The type of recurring cycle - Available values - SCHEDULED, IMMEDIATE | ||||||||||||||
cycle_numberrequired |
number |
A numbering that tracks the order of cycle objects generated by a recurring plan (e.g. in a monthly billing plan, the second month's cycle_number would be 2) Min - 1 |
||||||||||||||
attempt_countrequired |
number |
Number of times the recurring action has been attempted for this recurring cycle object. The value is an aggregate of the first attempt and the retries attempted | ||||||||||||||
attempt_detailsrequired |
array |
Detailed information of each action attempts
|
||||||||||||||
statusrequired |
enum |
Status of recurring cycle. Available values - SCHEDULED - cycle is waiting for execution time PENDING - execution of the recurring action has started (cycle is locked for updates) RETRYING - configured retries are ongoing FAILED - all attempts at action, including retries has failed SUCCEEDED - at least one attempt at action has succeeded CANCELLED - recurring cycle was terminated by merchant action |
||||||||||||||
scheduled_timestamprequired |
string |
ISO 8601 Timestamp (e.g. "2020-04-20T00:00:00Z" UTC+0) for the upcoming action attempt for the recurring cycle - value is updated on each retry (if any). Action will be executed within 24 hours of the scheduled timestamp with timezone taken into consideration. | ||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for recurring cycle creation. Timezone UTC+0. Example value: "2020-04-20T16:23:52Z" | ||||||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest cycle object update. Timezone UTC+0. Example value: "2020-04-20T16:23:52Z" | ||||||||||||||
currencyrequired |
enum |
ISO 4217 currency code of recurring plan. Supported currency - IDR, PHP | ||||||||||||||
amountrequired |
number |
Amount that recurring plan will charge to end users. Recurring cycles will be generated based on this value. If items param is used, amount should be equivalent to the sum of net_unit_amount multiplied by quantity in the items array Min - IDR 1,000 (Indonesia) / PHP 50 (Philippines) maximum amount is dependent on payment providers |
Customer - Create
Make a POST request to this endpoint to create a customer for use with recurring endpoint. The customer object will be used by recurring plan for end user notifications regarding activity updates on their recurring plan.
Note - one customer object can be used for multiple recurring plans.
Endpoint: Create Customer
POST https://api.xendit.co/customers
Version
For best compatibility, please use version 2020-10-31 at Create Customer API
Request Parameters
Example Create Customer Request
curl https://api.xendit.co/customers -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json'
--data-raw '{
"reference_id": "demo_1475801962607",
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe"
},
"email": "customer@website.com",
"mobile_number": "+628121234567890"
}'
<?php
$url = "https://api.xendit.co/customers";
$apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
$headers = [];
$headers[] = "Content-Type: application/json";
$data = [
"reference_id" => "demo_1475801962607",
"type" => "INDIVIDUAL",
"individual_detail" => [
"given_names" => "John",
"surname" => "Doe"
],
"email" => "customer@website.com",
"mobile_number" => "+628121234567890"
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
let apiKey = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:";
let url = "https://api.xendit.co/customers";
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(apiKey + ":"));
headers.append("Content-Type", "application/json");
var reqBody = JSON.stringify({
"reference_id": "demo_1475801962607",
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe"
},
"email": "customer@website.com",
"mobile_number": "+628121234567890"});
var requestOptions = {
method: 'POST',
headers: headers,
body: reqBody,
redirect: 'follow'
};
fetch(url, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
import requests
import base64
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
url = "https://api.xendit.co/customers"
api_key_bytes = api_key.encode('ascii')
base64_bytes = base64.b64encode(api_key_bytes)
base64_token = base64_bytes.decode('ascii')
payload = {
"reference_id": "demo_1475801962607",
"type": "INDIVIDUAL",
"individual_detail": {
"given_names": "John",
"surname": "Doe"
},
"email": "customer@website.com",
"mobile_number": "+628121234567890"
}
auth_token = 'Basic ' + base64_token
headers = {
'Authorization': auth_token
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
string apiKey = "xnd_development_P4qDfOss0OCpl8RtKrROHjaQYNCk9dN5lSfk+R1l9Wbe+rSiCwZ3jw==";
XenditClient xendit = new XenditClient(apiKey);
CustomerClient customer = xendit.Customer;
CustomerParameter individualParameter = new CustomerParameter
{
ReferenceId = "demo_11212163",
Type = CustomerType.Individual,
IndividualDetail = new IndividualDetail
{
GivenNames = "John",
Gender = CustomerGender.Male,
},
IdentityAccount = new IdentityAccount[]
{
new IdentityAccount
{
Country = Country.Indonesia,
Type = CustomerIdentityAccountType.BankAccount,
Properties = new IdentityAccountProperties { AccountNumber = "account_number" }
}
},
KycDocuments = new KycDocument[]
{
new KycDocument
{
Country = Country.Indonesia,
Type = CustomerKycDocumentType.IdentityCard,
SubType = CustomerKycDocumentSubType.NationalId,
}
},
};
CustomerResponse individualCustomerVersion20201031 = await customer.Create(individualParameter);
The following table displays parameters that will be used in recurring to notify your end users about recurring activity. Please see Create Customer API for the full feature list of Create Customer API.
Body Parameter | Type | Description | ||
---|---|---|---|---|
reference_idrequired |
string |
Merchant-provided identifier for the customer. Requests with a duplicate reference_id will return an error. You should PATCH the customer object resource instead.
|
||
typerequired |
string |
Type of customer. Supported values: INDIVIDUAL |
||
individual_detailconditionally required |
object |
JSON object containing details of the individual. Required if type is INDIVIDUAL
Individual detail child parameters
|
||
mobile_numberoptional |
string |
Mobile number of customer in E.164 format
|
||
emailoptional |
string |
E-mail address of customer
|
Response Parameters
Success responses will contain a single Customer Object
Error Codes
See other common errors here.
Error Code | Description |
---|---|
DUPLICATE_ERROR409 |
The provided reference_id has been used before. Please enter a unique reference_id . |
IDEMPOTENCY_ERROR409 |
Provided Idempotency-key already exists but the request body provided does not match the original request |
Plan - Create
Create recurring plan API will require the customer object, schedule object (optional) to set up the recurring logic for a particular end user. Merchant will tie the end user's payment details to a recurring plan using this API (either using the recurring plan's account linking UI or providing payment_method_id from the create payment method API). Once the request has been validated, webhooks will be sent to notify your system on whether the plan has been activated.
Please refer to our integration guide for more information.
Endpoint: Create Recurring Plan Request
POST https://api.xendit.co/recurring/plans
Request Parameters
Example: Create Recurring Plan Request
curl https://api.xendit.co/recurring/plans -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--data '{
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"currency": "IDR",
"amount": 13579,
"payment_methods": [{
"payment_method_id": "pm-asdaso213897821hdas",
"rank": 1
}],
"schedule": {
"reference_id": "test_reference_id",
"interval": "MONTH",
"interval_count": 1,
"total_recurrence": 12,
"anchor_date": "2022-02-15T16:23:52Z",
"retry_interval": "DAY",
"retry_interval_count": 3,
"total_retry": 2,
"failed_attempt_notifications": [1,2]
},
"immediate_action_type": "FULL_AMOUNT",
"notification_config": {
"recurring_created": ["WHATSAPP","EMAIL"],
"recurring_succeeded": ["WHATSAPP","EMAIL"],
"recurring_failed": ["WHATSAPP","EMAIL"],
"locale": "en"},
"failed_cycle_action": "STOP",
"payment_link_for_failed_attempt" : true,
"metadata": null,
"description": "Video Game Subscription",
"items": [
{
"type": "DIGITAL_PRODUCT",
"name": "Cine Mraft",
"net_unit_amount": 13579,
"quantity": 1,
"url": "https://www.xendit.co/",
"category": "Gaming",
"subcategory": "Open World"
}
],
"success_return_url": "https://www.xendit.co/successisthesumoffailures",
"failure_return_url": "https://www.xendit.co/failureisthemotherofsuccess"
}'
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.xendit.co/recurring/plans',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"currency": "IDR",
"amount": 13579,
"payment_methods": [{
"payment_method_id": "pm-asdaso213897821hdas",
"rank": 1
}],
"schedule": {
"reference_id": "test_reference_id",
"interval": "MONTH",
"interval_count": 1,
"total_recurrence": 12,
"anchor_date": "2022-02-15T16:23:52Z",
"retry_interval": "DAY",
"retry_interval_count": 3,
"total_retry": 2,
"failed_attempt_notifications": [1,2]
},
"immediate_action_type": "FULL_AMOUNT",
"notification_config": {
"recurring_created": ["WHATSAPP","EMAIL"],
"recurring_succeeded": ["WHATSAPP","EMAIL"],
"recurring_failed": ["WHATSAPP","EMAIL"],
"locale": "en"},
"failed_cycle_action": "STOP",
"payment_link_for_failed_attempt" : true,
"metadata": null,
"description": "Video Game Subscription",
"items": [
{
"type": "DIGITAL_PRODUCT",
"name": "Cine Mraft",
"net_unit_amount": 13579,
"quantity": 1,
"url": "https://www.xendit.co/",
"category": "Gaming",
"subcategory": "Open World"
}
],
"success_return_url": "https://www.xendit.co/successisthesumoffailures",
"failure_return_url": "https://www.xendit.co/failureisthemotherofsuccess"
}',
CURLOPT_HTTPHEADER => array(
'Authorization: Basic eG5kX2RldmVsb3BtZW50XzNRd3BPQzVrU2c4bWpKUGd2RHBqU3BEeGxnMU9PSGFwaXpVNTNHOFIxcmV4VU5oSnpQZnlGTWxTTVRDUVYxUk86',
'Content-Type: application/json'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
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-split-ruleoptional |
string |
Split Rule ID that you would like to apply to this subscriptions plan in order to split and route payments to multiple accounts. Please note: If you include this parameter, we will return the split_rule_id in the header of the API response. If for-user-id header is not present, Split Rule will still be routed from platform account to the specified destination account Please note that this is the newest header version, the older version with-fee-rule header will be deprecated by September 30, 2025. Please migrate to this version before the the deprecation date if you are still using with-fee-rule header.This header is only used if you have access to xenPlatform. See xenPlatform for more information. |
Body Parameter | Type | Description | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
reference_idrequired |
string |
Merchant-provided identifier for the recurring plan Min - 1 character Max - 64 characters |
||||||||||||||||||||
customer_idrequired |
string |
Xendit-generated customer ID with prefix cust-xxx. Only support customer with type INDIVIDUAL |
||||||||||||||||||||
recurring_actionrequired |
enum |
The type of recurring action requested. Supported values - "PAYMENT" | ||||||||||||||||||||
currencyrequired |
enum |
ISO 4217 currency code of recurring plan. Supported currency - IDR, PHP | ||||||||||||||||||||
amountrequired |
number |
Amount that recurring plan will charge to end users. Recurring cycles will be generated based on this value. If items param is used, amount should be equivalent to the sum of net_unit_amount multiplied by quantity in the items array Min IDR - 1000, Cards Min IDR - 5000 Min PHP - 20 Max - Dependent on individual payment providers |
||||||||||||||||||||
schedulerequired |
object |
Data object containing the configurations of how recurring cycles will be scheduled.
|
||||||||||||||||||||
payment_methodsoptional |
array |
Array of payment_method_id that the recurring plan will attempt to make payments with (attempts will be made according to the rank of each object in the array). Only one successful payment will be made If this parameter is not passed in, a URL to perform payment account linking by Xendit will be generated for end users
|
||||||||||||||||||||
immediate_action_typeoptional |
enum |
the type of action the recurring plan takes upon creation. If the action fails the recurring plan would be inactivated and an inactivated webhook will be sent. Supported values - FULL_AMOUNT - a full charge will be attempted upon recurring plan creation | ||||||||||||||||||||
notification_configoptional |
Object |
Object containing notification preferences for the recurring plan
|
||||||||||||||||||||
payment_link_for_failed_attemptoptional |
boolean |
Default = false . Indicates whether the plan should generate a payment link to be sent to the end customer when the first attempt of the cycle fails. The schedule object of the plan must have a minimum total_retry of 1. The plan's notification_config.recurring_failed determines the channel for which the end customer will receive the notification with the payment link URL. You will also receive the payment link URL in the recurring.cycle.retrying callback. For more information about payment links, please see this section |
||||||||||||||||||||
failed_cycle_actionoptional |
enum |
Default = RESUME. Indicate the behaviour the recurring plan should take when recurring cycles fail. RESUME will ignore failure and continue on with the next recurring cycle. STOP will inactivate the recurring plan and there will be no active recurring cycles. Supported values - RESUME, STOP | ||||||||||||||||||||
metadataoptional |
object |
Object of additional information the merchants 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 | ||||||||||||||||||||
descriptionoptional |
string |
Description of recurring plan - you can use this field to list what items are being paid for, or anything else of your choice that describes the function of the recurring plan. This field will be displayed to end users for UI, email or whatsapp. Min - 1 character Max - 1000 characters |
||||||||||||||||||||
itemsoptional |
array |
Array of objects describing the item/s
|
||||||||||||||||||||
success_return_urlconditionally required |
string |
URL where the end user is redirected after account linking has been successful. Must be HTTPS or HTTP. Required when payment_method_id is not passed into the request |
||||||||||||||||||||
failure_return_urlconditionally required |
string |
URL where the end-customer is redirected if the account linking has failed. Must be HTTPS or HTTP. Required when payment_method_id is not passed into the request |
Response Parameters
Success responses will contain a single Plan Object with PENDING
status. This is followed by a webhook that will inform your system if the plan was successfully activated.
Error Codes
Example: Create Recurring Plan Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
API_VALIDATION_ERROR400 |
schedule should be included in the request body for a successful response. Please check your request body |
API_VALIDATION_ERROR400 |
To create a cycle retry logic, all values in retry_interval , retry_interval_count and total_retry must be specified. Please check your request body to specify all values or remove the parameters that were filled |
API_VALIDATION_ERROR400 |
To configure failed_attempt_notifications, a retry logic must be specified using retry_interval , retry_interval_count and total_retry . Please check your request body to specify all values |
API_VALIDATION_ERROR400 |
The rank for payment methods must be sequential starting at 1 |
API_VALIDATION_ERROR400 |
Values in failed_attempt_notifications array cannot be duplicated or greater than total_retry value or the array values count greater than total_retry |
API_VALIDATION_ERROR400 |
The payment currency requested is not supported for this payment channel. Please refer to our API reference or docs to pick available currencies |
API_VALIDATION_ERROR400 |
anchor_date does not accept dates from 29 to 31. Please check your request body to specify all values |
API_VALIDATION_ERROR400 |
The sum of items.net_unit_amount must be equal to the plan amount |
INVALID_PAYMENT_METHOD_ID400 |
The payment_method_id provided has a mismatched currency or it is not "ACTIVE" because it has expired/ been unlinked/ linking has not been completed. Please retry with a valid payment_method_id |
INVALID_API_KEY401 |
API key format is invalid |
PAYMENT_METHOD_ID_NOT_FOUND404 |
The payment_method_id provided is not found. Please retry with a payment_method_id |
CUSTOMER_NOT_FOUND404 |
customer_id is invalid or not found. Please try again with valid customer_id |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Plan - Callback Events
Xendit notifies your system upon activated and inactivated plans via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Plan Activation Payload
The plan activation webhook is triggered when the recurring plan is able to complete all requested steps defined in create recurring plan API. There are two possible processes that could be involved - 1. recurring is helping to complete an immediate action (e.g. immediate payment action) or 2. recurring is waiting for end user to complete account linking.
Full details of webhooks can be found here
Example: Plan Activation Webhook Payload
{
"created": "2022-10-01T12:37:08.251Z",
"business_id": "62440e322008e87fb29c1fd0",
"event": "recurring.plan.activated",
"data": {
"id": "repl-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"recurring_cycle_count": 0,
"currency": "IDR",
"amount": 13579,
"status": "ACTIVE",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"payment_methods": [
{
"payment_method_id": "pm-239c16f4-866d-43e8-9341-7badafbc019f",
"rank": 1,
"type": "EWALLET"
}
],
"schedule_id": "resc-239c16f4-866d-43e8-9341-7badafbc019f",
"schedule": {
"reference_id": "test_reference_id",
"interval": "MONTH",
"interval_count": 1,
"created": "2022-02-15T16:23:52Z",
"updated": "2022-02-15T16:23:52Z",
"total_recurrence": 12,
"anchor_date": "2022-02-15T16:23:52Z",
"retry_interval": "DAY",
"retry_interval_count": 5,
"total_retry": 5,
"failed_attempt_notifications": [
2,
4
]
},
"immediate_action_type": "FULL_AMOUNT",
"notification_config": {
"recurring_created": [
"WHATSAPP",
"EMAIL"
],
"recurring_succeeded": [
"WHATSAPP",
"EMAIL"
],
"recurring_failed": [
"WHATSAPP",
"EMAIL"
],
"locale": "en"
},
"failed_cycle_action": "STOP",
"metadata": {
"meta_metadata": "meta_meta_metadata"
},
"description": "Video Game Subscription",
"items": [
{
"type": "DIGITAL_PRODUCT",
"name": "Cine Mraft",
"net_unit_amount": 13579,
"quantity": 1
}
],
"actions": [
{
"action": "AUTH",
"url": "https://linking-dev.xendit.co/pali_e53e1ca6-3c09-4026-be2e-95ed3d4bb25b",
"url_type": "WEB",
"method": "GET"
}
],
"success_return_url": "https://www.xendit.co/successisthesumoffailures",
"failure_return_url": "https://www.xendit.co/failureisthemotherofsuccess"
},
"api_version": "v1"
}
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - recurring.plan.activated |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for webhook notification creation. Timezone UTC+0. |
dataoptional |
object |
Plan Object with ACTIVE status |
api_versionoptional |
string |
Version value fixed as v1 |
Plan Inactivation Payload
The plan activation webhook is triggered when the recurring plan is unable to complete requested step to perform an immediate action, when a cycle fails, or when a cycle reached it last recurrence. For example, when the immediate payment action fails.
Example: Plan Inactivation Payload
{
"created": "2022-10-01T12:37:08.251Z",
"business_id": "62440e322008e87fb29c1fd0",
"event": "recurring.plan.inactivated",
"data": {
"id": "repl-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"recurring_cycle_count": 0,
"currency": "IDR",
"amount": 13579,
"status": "INACTIVE",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"payment_methods": [
{
"payment_method_id": "pm-239c16f4-866d-43e8-9341-7badafbc019f",
"rank": 1
}
],
"schedule_id": "resc-239c16f4-866d-43e8-9341-7badafbc019f",
"schedule": {
"reference_id": "test_reference_id",
"interval": "MONTH",
"interval_count": 1,
"created": "2022-02-15T16:23:52Z",
"updated": "2022-02-15T16:23:52Z",
"total_recurrence": 12,
"anchor_date": "2022-02-15T16:23:52Z",
"retry_interval": "DAY",
"retry_interval_count": 5,
"total_retry": 5,
"failed_attempt_notifications": [
2,
4
]
},
"immediate_action_type": "FULL_AMOUNT",
"notification_config": {
"recurring_created": [
"WHATSAPP",
"EMAIL"
],
"recurring_succeeded": [
"WHATSAPP",
"EMAIL"
],
"recurring_failed": [
"WHATSAPP",
"EMAIL"
],
"locale": "en"
},
"failed_cycle_action": "STOP",
"metadata": {
"meta_metadata": "meta_meta_metadata"
},
"description": "Video Game Subscription",
"items": [
{
"type": "DIGITAL_PRODUCT",
"name": "Cine Mraft",
"net_unit_amount": 13579,
"quantity": 1
}
],
"actions": [
{
"action": "AUTH",
"url": "https://linking-dev.xendit.co/pali_e53e1ca6-3c09-4026-be2e-95ed3d4bb25b",
"url_type": "WEB",
"method": "GET"
}
],
"success_return_url": "https://www.xendit.co/successisthesumoffailures",
"failure_return_url": "https://www.xendit.co/failureisthemotherofsuccess"
},
"api_version": "v1"
}
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - recurring.plan.inactivated |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for webhook notification creation. Timezone UTC+0. |
dataoptional |
object |
Plan Object with INACTIVE status |
api_versionoptional |
string |
Version value fixed as v1 |
Plan - Update
Recurring plan can be updated via this API to populate changes to newly generated recurring cycles. If changes need to be applied to recurring cycles that have been scheduled, include update-scheduled-cycle
parameter in request header.
Endpoint: Update Recurring Plan
PATCH https://api.xendit.co/recurring/plans/:id
Request Parameters
Example: Update Recurring Plan Request
curl https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f -X PATCH \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--header 'update-scheduled-cycle: TRUE' \
--data '{
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"currency": "IDR",
"amount": 100000,
"payment_methods": [{
"payment_method_id": "pm-239c16f4-866d-43e8-9341-7badafbc019f",
"rank": 1
}],
"notification_config": {
"recurring_created": ["WHATSAPP","EMAIL"],
"recurring_succeeded": [],
"recurring_failed": ["WHATSAPP","EMAIL"]
"locale": "en"},
"metadata": null
}' \
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 |
Xendit-generated recurring plan ID, with prefix repl-xxx |
Body Parameter | Type | Description | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
customer_idoptional |
string |
Xendit-generated customer ID, with prefix cust-xxx | ||||||||||||||||||||
currencyoptional |
enum |
ISO 4217 currency code of recurring plan. Supported currency - IDR, PHP | ||||||||||||||||||||
amountoptional |
number |
Amount that recurring plan will charge to end users. Recurring cycles will be generated based on this value. If items param is used, amount should be equivalent to the sum of net_unit_amount multiplied by quantity in the items array Min IDR - 1000 Min PHP - 50 Max - Dependent on individual payment providers |
||||||||||||||||||||
payment_methodsoptional |
array |
Array of payment_method_id that the recurring plan will attempt to make payments with (attempts will be made according to the rank of each object in the array). Only one successful payment will be made
|
||||||||||||||||||||
notification_configoptional |
Object |
Object containing notification preferences for the recurring plan
|
||||||||||||||||||||
payment_link_for_failed_attemptoptional |
boolean |
Default = false . Indicates whether the plan should generate a payment link to be sent to the end customer when the first attempt of the cycle fails. The schedule object of the plan must have a minimum total_retry of 1. The plan's notification_config.recurring_failed determines the channel for which the end customer will receive the notification with the payment link URL. You will also receive the payment link URL in the recurring.cycle.retrying callback. For more information about payment links, please see this section |
||||||||||||||||||||
metadataoptional |
object |
Object of additional information the merchants 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 | ||||||||||||||||||||
descriptionoptional |
string |
Description of recurring plan - you can use this field to list what items are being paid for, or anything else of your choice that describes the function of the recurring plan. This field will be displayed to end users for UI, email or whatsapp. Min - 1 character Max - 1000 characters |
||||||||||||||||||||
itemsoptional |
array |
Array of objects describing the item/s
|
Response Parameters
Success responses will contain a single Plan Object.
Error Codes
Example: Update Recurring Plan Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
API_VALIDATION_ERROR400 |
Each rank value for payment methods must be unique. Please check your request to deconflict the ranking. |
API_VALIDATION_ERROR400 |
Values in failed_attempt_notifications array cannot be duplicated or greater than total_retry value or the array values count greater than total_retry |
API_VALIDATION_ERROR400 |
The payment currency requested is not supported for this payment channel. Please refer to our API reference or docs to pick available currencies |
INVALID_PAYMENT_METHOD_ID400 |
The payment_method_id provided has a mismatched currency or it is not "ACTIVE" because it has expired/ been unlinked/ linking has not been completed. Please retry with a valid payment_method_id |
INVALID_API_KEY401 |
API key format is invalid |
PAYMENT_METHOD_ID_NOT_FOUND404 |
The payment_method_id provided is not found. Please retry with a valid payment_method_id |
CUSTOMER_NOT_FOUND404 |
customer_id is invalid or not found. Please try again with valid customer_id |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Plan - Deactivate
Recurring plans can be made inactive via this API. This will stop any new recurring cycles from being generated and for existing SCHEULED
cycles to be cancelled.
Endpoint: Deactivate Recurring Plan
POST https://api.xendit.co/recurring/plans/:id/deactivate
Request Parameters
Example: Deactivate Recurring Plan Request
curl https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f/deactivate -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f/deactivate',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => array(
'Authorization: Basic eG5kX2RldmVsb3BtZW50X09vbUFmT1V0aCtHb3dzWTZMZUpPSHpMQ1p0U2o4NEo5a1hEbitSeGovbUhXK2J5aERRVnhoZz09Og=='
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
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 |
Xendit-generated recurring plan ID, with prefix repl-xxx |
Response Parameters
Success responses will contain a single Plan Object with INACTIVE
status.
Error Codes
Example: Deactivate Recurring Plan Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
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 |
DATA_NOT_FOUND404 |
Recurring plan_id not found. Please check your query again. |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Plan - Fetch Object
Fetch information about created recurring plans via this API.
Endpoint: Get Recurring Plan
GET https://api.xendit.co/recurring/plans/:id/
Request Parameters
Example: Get Recurring Plan Request
curl https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f -X GET \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
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 |
Xendit-generated recurring plan ID, with prefix repl-xxx |
Response Parameters
Success responses will contain a single Plan Object.
Error Codes
Example: Get Recurring Plan Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
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 |
DATA_NOT_FOUND404 |
Recurring plan_id not found. Please check your query again. |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Plan - Get Cycles List
Fetch information about recurring cycles generated from the recurring plan via this API.
Endpoint: Get List of Cycles for Plan
GET https://api.xendit.co/recurring/plans/:id/cycles
Request Parameters
Example: Get List of Cycles for Plan Request
curl https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f/cycles -X GET \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--data '{
"limit": 2,
"after_id": "recy_239c16f4-866d-43e8-9341-7badafbc019f"
}' \
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 |
Xendit-generated recurring plan ID, with prefix repl-xxx |
Query Parameter | Type | Description |
---|---|---|
limitoptional |
number |
Indicating the maximum number of results to return at one time. This parameter MUST be optional for the client to provide and MUST have a default value of 10 (can be adjusted according to the resource that we are serving), for when the client does not provide a value |
after_idoptional |
string |
ID of the immediately previous item |
Response Parameters
Example: Get List of Cycles for Plan Response
{
"data": [
{
"id": "recy-AO12308u120jda",
"reference_id": "test_reference_id",
"customer_id": "cust-uhdquwy18237y213",
"recurring_action": "PAYMENT",
"type": "SCHEDULED",
"cycle_number": 2,
"attempt_count": 2,
"attempt_details": [
{
"attempt_number": 1,
"created": "2020-04-20T16:23:52Z",
"action_id": "ewc-asdaso213897821hdas",
"status": "SUCCEEDED",
"failure_code": null,
"next_retry_timestamp": null
},
{
"attempt_number": 1,
"created": "2020-04-20T16:23:52Z",
"action_id": "ewc-asdaso2138978trysecondmethod",
"status": "FAILTED",
"failure_code": "INSUFFICIENT_BALANCE",
"next_retry_timestamp": "2020-04-20T16:23:52Z"
}
],
"status": "SUCCEEDED",
"scheduled_timestamp": "2020-12-20T16:23:52Z",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"currency": "IDR",
"amount": 200000,
"metadata": null
}
],
"has_more": false
}
Body Parameter | Type | Description |
---|---|---|
datarequired |
array |
An array of Cycle Objects requested based on query parameters |
has_morerequired |
boolean |
A boolean parameter indicating whether there are more objects available but filtered out by limit of query parameters |
Error Codes
Example: Get List of Cycles for Plan Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
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 |
DATA_NOT_FOUND404 |
Recurring plan_id not found. Please check your query again. |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Cycle - Callback Events
Xendit notifies your system upon created, failed, successful, retrying cycles via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Cycle Creation Payload
The cycle creation webhook is a notification to inform your system of a upcoming cycle in the future. This webhook is triggered when a recurring plan has been successfully activated or when an upcoming recurring cycle has executed its first attempt at the recurring action (from SCHEDULED
status to PENDING
). For general use cases, it is recommended but not required to handle this webhook. For usage based subscriptions, it is required to handle this webhook.
Full details of webhooks can be found here
Example: Cycle Webhook Payload
{
"created": "2022-10-01T12:37:08.251Z",
"business_id": "62440e322008e87fb29c1fd0",
"event": "recurring.cycle.created",
"data": {
"id": "recy-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"type": "SCHEDULED",
"cycle_number": 1,
"attempt_count": 0,
"attempt_details": [],
"status": "SCHEDULED",
"scheduled_timestamp": "2020-12-20T16:23:52Z",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"currency": "IDR",
"amount": 13579
},
"api_version": "v1"
}
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - recurring.cycle.created |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for webhook notification creation. Timezone UTC+0. |
dataoptional |
object |
Cycle Object with SCHEDULED status |
api_versionoptional |
string |
Version value fixed as v1 |
Cycle Success Payload
The cycle success webhook is a notification to inform your system of a upcoming cycle in the future. This webhook is triggered when a recurring plan has been successfully activated or when an upcoming recurring cycle has executed its first attempt at the recurring action (from SCHEDULED
status to PENDING
)
Example: Cycle Success Payload
{
"created": "2022-10-01T12:37:08.251Z",
"business_id": "62440e322008e87fb29c1fd0",
"event": "recurring.cycle.succeeded",
"data": {
"id": "recy-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"type": "SCHEDULED",
"cycle_number": 1,
"attempt_count": 1,
"attempt_details": [
{
"attempt_number": 1,
"created": "2020-04-21T16:23:52Z",
"action_id": "ewc-239c16f4-866d-43e8-9341-7badafbc019f",
"status": "SUCCEEDED",
"Failure_code": null,
"next_retry_timestamp": null
}],
"status": "SUCCEEDED",
"scheduled_timestamp": "2020-12-20T16:23:52Z",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"currency": "IDR",
"amount": 13579
},
"api_version": "v1"
}
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - recurring.cycle.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for webhook notification creation. Timezone UTC+0. |
dataoptional |
object |
Cycle Object with SUCCEEDED status |
api_versionoptional |
string |
Version value fixed as v1 |
Cycle Retrying Payload
The cycle retrying webhook is a notification to inform your system an attempt at the recurring action has failed and the recurring cycle will attempt to perform the recurring action again. This webhook would only be triggered if a retry logic was configured in the recurring plan. For general use cases, it is recommended but not required to handle this webhook.
Example: Cycle Retrying Payload
{
"created": "2022-10-01T12:37:08.251Z",
"business_id": "62440e322008e87fb29c1fd0",
"event": "recurring.cycle.retrying",
"data": {
"id": "recy-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"type": "SCHEDULED",
"cycle_number": 1,
"attempt_count": 1,
"attempt_details": [
{
"attempt_number": 1,
"created": "2020-04-21T16:23:52Z",
"action_id": "ewc-239c16f4-866d-43e8-9341-7badafbc019f",
"status": "FAILED",
"Failure_code": "INSUFFICIENT_BALANCE",
"next_retry_timestamp": "2020-04-24T16:23:52Z"
}],
"status": "RETRYING",
"scheduled_timestamp": "2020-12-20T16:23:52Z",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"currency": "IDR",
"amount": 13579
},
"api_version": "v1"
}
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - recurring.cycle.retrying |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for webhook notification creation. Timezone UTC+0. |
dataoptional |
object |
Cycle Object with RETRYING status |
api_versionoptional |
string |
Version value fixed as v1 |
Cycle Failure Payload
The cycle failure webhook is a notification to inform your system that attempts at the recurring action and all the subsequent retries has failed.
Example: Cycle Failure Payload
{
"created": "2022-10-01T12:37:08.251Z",
"business_id": "62440e322008e87fb29c1fd0",
"event": "recurring.cycle.failed",
"data": {
"id": "recy-239c16f4-866d-43e8-9341-7badafbc019f",
"reference_id": "test_reference_id",
"customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
"recurring_action": "PAYMENT",
"type": "SCHEDULED",
"cycle_number": 1,
"attempt_count": 1,
"attempt_details": [
{
"attempt_number": 1,
"created": "2020-04-21T16:23:52Z",
"action_id": "ewc-239c16f4-866d-43e8-9341-7badafbc019f",
"status": "FAILED",
"Failure_code": "INSUFFICIENT_BALANCE",
"next_retry_timestamp": null
}],
"status": "FAILED",
"scheduled_timestamp": "2020-12-20T16:23:52Z",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"currency": "IDR",
"amount": 13579
},
"api_version": "v1"
}
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - recurring.cycle.failed |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for webhook notification creation. Timezone UTC+0. |
dataoptional |
object |
Cycle Object with FAILED status |
api_versionoptional |
string |
Version value fixed as v1 |
Cycle - Update
Recurring cycle can be updated via this API. Usage based subscription use cases should use this endpoint to update the amount for each specific billing instances.
Endpoint: Update Recurring Cycle
PATCH https://api.xendit.co/recurring/plans/:plan_id/cycles/:id
Request Parameters
Example: Update Recurring Cycle Request
curl https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f/cycles/recy-239c16f4-866d-43e8-9341-7badafbc019f -X PATCH \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--data '{
"scheduled_timestamp": "2020-12-20T16:23:52Z",
"currency": "IDR",
"amount": 200000
}' \
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 |
---|---|---|
plan_idrequired |
string |
Xendit-generated recurring plan ID, with prefix repl-xxx |
idrequired |
string |
Xendit-generated recurring cycle ID, with prefix recy-xxx |
Body Parameter | Type | Description |
---|---|---|
scheduled_timestampoptional |
string |
ISO 8601 Timestamp (e.g. "2020-04-20T00:00:00Z" UTC+0) for the upcoming action attempt for the recurring cycle - value is updated on each retry (if any). Action will be executed within 24 hours of the scheduled timestamp with timezone taken into consideration. |
currencyoptional |
enum |
ISO 4217 currency code of recurring plan. Supported currency - IDR, PHP |
amountoptional |
number |
Amount that recurring plan will charge to end users. Recurring cycles will be generated based on this value. If items param is used, amount should be equivalent to the sum of net_unit_amount multiplied by quantity in the items array Min IDR - 1000 Min PHP - 50 maximum amount is dependent on payment providers |
Response Parameters
Success responses will contain a single Cycle Object.
Error Codes
Example: Update Recurring Cycle Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
API_VALIDATION_ERROR400 |
Parameter scheduled_timestamp cannot be in the past. Please check your request body |
INVALID_API_KEY401 |
API key format is invalid |
INELIGIBLE_CYCLE_REQUEST403 |
Requested changes to cycle cannot be processed. Only cycles in "SCHEDULED" status can be cancelled or updated |
DATA_NOT_FOUND404 |
Recurring cycle_id not found. Please check your query again. |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Cycle - Cancel
Recurring cycles can be made cancelled via this API. This will the recurring cycles from processing any actions.
Endpoint: Cancel Recurring Cycle
POST https://api.xendit.co/recurring/plans/:plan_id/cycles/:id/cancel
Request Parameters
Example: Cancel Recurring Cycle Request
curl https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f/cycles/recy-239c16f4-866d-43e8-9341-7badafbc019f/cancel -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json'
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f/cycles/recy-239c16f4-866d-43e8-9341-7badafbc019f/cancel',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => array(
'Authorization: Basic eG5kX2RldmVsb3BtZW50X09vbUFmT1V0aCtHb3dzWTZMZUpPSHpMQ1p0U2o4NEo5a1hEbitSeGovbUhXK2J5aERRVnhoZz09Og=='
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Path Parameter | Type | Description |
---|---|---|
plan_idrequired |
string |
Xendit-generated recurring plan ID, with prefix repl-xxx |
idrequired |
string |
Xendit-generated recurring cycle ID, with prefix recy-xxx |
Response Parameters
Success responses will contain a single Cycle Object with CANCELLED
status.
Error Codes
Example: Cancel Recurring Cycle Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
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 |
UNSUPPORTED_CONTENT_TYPE403 |
The content type requested is not supported |
INELIGIBLE_CYCLE_REQUEST403 |
Requested changes to cycle cannot be processed. Only cycles in "SCHEDULED" status can be cancelled or updated |
DATA_NOT_FOUND404 |
Recurring plan_id not found. Please check your query again. |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Cycle - Force Cycle Attempt
Endpoint for merchants to manually force an attempt for the specified action of a recurring cycle. Please refer to our force cycle attempt docs for more details.
Endpoint: Force Cycle Attempt
POST https://api.xendit.co/recurring/plans/:id/cycles/:id/force_attempt
Request Parameters
Example: Force Cycle Attempt Request
curl https://api.xendit.co/recurring/plans/repl_532as23lew2321id/cycles/recy_5832948hjkeqw12/force_attempt -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
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 |
---|---|---|
plan_idrequired |
string |
Xendit-generated recurring plan ID, with prefix repl-xxx |
idrequired |
string |
Xendit-generated recurring cycle ID, with prefix recy-xxx |
Response Parameters
Return Cycle Object with status code 200 and status PENDING
Example: Force Cycle Attempt Response
{
"id": "repl-AO12308u120jda",
"reference_id": "test_reference_id",
"customer_id": "cust-uhdquwy18237y213",
"recurring_action": "PAYMENT",
"type": "SCHEDULED",
"cycle_number": 2,
"attempt_count": 1,
"attempt_details": [{
"attempt_number": null,
"created": "2020-04-20T16:23:52Z",
"action_id": "ewc-asdaso213897821hdas",
"status": "SUCCEEDED",
"failure_code": null,
"next_retry_timestamp": null
},
{
"attempt_number": 1,
"created": "2020-04-20T16:23:52Z",
"action_id": "ewc-asdaso2138978trysecondmethod",
"status": "FAILTED",
"failure_code": "INSUFFICIENT_BALANCE",
"next_retry_timestamp": "2020-04-20T16:23:52Z"
}],
"status": "PENDING",
"scheduled_timestamp": "2020-12-20T16:23:52Z",
"created": "2020-11-20T16:23:52Z",
"updated": "2020-11-20T16:23:52Z",
"currency": "IDR",
"amount": 200000
}
Error Codes
Example: Update Recurring Cycle Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
Error Code | Description |
---|---|
INELIGIBLE_CYCLE_REQUEST403 |
Requested attempt trigger for this cycle cannot be processed. Only cycles in SCHEDULED or RETRYING status are eligible for Force Attempt. |
MAXIMUM_LIMIT_REACHED403 |
Maximum number (5) of force attempts have been reached |
DATA_NOT_FOUND404 |
Recurring cycle_id not found. Please check your query again. |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Cycle - Fetch Object
Fetch information about generated recurring cycles via this API.
Endpoint: Get Recurring Cycle
GET https://api.xendit.co/recurring/plans/:plan_id/cycles/:id
Request Parameters
Example: Get Recurring Cycle Request
curl https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f/cycles/recy-239c16f4-866d-43e8-9341-7badafbc019f -X GET \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
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 |
---|---|---|
plan_idrequired |
string |
Xendit-generated recurring plan ID, with prefix repl-xxx |
idrequired |
string |
Xendit-generated recurring cycle ID, with prefix recy-xxx |
Response Parameters
Success responses will contain a single Cycle Object.
Error Codes
Example: Cancel Recurring Cycle Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
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 |
UNSUPPORTED_CONTENT_TYPE403 |
The content type requested is not supported |
DATA_NOT_FOUND404 |
Recurring cycle_id not found. Please check your query again. |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Cycle - Simulate Status
(Works only in Test Mode) To enable testing for subsequent recurring cycles, this endpoint helps merchants simulate whether a recurring actions (e.g. payments) has been successful or not. Please ensure that you are using development API key for this purpose. Xendit payments uses specific numbers in amount
parameter to simulate a success/ failed status. Please follow our documentation to simulate the error you need.
Endpoint: Simulate Recurring Cycle
POST https://api.xendit.co/recurring/plans/:plan_id/cycles/:id/simulate
Request Parameters
Example: Simulate Recurring Cycle Request
curl https://api.xendit.co/recurring/plans/repl-239c16f4-866d-43e8-9341-7badafbc019f/cycles/recy-239c16f4-866d-43e8-9341-7badafbc019f -X PATCH \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--data '{
"amount": 200000
}' \
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 |
---|---|---|
plan_idrequired |
string |
Xendit-generated recurring plan ID, with prefix repl-xxx |
idrequired |
string |
Xendit-generated recurring cycle ID, with prefix recy-xxx |
Body Parameter | Type | Description |
---|---|---|
amountrequired |
number |
Amount to be simulated |
Response Parameters
Success responses will contain a single Cycle Object.
Error Codes
Example: Update Recurring Cycle Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
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 |
INELIGIBLE_CYCLE_REQUEST403 |
Requested changes to cycle cannot be processed. Only cycles in "SCHEDULED" status can be cancelled or updated |
DATA_NOT_FOUND404 |
Recurring cycle_id not found. Please check your query again. |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Schedule - Update
Recurring schedule can be updated via this API to populate changes to newly generated recurring cycles. If changes need to be applied to recurring cycles that have been scheduled, include update-scheduled-cycle
parameter in request header.
Endpoint: Update Recurring Schedule
PATCH https://api.xendit.co/recurring/schedules/:id
Request Parameters
Example: Update Recurring Schedule Request
curl https://api.xendit.co/recurring/schedules/resc-239c16f4-866d-43e8-9341-7badafbc019f -X PATCH \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
--data '{
"interval" : "MONTH",
"interval_count" : 1,
"total_recurrence" : 12,
"anchor_date" : "2020-11-20T16:23:52Z",
"retry_interval" : "DAY",
"retry_interval_count" : 5,
"total_retry" : 5,
"failed_attempt_notifications" : [2,4]
}' \
Path Parameter | Type | Description |
---|---|---|
idrequired |
string |
Xendit-generated recurring schedule ID, with prefix resc-xxx |
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 |
---|---|---|
intervaloptional |
enum |
The type of interval between consecutive recurring cycles. Supported values - DAY, WEEK, MONTH WEEK - the day of the week which anchor_date lands on (e.g. anchor_date lands on Wed, subsequent cycles will be on Wed) MONTH - the date of the month which anchor_date lands on (anchor_date lands on the 25th, subsequent cycles will be on the 25th) |
interval_countoptional |
number |
The number of units of interval between consecutive recurring cycles (e.g. interval = MONTH, interval_count = 3, then recurring cycle happens every 3 month) |
total_recurrenceoptional |
number |
Default = NULL The total number of times the end user will be charged. The immediate charge instance does not count to total_recurrence . If the parameter is not used, recurring plan will run on indefinitely |
anchor_dateoptional |
string |
Default = the date of schedule creation (same day action). Timestamp in ISO 8601 ("2020-11-20T16:23:52+07:00"). A timestamp used to determine when a recurring plan starts. The date, day of week or date of month will be used to initialize the recurring cycle (back dated timestamps still works). If a timezone passed in, the recurring event will be executed based on the timezone, else UTC 0 wil be used. Supported values - Timestamps between 1st to 28th of a month If no anchor_date value is passed and date of schedule creation falls on 29/30/31, anchor date will be defaulted to 1st of next month |
retry_intervaloptional |
enum |
The type of interval between failed attempt and retries. Supported values - DAY |
retry_interval_countoptional |
number |
The number of units of retry_interval between consecutive retries (e.g. retry_interval = DAY, retry_interval_count = 3, then recurring cycle retries 3 days after a failed attempt) |
total_retryoptional |
number |
The number of times you will retry a failed recurring cycle. If no value is passed into total_retry , it will be null by default and no retries will be triggered Min - 1 Max - 10 |
failed_attempt_notificationsoptional |
string |
Specify which retry attempts will have failed recurring notifications to the end user. Array values count should not be greater than total_retry number or duplicated. 1 in this param refers to the first retry attempt. |
Response Parameters
Success responses will contain a single Schedule Object.
Error Codes
Example: Update Recurring Schedule Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
Error Code | Description |
---|---|
API_VALIDATION_ERROR400 |
There is invalid input in one of the required request fields |
API_VALIDATION_ERROR400 |
Each rank value for payment methods must be unique. Please check your request to deconflict the ranking. |
API_VALIDATION_ERROR400 |
Values in failed_attempt_notifications array cannot be duplicated or greater than total_retry value or the array values count greater than total_retry |
API_VALIDATION_ERROR400 |
anchor_date does not accept dates from 29 to 31. Please check your request body to specify all values |
INVALID_API_KEY401 |
API key format is invalid |
DATA_NOT_FOUND404 |
Recurring schedule_id not found. Please check your query again. |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Schedule - Fetch Object
Fetch information about created recurring schedule via this API.
Endpoint: Get Recurring Schedule
GET https://api.xendit.co/recurring/schedules/:id
Request Parameters
Example: Get Recurring Schedule Request
curl https://api.xendit.co/recurring/schedules/resc-239c16f4-866d-43e8-9341-7badafbc019f -X GET \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'content-type: application/json' \
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 |
Xendit-generated recurring schedule ID, with prefix resc-xxx |
Response Parameters
Success responses will contain a single Schedule Object.
Error Codes
Example: Update Recurring Schedule Request API Error Response
{
"error_code": "API_VALIDATION_ERROR",
"message": "There is an error with the format submitted to the server."
}
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 |
DATA_NOT_FOUND404 |
Recurring schedule_id not found. Please check your query again. |
UNSUPPORTED_CONTENT_TYPE415 |
The content type requested is not supported |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
xenPlatform
Description
xenPlatform is Xendit's solution for platform businesses that work with third-party partners. Platform businesses face complex payments challenges that range from partner onboarding, to moving funds, to payouts and billing.
With xenPlatform, you can onboard and create accounts for your partners, transact on behalf of them, split payments, monitor their transactions, and directly bill them.
Overview
Once xenPlatform has been activated for your account, you may use the Account API to create sub accounts that are linked to your master account.
Thereafter simply include a for-user-id
header in any standard Xendit API call to create a transaction for those accounts.
These accounts and their transactions will appear in the xenPlatform tab of your Xendit dashboard.
Create Account
The Create Account API allows you to create Accounts for your Partners that are linked to your Platform. Once an Account is created, you may accept payments on its behalf. Additionally, you can route payments to/from the Account via the Transfers API or Platform fee API.
There are two types of Accounts that can be created: MANAGED
, OWNED
. Review our documentation for recommendations on which Account type to use for your business model.
MANAGED
Accounts provide your Partners with full-fledged Xendit Accounts that your Platform can transact on behalf of. Your Partners may register their Account via an invitation email is sent to the email. Thereafter, your Partners login to their own Xendit dashboard to complete the onboarding process.
OWNED
Accounts are invisible to your Partners and fully controlled by you. You may transact on behalf of an OWNED
Account once they have been created using payment methods that have been enabled on your Platform.
You can also choose to configure the account yourself using the configurations
parameter below, instead of specifying a type.
Store the returned account id
value to make transactions for that Account in the future.
Make 2 API calls to accept payments on behalf of your Partners:
- Create an Account (this step)
- Create a payment transaction and handling related Callbacks
Note: Newly enabled payment methods and changes made to Callback URLs on the Platform do not automatically update for OWNED
Accounts created before those updates. We recommend activating payment methods you need and setting up your Callback URLs on the dashboard before creating OWNED
Accounts.
Alternatively, use the Set Callback URLs API, or contact us when you need to make a change.
Version
This version of the API is asynchronous
to improve performance and scalability. We have also added API permissions in this version. If you are using an existing API key, please edit your permissions in your Settings page.
It is mandatory to wait for the account.created
callback before attempting to create transactions. Set a Callback URL in your Dashboard to receive Account Updated Callbacks and know when payments can be processed for your Accounts.
Endpoint: Create Account
POST https://api.xendit.co/v2/accounts
Request Parameters
Example: Create Account (OWNED)
curl --request POST \
--url https://api.xendit.co/v2/accounts \
--header 'Authorization: Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==' \
--header 'Content-Type: application/json' \
--data '{"email":"angie@pinkpanther.com","type":"OWNED","public_profile":{"business_name":"Angie lemonade stand"}}'
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.xendit.co/v2/accounts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"email\":\"angie@pinkpanther.com\",\"type\":\"OWNED\",\"public_profile\":{\"business_name\":\"Angie lemonade stand\"}}",
CURLOPT_HTTPHEADER => [
"Authorization: Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("api.xendit.co")
payload = "{\"email\":\"angie@pinkpanther.com\",\"type\":\"OWNED\",\"public_profile\":{\"business_name\":\"Angie lemonade stand\"}}"
headers = {
'Content-Type': "application/json",
'Authorization': "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og=="
}
conn.request("POST", "/v2/accounts", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
Example: Create Account (CUSTOM)
curl --request POST \
--url https://api.xendit.co/v2/accounts \
--header 'Authorization: Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==' \
--header 'Content-Type: application/json' \
--data '{"email":"angie@pinkpanther.com","public_profile":{"business_name":"Angie lemonade stand"},"configurations":{"has_dashboard":true,"payment_settings_follow_platform":true,"has_withdrawal":false}}'
Body Parameter | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
email required |
string |
Email identifier for your account
|
||||||
type optional |
string |
The type of account you are creating. Defaults to CUSTOM if not specified, and will require the configurations parameter. Available values:
|
||||||
public_profile required for
|
object |
Contains information that will be seen by end-payers or end-recipients (e.g. appears on hosted checkout page, credit card statements, etc.).
|
||||||
configurations required if
|
object |
Contains the configurations for CUSTOM sub-accounts
|
Response Parameters
Example: Create Account Response (OWNED)
{
"id": "5cafeb170a2b18519b1b8761",
"created": "2021-01-01T10:00:00Z",
"updated": "2021-01-01T10:00:00Z",
"type": "OWNED",
"email": "angie@pinkpanther.com",
"public_profile": {
"business_name": "Angie lemonade stand"
},
"status": "LIVE"
}
Example: Create Account Response (CUSTOM)
{
"id": "5cafeb170a2b18519b1b8761",
"created": "2021-01-01T10:00:00Z",
"updated": "2021-01-01T10:00:00Z",
"type": "CUSTOM",
"email": "angie@pinkpanther.com",
"public_profile": {
"business_name": "Angie custom stand"
},
"status": "LIVE",
"configurations": {
"has_dashboard": true,
"payment_settings_follow_platform": true,
"has_withdrawal": false
}
}
Parameter | Type | Description |
---|---|---|
id required |
string |
ID of your Account, use this in the for-user-id header to create transactions on behalf of your Account |
created required |
string |
Timestamp of when the account was created Timezone:
|
updated required |
string |
Timestamp of when the account was updated Timezone:
|
type required |
string |
The type of account created Available values:
|
email required |
string |
Email identifier for the Account |
public_profile required |
object |
Contains information that will be seen by end-payers or end-recipients (e.g. appears on hosted checkout page, credit card statements, etc.). |
country required |
string |
The country (based on ISO 3166-1 Alpha-2) of incorporation for a business, or the country of residence for an individual. Available values: |
status required |
string |
Status of the Account you are creating. Available values: |
configurations optional |
object |
Contains the configurations for CUSTOM sub-accounts.Parameters available: payment_settings_follow_platform , has_withdrawal , has_dashboard |
Error Codes
Error Code | Error Message |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INVALID_CONFIGURATION400 |
The configurations parameter combination is invalid. Please follow the requirement of each parameter written in Request section. |
TYPE_AND_CONFIGURATION_CONFLICT400 |
Please provide either one of the type field or the configuration field |
Get Account by ID
Use the Get Account by ID endpoint to retrieve the relevant Account object.
Endpoint: Get Account
GET https://api.xendit.co/v2/accounts/{id}
Path Parameters
Parameter | Type | Description |
---|---|---|
id required |
string |
ID of an Account |
Example: Get Account
curl --request GET \
--url https://api.xendit.co/v2/accounts/5cafeb170a2b18519b1b8761 \
--header 'Authorization: Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og=='
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.xendit.co/v2/accounts/5cafeb170a2b18519b1b8761",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og=="
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("api.xendit.co")
headers = { 'Authorization': "Basic eG5kX2RldmVsb3BtZW50X1A0cURmT3NzME9DcGw4UnRLclJPSGphUVlOQ2s5ZE41bFNmaytSMWw5V2JlK3JTaUN3WjNqdz09Og==" }
conn.request("GET", "/v2/accounts/5cafeb170a2b18519b1b8761", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
Response Parameters
Example: Create Account Response
{
"id": "5cafeb170a2b18519b1b8761",
"created": "2021-01-01T10:00:00Z",
"updated": "2021-01-01T10:00:00Z",
"type": "OWNED",
"email": "angie@pinkpanther.com",
"public_profile": {
"business_name": "Angie lemonade stand"
},
"status": "LIVE"
}
Parameter | Type | Description |
---|---|---|
id required |
string |
ID of your Account, use this in the for-user-id header to create transactions on behalf of your Account |
created required |
string |
Timestamp of when the account was created Timezone:
|
updated required |
string |
Timestamp of when the account was updated Timezone:
|
type required |
string |
The type of account created Available values:
|
email required |
string |
Email identifier for the Account |
public_profile required |
object |
Contains information that will be seen by end-payers or end-recipients (e.g. appears on hosted checkout page, credit card statements, etc.). |
country required |
string |
The country (based on ISO 3166-1 Alpha-2) of incorporation for a business, or the country of residence for an individual. Available values: |
status required |
string |
Status of the Account you are creating. Available values:
|
List Accounts
Endpoint: List Accounts
GET https://api.xendit.co/v2/accounts
Use this endpoint to gather information regarding all of your sub accounts. You can also gather information regarding a particular sub account through filtering by email, sub account creation date, sub account type, sub account name, or status. The result will be paginated and ordered by the sub account creation date.
Request Parameters
Example List Transactions Request
curl --location --request GET 'https://api.xendit.co/v2/accounts' -X POST \
--user xnd_development_ksdjimLskjdwuasndjjwas \
--header Content-Type: application/json' \
<?php
$url = "https://api.xendit.co/v2/accounts";
$payload = array();
$headers = array(
'Content-Type: application/json',
'Authorization: Basic xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg=='
);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import requests
url = "https://api.xendit.co/v2/accounts"
payload={}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Basic xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg=='
}
response = requests.request("GET", url, headers=headers, data=payload)
url := "https://api.xendit.co/v2/accounts"
payload := strings.NewReader("")
req, _ := http.NewRequest("GET", url, payload)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Basic xnd_development_O46JfOtygef9kMNsK+ZPGT+TeStIngw3Dn+R1k+2fT/7GlCAN3jg==")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
Query Parameter | Type | Description |
---|---|---|
email optional |
array of strings |
The email of the accounts that will be filtered. If not specified, all account emails will be returned. |
status optional |
array of strings |
The status of the transactions that will be filtered. If not specified, all account status will be returned. Available status: INVITED ,REGISTERED ,AWAITING_DOCS ,LIVE ,SUSPENDED . |
public_profile.business_name optional |
string |
The public profile or business name of the accounts that will be filtered. If not specified, all account business name will be returned. This is the business name specified during account creation |
type optional |
string |
The type of accounts that will be filtered. If not specified, all account types will be returned. Available type: OWNED ,MANAGED . |
created[gte] optional |
string (ISO 8601) |
Start time of accounts by created date. If not specified will list all dates. |
created[lte] optional |
string (ISO 8601) |
End time of accounts by created date. If not specified will list all dates. |
updated[lte] optional |
string (ISO 8601) |
End time of accounts by updated date. If not specified will list all dates. |
updated[gte] optional |
string (ISO 8601) |
Start time of accounts by updated date. If not specified will list all dates. |
limit optionaldefault:
|
number |
A limit on the number of transactions to be returned for each request. Limit can range between 1 and 50. |
after_id optional |
string |
Id of the immediately previous item. Use this with links on the response for pagination. |
before_id optional |
string |
Id of the immediately following item. |
Response Parameters
Returns array of the Account object as follows:
Example List Accounts Response
{
"data": [
{
"id": "623ace8270bbddf93816b3a1",
"created": "2022-02-10T07:13:19.602Z",
"updated": "2022-02-10T07:13:22.193Z",
"email": "sample_email@sample.com",
"type": "OWNED",
"public_profile": {
"business_name": "Sample OWNED Business"
},
"country": "ID",
"status": "LIVE"
},
{
"id": "623ace8270bbddf93816b3g1",
"created": "2022-03-23T07:38:42.166Z",
"updated": "2022-03-23T07:39:55.440Z",
"email": "sample_email2@sample.com",
"type": "MANAGED",
"public_profile": {
"business_name": "Sample MANAGED Business"
},
"country": "ID",
"status": "REGISTERED"
}
],
"has_more": true,
"links": [
{
"href": "/v2/accounts?after_id=623ace8270bbddf93816b3g1",
"rel": "next",
"method": "GET"
}
]
}
Parameter | Type | Description |
---|---|---|
id required |
string |
ID of your Account, use this in the for-user-id header to create transactions on behalf of your Account |
created required |
string |
Timestamp of when the account was created Timezone:
|
updated required |
string |
Timestamp of when the account was updated Timezone:
|
type required |
string |
The type of account created Available values:
|
email required |
string |
Email identifier for the Account |
public_profile required |
object |
Contains information that will be seen by end-payers or end-recipients (e.g. appears on hosted checkout page, credit card statements, etc.). |
country required |
string |
The country (based on ISO 3166-1 Alpha-2) of incorporation for a business, or the country of residence for an individual. Available values: |
status required |
string |
Status of the Account you are creating. Available values:
|
Error Codes
See other common errors here.
Update Account
Use the Update Account endpoint to update your Accounts' business name and email. This operation is currently only enabled for OWNED
accounts.
Version
You are currently viewing the newest version of our Update Accounts API.
Endpoint: Update Account
PATCH https://api.xendit.co/v2/accounts/{id}
Example: Update Account
curl https://api.xendit.co/v2/accounts/{id} -X PATCH \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
-d $'{"email":"angie@pinkpanther.com","public_profile":{"business_name":"Angie\'s lemonade stand"}}'
<?php
$url = 'https://api.xendit.co/v2/accounts/{id}';
$apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==';
$headers = [];
$headers[] = 'Content-Type: application/json';
$data = [
'email' => 'angie@pinkpanther.com',
'public_profile' => [
'business_name' => 'Angie\'s lemonade stand'
]
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH');
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
Path Parameters
Path Parameter | Type | Description |
---|---|---|
id required |
string |
The id of the Account created |
Request Parameters
Request Parameter | Type | Description | ||
---|---|---|---|---|
email required |
string |
Email identifier for your account
|
||
public_profile required for OWNED, else optional |
object |
Contains information that will be seen by end-payers or end-recipients (e.g. appears on hosted checkout page, credit card statements, etc.).
|
Response Parameters
Example: Update Account Response
{
"id": "5cafeb170a2b18519b1b8761",
"created": "2021-01-01T10:00:00Z",
"updated": "2021-01-01T11:00:00Z",
"type": "OWNED",
"email": "angie@pinkpanther.com",
"public_profile": {
"business_name": "Angie lemonade stand"
},
"status": "LIVE"
}
Parameter | Type | Description |
---|---|---|
id required |
string |
ID of your Account, use this in the for-user-id header to create transactions on behalf of your Account |
created required |
string |
Timestamp of when the account was created Timezone:
|
updated required |
string |
Timestamp of when the account was updated Timezone:
|
type required |
string |
The type of account created Available values:
|
email required |
string |
Email identifier for the Account |
public_profile required |
object |
Contains information that will be seen by end-payers or end-recipients (e.g. appears on hosted checkout page, credit card statements, etc.). |
country required |
string |
The country (based on ISO 3166-1 Alpha-2) of incorporation for a business, or the country of residence for an individual. Available values: |
status required |
string |
Status of the Account you are creating. Available values: |
Account Holder Object
Example of Account Holder Object
{
"id": "4376b7b0-1c44-46be-8640-828f79cdc8be",
"business_detail": {
"type": "CORPORATION",
"legal_name": "test16",
"description": "testing",
"trading_name": "test",
"industry_category": "ACCOMMODATION",
"country_of_operation": "PH",
"date_of_registration": "2023-02-02T00:00:00.000Z"
},
"individual_details": {
"email": "test@xendit.co",
"gender": "MALE",
"surname": "test",
"given_names": "test",
"nationality": "PH",
"phone_number": "+63021234567",
"date_of_birth": "2000-02-02T00:00:00.000Z",
"place_of_birth": "PH",
"type": "PIC",
"role": "owner"
},
"address": {
"city": "test1",
"country": "PH",
"district": "test",
"postal_code": "1111",
"street_line1": "test",
"street_line2": "test",
"sub_district": "test",
"province_state": "test"
},
"kyc_documents": [
{
"type": "SEC_CERTIFICATE_REGISTRATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "ARTICLES_OF_INCORPORATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "NOTARIZED_SECRETARY_CERTIFICATE_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "LATEST_GIS_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "ACR_OR_IMMIGRANT_COR_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "SERVICE_AGREEMENT_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
}
],
"website_url": "https://xendit.co",
"phone_number": "+63281234567",
"email": "test@xendit.co",
"kyc": {
"status": "NOT_VERIFIED"
},
"created": "2023-03-30T11:41:57.881Z",
"updated": "2023-03-30T11:44:01.122Z"
}
Parameters
Please note that the required object parameters differ for each country. Refer to this guide for the complete requirements. This list of parameters covers the Philippines.
Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Xendit-generated unique identifier for each Account Holder. You will need to store this ID in order to link it to an Account later |
||||||||||||||||||||||||||||||||||||||||||
business_detailrequired |
object |
An object containing the business detail of the Account Holder Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||
individual_detailsrequired |
array[object] |
An object containing the individual details of the Account Holder. This could be the details of the business owner, director etc. You may submit multiple PIC (Person in Charge) for your business in this object. Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||
addressrequired |
object |
Object containing the business address of the respective Account Holder
|
||||||||||||||||||||||||||||||||||||||||||
kyc_documentsrequired |
object |
Object containing the any file type or documents required to be submitted by the account Account Holder (e.g National ID, Selfie etc.)
|
||||||||||||||||||||||||||||||||||||||||||
website_urlrequired |
string |
Company website or social media website page URL Maximum length 255 charactersMinimum length 1 character |
||||||||||||||||||||||||||||||||||||||||||
phone_numberrequired |
string |
Contact number of the Account Holder in E.164 format. This may also be a landline Maximum length 30 charactersMinimum length 1 character |
||||||||||||||||||||||||||||||||||||||||||
emailrequired |
string |
Email address of the Account Holder Maximum length 255 charactersMinimum length 1 character |
||||||||||||||||||||||||||||||||||||||||||
kycrequired |
array[object] |
An object containing the details of the Account Holder KYC verification process Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||
capabilitiesoptional |
array[object] |
An object containing the details of the Account Holder capabilities activation process Individual detail child parameters
|
Create Account Holder
An Account Holder represents the legal entity that holds the Xendit Account that is created in your Platform. In order to onboard an account, you need to complete the 2 following steps:
- Create Account
- Create Account Holder
The details that you need to provide in the request depend on the Account holders' legal entity type. Please refer to our documentation for full requirements
Endpoint: Create Account Holder
POST https://api.xendit.co/account_holders
Request Parameters
Please note that the required object parameters differ for each country. Refer to this guide for the complete requirements. This list of parameters covers the Philippines.
Example Create Account Holder Request
curl https://api.xendit.co/account_holders -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
--data-raw '{
"business_detail": {
"type": "INDIVIDUAL",
"legal_name": "test17",
"trading_name": "test",
"description": "testing",
"industry_category": "ACCOMMODATION",
"date_of_registration": "2023-02-02",
"country_of_operation":"PH"
},
"individual_details": [{
"given_names": "test",
"surname": "test",
"phone_number": "+63021234567",
"email": "test@xendit.co",
"nationality": "PH",
"place_of_birth": "PH",
"date_of_birth": "2000-02-02",
"gender": "MALE"
"type": "PIC",
"role": "owner"
}],
"address": {
"city": "test1",
"country": "PH",
"district": "test",
"postal_code": "1111",
"street_line1": "test",
"street_line2": "test",
"sub_district": "test",
"province_state": "test"
},
"kyc_documents": [
{
"type": "SELFIE_WITH_PRIMARY_ID_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "ACR_OR_IMMIGRANT_COR_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "SERVICE_AGREEMENT_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2"
}
],
"website_url": "https://xendit.co",
"phone_number": "+63281234567",
"email": "test@xendit.co"
}'
Example of Create Account Holder Request for Corporation entity type in the Phillippines
{
"business_detail": {
"type": "CORPORATION",
"legal_name": "test17",
"trading_name": "test",
"description": "testing",
"industry_category": "ACCOMMODATION",
"date_of_registration": "2023-02-02",
"country_of_operation":"PH"
},
"individual_details": [{
"given_names": "test",
"surname": "test",
"phone_number": "+63021234567",
"email": "test@xendit.co",
"nationality": "PH",
"place_of_birth": "PH",
"date_of_birth": "2000-02-02",
"gender": "MALE",
"type": "PIC",
"role": "owner"
}],
"address": {
"city": "test1",
"country": "PH",
"district": "test",
"postal_code": "1111",
"street_line1": "test",
"street_line2": "test",
"sub_district": "test",
"province_state": "test"
},
"kyc_documents": [
{
"type": "SEC_CERTIFICATE_REGISTRATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
},
{
"type": "ARTICLES_OF_INCORPORATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "NOTARIZED_SECRETARY_CERTIFICATE_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "LATEST_GIS_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "ACR_OR_IMMIGRANT_COR_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "SERVICE_AGREEMENT_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2"
}
],
"website_url": "https://xendit.co",
"phone_number": "+63281234567",
"email": "test@xendit.co"
}
Example of Create Account Holder Request for Corporation entity type in Indonesia
{
"business_detail": {
"type": "CORPORATION",
"legal_name": "test17",
"trading_name": "test",
"description": "testing",
"industry_category": "EDUTECH",
"tax_identification_number": "1234567891345678",
"business_identification_number": "1234567",
"initial_deed_of_establishment_status": "UNCHANGED",
"country_of_operation": "ID"
},
"individual_details": [{
"role": "owner",
"given_names": "Adrian",
"surname": "Fauzi",
"phone_number": "+6281234567",
"email": "test@xendit.co",
"passport_number": "ABC12345",
"ktp_number": "1234567891345678"
}],
"address": {
"city": "test1",
"country": "ID",
"district": "test",
"postal_code": "1111",
"street_line1": "test",
"street_line2": "test",
"sub_district": "test",
"province_state": "test"
},
"kyc_documents": [
{
"type": "AUTHORIZED_PERSON_KTP_DOCUMENT",
"country": "ID",
"file_id": "63f8719642f5856dcb142bd2",
},
{
"type": "SELFIE_WITH_KTP_DOCUMENT",
"country": "ID",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "NIB_DOCUMENT",
"country": "ID",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "DEED_OF_COMPANY_ESTABLISHMENT_DOCUMENT",
"country": "ID",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "CORPORATE_TAX_ID_DOCUMENT",
"country": "ID",
"file_id": "63f8719642f5856dcb142bd2"
},
{
"type": "SERVICE_AGREEMENT_DOCUMENT",
"country": "ID",
"file_id": "63f8719642f5856dcb142bd2"
}
],
"website_url": "https://xendit.co",
"phone_number": "+6281234567",
"email": "test@xendit.co"
}
Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
business_detailrequired |
object |
An object containing the business detail of the Account Holder Child parameters
|
||||||||||||||||||||||||||||||||||||||||||
individual_detailsrequired |
array[object] |
An object containing the individual details of the Account Holder. This could be the details of the business owner, director etc. You may submit multiple PIC (Person in Charge) for your business in this object. Child parameters
|
||||||||||||||||||||||||||||||||||||||||||
addressrequired |
object |
Object containing the business address of the respective Account Holder
|
||||||||||||||||||||||||||||||||||||||||||
kyc_documentsrequired |
object |
Object containing the any file type or documents required to be submitted by the account Account Holder (e.g National ID, Selfie etc.)
|
||||||||||||||||||||||||||||||||||||||||||
website_urlrequired |
string |
Company website or social media website page URL Maximum length 255 charactersMinimum length 1 character |
||||||||||||||||||||||||||||||||||||||||||
phone_numberrequired |
string |
Contact number of the Account Holder in E.164 format. This may also be a landline Maximum length 30 charactersMinimum length 1 character |
||||||||||||||||||||||||||||||||||||||||||
emailrequired |
string |
Email address of the Account Holder Maximum length 255 charactersMinimum length 1 character |
Response Parameters
Example: Create Account Holder Response
{
"id": "4376b7b0-1c44-46be-8640-828f79cdc8be",
"business_detail": {
"type": "CORPORATION",
"legal_name": "test16",
"description": "testing",
"trading_name": "test",
"industry_category": "ACCOMMODATION",
"country_of_operation": "PH",
"date_of_registration": "2023-02-02T00:00:00.000Z"
},
"individual_details": {
"email": "test@xendit.co",
"gender": "MALE",
"surname": "test",
"given_names": "test",
"nationality": "PH",
"phone_number": "+63021234567",
"date_of_birth": "2000-02-02T00:00:00.000Z",
"place_of_birth": "PH"
"type": "PIC",
"role": "owner"
},
"address": {
"city": "test1",
"country": "PH",
"district": "test",
"postal_code": "1111",
"street_line1": "test",
"street_line2": "test",
"sub_district": "test",
"province_state": "test"
},
"kyc_documents": [
{
"type": "SEC_CERTIFICATE_REGISTRATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "ARTICLES_OF_INCORPORATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "NOTARIZED_SECRETARY_CERTIFICATE_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "LATEST_GIS_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "ACR_OR_IMMIGRANT_COR_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "SERVICE_AGREEMENT_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
}
],
"website_url": "https://xendit.co",
"phone_number": "+63281234567",
"email": "test@xendit.co",
"kyc": {
"status": "NOT_VERIFIED"
},
"created_at": "2023-03-30T11:41:57.881Z",
"updated_at": "2023-03-30T11:44:01.122Z"
}
Returns Account Holder object with status 200
Error Codes
Error Code | Error Message |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
REQUEST_FORBIDDEN_ERROR 403 |
The API key is forbidden to perform this request. You need to use the Platform API key with Account Holder write access. |
FEATURE_NOT_ACTIVATED 403 |
This feature has not been activated for your account. Please reach out to help@xendit.co |
INVALID_API_KEY 401 |
API key format is invalid |
SERVER_ERROR 500 |
Something unexpected, our devs have been notified to troubleshoot the issue |
Linking Account Holder
Use the Update Account endpoint to link an Account Holder ID to this Account. This operation is currently only enabled for OWNED
accounts.
Endpoint: Update Account
PATCH https://api.xendit.co/v2/accounts/{id}
Example: Update Account
curl https://api.xendit.co/v2/accounts/{id} -X PATCH \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
-d $'{"account_holder_id":"4376b7b0-1c44-46be-8640-828f79cdc8be"}'
<?php
$url = 'https://api.xendit.co/v2/accounts/{id}';
$apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==';
$headers = [];
$headers[] = 'Content-Type: application/json';
$data = [
'acccount_holder_id' => '4376b7b0-1c44-46be-8640-828f79cdc8be'
]
];
$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, 'PATCH');
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
Path Parameters
Parameter | Type | Description |
---|---|---|
id required |
string |
The id of the Account created |
Body Parameters
Parameter | Type | Description |
---|---|---|
account_holder_id required |
string |
An Account Holder represents the legal entity that holds the Xendit Account. |
Response Parameters
Example: Update Account Response
{
"id": "5cafeb170a2b18519b1b8761",
"created": "2021-01-01T10:00:00Z",
"updated": "2021-01-01T11:00:00Z",
"type": "OWNED",
"email": "angie@pinkpanther.com",
"public_profile": {
"business_name": "Angie lemonade stand"
},
"status": "LIVE"
"account_holder_id": "4376b7b0-1c44-46be-8640-828f79cdc8be"
}
Parameter | Type | Description |
---|---|---|
id required |
string |
ID of your Account, use this in the for-user-id header to create transactions on behalf of your Account |
created required |
string |
Timestamp of when the account was created Timezone:
|
updated required |
string |
Timestamp of when the account was updated Timezone:
|
type required |
string |
The type of account created Available values:
|
email required |
string |
Email identifier for the Account |
public_profile required |
object |
Contains information that will be seen by end-payers or end-recipients (e.g. appears on hosted checkout page, credit card statements, etc.). |
country required |
string |
The country (based on ISO 3166-1 Alpha-2) of incorporation for a business, or the country of residence for an individual. Available values: |
status required |
string |
Status of the Account you are creating. Available values: |
account_holder_id required |
string |
Xendit-generated unique identifier for each Account Holder. This is created using the Create Account Holder Endpoint |
Activate Account Holder Capabilities
Use the Update Account Holder endpoint to link an Activate Account Holder Capabilities. This operation is currently only enabled for OWNED
accounts.
Endpoint: Update Account
PATCH https://api.xendit.co/account_holders
Example: Update Account
curl https://api.xendit.co/account_holder -X PATCH \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
-d $'{"capabilities":{"type":"MONEY_IN", "channel_code":"GCASH"}}'
<?php
$url = 'https://api.xendit.co/account_holders';
$apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==';
$headers = [];
$headers[] = 'Content-Type: application/json';
$data = [
'capabilities' => [
'type' => 'MONEY_IN'
'channel_code' => 'GCASH'
]
];
$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, 'PATCH');
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
Path Parameters
Parameter | Type | Description |
---|---|---|
id required |
string |
The id of the Account Holder created |
Body Parameters
Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
business_detailoptional |
object |
An object containing the business detail of the Account Holder Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||
individual_detailsoptional |
array[object] |
An object containing the individual details of the Account Holder. This could be the details of the business owner, director etc. You may submit multiple PIC (Person in Charge) for your business in this object. Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||
capabilitiesoptional |
object |
An object containing the details of the Account Holder capabilities activation process Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||
kyc_documentsoptional |
object |
Object containing the any file type or documents required to be submitted by the account Account Holder (e.g National ID, Selfie etc.)
|
Response Parameters
Example: Update Account Holder with Gcash capabilities response
{
"id": "5fa9014f44dee8737b1f05a4",
"business_detail": {
"type": "CORPORATION",
"legal_name": "PT Xendit",
"trading_name": "Xendit",
"description": "Payment solutions provider",
"industry_category": "Fintech",
"date_of_registration": "1980-01-01"
},
"individual_details": [
{
"given_names": "Putri",
"surname": "Mitja",
"nationality": "PH",
"phone_number": "+6385368541234",
"email": "sample@email.com",
"place_of_birth": "Makati",
"date_of_birth": "1980-01-01",
"gender": "MALE"
},
{
"given_names": "Putri 2",
"surname": "Mitja 2",
"nationality": "PH",
"phone_number": "+6385368541234",
"email": "sample@email.com",
"place_of_birth": "Makati",
"date_of_birth": "1980-01-01",
"gender": "MALE"
}
],
"address": {
"country": "PH",
"street_line1": "M.L. Quezon St.",
"street_line2": "M.L. Quezon St.",
"city": "Bantigue",
"sub_district": null,
"district": null,
"province_state": "Bantayan",
"postal_code": 2129
},
"kyc_documents": [
{
"country": "PH",
"type": "SELFIE_WITH_PRIMARY_ID",
"file_id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412"
},
{
"country": "PH",
"type": "IDENTITY_CARD",
"file_id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412"
},
{
"country": "PH",
"type": "DTI_REGISTRATION",
"file_id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412"
},
{
"country": "PH",
"type": "SEC_REGISTRATION",
"file_id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412"
},
{
"country": "PH",
"type": "ARTICLE_OF_INCORPORATION",
"file_id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412"
},
{
"country": "PH",
"type": "GENERAL_INFORMATION_SHEET",
"file_id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412"
},
{
"country": "PH",
"type": "NOTARIZED_SECRETARY_CERTIFICATION",
"file_id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412"
},
{
"country": "PH",
"type": "SECONDARY_LICENSE",
"file_id": "file-ec700c1c-db17-4496-b1fb-04ebe551b412"
}
],
"website_url": "https://api.xendit.co",
"phone_number": "+6385368541234",
"email": "account_holder@platform.com",
"kyc": {
"status": "PASSED",
"kyc_passed_at": "2021-01-01T10:00:00Z",
"verified_at": "2021-01-01T10:00:00Z",
"requested_at": "2021-01-01T10:00:00Z"
},
"capabilities": [
{
"type": "MONEY_IN",
"channel_code": "GCASH",
"activated_at": "2021-01-01T10:00:00Z",
"verified_at": "2021-01-01T10:00:00Z",
"requested_at": "2021-01-01T10:00:00Z",
"status": "VERIFICATION_IN_PROGRESS",
}
]
}
Returns Account Holder object with status 200
Error Codes
Error Code | Error Message |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INSUFFICIENT_ACCOUNT_HOLDER_DATA 400 |
The information in the Account Holder object is not sufficient to request activation for this payment channel. Please update the fields with the correct information. |
REQUEST_FORBIDDEN_ERROR 403 |
The API key is forbidden to perform this request. You need to use the Platform API key with Account Holder write access. |
FEATURE_NOT_ACTIVATED 403 |
This feature has not been activated for your account. Please reach out to help@xendit.co |
KYC_VERIFICATION_IN_PROGRESS 403 |
Account Holder cannot be updated while KYC verification is in progress, please try again when the verification process has been completed. |
CHANNEL_HAS_BEEN_ACTIVATED 403 |
Payment channel has been activated for this account holder. |
CHANNEL_ACTIVATION_IN_PROGRESS 403 |
Payment channel activation is in progress for this account holder. |
KYC_VERIFICATION_REQUIRED 403 |
Accounts KYC verification has not been completed for this sub-account. Please request capabilities after this process has been completed. |
INVALID_API_KEY 401 |
API key format is invalid |
DATA_NOT_FOUND 500 |
Could not find Account Holder by the ID specified because ID may be invalid. |
Get Account Holder by ID
Endpoint: Get Account Holder by ID
GET https://api.xendit.co/account_holders/{id}
This endpoint retrieves a single Account Holder that was previously created. This is often used for checking the verification status of a Account Holder using the id from the Account Holder Object.
Request Parameters
Example Get Account Holder Request
curl https://api.xendit.co/account_holders/4376b7b0-1c44-46be-8640-828f79cdc8be -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Path Parameter | Type | Description |
---|---|---|
idrequired |
string |
Xendit Account Holder ID generated by POST /account_holders |
Response Parameters
Example Get Account Holder Response
{
"id": "4376b7b0-1c44-46be-8640-828f79cdc8be",
"business_detail": {
"type": "CORPORATION",
"legal_name": "test16",
"description": "testing",
"trading_name": "test",
"industry_category": "ACCOMMODATION",
"country_of_operation": "PH",
"date_of_registration": "2023-02-02T00:00:00.000Z"
},
"individual_details": [
{
"email": "test@xendit.co",
"gender": "MALE",
"surname": "test",
"given_names": "test",
"nationality": "PH",
"phone_number": "+63021234567",
"date_of_birth": "2000-02-02T00:00:00.000Z",
"place_of_birth": "PH"
},
{
"email": "test@xendit.co",
"gender": "MALE",
"surname": "test",
"given_names": "test",
"nationality": "PH",
"phone_number": "+63021234567",
"date_of_birth": "2000-02-02T00:00:00.000Z",
"place_of_birth": "PH"
}
],
"address": {
"city": "test1",
"country": "PH",
"district": "test",
"postal_code": "1111",
"street_line1": "test",
"street_line2": "test",
"sub_district": "test",
"province_state": "test"
},
"kyc_documents": [
{
"type": "SEC_CERTIFICATE_REGISTRATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "ARTICLES_OF_INCORPORATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "NOTARIZED_SECRETARY_CERTIFICATE_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "LATEST_GIS_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "ACR_OR_IMMIGRANT_COR_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "ADDITIONAL_PROOF_OF_BUSINESS_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
}
],
"website_url": "https://xendit.co",
"phone_number": "+63281234567",
"email": "test@xendit.co",
"kyc": {
"status": "NOT_VERIFIED"
},
"created": "2023-03-30T11:41:57.881Z",
"updated": "2023-03-30T11:44:01.122Z"
}
Returns Account Holder object with status 200
Error Codes
Error Code | Error Message |
---|---|
REQUEST_FORBIDDEN_ERROR403 |
API key in use does not have necessary permissions to perform the request. Please assign proper permissions for the key. |
DATA_NOT_FOUND404 |
Could not find payout with the corresponding ID. Please try again with a valid ID. |
INVALID_API_KEY401 |
API Key is invalid. |
Update Account Holder
Use the Update Account Holder endpoint to update your Account Holder information. This step may be needed when the your information and document submission is insufficient or invalid e.g invalid website, blurry selfie, invalid ID etc. This operation is currently only enabled for OWNED
accounts.
Endpoint: Update Account Holder
PATCH https://api.xendit.co/account_holders/{id}
Example: Update Account
curl https://api.xendit.co/account_holders/{id} -X PATCH \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-H 'Content-Type: application/json' \
-d $'{"website_url": "louisa-marketplace.xendit.com"}'
Path Parameters
Path Parameter | Type | Description |
---|---|---|
id required |
string |
The id of the Account created |
Request Parameters
Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
business_detailrequired |
object |
An object containing the business detail of the Account Holder Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||
individual_detailsrequired |
array[object] |
An object containing the individual details of the Account Holder. This could be the details of the business owner, director etc. You may submit multiple PIC (Person in Charge) for your business in this object. Individual detail child parameters
|
||||||||||||||||||||||||||||||||||||||||||
addressrequired |
object |
Object containing the business address of the respective Account Holder
|
||||||||||||||||||||||||||||||||||||||||||
kyc_documentsrequired |
object |
Object containing the any file type or documents required to be submitted by the account Account Holder (e.g National ID, Selfie etc.)
|
||||||||||||||||||||||||||||||||||||||||||
website_urlrequired |
string |
Company website or social media website page URL Maximum length 255 charactersMinimum length 1 character |
||||||||||||||||||||||||||||||||||||||||||
phone_numberrequired |
string |
Contact number of the Account Holder in E.164 format. This may also be a landline Maximum length 30 charactersMinimum length 1 character |
||||||||||||||||||||||||||||||||||||||||||
emailrequired |
string |
Email address of the Account Holder Maximum length 255 charactersMinimum length 1 character |
||||||||||||||||||||||||||||||||||||||||||
capabilitiesoptional |
object |
An object containing the details of the Account Holder capabilities activation process Individual detail child parameters
|
Response Parameters
Example: Update Account Holder Response
{
"id": "4376b7b0-1c44-46be-8640-828f79cdc8be",
"business_detail": {
"type": "CORPORATION",
"legal_name": "test16",
"description": "testing",
"trading_name": "test",
"industry_category": "ACCOMMODATION",
"country_of_operation": "PH",
"date_of_registration": "2023-02-02T00:00:00.000Z"
},
"individual_details": [{
"email": "test@xendit.co",
"gender": "MALE",
"surname": "test",
"given_names": "test",
"nationality": "PH",
"phone_number": "+63021234567",
"date_of_birth": "2000-02-02T00:00:00.000Z",
"place_of_birth": "PH",
"type": "PIC",
"role": "owner"
}],
"address": {
"city": "test1",
"country": "PH",
"district": "test",
"postal_code": "1111",
"street_line1": "test",
"street_line2": "test",
"sub_district": "test",
"province_state": "test"
},
"kyc_documents": [
{
"type": "SEC_CERTIFICATE_REGISTRATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "ARTICLES_OF_INCORPORATION_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "NOTARIZED_SECRETARY_CERTIFICATE_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "LATEST_GIS_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "ACR_OR_IMMIGRANT_COR_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
},
{
"type": "SERVICE_AGREEMENT_DOCUMENT",
"country": "PH",
"file_id": "63f8719642f5856dcb142bd2",
"expires_at": "2023-02-02T19:00:00.000Z"
}
],
"website_url": "https://xendit.co",
"phone_number": "+63281234567",
"email": "test@xendit.co",
"kyc": {
"status": "NOT_VERIFIED"
},
"created": "2023-03-30T11:41:57.881Z",
"updated": "2023-03-30T11:44:01.122Z"
}
Returns Account Holder object with status 200
Error Codes
Error Code | Error Message |
---|---|
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
INSUFFICIENT_ACCOUNT_HOLDER_DATA 400 |
The information in the Account Holder object is not sufficient to request activation for this payment channel. Please update the fields with the correct information. |
REQUEST_FORBIDDEN_ERROR 403 |
The API key is forbidden to perform this request. You need to use the Platform API key with Account Holder write access. |
FEATURE_NOT_ACTIVATED 403 |
This feature has not been activated for your account. Please reach out to help@xendit.co |
KYC_VERIFICATION_IN_PROGRESS 403 |
Account Holder cannot be updated while KYC verification is in progress, please try again when the verification process has been completed. |
CHANNEL_HAS_BEEN_ACTIVATED 403 |
Payment channel has been activated for this account holder. |
CHANNEL_ACTIVATION_IN_PROGRESS 403 |
Payment channel activation is in progress for this account holder. |
KYC_VERIFICATION_REQUIRED 403 |
Accounts KYC verification has not been completed for this sub-account. Please request capabilities after this process has been completed. |
INVALID_API_KEY 401 |
API key format is invalid |
DATA_NOT_FOUND 500 |
Could not find Account Holder by the ID specified because ID may be invalid. |
Transfer Object
Object that would be generated upon creation of a Transfer
Example: Transfer Object
{
"created": "2020-01-01T08:51:44.484Z",
"transfer_id": "60b9d810-d9a3-456c-abbf-2786ec7a9651",
"reference": "transfer001",
"source_user_id": "54afeb170a2b18519b1b8768",
"destination_user_id": "5cafeb170a2b1851246b8768",
"status": "SUCCESSFUL",
"amount": 10000
}
Parameter | Tipe | Deskripsi |
---|---|---|
created required |
string |
Timestamp of when the Transfer was created Timezone:
|
transfer_id required |
string |
A unique reference for this Transfer set by Xendit systems |
reference required |
string |
A unique reference for this Transfer that you set when making the request |
source_user_id required |
string |
The source of the transfer. This is the user_id of either your master or sub account |
destination_user_id required |
string |
The destination of the transfer. This is the user_id of either your master or sub account |
status required |
string |
The status of the Transfer Available values:
|
amount required |
number |
The amount that was transferred |
Create Transfers
The Transfers API allows you to transfer balances: i) from your sub-accounts to your master account and vice versa, ii) between your sub-accounts. Use this to manage, or split payments between your platform and your sub accounts within the Xendit ecosystem.
Visit your xenPlatform dashboard in order to view the user_id
of your account and sub-accounts.
Endpoint: Create Transfer
POST https://api.xendit.co/transfers
Example: Create Transfer
curl https://api.xendit.co/transfers -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d reference=transfer001 \
-d amount=10000 \
-d source_user_id=54afeb170a2b18519b1b8768 \
-d destination_user_id=5cafeb170a2b1851246b8768 \
<?php
$url = 'https://api.xendit.co/transfers';
$apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
$headers = [];
$headers[] = 'Content-Type: application/json';
$data = [
'reference' => 'transfer001',
'amount' => 10000,
'source_user_id' => '54afeb170a2b18519b1b8768',
'destination_user_id' => '5cafeb170a2b1851246b8768'
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
from xendit import Xendit
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
xendit_instance = Xendit(api_key=api_key)
XenPlatform = xendit_instance.XenPlatform
xenplatform_transfers = XenPlatform.transfers(
reference="transfer001",
amount=10000,
source_user_id="54afeb170a2b18519b1b8768",
destination_user_id="5cafeb170a2b1851246b8768",
)
print(xenplatform_transfers)
Request Parameters
Body Parameter | Type | Description |
---|---|---|
reference required |
string |
A unique reference for this Transfer. Use this to reconcile transactions across your master and sub-accounts |
amount required |
number |
The amount that you would like to transfer. No decimal point for IDR , and max 2 decimal points for PHP |
source_user_id required |
string |
The account balance from which you would like to send the Transfer from. This can either be your platform or sub accounts user_id |
destination_user_id required |
string |
The account balance from which you would like to send the Transfer to. This can either be your platform or sub accounts user_id |
Response Parameters
Example: Transfers Response
{
"created": "2020-01-01T08:51:44.484Z",
"transfer_id": "60b9d810-d9a3-456c-abbf-2786ec7a9651",
"reference": "transfer001",
"source_user_id": "54afeb170a2b18519b1b8768",
"destination_user_id": "5cafeb170a2b1851246b8768",
"status": "SUCCESSFUL",
"amount": 10000
}
Parameter | Type | Description |
---|---|---|
created required |
string |
Timestamp of when the Transfer was created Timezone:
|
transfer_id required |
string |
A unique reference for this Transfer set by Xendit systems |
reference required |
string |
A unique reference for this Transfer that you set when making the request |
source_user_id required |
string |
The source of the transfer. This is the user_id of either your master or sub account |
destination_user_id required |
string |
The destination of the transfer. This is the user_id of either your master or sub account |
status required |
string |
The status of the Transfer Available values:
|
amount required |
number |
The amount that was transferred |
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_SOURCE_OR400 |
Source or destination account does not exist. Please input a valid business ID within your xenPlatform account. |
INSUFFICIENT_BALANCE400 |
The cash balance of your source account is insufficient. |
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 |
DUPLICATE_REFERENCE403 |
The reference parameter should be unique. |
XEN_PLATFORM_SUB_ACCOUNT_NOT_LIVE403 |
Your source or destination account is not live yet. Please specify live accounts for live transfers |
API_KEY_ENVIRONMENT403 |
Use your LIVE API key to transfer between LIVE accounts, or use TEST API key to transfer between TEST accounts. |
TRANSFER_IN_PROGRESS425 |
Transfer is currently being processed. Use GET Transfer By Reference to check its latest status |
MISMATCH_PAYLOAD_FOR_REFERENCE400 |
Reference has been used before. If you'd like to retry this transfer, please use the same payload as your previous request. |
INVALID_AMOUNT 400 |
Transfer amount has to be greater than 0, Transfer amount of IDR currency should not have decimal point, Transfer amount of PHP currency can only have max 2 decimal point |
Get Transfer by Reference
Endpoint: Get Transfer by Reference
GET https://api.xendit.co/transfers/reference={reference}
This endpoint queries the current status of a transfer. This is often used for checking the status of a transaction.
Request Parameters
Example Get Transfer Request
curl https://api.xendit.co/transfers/reference=Monthly_transfers_123 -X GET \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:
Path Parameter | Type | Description |
---|---|---|
referencerequired |
string |
reference ID of the transfer to retrieve The reference must match the unique reference provided upon transfer request |
Response Parameters
Example Get Transfer Response
{
"created": "2020-11-30T02:47:53.061Z",
"transfer_id": "bd1cc56b-ce7f-4ad7-8901-3eaa689e90eb",
"source_user_id":"5cafeb170a2b18519b1b8768",
"destination_user_id":"5f8d0c0603ffe06b7d4d9fcf",
"status": "SUCCESSFUL",
"amount": 90000,
"reference": "Monthly_Transfers_1234"
}
Returns Transfer object with status 200
Error Codes
Error Code | Description |
---|---|
DATA_NOT_FOUND404 |
Could not find transfer by reference because reference may be invalid. |
INVALID_API_KEY401 |
API key is not authorized for this API service, access to xenPlatform is needed |
Create Split Rule
A Split Rule Object defines how payments in xenPlatform can be routed and split to multiple destinations by xenPlatform. Include the split_rule_id
returned in the response in supported transaction endpoints to automatically route and split payments to multiple Account destinations once payments settle.
Version
You are currently viewing the newest version of Split Rule API. We have also added API permissions in this version. If you are using an existing API key, please edit your permissions in your Settings page.
Click here to view the older version.
Endpoint: Create Split Rule
POST https://api.xendit.co/split_rules
Example: Create Split Rule
curl -- request POST \
--url https://api.xendit.co/split_rules \
--header 'Authorization: Basic xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "20210908 Test",
"description": "Platform fee and Delivery Fee for Marketplace",
"routes": [
{
"flat_amount": 3000,
"currency": "IDR"
"destination_account_id": "5f8d0c0603ffe06b7d4d9fcf",
"reference_id": "reference"
},
{
"percent_amount": 5,
"currency": "IDR"
"destination_account_id": "5cafeb170a2b18519b1b8768",
"reference_id": "reference"
}
]
}'
'
<?php
$url = 'https://api.xendit.co/split_rules';
$apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
$headers = [];
$headers[] = 'Content-Type: application/json';
$data = [
'name' => 'standard_split_rule',
'description' => 'fee_for_all_transactions_accepted_on_behalf_of_vendors',
'routes' => [
[
'flat_amount' => '200',
'currency' => 'IDR',
'destination_account_id':'6548afe09059f97f211047b2',
'reference_id' => 'reference',
]
]
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
Request Parameters
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
name required |
string |
Name to identify split rule. Not required to be unique. Typically based on transaction and/or sub-merchant types. e.g. “standard platform fee and delivery fee”, “commission” |
||||||||||
description optional |
string |
Description to identify fee rule e.g. “Fee charged to insurance agents" |
||||||||||
routes required |
array |
Array of objects that define how the platform wants to route the fees and to which accounts. Each Route object is equivalent to a single payment split from the end user to a destination account.
|
Response Parameters
Example: Fee Rules Response
{
"id": "splitru_d9e069f2-4da7-4562-93b7-ded87023d749",
"name": "Standard platform fee",
"description": "Platform fee for all transactions accepted on behalf of vendors",
"routes": [
{
"flat_amount": 3000,
"currency": "IDR",
"destination_account_id": "5f8d0c0603ffe06b7d4d9fcf",
"reference_id": "reference"
},
{
"percent_amount": 5.25,
"currency": "IDR",
"destination_account_id": "5cafeb170a2b18519b1b8768",
"reference_id": "reference"
}
],
"created": "2020-09-01T07:00:00.007Z",
"updated": "2020-09-01T07:00:00.007Z",
"metadata": {}
}
Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
id required |
string |
Xendit system generated unique ID. Format: splitru_{{id}} e.g. splitru_NF5p90U3MQ5MXAuH1NF |
||||||||||
name required |
string |
Name to identify fee rule. Not required to be unique. Typically based on transaction and/or sub-merchant types | ||||||||||
description optional |
string |
Description to identify fee rule. Otherwise NULL |
||||||||||
routes required |
array |
Array of objects that define how the platform wants to route the fees and to which accounts. Each Route object is equivalent to a single fee route from the end-customer to a destination account.
|
||||||||||
created required |
string |
Timestamp in ISO 8601 when the fee rule object was created Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||||
updated required |
string |
Timestamp in ISO 8601 when the fee rule object was updated Format: YYYY-MM-DDTHH:mm:ssZ Timezone: UTC+0 |
||||||||||
metadata optional |
object |
Object of additional key-value pairs that the merchants may use like internal system parameters (business ID, shopping cart). 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. Otherwise NULL |
Error Codes
Error Code | Description |
---|---|
INVALID_FEE_AMOUNT400 |
Fee amount and/or unit is negative number or incorrect format. |
DESTINATION_ACCOUNT_NOT_FOUND404 |
Returned when destination_account_id is invalid or not connected to this xenPlatform account |
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
DUPLICATE_ERROR400 |
Returned if provided reference_id is not unique for the routes |
Set Webhook URLs
The Set Webhook URLs API allows you to set your account and sub-accounts Webhook URLs.
The following can be used in the :type
path parameters:
Money-In
invoice
: Xendit notifies your system when Invoice has been paid or expired.fva_status
: Xendit notifies your system when Virtual Account has been created or updated successfully. Support: Indonesia only 🇲🇨fva_paid
: Xendit notifies your system when Virtual Account has been paid successfully. Support: Indonesia only 🇲🇨ro_fpc_paid
: Xendit notifies your system when Retail Outlet payment code (Alfamart/Indomaret) in Indonesia has been paid successfully. Support: Indonesia only 🇲🇨regional_ro_paid
: Xendit notifies your system when Over-the-Counter payment code (7 Eleven, Cebuana, ECPay) in Philippines has been paid successfully. Support: Philippines only 🇵🇭ewallet
: New eWallet type to receive charge and other eWallet events across eWallets channels from /ewallets/charges API.payment_method
: Xendit notifies your system when payment method is expiring and/or has expired. Payment Method is a mandatory step to abstract Debit Card/Bank Account for Direct Debit transactions.payment_method_v2
: Xendit notifies your system when payment method V2 is expiring and/or has activated or expired. Learn more about Payment Method V2 here.direct_debit
: A Direct Debit payment event will be sent to your system for any successful transactions. Usedirect_debit
type to receive Direct Debit payment event via webhook.qr_code
: Xendit notifies your system when QR payment has been made or QR refund has been completed. This field is only supported forqr_codes
API version2022-07-31
.recurring
: Xendit notifies your system when Subscription plan has been activated/inactivated, cycle created/succeeded/retrying/failed, or force attempt failed.payment_succeeded
: Xendit notifies your system when a payment has been successfully confirmed or received from the partner channel (Only for payments initiated via new Payments API). Support: All businessespayment_awaiting_capture
: Xendit notifies your system when a payment request with capture_method set to MANUAL has been intialized and a call to the Payment Capture API needed to complete the payment. Support: All businessespayment_pending
: Xendit notifies your system when a payment is being processed by the partner channel awaiting for the terminal status of it (Only for payments initiated via new Payments API). Support: All businessespayment_failed
: Xendit notifies your system when a pending payment has failed (Only for payments initiated via new Payments API). Support: All businessescapture_succeeded
: Xendit notifies your system when a manual capture via the Payment Capture API has succeeded. Support: All businessescapture_failed
: Xendit notifies your system when a manual capture via the Payment Capture API has Failed. Support: All businessespayment_request_completed
: Xendit notifies your system when a Direct Debit or E-Wallet payment request has succeeded or failed. Please Note that this is for the Payment Request API only. Make sure that other payment callbacks for Direct Debit or E-wallet are not set to prevent duplication. Support: Thailand 🇹🇭 and Malaysia 🇲🇾 only
Money-Out
disbursement
: Xendit notifies your system when disbursement has been executed successfully by Xendit, either withCOMPLETED
orFAILED
status. Support: Indonesia only 🇲🇨ph_disbursement
: Xendit notifies your system when disbursement has been executed successfully by Xendit, either withCOMPLETED
orFAILED
status. Support: Philippines only 🇵🇭batch_disbursement
: Xendit notifies your system when Batch Disbursement has been executed successfully by Xendit. Support: Indonesia only 🇲🇨payout
: Xendit notifies your system upon failed and successful payouts. Learn more about Payouts V2 webhooks here.
Others
report
: Xendit notifies your system to send the report to the specified URLs. Support: All businesses
Endpoint: Set Webhook URLs
POST https://api.xendit.co/callback_urls/:type
Request Parameters
Example: Set Webhook URLs
curl https://api.xendit.co/callback_urls/:type -X POST \
-u xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==: \
-d url=https://www.xendit.co/webhook_catcher \
<?php
$url = 'https://api.xendit.co/callback_urls';
$apiKey = 'xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:';
$headers = [];
$headers[] = 'Content-Type: application/json';
$data = [
'url' => 'https://www.xendit.co/webhook_catcher'
];
$curl = curl_init();
$payload = json_encode($data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERPWD, $apiKey.":");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
echo $result;
from xendit import Xendit, XenPlatformURLType
api_key = "xnd_development_O46JfOtygef9kMNsK+ZPGT+ZZ9b3ooF4w3Dn+R1k+2fT/7GlCAN3jg==:"
xendit_instance = Xendit(api_key=api_key)
XenPlatform = xendit_instance.XenPlatform
xenplatform_callback_url = XenPlatform.set_callback_url(
type=XenPlatformURLType.INVOICE,
url="https://test-url-invoice.com",
)
print(xenplatform_callback_url)
Header Parameter | Type | Description |
---|---|---|
for-user-idoptional |
string |
The sub-account user-id that you want to set this Webhook URL on. This header is only used if you have access to xenPlatform. See xenPlatform for more information |
Path Parameter | Type | Description |
---|---|---|
type required |
string |
The type of Webhook URL you want to set Available values:
|
Body Parameter | Type | Description |
---|---|---|
url required |
string |
URL of your server that you want to receive our Webhooks at
|
Response Parameters
Example: Set Webhook URLs Response
{
"status": "SUCCESSFUL",
"user_id": "5e6b30d967627b957de8c123",
"url": "https://www.xendit.co/webhook_catcher",
"environment": "TEST",
"callback_token": "66a6680348e1c33ed2b9053a8eb9291b9e2230ff4f4d3057c9f4ac26405d2123"
}
Parameter | Type | Description |
---|---|---|
status required |
string |
The status of setting the Webhook URL Available values:
|
user_id required |
string |
The user_id on which the Webhook URL has been set |
url required |
string |
The Webhook URL that has been set |
environment required |
string |
The environment on which the Webhook URL has been set Available values:
|
callback_token required |
string |
The unique Webhook token that is attached to each sub-account. Use this to validate that a Webhook is sent from Xendit's servers. |
Error Codes
Error Code | Description |
---|---|
INVALID_URL_FORMAT400 |
You have provided an invalid URL format |
CALLBACK_AUTHENTICATION_TOKEN_NOT_FOUND_ERROR404 |
No webhook verification token found for this business, please contact help@xendit.co to resolve this issue |
API_VALIDATION_ERROR400 |
Inputs are failing validation. The errors field contains details about which fields are violating validation. |
Account Holder KYC Verification Callback
Endpoint: Account Holder KYC verification Webhook
POST https://yourcompany.com/xenplatform_webhook_url
The Account Holder KYC verification status webhook can be used to let your system know when your Account Holder KYC verification status is PASSED
,FAILED
, or RESUBMISSION_REQUIRED
. This Webhook is only sent for OWNED
accounts.
You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Example Account Holder KYC verification Passed Webhook Request
{
"event": "account_holder.kyc.status",
"created": "2021-01-01T10:00:00Z",
"business_id": "5fe2b0137b7d62542fe6d7de",
"data": {
"id": "57fb4e076fa3fa296b7f5a97",
"created": "2021-01-01T10:00:00Z",
"updated": "2021-01-01T10:00:00Z",
"kyc": {
"status": "PASSED",
"verified_at": "2021-01-01T10:00:00Z",
"requested_at": "2021-01-01T10:00:00Z",
"kyc_passed_at": "2021-01-01T10:00:00Z",
}
}
}
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
event required |
string |
The type of event webhook that was sent Available values:
|
||||||||||||||||||||||||||
business_id required |
string |
ID of the Account that this event occurred on. This would be your Platform account ID for Account webhooks. | ||||||||||||||||||||||||||
created required |
string |
Indicates when the webhook was sent Timezone:
|
||||||||||||||||||||||||||
data required |
array[object] |
Contains metadata for the event type. For account_holder.kyc.status , contains the kyc object in the Account Holder
|
Account Holder Capabilities Activation Callback
Endpoint: Account Holder Capabilities Activation Webhook
POST https://yourcompany.com/xenplatform_webhook_url
The Account Holder Capabilities Activation webhook can be used to let your system know when your Account Holder capabilities activaion status is LIVE
,DECLINED
, or RESUBMISSION_REQUIRED
. This Webhook is only sent for OWNED
accounts.
You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Example Account Holder Capabilities Activation Webhook Request
{
"event": "account_holder.kyc.status",
"created": "2021-01-01T10:00:00Z",
"business_id": "5fe2b0137b7d62542fe6d7de",
"data": {
"id": "57fb4e076fa3fa296b7f5a97",
"created": "2021-01-01T10:00:00Z",
"updated": "2021-01-01T10:00:00Z",
"capabilities": [
{
"type": "MONEY_IN",
"channel_code": "GCASH",
"activated_at": "2021-01-01T10:00:00Z",
"verified_at": "2021-01-01T10:00:00Z",
"requested_at": "2021-01-01T10:00:00Z",
"status": "RESUBMISSION_REQUIRED",
"failure_reason": "Your website URL is not related to your business"
}
]
}
}
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
event required |
string |
The type of event webhook that was sent Available values:
|
||||||||||||||||||||||||
business_id required |
string |
ID of the Account that this event occurred on. This would be your Platform account ID for Account webhooks. | ||||||||||||||||||||||||
created required |
string |
Indicates when the webhook was sent Timezone:
|
||||||||||||||||||||||||
data required |
array[object] |
Contains metadata for the event type. For account_holder.capabilities.status , contains the capabilities object in the Account Holder
|
Account Callback
Xendit notifies 2 types of webhook upon account creation:
- Account Created webhook for
OWNED
Accounts to notify you when an Account has been successfully created - Account Updated webhook for
MANAGED
Accounts to notify you when your MANAGED Accounts have successfully registered and enabled for live payments
You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Version
You are currently viewing the newest version of our Accounts API. We have made some changes to the Webhooks that we send. Click here to view the older version.
Version | Changelog |
---|---|
v2 Latest version |
Removed account.registered Callback for OWNED Accounts |
v1 | First version of Accounts API |
Owned Account Created Callback
Endpoint: Account Created Callback
POST https://yourcompany.com/xenplatform_webhook_url
The Account Created webhook can be used to let your system know when your Accounts have been successfully created. This Callback is only sent for OWNED
accounts.
Callback Payload
Example Account Created Callback Request
{
"event": "account.created",
"created": "2021-01-01T10:00:00Z",
"data": {
"id": "5cafeb170a2b18519b1b8761",
"created": "2021-01-01T10:00:00Z",
"updated": "2021-01-01T10:00:00Z",
"type": "OWNED",
"email": "test@xendit.co",
"public_profile": {
"business_name": "Aaron Warung"
},
"country": "ID",
"status": "LIVE"
}
}
curl --request POST \
--url https://yourcompany.com/xenplatform_webhook_url \
--data '{"event":"account.created","business_id":"6abceb170a2b18519b1b1234","created":"2021-01-01T10:00:00Z","data":{"id":"5cafeb170a2b18519b1b8761","created":"2021-01-01T10:00:00Z","updated":"2021-01-01T10:00:00Z","type":"OWNED","email":"aaron@xendit.co","public_profile":{"business_name":"Aaron Warung"},"country":"ID","status":"LIVE"}}'
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://yourcompany.com/xenplatform_webhook_url",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"event\":\"account.created\",\"business_id\":\"6abceb170a2b18519b1b1234\",\"created\":\"2021-01-01T10:00:00Z\",\"data\":{\"id\":\"5cafeb170a2b18519b1b8761\",\"created\":\"2021-01-01T10:00:00Z\",\"updated\":\"2021-01-01T10:00:00Z\",\"type\":\"OWNED\",\"email\":\"aaron@xendit.co\",\"public_profile\":{\"business_name\":\"Aaron Warung\"},\"country\":\"ID\",\"status\":\"LIVE\"}}",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
event required |
string |
The type of event webhook that was sent Available values:
|
||||||||||||||||
business_id required |
string |
ID of the Account that this event occurred on. This would be your Platform account ID for Account webhooks. | ||||||||||||||||
created required |
string |
Indicates when the webhook was sent Timezone:
|
||||||||||||||||
data required |
object |
Contains metadata for the event type. For account.created , this contains the Account object.
|
Managed Account Updated Callback
Endpoint: Account Updated Callback
POST https://yourcompany.com/xenplatform_webhook_url
The Account Updated webhook can be used to let your system know when your MANAGED
Accounts have been successfully registered and live payments enabled.
You will receive webhooks at various points during the Account onboarding process for MANAGED
Accounts:
account.registered
- When an Account has been registered via the invitation emailaccount.activated
- When live payments has been enabled for your Account (i.e. activated)
Account Suspension Callback
Endpoint: Account Suspension Webhook
POST https://yourcompany.com/xenplatform_webhook_url
The Account Suspension webhook can be used to let your system know when Xendit has suspected
, suspended
or cleared
the Accounts linked to your Platform. Our teams and systems automatically and regularly review Account behaviour to help Platforms mitigate potential fraud.
These events may occur if we have reason to believe that the Account has engaged in fraudulent activity. When these events occur, only the transactions occurring on that specific Account will be affected. This approach allows your Platform to continue accepting payments for your other Accounts normally.
The events that may be sent through this Webhook include:
account.suspected
- When an Account is suspected, Xendit will disable all money-out activities from happening on the Account. Thestatus
parameter of the Account will continue to beLIVE
as money-in activities can still occur.account.suspended
- When an Account is suspended, Xendit will disable all money-in and money-out activities from happening on the Account. Thestatus
parameter of the Account will be changed toSUSPENDED
.account.cleared
- When an Account is cleared, Xendit will enable all money-in and money-out activities to happen on the Account. Thestatus
parameter of the Account will be changed toLIVE
.
You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard.
The payment notification will be sent as POST request to the URL you set. Xendit attach x-callback-token
header that you can validate against Verification Token in Webhook Settings to verify message authenticity.
Please response back with status 200 immediately. Xendit marks webhook event as failed if there is no response within 30s. When events failed, automatic retry will kick-off for the next 24h. Alternatively, you can resend any event in Webhook tab at anytime. You can also receive notification via email every 6h to check your webhook health.
Learn more about Webhook.
Webhook Payload
Example Account Suspended Webhook Request
{
"event": "account.suspended",
"created": "2022-01-01T02:33:56.113Z",
"business_id": "61b1ae8459d12951b1a2d7fd",
"api_version": null,
"data": {
"id": "5fe2b0134b5d62542fe6d7de",
"email": "john@warungshop.co",
"public_profile": {
"business_name": "John warung shop"
},
"status": "SUSPENDED",
"reason": "FRAUD_PROMO_ABUSE"
}
}
curl --request POST \
--url https://yourcompany.com/xenplatform_webhook_url \
--data '{ "created": "2022-01-01T02:33:56.113Z", "business_id": "61b1ae8459d12951b1a2d7fd", "event": "account.suspended", "api_version": null, "data": { "id": "5fe2b0134b5d62542fe6d7de", "email": "john@warungshop.co", "public_profile": { "business_name": "John warung shop" }, "status": "SUSPENDED", "reason": "FRAUD_PROMO_ABUSE" } }'
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://yourcompany.com/xenplatform_webhook_url",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"created\":\"2022-01-01T02:33:56.113Z\",\"business_id\":\"61b1ae8459d12951b1a2d7fd\",\"event\":\"account.suspended\",\"api_version\":"NULL",\"data\":{\"id\":\"5fe2b0134b5d62542fe6d7de\",\"email\":\"john@warungshop.co\",\"public_profile\":{\"business_name\":\"John warung shop\"},\"status\":\"SUSPENDED\",\"reason\":\"FRAUD_PROMO_ABUSE\"}}",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique webhook token to verify the origin of the webhook |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double webhooks by implementing idempotency. When you receive the same webhook-id twice, treat the subsequent request as duplicate and reject the webhook accordingly to prevent double webhooks |
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
event required |
string |
The type of event webhook that was sent Available values:
|
||||||||||
created required |
string |
Indicates when the webhook was sent Timezone:
|
||||||||||
business_id required |
string |
ID of the Account that this event occurred on. This would be your Platform account ID for Account webhooks. | ||||||||||
data required |
object |
Contains metadata for the event type.
|
Errors when transacting on behalf of Accounts
This section contains general errors that you may face when attempting to transact on behalf of your Accounts (e.g. making an API request which includes the for-user-id
header).
Error Codes
Error Code | Description |
---|---|
XEN_PLATFORM_SUB_ACCOUNT_NOT_LIVE404 |
The Account is not yet live or has been suspended based on internal risk policies, please contact help@xendit.co for more information |
Test Scenarios
This section includes test scenarios and other information to make sure your integration works as planned. Use it to trigger different flows in your integration and ensure they are handled accordingly
- Credit/Debit Card test scenarios
- Ewallets test scenarios
- Direct Debit test scenarios
- Virtual Accounts test scenarios
- Retail Outlet test scenarios
- Invoices test scenarios
- Disbursements and Payouts test scenarios
- Cross-border Payout test scenarios
Checklists
Xendit has designed its live and test modes to function as similarly as possible. Flipping the switch is mostly a matter of swapping your API keys.
If you are a developer, or had a developer perform an integration for you, you should also consider the following items before going live.
Handle Edge Cases
We have created several test cases you can use to replicate various states and responses. Beyond these options, perform your due diligence, testing your integration with:
- Incomplete data
- Invalid data
- Duplicate data (e.g., retry the same request to see what happens)
We also recommend you have someone else test your integration, especially if that other person is not a developer themselves.
Review Error Handling
Once you have gone live is an unfortunate time to discover you have not properly written your code to handle every possible error type, including those that should "never" happen. Be certain your code is defensive, handling not just the common errors, but all possibilities.
When testing your error handling, especially watch what information is shown to your users. A card being declined (i.e., CARD_DECLINED
) is a different concern than an error on your backend (e.g., an API_VALIDATION_ERROR
).
Review Your Logging
Xendit logs every request made with you API keys. We recommend that you log all important data on your end, too, despite the apparent redundancy. Your own logs will be a life-saver if your server has a problem contacting Xendit or there's an issue with your API keys--both cases would prevent us from logging your request.
Regularly examine your logs to ensure they're storing all the information you may need and they are not storing anything of a sensitive nature (e.g., personally identifiable information).
Independent From Test Mode Objects
Xendit objects created in test mode--such as charge, virtual accounts, retail outlets, etc---are not usable in live mode. This prevents your test data from being inadvertently used in your production code. When recreating necessary objects in live mode, be certain to use the same ID values (e.g. the same Virtual Account external ID) to guarantee your code will continue to work without issue
Register Live Webhook URL
Your Xendit account can have both test and live webhook URLs. If you are using webhook, make sure you have defined live endpoints in your Xendit account. Then confirm that the live endpoint functions exactly the same as your test endpoint.
While examining your webhook status, also take a moment to check that your live endpoint:
- Gracefully handles delayed webhook notifications
- Gracefully handles duplicate webhook notifications
- Does not require event notifications to occur in a specific order
Secure Your API keys
As a security measure, we recommend change your API keys on a regular basis, and also just before going live. This is in case they have been saved somewhere outside of your codebase during development. Make sure your workflow doesn't result in your API keys being represented or stored in multiple places--this leads to bugs--or even ending up in your version control software.
Docs Changelog
API Reference Changelog
November 18, 2024
- Removed the
Safe Acceptance API integration
from Credit Cards section since the API is already deprecated.
November 5, 2024
- Removed the
UANGME
Paylater channel in Indonesia
November 4, 2024
- Added
network_transaction_id
in network response for charge (authorization and/or capture) endpoints in card payments
October 23, 2024
- Added support for
WECHATPAY
eWallet in Malaysia - Added
allowed_payment_options
channel property for MY GrabPay ewallet
October 4, 2024
- Added
network_response
for cards tokenization, authentication, authorization and charge endpoints
September 18, 2024
- Update
card_data.card_holder_first_name
andcard_data.card_holder_last_name` maximum character length to 50
- Update
card_data.card_holder_email
maximum character length to 254
September 3, 2024
- Change randomly generated OTC payment code format from
<prefix><alphanumeric>
to be<prefix><alphabet><number>
September 4, 2024
- Added UBP & BPI on Subscriptions
- Removed Mandiri DD on Subscriptions
- Change
card_data
parameter from required to optional in create authentication API using token ID.
September 3, 2024
- Change randomly generated OTC payment code format from
<prefix><alphanumeric>
to be<prefix><alphabet><number>
August 16, 2024
- Added accepted parameter for card holder information on tokenization, authentication, and payments API
- Added support for
AMBANK
virtual account in Malaysia
August 5, 2024
- Added support for
BIDV
virtual account in Vietnam - Added support for
UOB
virtual account in Malaysia
August 1, 2024
- Added new parameters to collect cardholder information on card_data for cards tokenization
- Added new parameter
card_data
to collect cardholder information for authentication - Added new parameters to collect cardholder information on card_information for create payment method
July 29, 2024
- Removed
update-scheduled-cycle
in Subscriptions, function forupdate-scheduled-cycle
still exists for existing merchants
July 10, 2024
- Added new
allow_installment
in Create Invoice API
June 21, 2024
- Added minimum and maximum character limit for payment code in Over-The-Counter (OTC) Payments
June 21, 2024
- Added minimum and maximum character limit for payment code in Over-The-Counter (OTC) Payments
June 4, 2024
- Added new
metadata
parameter in Create Invoice API
May 14, 2024
- Added support for
VPB
virtual account in Vietnam - Added
ALTERNATIVE_DISPLAYS
forVietQR
in Vietnam
May 7, 2024
- Support eWallet Refund in VN
May 3, 2024
- Added new Cross-border Payout API Reference
Apr 17, 2024
- Added support for xenPlatform
CUSTOM
sub-account creation
Apr 11, 2024
- Introduce Online Banking channels for PH market via payment links
- Introduce QR PH channel for PH market
Apr 7, 2024
- Added CHANNEL_UNAVAILABLE 503 error for create VA
Mar 26, 2024
- Added new
channel_properties
parameter in Create Invoice API to configure cards configurations such as allowed BINs and installment terms
Mar 20, 2024
- Added
at_timestamp
in Get Balance API to get historical total balance in the past - Added
DETAILED_TRANSACTIONS
type for Generate Report API
Mar 05, 2024
- Added
BPI_RECURRING
andUBP_EADA
as new channel code in Direct Debit
Feb 26, 2024
- Added
pending_redirect_url
field for Create VN eWallet Charge API - Added
pending_return_url
field for Create VN eWallet Payment Requests API
Feb 20, 2024
- Remove documentations for the deprecated xenPlatform v1 Create Account API
Feb 6, 2024
- Added
TOUCHNGO
eWallet channel for MY Invoice API
Feb 5, 2024
- Update maximum amount for
PH_7ELEVEN
from10,000
to50,000
Feb 3, 2024
- Remove 'MINIMAL_TRANSFER_AMOUNT_ERROR' and 'MAXIMUM_TRANSFER_AMOUNT_ERROR' on Invoice
Feb 1, 2024
- Added
TRANSACTION_ANALYSIS
type to Generate Report API
Jan 15, 2024
- Added support for
MSB
virtual account in Vietnam - Added support for
STANDARD_CHARTERED
virtual account in Thailand
Jan 19, 2024
- Added Touch n Go channel code
Dec 18, 2023
- Added
amount
format for MYR, VND, and THB currency in Payouts API section - Added MYR, VND, and THB currency in the title of Payouts API section
Dec 15, 2023
- Support QR Refund on Payments API
Nov 21, 2023
- Create new Split Payments API
Nov 15, 2023
- Added
account_type
field on Payouts object
November 9, 2023
- Adding new XenPlatform Webhooks callback enums
report
,payment_succeeded
,payment_awaiting_capture
,payment_pending
,payment_failed
,capture_suceeded
,capture_failed
,payment_request_completed
November 3, 2023
- Support GCash Tokenization for Payments API
October 19, 2023
- Added information regarding per IP rate limits
October 16, 2023
- Removed
metadata
on cycle-object in bash code under Subscriptions - Removed
metadata
on event-callbacks-plan - Removed
metadata
on update-cycle - Removed
metadata
on force-attempt - Removed create-schedule tab on recurring
- Removed
scheduled_id
on create plan Subscriptions - Removed
metadata
on cycle-object under Subscriptions
October 12, 2023
- Added cards activation support on Account Holder API
October 09, 2023
- Added Customers API to New SDKs
October 03, 2023
- Added Customer object support for MULTIPLE_USE Payment Methods
October 03, 2023
- Added Indonesia Ewallet JeniusPay channel to Invoice API
September 25, 2023
- Added New SDK Information and removed Legacy SDKs
September 20, 2023
- Added
API_VALIDATION_ERROR
on Create Payout Link API error codes - Added minimum and maximum limit on
amount
field for Payout Links section
September 14, 2023
- Added FPX Corporate channels to Payment APIs
September 6, 2023
- Added Thailand eWallet Channels
WECHATPAY
,LINEPAY
,SHOPEEPAY
,TRUEMONEY
to eWallets APIs, Payment Methods V2 APIs, and Payment Requests APIs
August 10, 2023
- Added
BNC
as a new value forpayment_methods
field on Create Invoice API
July 26, 2023
- Improve cards error code recommendation on tokenization, charge, and capture
- Remove PROCESSOR_ERROR duplication on create charge section
July 17, 2023
- Added THB and VND possible currency value to create invoice API
- Added PROMPTPAY and CREDIT CARD on possible value on payment method for Thailand on Invoice API
- Added CREDIT CARD on possible value on payment method for Vietnam on Invoice API
July 3, 2023
- Added xenPlatform with-fee-rule support on Direct Debit API
June 26, 2023
- Added Vietnam eWallet Channels
APPOTA
,MOMO
,SHOPEEPAY
,VNPTWALLET
,VIETTELPAY
,ZALOPAY
to eWallets APIs, Payment Methods V2 APIs, and Payment Requests APIs - Removed
BRI
channel code from Resend Auth for Payment Request API - Changed card_expiry from required to optional in Create Payment Method V2 API
- Added capture_methods parameter for Cards in Create Payment Request API
- Removed limitation of premade customer object only for
ONE_TIME_USE
payment in Create Payment Request API.
June 22, 2023
- Removed
payer_email
andshould_send_email
to the Create Invoice API
June 13, 2023
- Added PREPAID and UNKNOWN card type to Credit Card charge response
June 12, 2023
- Added new failure reasons for Credit Card payments
June 11, 2023
- Added XenPlatform
for-user-id
header on Subscriptions API
June 8, 2023
- Added
qr_code
andrecurring
to Set Callback URL API
May 31, 2023
- Added
SM_BILLS
andROBINSONS_BILLS
new OTC channels in Payments Method V2 API
May 23, 2023
- Added new page for charging CVV using multiple use token
- Removed CVN from charge and authorization pages
- Clarify amount for cards refund
May 22, 2023
- Added FPX as a supported payment under Direct Debit API.
- Added MYR Currency and FPX Channel List Under Direct Debit and Payments API.
May 21, 2023
- Changed
channel_code
as conditional parameter for QR in Create Payment Method V2 API, where Indonesia QR channel code can be nullable.
May 15, 2023
- Added Philippines Direct Debit BDO EPay channel to Invoice API
April 17, 2023
- Released Account Holder API on xenPlatform
- Added Account Holder callbacks
April 14, 2023
- Added
country
andcurrency
to the Get Virtual Account Banks API
April 12, 2023
- Added
currency
request parameter in Get Balance API
April 4, 2023
- Added unlink with confirmation for KTB direct debit in Thailand
March 29, 2023
- Added
GET list accounts API
in xenPlatform features
March 22, 2023
- Added
BNC
(Bank Neo Commerce) as a new channel for Virtual Accounts
March 20, 2023
- Added new optional request object
payment_link_for_failed_attempt
on Recurring - plan object to generate payment link for failed auto charged
March 14, 2023
- Added Succeeded Status in refund object
- Added PAYMENT_METHOD_ALREADY_EXISTS failure code
March 7, 2023
- Deprecated
ovo_paid
enums in Set Callback URL API (scheduled deprecation: 31 May 2022)
March 2, 2023
- New Simulate Payments API
February 26, 2023
- Update idempotency key from x-idempotency-key to idempotency-key for Payments API.
February 19, 2023
- Added Perform Capture Endpoint.
February 14, 2023
- Payment Method, Payment Request, Payment Object - Added additional description of customer_id,
Pending Status
, andTHB
currency - Revised
status
in Batch Disbursement creation
February 13, 2023
- New Force Attempt API for Recurring
February 8, 2023
- Added direct debit payment method and payment request for Thailand Bank:
SCB
,BBL
,KTB
,BAY
.
February 8, 2023
- Changed possible values in invoice callback
payment_method
parameter fromQRIS
toQR_CODE
February 7, 2023
- Deprecate
fixed_va
for Invoice creation
February 6, 2023
- Added QR Refund APIs
January 31, 2023
- Added
country
andcurrency
as a new parameter for VA creation - VA supports 3 new bank codes in Vietnam
January 12, 2023
- Updated maximum value for
items.quantity
field on Create Invoice API from 1000 to 100000 - Introduce new TH channel code:
BA_BAY
to Direct Debit linking auth and payment methods
January 6, 2023
- Revised some rules and error messages for eWallets and QR Codes
January 3, 2023
- Added
SAHABAT_SAMPOERNA
as a new value forpayment_methods
field on Create Invoice API
December 22, 2022
- Rate Limit documentation
Desember 16, 2022
- Perbaikan error code di API Transfers
December 13, 2022
- Introduce new TH channel codes:
BA_BBL
,BA_KTB
, andBA_SCB
to Direct Debit linking auth and payment methods
Desember 8, 2022
- Produk baru: Payouts
- Produk "Payouts" yang sudah ada diganti namanya menjadi "Payout Links"
November 29, 2022
- Added
payment_id
on Invoice Callback parameter
November 11, 2022
- Added new Cancel API for PayLater charges
- Added
DD_RCBC
as a new value forpayment_methods
field on Create Invoice API
November 11, 2022
- Menambahkan
DD_RCBC
sebagai nilaipayment_methods
baru di API Pembuatan Invoice
November 8, 2022
- Menambahkan parameter
report_version
pada API Menghasilkan Laporan
November 3, 2022
- Menambahkan izin API key baru
Report
pada API Report - Menambahkan izin API key baru
Transaksi
pada API Transaksi
October 28, 2022
- Menambahkan
ATOME
sebagai nilaipayment_methods
baru di API Pembuatan Invoice
October 27, 2022
- Menambahkan
date_of_registration
dandomicile_of_registration
pada Customer Object - Mengubah panjang maksimum email menjadi 50 karakter di Customer Object
Oktober 18, 2022
- Menambahkan
MAXIMUM_REFUND_TRANSACTION_REACHED
sebagai kode kesalahan pengembalian dana eWallet baru
Oktober 12, 2022
- Menambahkan
ID_JENIUSPAY
sebagai channel pembayaran eWallet - Menambahkan
destination_account_id
pada Fee Rule API - Membuat
for-user-id
sebagai optional saat headerwith-fee-rule
tersedia
Oktober 11, 2022
- Get Balance API menggunakan API key permission baru
Balance
September 30, 2022
- Menambahkan pemberitahuan bahwa API xenPlatform v1 Buat Akun dan Update Akun akan berhenti beroperasi pada tanggal 30 September 2023
September 12, 2022
- Menambahkan
min_amount
danmax_amount
sebagai parameter baru pada pembuatan VA - Menambahkan
reference
sebagai parameter baru ke dalam objekpayment_detail
pada notifikasi pembayaran
September 6, 2022
- Menghapus duplikasi field
country
dalam fieldidentity_accounts
- Menambahkan deskripsi alphanumeric dalam semua field freetext
Agusttus 23, 2022
- Halaman Request-ID baru di API Reference
Agustus 22, 2022
- Menambahkan alur pengalihan/non-auto debit
ID_LINKAJA
pada Postman Collection - Menambahkan alur pengalihan/non-auto debit
ID_DANA
pada Postman Collection
Agustus 15, 2022
- Menambahkan tipe webhook baru
payment_method_v2
pada API Pengaturan Callback URL
Agustus 9, 2022
- Perbarui Tipe Transaksi di Laporan Transaksi
Agustus 5, 2022
- Menambahkan alur pengalihan/non-auto debit
ID_LINKAJA
- Menambahkan alur pengalihan/non-auto debit
ID_DANA
- Jumlah maksimal QRIS yang diperbarui menjadi Rp 10.000.000
- Jumlah maksimal Cashalo yang diperbarui menjadi 8.000 PHP
- Akulaku sekarang menerima diskon sebagai item
Juli 27, 2022
- Menambahkan
DBS
sebagai channel baru Virtual Accounts - Menambahkan
BSI
sebaagai channel yang tersedia untuk parametersuggested_amount
Juli 15, 2022
- Menambahkan
ID_ATOME
danPH_ATOME
sebagai saluran paylater baru
Juli 14, 2022
- Attribut Customer Object
type
dirubah darioptional
menjadirequired
Juni 20, 2022
- Menambahkan
payment_remark
pada object pembayaran Virtual Account untuk BSS VA
Juni 13, 2022
- Menambahkan ID_ASTRAPAY sebagai channel pembayaran eWallet
- Menjelaskan bahwa PayMaya sama dengan Maya
- Menambahkan
FAILURE_DETAILS_UNAVAILABLE
sebagai salah satu kode eror eWallet - Mengubah "card_expiry" dari required ke optional dalam API Initialize Linked Account Token
Juni 2, 2022
- GET by id dan PATCH requests untuk servis customer object
Mei 27, 2022
- Menggunakan versi terbaru: 2020-10-31 sebagai versi “default” untuk customer object service
- Menambahkan respons field baru yaitu: hashed_phone_number & trading_name
Mei 12, 2022
- Menambahkan callback Account Suspension pada xenPlatform
Mei 11, 2022
- Menghapus endpoint GET
/payment_channels
Mei 10, 2022
- Menambahkan with-fee-rule header di RO (PH & ID)
Apr 25, 2021
- Menambahkan
settlement_status
danestimated_settlement_time
di objek Transaction
Apr 21, 2021
- Pembaharuan error code untuk endpoint Charge, Void, dan Refund eWallet
- Menambahkan deskripsi pada
fees_paid_amount
danadjusted_received_amount
di invoice callback mengenai rencana penghapusan - Menghapus
fees_paid_amount
danadjusted_received_amount
pada contoh invoice callback
Apr 19, 2022
- Menambahkan opsi
CASHALO
,DD_BCA_KLIKPAY
,UANGME
ke dalam pembuatan invoice payment_methods
Apr 18, 2022
- Menambahkan
SUSPENDED
sebagai nilai tersedia untukstatus
parameter pada API GET Account by ID
Apr 05, 2022
- Menambahkan promo pada API Safe Acceptance sebagai objek opsional
Mar 21, 2022
- Menambahkan kanal notifikasi baru
viber
pada API Invoice dan Recurring Payment
Mar 16, 2022
- Menambahkan Shopeepay Filipa pada API Invoice
- Menambahkan kanal Paylater baru
ID_INDODANA
pada Paylater API
Mar 11, 2022
- Menambahkan
surname
pada buat invoice APIcustomer
object - Menambahkan
customer
andcustomer_notification_preference
pada invoice response
Mar 10, 2022
- Menambahkan with-fee-rule pada eWallet v2 di ID
Mar 09, 2022
- Menambahkan kanal Paylater baru
PH_CASHALO
Feb 28, 2022
- Menghapus persyaratan keunikan
reference_id
di ewallets charge API
Feb 08, 2022
- Menambahkan contoh mendapatkan invoice berdasarkan External ID
- Memberi keterangan pada
fees_paid_amount
danadjusted_received_amount
pada Notifikasi Invoice
Feb 04, 2022
- Menambahkan DANA sebagai metode pembayaran eWallet tokenisasi
- Menambahkan ShopeePay ke metode pembayaran eWallet PH
- Alur account linking API tokenisasi yang baru dan disimplifikasi
- Menambahkan metode pengembalian sebagian dana untuk ShopeePay
Feb 03, 2022
- Menambahkan parameter external_id yang bisa digunakan untuk update Virtual Account
Jan 20, 2022
- Menambahkan header
with-fee-rule
pada API ewallet untuk kanal Filipina - Menambahkan rincian kode kegagalan untuk transaksi kartu kredit yang gagal
Jan 17, 2022
- Menghilangkan
bank_account_number
andpayment_code
from Buat Invoice respon
Jan 14, 2022
- Menambahkan retail-outlet endpoint cek daftar pembayaran dari ID Fixed Payment Code
Jan 13, 2022
- Menambahkan Android dan iOS SDK
- Mengganti Github repository iOS SDK ke repository baru. Repository lama akan tetap didukung
Jan 11, 2022
- Menambahkan tipe
ph_disbursement
pada API Pengaturan Callback URL
Jan 05, 2022
- Menghilangkan status
REFUNDED
dan menambahkan tipe transaksiREFUND
pada API Transaksi
Dec 28, 2021
- Menambahkan penjelasan bahwa khusus untuk BCA Aggregator, merchant bisa membuat VA name dengan karakter angka.
Dec 24, 2021
- Menambahkan BJB pada API Reference Virtual Account
Dec 22, 2021
- Menambahkan fitur void & refund untuk LinkAja
- Memperjelas bahwa fitur refund OVO hanya tersedia untuk tokenized payment
Dec 15, 2021
- Menambahkan response Dapatkan/Buat Faktur dan Daftar Faktur untuk menyertakan
available_paylaters
Dec 13, 2021
- Menambahkan detail pembayaran dalam panggilan balik kode QR
Dec 10, 2021
- Menambahkan opsi QRIS ke dalam pembuatan invoice payment_methods
- Perbarui deskripsi pembuatan faktur payment_methods
Dec 9, 2021
- Menambahkan metode pembayaran
CEBUANA
untuk POST Buat Invoice dan Invoice Callback
Dec 2, 2021
- Menambahkan dokumentasi
metadata
di Cards Create Charge Endpoint
Nov 18, 2021
- Menghapus BJB pada API Reference Virtual Account
- Mengubah merchant descriptor dari XENDIT menjadi XDT
Nov 15, 2021
- Menambahhkan parameter baru
locale
pada Buat Invoice dan Get Invoice API
Nov 12, 2021
- Menambahkan
url
dancategory
untuk setiap item pesanan pada INVOICE
Nov 1, 2021
- Menambahkan metode void dan refund untuk eWallet
- Menambahkan parameter baru status, refunded_amount, void_status, dan voided_at pada Charge Object untuk Charge API, Get Payment Status dan Payment Callback
Oct 29, 2021
- Menambahkan INCOMPLETE_AUTHENTICATION pada respon charge credit card
Oct 21, 2021
- BARU - GET Transfer API untuk pengguna XenPlatform
- Menambahkan objek payment_details ke GET Invoice response payload
- Menambahkan objek payment_details ke panggilan balik Faktur
Oct 19, 2021
- Menambahkan detail untuk Paylater refund dan Akulaku
Oct 18, 2021
- Tambahkan
fee object
sebagai parameter body ditransaction object
- Mengubah channel menjadi channel_code di transaction object
- Menambahkan kode error
INVALID_DESTINATION
di Buat Disbursement
Oct 08, 2021
- Memperbarahui limitasi nominal pembayaran minimum dan maksimum untuk Virtual Account
- Memperbarahui deskripsi parameter untuk Virtual Account
Oct 07, 2021
- Menambahkan header Fee Rule di QRIS
Oct 05, 2021
- Menambahkan larangan pengunaan prefix pada saat membuat Fixed Payment Code
Oct 04, 2021
- Menambahkan BSI (Bank Syariah Indonesia) sebagai bank channel baru untuk Invoice
Sep 30, 2021
- Billease PayLater sudah ditambahkan sebagai metode pembayaran di PH
- Kredivo dan Akulaku sudah ditambahkan sebagai metode pembayaran di ID
- Deskripsi status sudah diperbaharui di callback payload
Sep 28, 2021
- Menambahkan BSI (Bank Syariah Indonesia) sebagai bank channel baru untuk Virtual Account
Sep 27, 2021
- Menambahkan kode sampel .NET untuk Balance, Virtual Account, Disbursement, Invoice, Customer, Linked Account, Payment Method, Direct Debit Payment, and eWallets API dalam versi EN dan ID
- Menambahkan kode sampel .NET untuk Retail Outlet (PH) dalam versi EN
- Menambahkan Virtual Account, Disbursement, Invoice, Customer, Direct Debit, Retail Outlet (PH) dan eWallets ke dalam daftar produk yang didukung oleh library .NET dalam versi EN dan ID
Sep 21,2021
- Menambahkan Karakter Spesial pada Nama Fixed Payment Code
Sep 19,2021
- Menambahkan panggilan balik kedaluwarsa tokenisasi eWallet
- Menambahkan kode kesalahan untuk tokenized yang diisi dengan token yang kedaluwarsa
Sep 15,2021
- Menambahkan Akulaku sebagai saluran pembayaran di Paylater
- Menambahkan metode pengembalian dana di Paylater
Sep 10, 2021
- Menambahkan BJB (Bank Jabar Banten) sebagai bank channel baru untuk Virtual Account
Aug 26, 2021
- Menambahkan pembeda produk/layanan DIGITAL dan FISIK ke jenis item pesanan paylater
- Diskon dan biaya yang dihapus dari jenis item pesanan
Aug 25, 2021
- Menambahkan Prefix pada nama BNI VA
- Menambahkan status aktivasi pada Get Virtual Account Banks
- Menambahkan request parameter pada header untuk RO PH
Aug 19, 2021
- Menambahkan 2 parameter opsional untuk membuat invoice:
items
danfees
Aug 18, 2021
- Menambahkan kode sampel PHP untuk Linked Account, Payment Method, Recurring Payment, dan Direct Debit Payment API dalam versi EN dan ID
- Menambahkan Direct Debit ke dalam daftar produk yang didukung oleh library PHP dalam versi EN dan ID
Aug 18, 2021
- Menambahkan kode sampel PHP untuk Customer API dalam versi EN dan ID
- Menambahkan Customer ke dalam daftar produk yang didukung oleh library PHP dalam versi EN dan ID
Aug 5, 2021
- Menambahkan kode sampel Go untuk Linked Account, Payment Method, Recurring Payment, dan Direct Debit Payment API dalam versi EN dan ID
- Menambahkan Direct Debit ke dalam daftar produk yang didukung oleh library Go dalam versi EN dan ID
Aug 5, 2021
- Menambahkan metode pemutusan tautan Tokenisasi eWallets
Aug 4, 2021
- Menambahkan kode sampel Go untuk Customer API dalam versi EN dan ID
- Menambahkan Customer ke dalam daftar produk yang didukung oleh library Go dalam versi EN dan ID
Jul 29, 2021
- Menambahkan kode sampel Java untuk Linked Account, Payment Method, Recurring Payment, dan Direct Debit Payment API dalam versi EN dan ID
- Menambahkan Direct Debit ke dalam daftar produk yang didukung oleh library Java dalam versi EN dan ID
Jul 28, 2021
- Menambahkan kode sampel Java untuk Customer API dalam versi EN dan ID
- Menambahkan Customer ke dalam daftar produk yang didukung oleh library Java dalam versi EN dan ID
Jul 28, 2021
- Mengganti parameter wajib
payer_email
dandeskripsi
pada Buat Invoice API menjadi paramater opsional
Jul 27, 2021
- QR Code DYNAMIC dapat dibayarkan satu-kali
Jul 23, 2021
- Menambahkan kode error di xenPlatform Transfers
Jul 5, 2021
- API Refund Terbaru
- Update Object Direct Debit Payment BCA KlikPay, BCA OneKlik, dan dukungan refund
- Menambahkan deskripsi error untuk PAYMENT_STATUS_FAILED
- Menambahkan deskripsi callback untuk payment method expired/expired event
Jul 21, 2021
- Menambahkan bagian Laporan
Jul 13, 2021
- Menambahkan Buat Akun v2
- Menambahkan Callback Pembaruan Akun v2
- Menambahkan Dapatkan Akun dengan ID
Jul 12, 2021
- Menambahkan definisi type dan status pada Retail Outlet - ID
- Menambahkan penautan akun untuk tokenisasi Shopeepay
Jun 28, 2021
- Menambahkan
ewallet
,direct_debit
, danpayment_method
pada API POST /callback_urls
Jun 24, 2021
- Menambahkan bagian Transactions
Jun 21, 2021
- Ditambahkan SAKUKU eWallets API
Jun 3, 2021
- Perbaiki langkah tokenisasi eWallets
- Menambahkan penautan akun untuk tokenisasi OVO
June 2, 2021
- Penambahan batasan jumlah maksimum dan minimum Disbursements
- Menambahkan VA pada Fee Rule API
May 28, 2021
- Menambahkan
QRIS
pada API GET/payment_channels
- Menambahkan Cards pada Fee Rule API
May 12, 2021
- Batas pembayaran kode QR yang diperbarui hingga 5 juta IDR
May 5, 2021
- Menambahkan Kode Error pada API Mengatur Callback URLs
Apr 28, 2021
- Menambahkan halaman testing untuk Safe Acceptance pada Cards
Apr 12, 2021
- Menambahkan parameter
metadata
pada QR Codes
Apr 08, 2021
- Menambahkan bagian alur tokenisasi untuk eWallet
Apr 07, 2021
- Endpoint baru untuk menghapuskan token akun yang bertaut
- Pembaruan kode error untuk Inisiasi penautan akun Direct Debit
- Pembaruan kode error untuk Membuat Pembayaran Direct Debit
- Pembaruan kode error untuk Validasi OTP untuk Pembayaran Direct Debit
- Tambahan alasan kegagalan untuk Pembayaran Direct Debit
Mar 29, 2021
- API Mendapatkan Token baru pada Kartu Kredit
Mar 26, 2021
- Akun tipe
OWNED
sekarang tersedia di Filipina
Mar 25, 2021
- Menambahkan parameter
approval_code
pada respon Safe Acceptance - Memperbaiki deskripsi dari
approval_code
pada respon Charge - Memperbaiki posisi dari parameter
reward
pada respon Get Charge Option
Mar 17, 2021
- Terdapat batasan maksimum jumlah karakter untuk business_name pada endpoint /accounts. Jika jumlahnya lebih dari 128 karakter maka akan terpotong.
Mar 12, 2021
- Menambahkan tautan ke dokemuntasi Safe Acceptance sebagai petunjuk untuk membuat signature pada fitur Safe Acceptance
- Menambahkan paremeter baru pada permintaan dan respons Safe Acceptance
- Menambahkan paremeter baru pada permintaan dan respons Get Charge Option
Mar 10, 2021
- Menambahkan Gcash dan Grabpay sebagai saluran eWallet di Filipina untuk pembayaran satu kali
Mar 05, 2021
- Menambahkan limitasi panjang karakter pada nama RO
- API Customers kini dapat menggunakan header
for-user-id
untuk XenPlatform
Mar 04, 2021
- API Safe Acceptance baru pada Kartu Kredit
Mar 01, 2021
- Menambahkan jumlah karakter yang diperbolehkan untuk nama pada BCA VA
Feb 26, 2021
- API Direct Debit sekarang mendukung header XenPlatform
for-user-id
- Kode VA bank terbaru yaitu
BNI_SYARIAH
- Melarang penggunaan nama institusi atau bank di Indonesia pada pembuatan VA
- Menambahkan kode sampel Node.js pada API
/ewallets/charges
Feb 22, 2021
- Menambahkan Go di section library untuk versi bahasa
- Menambahkan PHP di section library untuk versi bahasa
- Menambahkan Java di section library untuk versi bahasa
- Menambahkan kode sampel Go pada API
/ewallets/charges
- Menambahkan kode sampel PHP pada API
/ewallets/charges
- Menambahkan kode sampel Java pada API
/ewallets/charges
Feb 17, 2021
Menambahkan kode sampel Python pada API /ewallets/charges
Feb 15, 2021
- Menambahkan Customers & Direct Debit ke dalam daftar produk yang didukung oleh library Node JS
- Menambahkan kode sampel Node JS pada API
/customers
,/linked_account_tokens
,/payment_methods
,/direct_debits
Feb 10, 2021
- Menambahkan
status
pada respon Kartu Kredit Charge API - Menambahkan status
REVERSED
pada daftar status respon API charge - Menambahkan query parameter
id_type
pada API permintaan charge untuk membantu pengguna mendapatkan rincian charge dengan menggunakan ID charge maupun external ID - Menambhakan
cvn_code
pada respon Kartu Kredit Charge API
Feb 09, 2021
- Menambahkan catatan bahwa channel_properties diperlukan saat checkout_method = ONE_TIME_PAYMENT
Feb 05, 2021
API eWallet baru yang simple dan konsisten yang mendukung top provider eWallet di Indonesia dan Filipina
Feb 4, 2021
- Menambahkan Node JS di section library dalam versi bahasa
- Menambahkan QR Codes ke dalam daftar produk yang didukung oleh library Node JS dalam versi inggris dan bahasa
- Menambahkan kode sampel Node JS pada API
/qr_codes
Feb 1, 2021
- Penambahan batas maksimum Disbursements/Transfer antar bank dari Rp 50,000,000 menjadi Rp 100,000,000
Jan 22, 2021
- Penambahan parameter currency pada pembuatan otentikasi kartu kredit
Jan 21, 2021
- Penambahan objek customer sebagai endpoint tersendiri
- Penambahan File service
Jan, 19, 2021
- Menambah kekurangan dokumentasi parameter "currency" pada pembuatan VA untuk API versi 2018-12-12
Jan, 04, 2021
- Menambahkan feature untuk GET Pembayaran QR Code dengan pagination
Dec, 29, 2020
- Memperbarui halaman membuat virtual akun
Dec, 17, 2020
- Menambahkan API untuk membuat akun Philippines pada xenPlatform
Dec, 8, 2020
- Menambahkan billing_details dan customer pada parameter request pembuatan token
- Memperbaiki contoh pada parameter billing_details pada pembuatan charge
- Menghapus TOKENIZATION_ERROR dan CREDIT_CARD_DATA_ERROR pada bagian kode error pada tokenisasi
Nov, 26, 2020
- Memperpanjang durasi payout dari 1 hari menjadi 3 hari
Nov, 11, 2020
- Tambahkan PATCH account
Nov, 2, 2020
- Perubahan payload create, update, dan respon get fixed payment code
Oct 22, 2020
- Penambahan pointer pada referensi Shopeepay
Oct 20, 2020
- Penambahan payload Virtual Account Payment Callback Request
Okt 4, 2020
- Penambahan endpoint update promotion
- Penambahan endpoint delete promotion
- Penambahan parameter min_original_amount pada create promotion dan object promotion
- Penambahan parameter min_original_amount pada respon get charge option promotion
- Penambahan parameter max_discount_amount pada create promotion
- Penambahan parameter max_discount_amount pada respon get charge option promotion
- Perubahan struktur direktori Cards
Agu 04, 2020
- Penambahan kode sampel Python untuk Balance
- Penambahan kode sampel Python untuk Batch Disbursement
- Penambahan kode sampel Python untuk Cards
- Penambahan kode sampel Python untuk Cardless Credit
- Penambahan kode sampel Python untuk Disbursement
- Penambahan kode sampel Python untuk Direct Debit
- Penambahan kode sampel Python untuk Ewallets
- Penambahan kode sampele Python untuk Invoice
- Penambahan kode sampel Python untuk Payout
- Penambahan kode sampel Python untuk QR Codes
- Penambahan kode sampel Python untuk Recurring Payment
- Penambahan kode sampel Python untuk Retail Outlets
- Penambahan kode sampel Python untuk Virtual Account
- Penambahan kode sampel Python untuk XenPlatform
- Penambahan kode sampel Go untuk Balance
- Penambahan kode sampel Go untuk Cards
- Penambahan kode sampel Go untuk Cardless Credit
- Penambahan kode sampel Go untuk Disbursement
- Penambahan kode sampel Go untuk Ewallets
- Penambahan kode sampel Go untuk Invoice
- Penambahan kode sampel Go untuk Payouts
- Penambahan kode sampel Go untuk Recurring Payment
- Penambahan kode sampel Go untuk Retail Outlets
- Penambahan kode sampel Go untuk Virtual Account
Aug 3, 2020
- Penambahan API Get Virtual Account Details pada Postman Collection
- Penambahan API Update Virtual Account pada Postman Collection
- Penambahan API Get Virtual Account Payment Details pada Postman Collection
- Penambahan API Update Fixed Payment Code pada Postman Collection
- Penambahan API Get Fixed Payment Code Details pada Postman Collection
Sep 28, 2020
- Perubahan pada respons pembuatan Virtual Accounts dari ACTIVE menjadi PENDING
- Penambahan parameter expiration_date untuk respons pembuatan Virtual Accounts
Sep 17, 2020
Penambahan Platform Fee sebagai fitur baru untuk xenPlatform
Sep 14, 2020
Upaya Pengiriman Callback Terbaru
Agu 04, 2020
- Penambahan kode sampel Python untuk Balance
- Penambahan kode sampel Python untuk Batch Disbursement
- Penambahan kode sampel Python untuk Cards
- Penambahan kode sampel Python untuk Cardless Credit
- Penambahan kode sampel Python untuk Disbursement
- Penambahan kode sampel Python untuk Direct Debit
- Penambahan kode sampel Python untuk Ewallets
- Penambahan kode sampel Python untuk Invoice
- Penambahan kode sampel Python untuk Payouts
- Penambahan kode sampel Python untuk QR Codes
- Penambahan kode sampel Python untuk Recurring payment
- Penambahan kode sampel Python untuk Retail outlets
- Penambahan kode sampel Python untuk Virtual account
- Penambahan kode sampel Python untuk xenPlatform
- Penambahan kode sampel Go untuk Balance
- Penambahan kode sampel Go untuk Cards
- Penambahan kode sampel Go untuk Cardless Credit
- Penambahan kode sampel Go untuk Disbursement
- Penambahan kode sampel Go untuk Ewallets
- Penambahan kode sampel Go untuk Invoice
- Penambahan kode sampel Go untuk Payouts
- Penambahan kode sampel Go untuk Recurring payment
- Penambahan kode sampel Go untuk Retail outlets
- Penambahan kode sampel Go untuk Virtual account
Sept 9, 2020
- Perubahan maksimum expected_amount menjadi Rp 2,500,000 untuk Alfamart
Aug 13, 2020
- Perubahan panjang maksimum external_id dari 1000 menjadi 950 untuk Virtual Account
Aug 12, 2020
- Penambahan bagian dokumentasi baru: Versioning
- Penambahan definisi kompatibilitas dengan versi sebelumnya
- Penambahan panduan migrasi untuk Versioning
- Penambahan Changelog untuk API pada bagian Versioning
Agu 11, 2020
- Penambahan custom header pada create refund
Aug 04, 2020
- Penambahan kode sampel Python untuk Balance
- Penambahan kode sampel Python untuk Batch Disbursement
- Penambahan kode sampel Python untuk Kartu Kredit
- Penambahan kode sampel Python untuk Cardless Credit
- Penambahan kode sampel Python untuk Disbursement
- Penambahan kode sampel Python untuk Direct Debit
- Penambahan kode sampel Python untuk Ewallets
- Penambahan kode sampel Python untuk Invoice
- Penambahan kode sampel Python untuk Payouts
- Penambahan kode sampel Python untuk QR Codes
- Penambahan kode sampel Python untuk Recurring payment
- Penambahan kode sampel Python untuk Retail outlets
- Penambahan kode sampel Python untuk Virtual account
- Penambahan kode sampel Python untuk xenPlatform
Aug 3, 2020
- Penambahan API Get Virtual Account Details pada Postman Collection
- Penambahan API Update Virtual Account pada Postman Collection
- Penambahan API Get Virtual Account Payment Details pada Postman Collection
- Penambahan API Update Fixed Payment Code pada Postman Collection
- Penambahan API Get Fixed Payment Code Details pada Postman Collection
Jul 31, 2020
- Penambahan API Transfer xenPlatform untuk dapat melakukan transfer antar sub-akun
Jul 30, 2020
- Pembaruan kode sampel PHP untuk Balance
- Pembaruan kode sampel PHP untuk Cards
- Pembaruan kode sampel PHP untuk Cardless Credit
- Pembaruan kode sampel PHP untuk Disbursement
- Pembaruan kode sampel PHP untuk Ewallets
- Pembaruan kode sampel PHP untuk Invoice
- Pembaruan kode sampel PHP untuk Payouts
- Pembaruan kode sampel PHP untuk Recurring payment
- Pembaruan kode sampel PHP untuk Retail outlets
- Pembaruan kode sampel PHP untuk Virtual account
Jul 28, 2020
- Pembaruan expiration_date Virtual Account & Retail Outlets menjadi 31 tahun dari 30 tahun
- Pembaruan name Retail Outlets dari huruf menjadi alfanumerik
- Pembaruan expected_amount minimal Retail Outlet Indomaret menjadi 10,000 dari 11,000
Jul 27, 2020
- Penambahan kode sampel Java untuk Balance
- Penambahan kode sampel Java untuk Batch Disbursement
- Penambahan kode sampel Java untuk Kartu Kredit
- Penambahan kode sampel Java untuk Cardless Credit
- Penambahan kode sampel Java untuk Disbursement
- Penambahan kode sampel Java untuk Ewallets
- Penambahan kode sampel Java untuk Invoice
- Penambahan kode sampel Java untuk Payouts
- Penambahan kode sampel Java untuk Recurring payment
- Penambahan kode sampel Java untuk Retail outlets
- Penambahan kode sampel Java untuk Virtual account
Jul 24, 2020
- Penambahan recurring pada Direct Debit
- Penambahan bagian
Library
- Penambahan library Python
Jul 16, 2020
- Pembaruan deskripsi payment_code Retail Outlets untuk melingkupi informasi mengenai Payment via Barcode
Jul 07, 2020
- Pembaruan callback paths retail outlet, ovo, dan batch disbursement untuk penyetelan API Callback URL
Jul 07, 2020
- Penambahan mata uang pada pembuatan recurring payment
Jul 07, 2020
- Penambahan error baru AMOUNT_BELOW_MINIMUM_LIMIT dan AMOUNT_ABOVE_MINIMUM_LIMIT ketika merchant melakukan request charge diatas atau dibawah nominal tertentu
- Penambahan error baru AUTHORIZATION_EXPIRED ketika merchant melakukan capture authorization diatas 7 hari
Jul 01, 2020
- Penambahan versi ID untuk direct debit
June 30, 2020
- Penambahan opsi get charge untuk mendapatkan cicilan yang tersedia
- Penambahan cicilan pada request charge
- Pembuangan tipe promo pada pembuatan promo
- Penambahan kode error baru untuk menangani cicilan tanpa nama pemegang kartu pada request
Jun 24, 2020
- Pembuangan limit traksaksi dan is_deleted dari contoh promotion
Jun 18, 2020
- Penambahan bagian untuk recurring direct debit
June 17, 2020
- Penambahan field billing details pada endpoint charge
- Penambahan alasan baru untuk gagal refund
Jun 11, 2020
- Penambahan kode bank baru SAHABAT_SAMPOERNA untuk Virtual Accounts
- Penambahan field sender_name untuk respon callback Virtual Account
Jun 06, 2020
- Penambahan produk Direct Debit
May 31, 2020
- Penambahan endpoint baru untuk tipe pembayaran Kredito - perhitungan terhadap nilai cicilan
May 26, 2020
- Penambahan alasan gagal pada respon Reverse Authorization di Bahasa Inggris dan Indonesia
- Perbaikan fields yang tidak akurat pada respon authorization
May 21, 2020
- Penambahan endpoint Callback URL untuk xenPlatform
May 13, 2020
- Pembaruan status issued pada payout ke pending
May 12, 2020
- Penambahan payment_method_id pada endpoint recurring payment
May 06, 2020
- Pembaruan kode gagal OVO
April 28, 2020
email
sekarang diharuskan saat pembuatan payout- Pembuangan
passcode
dari respon payout
April 24, 2020
- Perbaikan copywriting untuk get payment channels
April 20, 2020
- Perbaikan kode error untuk eWallets and QR
April 16, 2020
- Pembaruan referensi untuk QR code
April 16, 2020
- Penambahan referensi API payment channels
April 14, 2020
- Pembaruan status pada payouts
March 20,2020
- Pemasukan checkout expiry pada LINKAJA
- Perbaikan error format timestamp pada callback pembayaran DANA dan get payment status
- Pembuangan catatan "only alphanumeric characters" pada pembuatan pembayaran OVO disebabkan catatan "The only allowed punctuation is -" yang adalah constraint pengganti
March 19, 2020
- Pembaruan error pada body respon GET ewallets
- Pembaruan postman collection untuk ewallets dan cardless credit
March 11, 2020
- Pembuangan dan pemberian label pada fields yang sudah tidak digunakan di invoice
March 5, 2020
- Pembuangan endpoint legacy bank account data request
March 3, 2020
- Perbaikan endpoint yang hilang untuk cardless credit
- Perbaikan kode error LINKAJA
- Perbaikan error kode DANA
- Revisi kode error OVO
March 2, 2020
- Penambahan
email
sebagai field optional saat pembuatan payout
February 28, 2020
- Penambahan
reminder_time
sebagai field optional saat pembuatan invoice - Penambahan
reminder_date
sebagai field optional pada respon pembuatan invoice - Peningkatan kualitas dokumentasi virtual accounts dan retail outlets
February 26, 2020
- Library Go baru
- Library PHP baru
- Penambahan produk baru untuk library Java
February 18, 2020
- Introduce new EWallet: OVO asynchronous create payment callback flow
- New Versioning section
February 14, 2020
- Penambahan API Transfers untuk xenPlatform
- Klarifikasi field yang sudah tidak digunakan pada respon callback invoice
- Pembaruan tanggal ke 2020 pada halaman Invoice
February 12, 2020
- Pembaruan API Refund dengan required header dan values respon baru
- Pembaruan API Charge dengan detail pada labels MID
February 04, 2020
- Penambahan kode sample Node.js
January 23, 2020
- Penambahan currency dan mid_label pada Create Charge API
January 20, 2020
- Pembaruan untuk melingkupi headers xenPlatform untuk semua API yang kompatibel
January 16, 2020
- Pembaruan field dari
email_to
keemail
pada payout
January 14, 2020
- Pembaruan respon get payment status untuk eWallets
- Pembaruan requirement alfanumerik pada external_id OVO
January 9, 2020
- Pengenalan library Node.js baru
January 6, 2020
- Penambahan API xenPlatform
December 15, 2019
- Pembaruan limit nominal Disbursement
December 14, 2019
- Pembaruan beberapa request callback pada invoice
December 12, 2019
- Produk baru: Payouts
- Bagian Skenario Testing baru
December 11, 2019
- Bagian Checklists baru
- Bagian Error Handling baru
- iOS SDK baru
December 9, 2019
- Bagian Authentication baru
- Bagian Libraries / SDKs baru
- Bagian Errors baru
- Bagian Callback baru
November 27, 2019
- Pembaruan beberapa respon pada dokumentasi API recurring
November 26, 2019
- Pembuangan status
EXPIRED
danPENDING
pada callback DANA - Penambahan penjelasan pada API_VALIDATION_ERROR
November 21, 2019
- Perubahan satu field pada respon checkoutRequest untuk LinkAJa dari
redirect_url
tocheckout_url
November 7, 2019
- Pembaruan deskripsi parameter untuk callback invoice
October 31, 2019
- Pembuantan
items
pada INVOICE
October 30, 2019
- Peningkatan kualitas contoh PHP untuk Cardless Credit (Kredivo)
- Penambahan eWallet baru: LINKAJA
October 23, 2019
- Pembuangan callback Refund
- Pembuangan status Refund PENDING