Payments API Introduction
Our new set of Payment APIs allows merchants to integrate to any of our supported money-in payment channels using a consolidated and unified set of APIs. Through these APIs, merchants are able to use the same endpoint for any payment method type in any supported market.
The Payment APIs consist of three main resources:
- Payment Method - refers to the source of funds or the payment instrument used for the payment. This may also refer to linked/tokenized cards, bank accounts, payment instrument (virtual account number, QR codes, or fixed payment code) or e-wallet accounts.
- Payment Request - initializes a payment transaction for a particular
PaymentMethod
- Payments API - unifies callback notification across all money-in channels. It represents the actual funds transaction/attempt made to a payment method. This object will be delivered in the form of webhooks.
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) |
โ | โ | โ |
Payment Object
Payment object represents the actual funds transaction/attempt made to a payment method. This object will be found through payment webhooks (e.g payment.suceeeded
or payment.failed
) to give the final status of the trasaction.
Payment Object Example
{
"id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"amount": 1000,
"status": "SUCCEEDED",
"country": "PH",
"created": "2022-08-12T13:30:40.9209Z",
"updated": "2022-08-12T13:30:58.729373Z",
"currency": "PHP",
"metadata": {
"sku": "ABCDEFGH"
},
"customer_id": "c832697e-a62d-46fa-a383-24930b155e81",
"reference_id": "25cfd0f9-baee-44ca-9a12-6debe03f3c22",
"payment_method": {
"id": "pm-951b1ad9-1fbb-4724-a744-8956ab6ed17f",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:40.221525Z",
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"direct_bank_transfer": null
},
"description": null,
"failure_code": null,
"payment_detail": null,
"channel_properties": null,
"payment_request_id": "pr-5b26cae1-545b-49e9-855e-f85128f3e705"
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for the payment. Its prefix varies based on the payment method type. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
payment_request_idnullable |
string |
Unique identifier for the payment request. Prefix will vary according to the payment method used. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
reference_idrequired |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer_idnullable |
string |
ID of the customer object to which the account token are linked to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
amountrequired |
number |
Authorized amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment method will accept any amount as payment (open amount). (Applicable only for OVER_THE_COUNTER and VIRTUAL_ACCOUNT ) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 ). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
statusrequired |
string |
Status of the payment method. Possible values:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
payment_methodrequired |
object |
Corresponding Payment Method created or used for the Payment Method. Note: customer_id , currency , and amount are moved to the root level of the Payment Request object. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
channel_propertiesnullable |
object |
Specific settings applied to the payment request, overwriting the ones in the Payment Method object. For multiple use OVO, and SHOPEEPAY (ID & MY):
For PAYMAYA:
For SHOPEEPAY(VN), APPOTA, MOMO, ZALOPAY, VNPTWALLET, VIETTELPAY:
For WECHATPAY (MY):
For BRI Direct Debit:
For BPI, UBP, RCBC, CHINABANK Direct Debit:
For
|
Key | Value |
---|---|
skip_three_d_secure required |
boolean To indicate whether to perform 3DS on the payment requestDefaults to false
|
success_return_urlnullable |
string URL where the end-customer is redirected if the linking is successful.Required when skip_three_d_secure = false . This will be null if not applicable. |
failure_return_urlnullable |
string URL where the end-customer is redirected if the linking has failed.Required when skip_three_d_secure = false . This will be null if not applicable. |
merchant_id_tagnullable |
string Tag for the Merchant ID that you want to associate this payment with. This is for merchants using their own MIDs to specify which MID they want to use |
cardonfile_typenullable |
string Type of โcredential-on-fileโ / โcard-on-fileโ / COF payment for subsequent usage. Indicates future card-on-file usage.If you intend for a card to be used for future COF transactions, then this value must be included so that Xendit can inform the processors of this setup, and then after that on every transaction following the first transaction. Default: CUSTOMER_UNSCHEDULED Possible values:
Notes: In order to process MERCHANT_UNSCHEDULED and RECURRING card-on-file transaction types:
|
For GRABPAY (MY):
Key | Value |
---|---|
allowed_payment_optionsnullable |
Array of enums
Usage for each Payment method reusability
|
nullable
object
For VIRTUAL_ACCOUNT
Payments:
Key | Value |
---|---|
networknullable |
string This can be provided by the partner channel to indicate the network used for making the payment. For Philippines multi-use VA payments, this will be "InstaPay" for payments โคP50000, and "PESONet" for payments >P50000. |
For OVER_THE_COUNTER
Payments:
Key | Value |
---|---|
remarksnullable |
string This can be provided by the partner channel for additional information upon payment of the end-customer in the outlet/branch. Will be null if none is provided. |
For EWALLET
Payments:
Key | Value |
---|---|
fund_sourcenullable |
string The type of the fund originSHOPEEPAY ID - EWALLET_BALANCE , 1_MONTH_INSTALLMENT , 2_MONTH_INSTALLMENT , 3_MONTH_INSTALLMENT , 6_MONTH_INSTALLMENT , 12_MONTH_INSTALLMENT SHOPEEPAY MY - SHOPEEPAY_BALANCE , SPAYLATER_INSTALLMENTS_1MO , SPAYLATER_INSTALLMENTS_2MO , SPAYLATER_INSTALLMENTS_3MO , SPAYLATER_INSTALLMENTS_6MO , SPAYLATER_INSTALLMENTS_12MO
|
sourcenullable |
string The name of the channel SHOPEEPAY ID - Shopeepay
|
nullable
string
FAILED
, this describes the reason for failure.Will be null if the transaction did not fail.
required
string
required
string
nullable
object
Payment Request Object
This object will be found in the response of Create Payment Request endpoint. This object will give you the information of the status after the payment request.
Payment Request Object Example
{
"id": "pr-76aca7a8-da92-4480-b97a-1c44b05d132d",
"reference_id": "15bafc7c-b5ea-484b-a151-41d60bb1e964",
"business_id": "5f27a14a9bf05c73dd040bc8",
"currency": "IDR",
"amount": 10000,
"country": "ID",
"payment_method": {
"id": "pm-f77e73c7-ade1-45bf-8aa8-bc320124877c",
"type": "CARD",
"reference_id": "ed9061ee-0f0e-4086-b6b9-5282a30fadf3",
"description": "Card Transaction",
"created": "2022-09-13T02:14:31.096959Z",
"updated": "2022-09-13T02:14:31.318608Z",
"card": {
"currency": "IDR",
"channel_properties": {
"skip_three_d_secure": null,
"success_return_url": "https://your-redirect-website.com/success",
"failure_return_url": "https://your-redirect-website.com/failure",
"cardonfile_type": null
},
"card_information": {
"token_id": "8b8b6ff69cf169c534a828fbce61e0a2",
"masked_card_number": "400000XXXXXX1091",
"cardholder_name": "Test Person",
"expiry_month": "10",
"expiry_year": "2026",
"fingerprint": "c5fdf4f5e775ac60ced4447857c3e9ef",
"type": "CREDIT",
"network": "VISA",
"country": "ID",
"issuer": "BRI"
},
"card_verification_results": null
},
"ewallet": null,
"direct_debit": null,
"direct_bank_transfer": null,
"over_the_counter": null,
"virtual_account": null,
"qr_code": null,
"metadata": {},
"reusability": "ONE_TIME_USE",
"status": "ACTIVE"
},
"description": null,
"metadata": null,
"customer_id": null,
"created": "2022-09-13T02:14:37.192601423Z",
"updated": "2022-09-13T02:14:37.192601423Z",
"status": "PENDING",
"actions": [],
"failure_code": null,
"capture_method": "AUTOMATIC",
"initiator": "CUSTOMER",
"card_verification_results": null,
"channel_properties": {
"skip_three_d_secure": true
},
"shipping_information": null
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for the payment request. This has a prefix of pr- . Example: pr-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer_idnullable |
string |
ID of the customer object to which the account token will be linked to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer optional |
object
|
This object may be used if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
reference_idnullable |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
amountnullable |
number |
Authorized amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment method will accept any amount as payment (open amount). (Applicable only for OVER_THE_COUNTER and VIRTUAL_ACCOUNT ) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 ). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
statusrequired |
string |
Status of the payment method. Possible values:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
descriptionnullable |
string |
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
payment_methodrequired |
object |
Corresponding Payment Method created or used for the Payment Method. Note: customer_id , currency , and amount are moved to the root level of the Payment Request object. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
actionsrequired |
object array |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to complete a payment. Only one of the provided actions is required to be fulfilled. If no further action is needed, this parameter will be an empty array [] . Each object will have the following properties:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
capture_methodnullable |
string |
Describes when the funds are captured. Defaults to AUTOMATIC Possible values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
initiatorrequired |
string |
Identifies whether the payment is initiated by the end-customer or the merchant. Defaults to CUSTOMER Possible values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
channel_propertiesnullable |
object |
Specific settings applied to the payment request, overwriting the ones in the Payment Method object. For multiple use OVO, and SHOPEEPAY (ID & MY):
For SHOPEEPAY(VN), APPOTA, MOMO, ZALOPAY, VNPTWALLET, VIETTELPAY:
For PAYMAYA:
For WECHATPAY (MY):
For BRI Direct Debit:
For BPI, UBP, RCBC, CHINABANK Direct Debit:
For SCB and BBL Direct Debit:
For KTB and BAY Direct Debit:
For
|
Key | Value |
---|---|
skip_three_d_secure required |
boolean To indicate whether to perform 3DS on the payment requestDefaults to false
|
success_return_urlnullable |
string URL where the end-customer is redirected if the linking is successful.Required when skip_three_d_secure = false . This will be null if not applicable. |
failure_return_urlnullable |
string URL where the end-customer is redirected if the linking has failed.Required when skip_three_d_secure = false . This will be null if not applicable. |
merchant_id_tagnullable |
string Tag for the Merchant ID that you want to associate this payment with. This is for merchants using their own MIDs to specify which MID they want to use |
cardonfile_typenullable |
string Type of โcredential-on-fileโ / โcard-on-fileโ / COF payment for subsequent usage. Indicates future card-on-file usage.If you intend for a card to be used for future COF transactions, then this value must be included so that Xendit can inform the processors of this setup, and then after that on every transaction following the first transaction. Default: CUSTOMER_UNSCHEDULED Possible values:
Notes: In order to process MERCHANT_UNSCHEDULED and RECURRING card-on-file transaction types:
|
For GRABPAY (MY):
Key | Value |
---|---|
allowed_payment_optionsnullable |
Array of enums
Usage for each Payment method reusability
|
nullable
object
Key | Value |
---|---|
countryrequired |
string 2-letter ISO 3166-2 country code for the customerโs shipping country |
street_line1nullable |
string Building name and apartment unit number |
street_line2nullable |
string Building street address |
citynullable |
string City, village or town as appropriate |
province_statenullable |
string Either one of (whichever is applicable):
|
postal_codenullable |
string Postal, zip or rural delivery code, if applicable |
nullable
object
CARD
transactions. This contains the results of various checks done to verify the transaction such as CVV, and AVS. Key | Value | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
three_d_securenullable |
object Only applicable for Payment Requests when 3DS is performed Indicates the result of any 3DS transaction initiated when Payment Request creation is performed using 3DS. Note that each 3DS transaction performed using a unique Payment Method will be unique and may have a different three_ds_result unique for each Payment Request.
|
||||||||||
cvv_resultnullable |
Indicates the result from verifying the Card Validation Value / Card Validation Code (CVV / CVC) when creating the Payment Method / token. Possible values:
|
||||||||||
address_verification_resultnullable |
Only applicable for cards issued in USA, CAN or the UK. Indicates the result from verifying the street address and zip code provided when creating the Payment Request. Possible values:
|
nullable
string
FAILED
, this describes the reason for failure.Will be null if the transaction did not fail.
See possible codes here.
required
string
required
string
nullable
object
nullable
array
Object parameters
Key | Value |
---|---|
typerequired |
string Type of itemDIGITAL_PRODUCT , PHYSICAL_PRODUCT , DIGITAL_SERVICE , PHYSICAL_SERVICE ,FEE ,DISCOUNT (Atome does not support DISCOUNT) |
reference_idrequired |
string Merchantโs identifier for specific item (ie. SKU, promotion code, etc)Format Special and alphanumericMax length 255 characters |
namerequired |
string Item nameFormat Special and alphanumericMax length 255 characters |
net_unit_amountrequired |
number Net amount to be charged per unit, please put negative amount for DISCOUNT (e.g. -1000000) |
quantityrequired |
number Number of units of this item in the basketMin 1 |
urlrequired |
string URL of the itemMust be HTTPS or HTTP |
categoryrequired |
string Merchant category for itemFormat Special and alphanumericMax length 255 characters |
subcategoryoptional |
string Merchant subcategory for itemFormat Special and alphanumericMax length 255 characters |
descriptionoptional |
string Item descriptionFormat Special and alphanumericMax length 255 characters |
metadataoptional |
object Additional object that may be used for additional item attributes |
Payment Method Object
This object is refered to the source of funds or the payment instrument used for the payment. This may also refer to linked/tokenized cards, bank accounts, payment instrument (virtual account number, QR codes, or fixed payment code) or e-wallet accounts.
Payment Method Object Example
{
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "PH",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"business_id": "5f27a14a9bf05c73dd040bc8"
}
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 |
||||||||||||||||||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||||||||||||||||||
customer_idnullable |
string |
ID of the customer object to which the account token will be linked to | ||||||||||||||||||||||||||
customer nullable |
object
|
A customer object to skip Create Customer URL endpoint process. This object is required for all DIRECT_DEBIT payment methods and MULTIPLE_USE EWALLET s if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||
reference_idnullable |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
||||||||||||||||||||||||||
reusabilityrequired |
string |
Describes whether or not the payment method can be reused for subsequent payments without going through the same linking process again. Possible values:
|
||||||||||||||||||||||||||
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 ). |
||||||||||||||||||||||||||
statusrequired |
string |
Status of the payment method. Possible values:
| ||||||||||||||||||||||||||
actionsrequired |
object array |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to activate a payment method. Only one of the provided actions is required to be fulfilled. If no further action is needed, this parameter will be an empty array [] . Each object will have the following properties:
|
||||||||||||||||||||||||||
typerequired |
string |
Type of payment method. Refer to the corresponding object to access further information Possible values:
|
||||||||||||||||||||||||||
ewalletnullable |
object |
For type='EWALLET' , this contains the necessary information to describe an ewallet payment method. This will be null otherwise. Please refer to Ewallet Object for more parameter details. |
||||||||||||||||||||||||||
direct_debitnullable |
object |
For type='DIRECT_DEBIT' , this contains the necessary information to describe a direct debit payment method. This will be null otherwise. Please refer to Direct debit Object for more parameter details. |
||||||||||||||||||||||||||
cardnullable |
object |
For type='CARD' , this contains the necessary information to describe a Card payment method. This will be null otherwise. Please refer to Card Object for more parameter details. |
||||||||||||||||||||||||||
over_the_counternullable |
object |
For type='OVER_THE_COUNTER' , this contains the necessary information to describe an over-the-counter payment method. This will be null otherwise. Please refer to OTC Object for more parameter details. |
||||||||||||||||||||||||||
virtual_accountnullable |
object |
For type='VIRTUAL_ACCOUNT' , this contains the necessary information to describe a virtual account payment method. This will be null otherwise. Please refer to Virtual Account Object for more parameter details. |
||||||||||||||||||||||||||
qr_codenullable |
object |
For type='QR_CODE' , this contains the necessary information to describe a QR Code payment method. This will be null otherwise. Please refer to QR Object for more parameter details. |
||||||||||||||||||||||||||
descriptionnullable |
string |
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||
billing_informationnullable |
object |
Object containing the payor's billing address. For CARD , this should match the billing information on record with the cardholder's issuer.
|
||||||||||||||||||||||||||
failure_codenullable |
string |
If the status of the transaction is FAILED , this describes the reason for failure.Will be null if the transaction did not fail. See possible codes here. |
||||||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for Payment Method object creation. Timezone UTC+0 | ||||||||||||||||||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest Payment Method object update. Timezone UTC+0 | ||||||||||||||||||||||||||
metadatanullable |
object |
User defined object with JSON properties and values passed in during Payment Method creation. |
Cards Object
Card Object Example
{
"currency": "IDR",
"channel_properties": {
"skip_three_d_secure": null,
"success_return_url": "https://redirect.me/goodstuff",
"failure_return_url": "https://redirect.me/badstuff",
"cardonfile_type": null
},
"card_information": {
"token_id": "651d1fa8e16b180017aab0f0",
"masked_card_number": "40000000XXXX1091",
"cardholder_name": "John Doe",
"expiry_month": "12",
"expiry_year": "2040",
"type": "CREDIT",
"network": "VISA",
"country": "ID",
"issuer": "BRI",
"fingerprint": "636a577b635d29001b94f2fe",
"cardholder_email": "johndoe@gmail.com",
"cardholder_phone_number": "628212223242526"
},
"card_verification_results": {
"address_verification_result": "MATCH",
"cvv_result": "MATCH",
"three_d_secure": {
"eci_code": "05",
"three_d_secure_flow": "CHALLENGE",
"three_d_secure_result": "AUTHENTICATED",
"three_d_secure_result_reason": null,
"three_d_secure_version": "2.1.0"
}
},
"card_data_id": null,
"is_cvn_submitted": null
}
Body Parameter | Type | Description | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||||||||||||||||||||
channel_propertiesrequired |
object |
Information provided specific to the channel partner that was provided during the request
|
||||||||||||||||||||||||||
card_informationrequired |
object
| Information pertaining to the actual card
|
||||||||||||||||||||||||||
card_verification_resultsrequired |
object
| For card transactions, this contains the results of various checks done such as 3DS, CVV, and AVS.
|
||||||||||||||||||||||||||
card_data_idnullable |
string |
Unique consistent identifier for the card. This does not change values over different authorizations. | ||||||||||||||||||||||||||
is_cvn_submittednullable |
boolean |
Whether CVN was provided as part of the tokenization step. |
Direct Debit Object
Direct Debit Object Example
{
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "ed9c7984efecd163b0ffc4d79240fb64477592bdcce6cc0f7dd43ee4018bc4c2",
"masked_bank_account_number": "XXXXXXX3213"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
}
}
Body Parameter | Type | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
channel_coderequired |
string |
Identifier for the payment channel partner. Possible values:
|
||||||||||||||||
channel_propertiesrequired |
object |
object Information provided specific to the channel partner that was provided during the request
|
||||||||||||||||
bank_accountnullable |
object |
object If direct_debit.type='BANK_ACCOUNT' , this contains details regarding the underlying bank account of the payment method. This will be null otherwise.
|
||||||||||||||||
debit_cardnullable |
object |
object If direct_debit.type='DEBIT_CARD' , this contains details regarding the debit card to be used for payments. This will be null otherwise.
|
E-Wallets Object
E-Wallets Object Example
{
"account": {
"name": "John Doe",
"balance": null,
"point_balance": null,
"account_details": "+62123456XXXX"
},
"channel_code": "OVO",
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
}
}
Body Parameter | Type | Description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
channel_coderequired |
string |
Identifier for the payment channel partner. Possible values:
|
||||||||||||||||||
channel_propertiesrequired |
object |
Information provided specific to the channel partner that was provided during the request
|
accountnullable |
object |
Object that contains information of the linked eWallet account. Will be null if information is not available.
|
Retail Outlet (OTC) Object
Over-the-counter Object Example
{
"amount": 10000,
"currency": "IDR",
"channel_code": "INDOMARET",
"channel_properties": {
"payment_code": "TESTABCD1234",
"customer_name": "John Doe",
"expires_at": "2023-06-22T04:40:51Z"
}
}
Body Parameter | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
channel_coderequired |
string |
Identifier for the payment channel partner Possible values:
| ||||||||
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||
amountnullable |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment code will accept any amount as payment (open amount). |
||||||||
channel_propertiesrequired |
object |
Information provided specific to the channel partner that was provided during the request
|
QR Object
QR Object Example
{
"amount": 15000,
"channel_code": "DANA",
"channel_properties": {
"expires_at": "2023-06-02T07:17:32.34039Z",
"qr_string": "some-random-qr-string"
},
"currency": "IDR"
}
Body Parameter | Type | Description | ||||
---|---|---|---|---|---|---|
channel_codeconditional |
string |
Identifier for the QR Code standard used. This parameter is not required for Indonesia channel code. Possible values:
| ||||
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||
amountnullable |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding QR will accept any amount as payment (open amount). Open amount QR is not supported for QRPH at the moment. |
||||
channel_propertiesrequired |
object |
Information regarding the payment method / instrument
|
Virtual Account Object
Virtual Account Object Example
{
"amount": 100000,
"channel_code": "BRI",
"channel_properties": {
"customer_name": "John Doe",
"expires_at": "2054-05-24T17:00:00Z",
"virtual_account_number": "920019999095203"
},
"currency": "IDR",
"alternative_displays": [
{
"type": "QR_STRING",
"data": "SAMPLE_QR_DATA"
}
]
}
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
channel_coderequired |
string |
Identifier for the payment channel partner Possible values:
| ||||||||||
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||||
amountnullable |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding virtual account will accept any amount as payment (open amount). |
||||||||||
channel_propertiesrequired |
object |
Information provided specific to the channel partner that was provided during the request
|
||||||||||
alternative_display_typesnullable |
array of strings |
Alternative display type for the virtual account. Note:This value is currently only applicable to Vietnam virtual accounts. Accepted values:
|
||||||||||
alternative_displaysnullable |
array of object |
Alternative displays for the virtual account based on alternative_display_types value during request.Note:This value is currently only applicable to Vietnam virtual accounts. Contains an array with the following data:
|
Refund Object
The Refund Object represents a request to have a certain amount to be refunded from a succeeded payment.
Refund Object Example
{
"id": "rfd-69e77490-d2cc-4bf3-8319-e064e121db93",
"payment_id": "pr-d5fe8554-fbcd-42b3-956d-867376550ed9",
"invoice_id": "",
"amount": 3000,
"payment_method_type": "CARD",
"channel_code": "",
"currency": "PHP",
"status": "SUCCEEDED",
"reason": "CANCELLATION",
"reference_id": "9d9c04a9-55c8-4eea-8b09-4109ac10b7f0",
"failure_code": null,
"refund_fee_amount": null,
"created": "2022-09-29T03:37:07.06648896Z",
"updated": "2022-09-29T03:37:07.06648906Z",
"metadata": null
}
Body Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique identifier for the refund request. It will have the prefix rfd- . |
payment_idrequired |
string |
Identifier for the corresponding Payment that is being refunded |
invoice_idnullable |
string |
If the refund request was made using the ID for a Invoice/Checkout/Payment Link, this is the corresponding identifier for it. |
payment_method_typerequired |
string |
Type of the payment method used in the original payment. Possible values:
|
reference_idnullable |
string |
Identifier provided by the merchant for the refund request. This may be automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
amountrequired |
string |
Amount of the transaction reflecting the actual decimal places. (Ex. 1234.56 with currency PHP is one thousand thirty-four pesos and fifty-six centavos) Decimal places support varies per currency:
|
currencyrequired |
string |
Three-letter ISO 4217 currency code of the transaction, in uppercase. |
statusrequired |
string |
Status of the refund. Possible values:
|
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 ). |
channel_coderequired |
string |
Identifier for the payment channel partner |
reasonrequired |
string |
Provided reason why the refund was requested. Possible values:
|
failure_codenullable |
string |
If the status of the refund is FAILED , this describes the reason for failure.Will be null if the refund did not fail. See possible codes here. |
refund_fee_amountnullable |
number |
(if applicable) This will be the corresponding additional fee for processing the refund. |
createdrequired |
string |
ISO 8601 Timestamp for refund object creation. Timezone UTC+0 |
updatedrequired |
string |
ISO 8601 Timestamp for latest refund object update. Timezone UTC+0 |
metadatanullable |
object |
User defined object with JSON properties and values passed in during Refund creation. |
Payments API Endpoints
Create Payment Request
This endpoint provides the following functionalities:
- Initializes the payment/capture process for Cards, E-wallets and Direct Debits
- Creates a payment method object along with the payment initialization
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"currency": "IDR",
"amount": 100000,
"payment_method": {
"type": "EWALLET",
"reusability": "ONE_TIME_USE",
"ewallet": {
"channel_code": "SHOPEEPAY",
"channel_properties": {
"success_return_url": "https://your-redirect-website.com/success"
}
}
},
"customer_id": "fc4c060b-3c41-4707-b7b2-df9c3376edde",
"metadata": {
"sku": "ABCDEFGH"
}
}' \
Header | 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. 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 Payment Request 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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
amountconditional |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer_id conditional |
string
|
ID of the customer object to which the account token will be linked to. Call Create Customer to generate Customer ID. A customer_id is required for all DIRECT_DEBIT payment methods and MULTIPLE_USE EWALLET s. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer optional |
object
|
A customer object to skip Create Customer URL endpoint process. This object only available if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
country conditional |
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 ). Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
payment_methodconditional |
object |
Note: Only one of payment_method{} or payment_method_id must be present.Respective Payment Method properties that corresponds to the chosen payment method type or channel. The request will apply the top-most values for customer_id , currency , and amount . |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
payment_method_idconditional |
object |
Note: Only one of payment_method{} or payment_method_id must be present.ID of the ACTIVE Payment Method to be used in the payment. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
capture_methodconditional |
string |
Note: Only available for cards Describes when the funds are captured. Default: AUTOMATIC Accepted values: - AUTOMATIC - Capture is done immediately as the request passes validation- MANUAL - Capture is only done when the Capture endpoint is triggered. This is only applicable for CARD transactions. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
channel_propertiesoptional |
object |
Specific settings to be applied to the transaction. This also overwrites any common parameters with the Payment Method Object. For multiple use OVO, and SHOPEEPAY (ID & MY):
For PAYMAYA:
For WECHATPAY (MY):
For BRI Direct Debit:
For BPI, UBP, RCBC, CHINABANK, and FPX Channels under Direct Debit:
For SCB and BBL Direct Debit:
For KTB and BAY Direct Debit:
For GRABPAY (MY):
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"currency": "IDR",
"amount": 100000,
"customer_id": "fc4c060b-3c41-4707-b7b2-df9c3376edde",
"business_id": "5f27a14a9bf05c73dd040bc8",
"status": "REQUIRES_ACTION",
"payment_method": {
"id": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "EWALLET",
"reusability": "ONE_TIME_USE",
"status": "ACTIVE",
"ewallet": {
"channel_code": "SHOPEEPAY",
"channel_properties": {
"success_return_url": "https://your-redirect-website.com/success",
},
"account": {
"account_details": null,
"name": null,
"balance": null,
"point_balance": null
}
},
"direct_debit": null
},
"channel_properties": {
"redeem_points": "REDEEM_NONE"
},
"actions": [
{
"action": "AUTH",
"url_type": "WEB",
"url": "https://link-web.xendit.co/oauth/lat-4ec01c8d-0326-4a35-bc11-b64c85f7408e/confirm",
"method": "GET"
}
],
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "ABCDEFGH"
}
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_ACCOUNT_DETAILS400 |
The provided details were rejected by the partner channel due to incorrect information. |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
MAX_ACCOUNT_LINKING400 |
The direct debit account being attempted to be linked has reached the maximum linking allowed by the partner channel. |
PARTNER_CHANNEL_ERROR400 |
Error received from partner channel but no reasons provided |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
PROCESSOR_CONFIGURATION_ERROR 500 |
Payment declined due to a problem with the merchant configuration on the Card Processor. Contact Xendit to troubleshoot the issue. |
CHANNEL_UNAVAILABLE503 |
The payment channel requested is currently experiencing unexpected issues. The eWallet provider will be notified to resolve this issue |
OTP_DELIVERY_ERROR 503 |
The partner channel has failed to send the OTP to the Customer |
PROCESSOR_ERROR 503 |
General system failure returned by the Card processor. Retry the request again after couple of minutes. |
PROCESSOR_TEMPORARILY_UNAVAILABLE 503 |
The Card Processor appears to be temporarily unavailable. Wait for a couple minutes, then resend the request. If it fails again, Cardholder can try using a different card or other form of payment. |
PROCESSOR_TIMEOUT_ERROR 503 |
Request was received by the processor, but there was a server timeout. Wait for a couple minutes and then retry the request. |
Get Payment Request by ID
This endpoints returns the corresponding Payment Method that matches the provided ID.
Endpoint: Get Payment Request by ID
GET https://api.xendit.co/payment_requests/:id
Get Payment Request by ID Request
Example Get Payment Request by ID Request
curl https://api.xendit.co/payment_requests/pr-6e9778ea-7d62-40fe-8b25-a4d740754c5f -X GET \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoRe
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
|
Primary identifier for the Payment Request object. |
Get Payment Request by ID Response
Example Get Payment Request by ID Success Response
{
"id": "pr-6e9778ea-7d62-40fe-8b25-a4d740754c5f",
"currency": "PHP",
"amount": 10000,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"business_id": "5f27a14a9bf05c73dd040bc8",
"status": "SUCCEEDED",
"reference_id": "a2c66ceb-2cbe-4541-bb69-9f50fd2040e0",
"payment_method": {
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "PH",
"ewallet": null,
"qr_code": null,
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"created": "2022-08-12T13:30:26.579048Z",
"updated": "2022-08-12T13:30:58.908220358Z"
},
"channel_properties": null,
"actions": [],
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "ABCDEFGH"
}
}
A successful Payment Request retrieval returns the matching Payment Request Object with an HTTP 200
status code.
Get Payment Request by ID Errors
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 |
The provided id did not match any of our records |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
List Payment Requests
This endpoints returns a list of matching Payment Request objects based on the provided query.
Each unique query string parameter is AND
-ed to each other.
Endpoint: List Payment Requests
GET https://api.xendit.co/payment_requests
List Payment Requests Request
Example List Payment Requests Request
curl https://api.xendit.co/payment_requests?reference_id="a2c66ceb-2cbe-4541-bb69-9f50fd2040e0" -X GET \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header '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 |
Query String Parameter | Type | Description |
---|---|---|
id optional |
string
|
Primary identifier for the Payment Request object. |
reference_id optional |
string
|
Merchant-provided identifier for this payment request. |
customer_id optional |
string
|
ID of the customer object to which the payment request is attached to. |
limit optional |
number
|
Maximum number of resources to be returned in the response. Use after_id and before_id to navigate to other resources. Default: 10 |
after_id optional |
string
|
Retrieve all resources created after the provided Payment Request ID |
before_id optional |
string
|
Retrieve all resources created before the provided Payment Request ID |
List Payment Requests Response
Example List Payment Requests Response
{
"data": [
{
"id": "pr-6e9778ea-7d62-40fe-8b25-a4d740754c5f",
"currency": "PHP",
"amount": 10000,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"business_id": "5f27a14a9bf05c73dd040bc8",
"status": "SUCCEEDED",
"reference_id": "a2c66ceb-2cbe-4541-bb69-9f50fd2040e0",
"payment_method": {
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "PH",
"ewallet": null,
"qr_code": null,
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"created": "2022-08-12T13:30:26.579048Z",
"updated": "2022-08-12T13:30:58.908220358Z"
},
"channel_properties": null,
"actions": [],
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "ABCDEFGH"
}
}
],
"has_more": false
}
Body Parameter | Type | Description |
---|---|---|
data required |
array of objects |
Returns an array of matching Payment Request Objects. Returns empty array when there is no result. |
has_more required |
boolean |
Indicates whether there are more items to be queried with after_id of the last item from the current result. |
List Payment Requests Errors
Error Code | Description |
---|---|
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Refunds API Endpoints
Create Refund
This endpoint initialized the refund process for the provided amount for a given successful payment.
For refunds made for the QR
channel within 24 hours of payment, the original fee and VAT are also returned. Take note that not all issuers are supported for QR refunds, for a list of all supported issuers please refer to this section
Endpoint: Create Refund
POST https://api.xendit.co/refunds
Create Refund Request
Example Create Refund Request
curl https://api.xendit.co/refunds -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"payment_request_id": "pr-6e9778ea-7d62-40fe-8b25-a4d740754c5f",
"reference_id": "b2756a1e-e6cd-4352-9a68-0483aa2b6a2f",
"currency":"PHP",
"reason":"CANCELLATION"
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. 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 |
---|---|---|
payment_request_idconditional |
string |
Identifier for the corresponding Payment Request to be refunded Note: One of payment_request_id or invoice_id must be provided in the request. |
reference_idnullable |
string |
Identifier provided by the merchant for the refund request. This may be automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
invoice_idconditional |
string |
Identifier for the corresponding Invoice / Payment Link transaction to be refunded Note: One of payment_request_id or invoice_id must be provided in the request. |
currencynullable |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
amountconditional |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
Note: If amount is not provided, the refund request will default to the maximum possible amount to be refunded from the provided transaction. Amount is required if payment is 'CARD' type |
reasonrequired |
string |
Provided reason why the refund was requested. Accepted values:
|
metadata optional |
object
|
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Refund Response
Example Create Refund Response
{
"id": "rfd-6f4a377d-a201-437f-9119-f8b00cbbe857",
"payment_id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"invoice_id": null,
"amount": 10000,
"payment_method_type": "DIRECT_DEBIT",
"channel_code": "BPI",
"currency": "PHP",
"status": "SUCCEEDED",
"reason": "CANCELLATION",
"reference_id": "b2756a1e-e6cd-4352-9a68-0483aa2b6a2",
"failure_code": null,
"refund_fee_amount": null,
"created": "2020-08-30T09:12:33.001Z",
"updated": "2020-08-30T09:12:33.001Z",
"metadata": null
}
A successful Refund creation returns a Refund Object with an HTTP 201
status code.
Listen to the refund.*
callbacks for the final status of the transaction.
Create Refund Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
INELIGIBLE_TRANSACTION 400 |
Error because the transaction provided has either been fully refunded or was never successful |
INSUFFICIENT_BALANCE 400 |
Error because there is no sufficient balance in your Xendit balance to perform the refund |
MAXIMUM_REFUND_AMOUNT_REACHED 400 |
Error because the provided amount is greater than the allowed refund amount. |
PARTIAL_REFUND_NOT_SUPPORTED 400 |
Error because the partner channel for the transaction does not support partial transactions |
REFUND_NOT_SUPPORTED 400 |
Refund request failed because refunds are not supported by the channel. |
REFUND_IN_PROGRESS 400 |
Concurrent refund requests to a single transaction are not allowed. Please wait for the pending full 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 |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 downstream provider will be notified to resolve this issue |
Get Refund by ID
This endpoints returns the corresponding Refund that matches the provided ID.
Endpoint: Get Payment Request by ID
GET https://api.xendit.co/refunds/:id
Get Refund by ID Request
Example Get Refund by ID Request
curl https://api.xendit.co/refunds/rfd-6f4a377d-a201-437f-9119-f8b00cbbe857 -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header '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
|
Primary identifier for the Refund object. |
Get Refund by ID Response
Example Get Refund by ID Success Response
{
"id": "rfd-6f4a377d-a201-437f-9119-f8b00cbbe857",
"payment_id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"invoice_id": null,
"amount": 10000,
"payment_method_type": "DIRECT_DEBIT",
"channel_code": "BPI",
"currency": "PHP",
"status": "SUCCEEDED",
"reason": "CANCELLATION",
"reference_id": "b2756a1e-e6cd-4352-9a68-0483aa2b6a2",
"failure_code": null,
"refund_fee_amount": null,
"created": "2020-08-30T09:12:33.001Z",
"updated": "2020-08-30T09:12:33.001Z",
"metadata": null
}
A successful Payment Request retrieval returns the matching Refund Object with an HTTP 200
status code.
Get Refund by ID Errors
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 |
The provided id did not match any of our records |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
Tokenization API Endpoints
Create Payment Method
This endpoint is used for account linking which provides the following functionalities:
- Initializes the tokenization and linking process for Cards, multiple-use E-wallets and Direct Debits
- Creates an payment method object placeholder for one-time use E-wallets and Direct Debits
Explore detailed scenario-based information on various payment methods:
Endpoint: Create Payment Method
POST https://api.xendit.co/v2/payment_methods
Create Payment Method Request
Example 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"
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. 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 | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
type required |
string
|
Type of payment method Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||
reusability required |
string
|
Describes whether or not the payment method can be reused for subsequent payments. For VIRTUAL_ACCOUNT , OVER_THE_COUNTER , and QR_CODE , this determines whether or not the payment instrument stays valid after a successful payment is made. For CARD , EWALLET , and DIRECT_DEBIT , this determines whether or not authentication is performed again for subsequent payments. Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment method. If none is provided, Xendit will randomly generate a unique reference_id . For OVER_THE_COUNTER , QR_CODE , and VIRTUAL_ACCOUNT , this will be extended to the actual payments made. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||
customer_id conditional |
string
|
ID of the customer object to which the account token will be linked to. Call Create Customer to generate Customer ID. The value will always have prefix cust-xxx A customer_id is required for all DIRECT_DEBIT payment methods and MULTIPLE_USE EWALLET s. Except that, you need to ignore this parameter or set as null . |
||||||||||||||||||||||||||||||||||||||||||
customer optional |
object
|
A customer object to skip Create Customer URL endpoint process. This object is required for all DIRECT_DEBIT payment methods and MULTIPLE_USE EWALLET s if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||||||||||||||||||
country conditional |
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 ). Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||
billing_informationoptional |
object |
Object containing the payor's billing address. For CARD , this should match the billing information on record with the cardholder's issuer. This is recommended for 3DS 2 / AVS.
|
||||||||||||||||||||||||||||||||||||||||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
||||||||||||||||||||||||||||||||||||||||||
ewallet conditional |
object
|
Required for type='EWALLET' , this contains the necessary information to describe an ewallet payment method.
DANA (
|
Key | Value |
---|---|
success_return_urlrequired |
string URL where the end-customer is redirected if the authorization is successful |
SHOPEEPAY (ONE_TIME_USE
) (VN), APPOTA, MOMO, ZALOPAY, VNPTWALLET, VIETTELPAY (ONE_TIME_USE
) required fields
Key | Value |
---|---|
success_return_urlrequired |
string URL where the end-customer is redirected if the authorization is successful |
pending_return_urlrequired |
string URL where the end-customer is redirected if the authorization is pending |
GRABPAY (PH & MY), OVO (MULTIPLE_USE
), DANA (MULTIPLE_USE
), LINKAJA (MULTIPLE_USE
), SHOPEEPAY (MULTIPLE_USE
) (ID, PH & MY), ASTRAPAY (MULTIPLE_USE
), GCASH (MULTIPLE_USE
), TOUCHNGO (MULTIPLE_USE
) fields
Key | Value |
---|---|
success_return_urlrequired |
string URL where the end-customer is redirected if the authorization is successful |
failure_return_urlrequired |
string URL where the end-customer is redirected if the authorization failed |
MAYA (PAYMAYA) required fields
Key | Value |
---|---|
success_return_urlrequired |
string URL where the end-customer is redirected if the authorization is successful |
failure_return_urlrequired |
string URL where the end-customer is redirected if the authorization failed |
cancel_return_urlrequired |
string URL where the end-customer is redirected if the authorization has been cancelled. End-customer can retry payment on the same link within 15 minutes. |
JENIUSPAY required fields
Key | Value |
---|---|
cashtagrequired |
string Cashtag of the funding source |
For GRABPAY (MY):
Key | Value |
---|---|
allowed_payment_optionsnullable |
Array of enums
Usage for each Payment method reusability
|
conditional
object
type='DIRECT_DEBIT'
, this contains the necessary information to describe a direct debit payment method. Key | Value | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
channel_coderequired |
string Identifier for the payment channel partner Supported banks and their channel codes:
|
||||||||||||||||||||||||||||||||||
channel_propertiesrequired |
object Object that contains the required information to perform payments using direct debit BRI Direct Debit required fields
MANDIRI, BPI, UBP, RCBC, CHINABANK, and FPX Channels under Direct Debit required fields
SCB and BBL Direct Debit required fields
KTB and BAY Direct Debit required fields
|
conditional
object
type='CARD'
, this contains the necessary information to describe a Card payment method. This will be null
otherwise. Key | Value | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||||||||
channel_propertiesrequired |
object Information provided specific to the channel partner that was provided during the request
|
||||||||||||||
card_informationrequired |
object Information pertaining to the actual card
|
conditional
object
type='OVER_THE_COUNTER'
, this contains the necessary information to describe an over-the-counter payment method. Key | Value | ||||||||
---|---|---|---|---|---|---|---|---|---|
channel_coderequired |
string Identifier for the payment channel partner Supported over-the-counter channels and their respective codes:
|
||||||||
currencyoptional |
string ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||
amountoptional |
number Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment code will accept any amount as payment (open amount). |
||||||||
channel_propertiesrequired |
object Object that contains the information to generate a valid payment code
|
conditional
object
type='VIRTUAL_ACCOUNT'
, this contains the necessary information to describe a virtual account payment method. Key | Value | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
channel_coderequired |
string Identifier for the payment channel partner Supported virtual account channels and their respective codes:
|
||||||||||
currencyoptional |
string ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||
amountoptional |
number Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding virtual account will accept any amount as payment (open amount). |
||||||||||
channel_propertiesrequired |
object Object that contains the information to generate a valid payment code
|
conditional
object
type='QR_CODE'
, this contains the necessary information to describe a QR Code payment method. Key | Value |
---|---|
channel_codeconditional |
string QR payments standard used in generating the QR code. Channel_code is not required for Indonesia country.
|
currencyoptional |
string ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
amountconditional |
number Expected and accepted amount of the transaction in the actual value in the provided currency . Requied if the Reusability is ONE_TIME_USE . Decimal places support varies per currency:
If amount is not provided, the corresponding QR Code will accept any amount as payment (open amount). |
Create Payment Method Response
Example Create Payment Method Success Response
{
"id": "pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39",
"type": "EWALLET",
"reusability": "MULTIPLE_USE",
"customer_id": "fc4c060b-3c41-4707-b7b2-df9c3376edde",
"business_id": "5f27a14a9bf05c73dd040bc8",
"status": "REQUIRES_ACTION",
"country": "ID",
"actions": [
{
"action": "AUTH",
"url_type": "WEB",
"url": "https://link-web.xendit.co/oauth/user_redirection_url",
"method": "GET"
}
],
"ewallet": {
"channel_code": "OVO",
"channel_properties": {
"success_return_url": "https://your-redirect-website.com/success",
"failure_return_url": "https://your-redirect-website.com/failure"
},
"account": {
"account_details": "+62*****3123",
"name": null,
"balance": 123456,
"point_balance": 123456
}
},
"qr_code": null,
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "iPixel phone - 123xa2"
}
}
A successful Payment Method creation returns a Payment Method Object with an HTTP 201
status code.
Create Payment Method Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
INVALID_ACCOUNT_DETAILS400 |
The provided details were rejected by the partner channel due to incorrect information. |
MAX_ACCOUNT_LINKING400 |
The direct debit account being attempted to be linked has reached the maximum linking allowed by the partner channel. |
VA_NUMBER_OUT_OF_RANGE400 |
The provided virtual_account_number is out of the merchant's range |
INVALID_API_KEY401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details. If you provide customer object request, the reference_id of customer object may already exist. |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 |
OTP_DELIVERY_ERROR 503 |
The partner channel has failed to send the OTP to the Customer |
Update Payment Method
This endpoint is used to update specific information of a particular payment method.
Endpoint: Update Payment Method
PATCH https://api.xendit.co/v2/payment_methods/:id
Update Payment Method Request
Example Update Payment Method Request
curl https://api.xendit.co/v2/payment_methods/pm-4c85fd2c-29da-4bc4-b642-064a42727d89 -X PATCH \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"over_the_counter": {
"channel_properties": {
"expires_at": "2022-08-29T09:12:33.001Z",
}
},
}' \
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
|
Primary identifier for the Payment Method object. This starts with the prefix pm- . |
Request Body Parameter | Type | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
reference_id optional |
string
|
Merchant-provided identifier for this payment method. For OVER_THE_COUNTER , QR_CODE , and VIRTUAL_ACCOUNT , this will be extended to the actual payments made. Maximum length: 255 characters |
||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||
status optional |
object
|
Desired new status of the payment method. This is used for temporarily disable/enable a certain payment method. Only toggle from ACTIVE to INACTIVE and vice versa is supported. |
||||||||||||
reusability optional |
object
|
Only supported for select VIRTUAL_ACCOUNT channels. Describes whether or not the payment method can be reused for subsequent payments without going through the same linking process again. Accepted values:
|
||||||||||||
over_the_counter optional |
object
|
For type='OVER_THE_COUNTER' , the following properties may be updated:
|
||||||||||||
virtual_account optional |
object
|
For type='VIRTUAL_ACCOUNT' , the following properties may be updated:
|
Update Payment Method Response
Example Update Payment Method Response
{
"id": "pm-4c85fd2c-29da-4bc4-b642-064a42727d89",
"type": "OVER_THE_COUNTER",
"reusability": "MULTIPLE_USE",
"customer_id": null,
"business_id": "5f27a14a9bf05c73dd040bc8",
"status": "PENDING",
"country": "PH",
"description": null,
"actions": [],
"ewallet": null,
"direct_debit": null,
"over_the_counter": {
"channel_code": "7ELEVEN_CLIQQ",
"currency": "PHP",
"amount": 1000,
"channel_properties": {
"customer_name": "John Doe",
"payment_code": "12345678",
"expires_at": "2022-08-29T09:12:33.001Z"
}
},
"virtual_account": null,
"qr_code": null,
"reference_id": "371d8a6e-587c-4789-bea5-fac4319b2409",
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z"
}
The updated Payment Method Object with an HTTP 200
status code.
Update Payment Method Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
INVALID_API_KEY401 |
API key format is invalid |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
The provided id did not match any of our records |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 |
Expire Payment Method
This API is used to force expiry or revoke authorization to an active payment method. For VIRTUAL_ACCOUNT
and OVER_THE_COUNTER
, this will also set the expires_at
to the time the expiration request was made. For DIRECT_DEBIT
with KTB
as channel_code
, required confirmation from end users.
Endpoint: Expire Payment Method
POST https://api.xendit.co/v2/payment_methods/:id/expire
Endpoint: Expire Direct Debit KTB Payment Method
POST https://api.xendit.co/v2/payment_methods/:id/expire?success_return_url=https://your-redirect-website.com/success&failure_return_url=https://your-redirect-website.com/failure
Expire Payment Method Request
Example Expire Payment Method Request
curl https://api.xendit.co/v2/payment_methods/pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a/expire -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. 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 |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Primary identifier for the Payment Method object. This starts with the prefix pm- . |
Query String Parameter | Type | Description |
---|---|---|
success_return_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_return_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. |
Expire Payment Method Response
Example Expire Payment Method Success Response
{
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "EXPIRED",
"actions": [],
"country": "PH",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Example Expire Direct Debit KTB Payment Method REQUIRES_ACTION Response
{
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485b",
"card": null,
"type": "DIRECT_DEBIT",
"status": "REQUIRES_ACTION",
"actions": [
{
"action": "AUTH",
"url": "https://link-web.xendit.co/oauth/lat-aa620619-124f-41db-995b-66a52abe036a/confirm_unlink",
"url_type": "WEB",
"method": "GET"
}
],
"country": "TH",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "KTB",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success",
"mobile_number": "",
"identity_document_number": ""
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8b",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"business_id": "5f27a14a9bf05c73dd040bc9"
}
Returns a Payment Method Object with an HTTP 200
status code.
Expire Payment Method Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
INVALID_API_KEY401 |
API key format is invalid |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
The provided id did not match any of our records |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 Payment Method by ID
This endpoints returns the corresponding Payment Method that matches the provided ID.
Endpoint: Get Payment Method by ID
GET https://api.xendit.co/v2/payment_methods/:id
Get Payment Method Request
Example Get Payment Method by ID Request
curl https://api.xendit.co/v2/payment_methods/pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header '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
|
Primary identifier for the Payment Method object. This starts with the prefix pm- . |
Get Payment Method by ID Response
Example Get Payment Method by ID Response
{
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "ID",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "DEBIT_CARD",
"debit_card": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "email@email.com"
},
"bank_account": null,
"channel_code": "BRI",
"channel_properties": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "test.email@xendit.co"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"business_id": "5f27a14a9bf05c73dd040bc8"
}
A successful Payment Method retrieval returns the matching Payment Method Object with an HTTP 200
status code.
Get Payment Method by ID Errors
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 |
The provided id did not match any of our records |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
List Payment Methods
This endpoints returns a list of matching Payment Method objects based on the provided query.
Each unique query string parameter is AND
operator to each other.
Endpoint: List Payment Methods
GET https://api.xendit.co/v2/payment_methods
List Payment Methods Request
Example List Payment Methods Request by Reference ID and Customer ID
curl https://api.xendit.co/v2/payment_methods?reference_id=620b9df4-fe69-4bfd-b9d4-5cba6861db8a&customer_id=e2878b4c-d57e-4a2c-922d-c0313c2800a3 -X GET \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header '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 |
Query String Parameter | Type | Description |
---|---|---|
type optional |
string
|
Type of payment method Accepted values:
|
reusability optional |
string
|
Describes whether or not the payment method can be reused for subsequent payments. For VIRTUAL_ACCOUNT , OVER_THE_COUNTER , and QR_CODE , this determines whether or not the payment instrument says valid after a successful payment is made. For CARD , EWALLET , and DIRECT_DEBIT , this determines whether or not authentication is performed again for subsequent payments. Accepted values:
|
reference_id optional |
string
|
Merchant-provided identifier for this payment method. If none is provided, Xendit will randomly generate a unique reference_id . For OVER_THE_COUNTER , QR_CODE , and VIRTUAL_ACCOUNT , this will be extended to the actual payments made. |
customer_id optional |
string
|
ID of the customer object to which the account token will be linked to. |
limit optional |
number
|
Maximum number of resources to be returned in the response. Use after_id and before_id to navigate to other resources. Default: 10 |
after_id optional |
string
|
Retrieve all resources created after the provided after_id
|
before_id optional |
string
|
Retrieve all resources created before the provided before_id
|
List Payment Methods Response
Example List Payment Methods Response
{
"data": [
{
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "ID",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "DEBIT_CARD",
"debit_card": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "email@email.com"
},
"bank_account": null,
"channel_code": "BRI",
"channel_properties": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "test.email@xendit.co"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"business_id": "5f27a14a9bf05c73dd040bc8"
}
],
"has_more": false
}
Body Parameter | Type | Description |
---|---|---|
data required |
array of objects |
Returns an array of matching Payment Method Objects. Returns empty array when there is no result. |
has_more required |
boolean |
Indicates whether there are more items to be queried with after_id of the last item from the current result. |
List Payment Methods Errors
Error Code | Description |
---|---|
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
List Payments by Payment Method ID
This endpoints returns a list of matching Payment objects made on a Payment Method.
Each unique query string parameter is AND
-ed to each other.
Endpoint: List Payments by Payment Method ID
GET https://api.xendit.co/v2/payment_methods/:id/payments
List Payments by Payment Method ID Request
Example List Payments by Payment Method ID Request
curl https://api.xendit.co/v2/payment_methods/pm-a327c780-66f0-4eb0-aa92-277afdf777c6/payments -X GET \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header '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
|
Primary identifier for the Payment Method object. This starts with the prefix pm- . |
Query String Parameter | Type | Description |
---|---|---|
payment_request_id optional |
string
|
Retrieve payments made via this payment_request_id
|
reference_id optional |
string
|
Retrieve payments that match the provided reference_id
|
status optional |
string
|
Retrieve payments with the provided status Accepted values:
|
limit optional |
number
|
Maximum number of resources to be returned in the response. Use after_id and before_id to navigate to other resources. Default: 10 |
after_id optional |
string
|
Retrieve all resources created after the provided after_id
|
before_id optional |
string
|
Retrieve all resources created before the provided before_id
|
created[gte] optional |
string
|
Retrieve all resources created after or on the the provided UTC+0 ISO 8601 timestamp |
created[lte] optional |
string
|
Retrieve all resources created before or on the the provided UTC+0 ISO 8601 timestamp |
updated[gte] optional |
string
|
Retrieve all resources updated after or on the the provided UTC+0 ISO 8601 timestamp |
updated[lte] optional |
string
|
Retrieve all resources updated before or on the the provided UTC+0 ISO 8601 timestamp |
List Payments by Payment Method ID Response
Example List Payments by Payment Method ID Success Response
{
"data": [
{
"id": "qrpy_0de1622b-677c-48c5-ac8c-ea1b9636c48f",
"amount": 10000,
"status": "SUCCEEDED",
"channel_properties": null,
"country": "ID",
"created": "2022-09-22T09:05:29.649418Z",
"currency": "IDR",
"customer_id": null,
"description": null,
"failure_code": null,
"metadata": null,
"payment_method": {
"type": "QR_CODE",
"card": null,
"description": null,
"direct_bank_transfer": null,
"direct_debit": null,
"ewallet": null,
"id": "pm-a327c780-66f0-4eb0-aa92-277afdf777c6",
"metadata": null,
"over_the_counter": null,
"qr_code": {
"amount": 10000,
"channel_code": "QRIS",
"channel_properties": {
"qr_string": "some-random-qr-string"
},
"currency": "IDR"
},
"reference_id": "a4486137-7624-4b34-b879-16cbbfc1a032",
"reusability": "ONE_TIME_USE",
"status": "EXPIRED",
"virtual_account": null,
"created": "2022-09-22T09:03:39.197475Z",
"updated": "2022-09-22T09:03:39.197475Z"
},
"payment_request_id": "pr-b33ecb15-c8e6-455c-9b1b-84612b6fd13b",
"reference_id": "a4486137-7624-4b34-b879-16cbbfc1a032",
"created": "2022-09-22T09:05:30.452Z",
"updated": "2022-09-22T09:05:29.649418Z"
}
],
"has_more": false,
"links": [
{
"href": "/v2/payment_methods/pm-a327c780-66f0-4eb0-aa92-277afdf777c6/payments",
"rel": "first",
"method": "GET"
}
]
}
Body Parameter | Type | Description |
---|---|---|
data required |
array of objects |
Returns an array of matching Payment Objects. Returns empty array when there is no result. |
has_more required |
boolean |
Indicates whether there are more items to be queried with after_id of the last item from the current 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 . |
List Payment Methods Errors
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 |
The provided id did not match any of our records |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
API Webhooks
Payment Succeeded
This callback is triggered when a payment is successfully received on a OVER_THE_COUNTER
, VIRTUAL_ACCOUNT
or QR_CODE
payment method.
This is also send for successful Payment Requests for EWALLET
, DIRECT_DEBIT
, and CARD
.
Callback Payload
Example: Payment Succeeded Callback Payload
{
"event": "payment.succeeded",
"data": {
"id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"amount": 1000,
"status": "SUCCEEDED",
"country": "PH",
"created": "2022-08-12T13:30:40.9209Z",
"updated": "2022-08-12T13:30:58.729373Z",
"currency": "PHP",
"metadata": {
"sku": "ABCDEFGH"
},
"customer_id": "c832697e-a62d-46fa-a383-24930b155e81",
"reference_id": "25cfd0f9-baee-44ca-9a12-6debe03f3c22",
"payment_method": {
"id": "pm-951b1ad9-1fbb-4724-a744-8956ab6ed17f",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:40.221525Z",
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"direct_bank_transfer": null
},
"description": null,
"failure_code": null,
"payment_detail": null,
"channel_properties": null,
"payment_request_id": "pr-5b26cae1-545b-49e9-855e-f85128f3e705"
},
"created": "2022-08-12T13:30:58.986Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Payment Failed
This callback is sent when a pending EWALLET
, DIRECT_DEBIT
, and CARD
has failed.
Note: Make sure that you ONLY have a callback URL registered in the Payment Request
section in your Dashboard settings for payments. To prevent duplicate callbacks, DO NOT fill out product-specific sections.
Callback Payload
Example: Payment Failed Callback Payload
{
"event": "payment.failed",
"data": {
"id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"amount": 1000,
"status": "FAILED",
"country": "PH",
"created": "2022-08-12T13:30:40.9209Z",
"updated": "2022-08-12T13:30:58.729373Z",
"currency": "PHP",
"metadata": {
"sku": "ABCDEFGH"
},
"customer_id": "c832697e-a62d-46fa-a383-24930b155e81",
"reference_id": "25cfd0f9-baee-44ca-9a12-6debe03f3c22",
"payment_method": {
"id": "pm-951b1ad9-1fbb-4724-a744-8956ab6ed17f",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:40.221525Z",
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"direct_bank_transfer": null
},
"description": null,
"failure_code": "INSUFFICIENT_BALANCE",
"payment_detail": null,
"channel_properties": null,
"payment_request_id": "pr-5b26cae1-545b-49e9-855e-f85128f3e705"
},
"created": "2022-08-12T13:30:58.986Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.failed |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Payment Error Codes
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
ACCOUNT_NOT_ACTIVATED |
End-customer's account is not activated for payments. |
CHANNEL_UNAVAILABLE |
The partner channel cannot be reached or currently having a downtime |
CUSTOMER_UNREACHABLE |
The end-user's device cannot be reached at this moment by the partner channel |
DUPLICATE_ERROR |
There's an existing record of linking the same underlying account for the provided customer_id OR Virtual Account Number/Payment Code already exists |
INSUFFICIENT_BALANCE |
Source of funds has insufficient balance to complete the transaction |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the partner channel |
INVALID_PAYMENT_METHOD |
The provided payment method id has already expired or is inactive |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
MAX_AMOUNT_LIMIT_ERROR |
The transaction amount exceeds the partner channel's set limits |
MAX_OTP_ATTEMPTS_ERROR |
The maximum incorrect attempts allowed by the channel has been reached. |
PARTNER_CHANNEL_ERROR |
Error received from partner channel but no reasons provided |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_METHOD_ALREADY_EXISTS |
An active Payment Method with the same customer_id, channel_code for that merchant already exists. |
PAYMENT_EXPIRED |
If you are using Xendit-hosted OTP page, end-user needs to input their OTP within 15 minutes or else the payment will be expired. You may need to create a new payment. |
PAYMENT_STATUS_FAILED |
Payment has failed with no further information from channel. You may need to check before retrying. Recommended to wait ~30 minutes before retrying unless given further instruction. |
Payment Method Activated
This callback is triggered when the E-Wallet or Direct Debit has been successfully linked or when the Virtual Account, QR string, or Over-The-Counter Payment code has been successfully activated and can be used for payments. The event will be sent as payment_method.activated
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Activated Callback Payload
{
"event": "payment_method.activated",
"data": {
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "PH",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null
},
"created": "2022-08-12T13:30:59.074277334Z",
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
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 with status ACTIVE |
Payment Method Expired
This callback is triggered when the linked E-Wallet or Direct Debit has been unlinked or when the Virtual Account, QR string, or Over-The-Counter Payment code has been expired and can no longer be used for payments. The event will be sent as payment_method.expired
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Expired Callback Payload
{
"event": "payment_method.expired",
"data": {
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "EXPIRED",
"actions": [],
"country": "PH",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null
},
"created": "2022-08-12T13:30:59.074277334Z",
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.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 with status EXPIRED |
Payment Method Failed
This callback is triggered when a particular Payment Method has failed during authentication/authorization. The event will be sent as payment_method.failed
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Failed Callback Payload
{
"event": "payment_method.failed",
"data": {
"id": "pm-d15e011d8-d238-47f6-8041-4a0fe1cc78f0",
"type": "CARD",
"status": "FAILED",
"card": {
"currency": "PHP",
"card_information": {
"type": "UNKNOWN",
"issuer": "UNKNOWN",
"country": "US",
"network": "VISA",
"token_id": "7ac5069c3e52ececb8e0d7302002a739",
"expiry_year": "2023",
"fingerprint": "bdf256307a23088dbd41cf9668a7c95a",
"expiry_month": "11",
"cardholder_name": null,
"masked_card_number": "450159XXXXXX6146"
},
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success",
"skip_three_d_secure": false
},
"card_verification_results": {
"cvv_result": null,
"three_d_secure": {
"eci_code": "07",
"three_d_secure_flow": "CHALLENGE",
"three_d_secure_result": "FAILED",
"three_d_secure_version": "1.0.2",
"three_d_secure_result_reason": "REJECTED"
},
"address_verification_result": null
}
},
"actions": [],
"country": "PH",
"created": "2022-09-06T05:36:09.674547Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-09-06T05:36:26.158740637Z",
"metadata": {},
"customer_id": "15e011d8-d238-47f6-8041-4a0fe1cc78f0",
"description": "Card Failure",
"reusability": "MULTIPLE_USE",
"direct_debit": null,
"failure_code": "AUTHENTICATION_FAILED",
"reference_id": "ec13dd21-8e14-4a4f-ab0e-727a2b977e50",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null
},
"created": "2022-09-06T05:36:26.166166474Z",
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.failed |
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 with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Payment Method Error Codes
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
CHANNEL_UNAVAILABLE |
The partner channel cannot be reached or currently having a downtime |
DUPLICATE_ERROR |
There's an existing record of linking the same underlying account for the provided customer_id OR Virtual Account Number/Payment Code already exists |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_METHOD_ALREADY_EXISTS |
An active Payment Method with the same customer_id, channel_code for that merchant already exists. |
Refund Succeeded
Xendit notifies your system when a refund is successfully processed via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard under Unified Refund
.
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: Refund Succeeded Webhook Payload
{
"event": "refund.succeeded",
"business_id": "5f27a14a9bf05c73dd040bc8",
"created": "2020-08-29T09:12:33.001Z",
"data": {
"id": "rfd-6f4a377d-a201-437f-9119-f8b00cbbe857",
"payment_id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"invoice_id": null,
"amount": 10000,
"payment_method_type": "DIRECT_DEBIT",
"channel_code": "BPI",
"currency": "PHP",
"status": "SUCCEEDED",
"reason": "CANCELLATION",
"reference_id": "b2756a1e-e6cd-4352-9a68-0483aa2b6a2",
"failure_code": null,
"refund_fee_amount": null,
"created": "2020-08-30T09:12:33.001Z",
"updated": "2020-08-30T09:12:33.001Z",
"metadata": null
}
}
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 webhook 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 - refund.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for webhook notification creation. Timezone UTC+0. |
dataoptional |
object |
Refund Object with status SUCCEEDED |
Refund Failed
Xendit notifies your system when a refund is successfully processed via webhook. You need to provide an URL to receive webhook. Please specify your URL in Webhook Settings in Xendit Dashboard under Unified Refund
.
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: Refund Failed Webhook Payload
{
"event": "refund.failed",
"business_id": "5f27a14a9bf05c73dd040bc8",
"created": "2020-08-29T09:12:33.001Z",
"data": {
"id": "rfd-fca8d8bc-497c-42a5-b16f-97825323502a",
"payment_id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"invoice_id": null,
"amount": 10000,
"payment_method_type": "DIRECT_DEBIT",
"channel_code": "BPI",
"currency": "PHP",
"status": "FAILED",
"reason": "CANCELLATION",
"reference_id": "b2756a1e-e6cd-4352-9a68-0483aa2b6a2",
"failure_code": "DUPLICATE_ERROR",
"refund_fee_amount": null,
"created": "2020-08-30T09:12:33.001Z",
"updated": "2020-08-30T09:12:33.001Z",
"metadata": null
}
}
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 webhook 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 - refund.failed |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for webhook notification creation. Timezone UTC+0. |
dataoptional |
object |
Refund Object with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Refund Error Codes
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer account has been blocked, end user should contact the bank for resolution. |
ACCOUNT_NOT_FOUND |
Destination account for refund was not found |
DUPLICATE_ERROR |
There's an existing record of refund |
INSUFFICIENT_BALANCE |
Error because there is no sufficient balance in your Xendit balance to perform the refund |
REFUND_FAILED |
Refund rejected by the partner channel |
Payment Scenario
This section provides the following scenario that can be handled payment Payment Request Scenario :
- Initializes the payment/capture process for Cards, E-wallets and Direct Debits
- Creates a payment instrument along with the payment initialization e.g Virtual Account Creation, QR Creation, and Fixed Payment Code Generator
Direct Debit
Initiate One Time Payment
This flow is designed for scenarios where you want to enable a guest user to make a checkout payment.
After making the following payment, the next task is to verify it using an OTP (One-Time Password). For this flow, you may need to use xendit hosted OTP given in action parameter in the response.
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 500,
"currency": "PHP",
"payment_method": {
"type": "DIRECT_DEBIT",
"direct_debit": {
"channel_code": "BPI",
"channel_properties": {
"success_return_url" : "https://redirect.me/goodstuff",
"failure_return_url" : "https://redirect.me/badstuff"
}
},
"reusability": "ONE_TIME_USE"
},
"customer_id": "cust-1e68806c-38d7-4109-b1cd-4f10ef4cf99b",
"description": "This is a description.",
"metadata": {
"foo": "bar"
}
}' \
Header | 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. 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 Payment Request 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. |
Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
amountrequired |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer_id conditional |
string
|
ID of the customer object to which the account token will be linked to. Call Create Customer to generate Customer ID. A customer_id is required for all DIRECT_DEBIT payment methods if customer object is null. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer conditional |
object
|
A customer object to skip Create Customer URL endpoint process. This object is required if customer_id is null.The parameters to be set for the customer object
business_detail |
conditional
|
|
Key | Value |
---|---|
business_namerequired |
string Name of business entity |
trading_nameoptional |
string Brand name or trading name known in market |
business_typerequired |
string Legal entity type of the businessSupported values: CORPORATION ,SOLE_PROPRIETOR ,PARTNERSHIP ,COOPERATIVE ,TRUST ,NON_PROFIT ,GOVERNMENT
|
nature_of_businessoptional |
string Free text description of the type of business this entity pursues. Examples are: Ecommerce, Travel |
business_domicileoptional |
string Registered country of the business
|
date_of_registrationoptional |
string Business registration date
|
optional
string
E-mail address of customer. Maximum length 50 characters optional
string
Mobile number of customer in E.164 format Maximum length 50 characters
optional
string
Accepted values:
ID
- IndonesiaPH
- PhilippinesTH
- ThailandMY
- Malaysia
optional
string
Maximum length: 255 characters
conditional
object
payment_method{}
or payment_method_id
must be present.Respective Payment Method properties that corresponds to the chosen payment method type or channel.
The request will apply the top-most values for
customer_id
, currency
, and amount
.The parameters to be set for the payment method object
Key | Value | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
type required |
string Type of payment method For Direct debit:
|
||||||||||||||||||||||||||||||||||||||||
reusability required |
string Describes whether or not the payment method can be reused for subsequent payments. For DIRECT_DEBIT , this determines whether or not authentication is performed again for subsequent payments. Accepted values for one time case:
|
||||||||||||||||||||||||||||||||||||||||
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. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||
metadata optional |
object A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
||||||||||||||||||||||||||||||||||||||||
direct_debit required |
object Required for type='DIRECT_DEBIT' , this contains the necessary information to describe a direct debit payment method.
|
optional
object
object
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long.
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-8f9a5d3a-0f9f-47bf-8452-a4be9388b490",
"country": "PH",
"amount": 500,
"currency": "PHP",
"business_id": "6396e6d48c59c18ca0e55218",
"reference_id": "eeaf6501-dea4-4103-bb7e-8ee706ce04f6",
"payment_method": {
"id": "pm-02318afc-9810-4044-b8b4-d0eacb0a77a8",
"type": "DIRECT_DEBIT",
"reference_id": "54ee6999-a032-40c6-b731-dcc7f6d26040",
"description": null,
"created": "2023-07-16T22:38:13.474210828Z",
"updated": "2023-07-16T22:38:13.474210828Z",
"card": null,
"ewallet": null,
"direct_debit": {
"channel_code": "BPI",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff",
"failure_return_url": "https://redirect.me/badstuff"
},
"type": "BANK_ACCOUNT",
"bank_account": {
"masked_bank_account_number": null,
"bank_account_hash": null
},
"debit_card": null
},
"direct_bank_transfer": null,
"over_the_counter": null,
"virtual_account": null,
"qr_code": null,
"metadata": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"province_state": null,
"street_line1": null,
"street_line2": null
},
"reusability": "ONE_TIME_USE",
"status": "PENDING"
},
"description": "This is a description.",
"metadata": {
"foo": "bar"
},
"customer_id": "cust-bf61e185-da02-4223-a594-5da05c45218e",
"capture_method": "AUTOMATIC",
"initiator": null,
"card_verification_results": null,
"created": "2023-07-16T22:38:13.231458108Z",
"updated": "2023-07-16T22:38:13.231458108Z",
"status": "REQUIRES_ACTION",
"actions": [
{
"action": "AUTH",
"url": "https://link-web-staging.xendit.co/oauth/lat-17702cc1-31c8-4791-b243-8699a3575146/confirm",
"url_type": "WEB",
"method": "GET",
"qr_code": null
}
],
"failure_code": null,
"channel_properties": null,
"shipping_information": null,
"items": null
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for the payment request. This has a prefix of pr- . Example: pr-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 |
||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||
customer_idnullable |
string |
ID of the customer object to which the account token will be linked to | ||||||||||
reference_idnullable |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
||||||||||
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||||
amountnullable |
number |
Authorized amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment method will accept any amount as payment (open amount). (Applicable only for OVER_THE_COUNTER and VIRTUAL_ACCOUNT ) |
||||||||||
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 ). |
||||||||||
statusrequired |
string |
Status of the payment method. Possible values:
| ||||||||||
descriptionnullable |
string |
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||
payment_methodrequired |
object |
Corresponding Payment Method created or used for the Payment Method. Note: customer_id , currency , and amount are moved to the root level of the Payment Request object. |
||||||||||
actionsrequired |
object array |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to complete a payment. Only one of the provided actions is required to be fulfilled. If no further action is needed, this parameter will be an empty array [] . Each object will have the following properties:
|
||||||||||
failure_codenullable |
string |
If the status of the transaction is FAILED , this describes the reason for failure.Will be null if the transaction did not fail. See possible codes here. |
||||||||||
createdrequired |
string |
ISO 8601 Timestamp for Payment Request object creation. Timezone UTC+0 | ||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest Payment Request object update. Timezone UTC+0 | ||||||||||
metadatanullable |
object |
User defined object with JSON properties and values passed in during Payment Request creation. |
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_ACCOUNT_DETAILS400 |
The provided details were rejected by the partner channel due to incorrect information. |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
MAX_ACCOUNT_LINKING400 |
The direct debit account being attempted to be linked has reached the maximum linking allowed by the partner channel. |
PARTNER_CHANNEL_ERROR400 |
Error received from partner channel but no reasons provided |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 provider will be notified to resolve this issue |
OTP_DELIVERY_ERROR 503 |
The partner channel has failed to send the OTP to the Customer |
PROCESSOR_ERROR 503 |
General system failure returned by the Card processor. Retry the request again after couple of minutes. |
INSUFFICIENT_BALANCE 400 |
Source of funds has insufficient balance to complete the transaction. |
MAX_AMOUNT_LIMIT_ERROR 400 |
The transaction amount exceeds the partner channel's set limits. |
FORBIDDEN 403 |
Provided API key does not have the correct permissions to perform the operation. |
Validate OTP One Time Payment
This endpoint only applies to BRI Direct Debit. This is used when an additional authorization (ex. OTP Validation) is required in order to successfully activate a payment method. This is equivalent to the POST - AUTH
action provided when a Payment Method has the status REQUIRES_ACTION
.
Endpoint: Account Linking - Authorize Payment Method
POST https://api.xendit.co/v2/payment_methods/:id/auth
Authorize Payment Method Request
Example Account Linking - Authorize Payment Method Request
curl https://api.xendit.co/v2/payment_methods/pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a/auth -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"auth_code": "356443"
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. 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 |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Primary identifier for the Payment Method object. This starts with the prefix pm- . |
Request Body Parameter | Type | Description |
---|---|---|
auth_code required |
string
|
The authorization code or OTP inputted by the end-customer. |
Authorize Payment Method Response
Example Account Linking - Authorize Payment Method Success Response
{
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "ID",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "DEBIT_CARD",
"debit_card": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "email@email.com"
},
"bank_account": null,
"channel_code": "BRI",
"channel_properties": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "test.email@xendit.co"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Returns a Payment Method Object with an HTTP 200
status code.
Authorize Payment Method Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
EXPIRED_OTP_ERROR400 |
The provided auth_code has expired |
INVALID_OTP_ERROR400 |
The provided auth_code is incorrect |
MAX_OTP_ATTEMPTS_ERROR400 |
The maximum attempts allowed by the channel has been reached |
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
DATA_NOT_FOUND404 |
The provided id did not match any of our records |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
PAYMENT_METHOD_ALREADY_ACTIVE409 |
Cannot proceed because the payment method is already active or has been activated |
PAYMENT_METHOD_ALREADY_FAILED409 |
Cannot proceed because the payment method has failed authorization and cannot be retried |
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 |
Webhook Payment Succeeded Direct Debit One Time
This callback will be sent to you once the payment has been detected from you end-customer.
Callback Payload
Example: Payment Succeeded Callback Payload
{
"created": "2023-08-07T17:41:00.766Z",
"business_id": "6396e6d48c59c18ca0e55333",
"event": "payment.succeeded",
"data": {
"id": "ddpy-43f10ddb-dc10-46a7-951c-00f834d2f555",
"items": null,
"amount": 500,
"status": "SUCCEEDED",
"country": "PH",
"created": "2023-08-07T17:40:54.452582Z",
"updated": "2023-08-07T17:41:00.456517Z",
"currency": "PHP",
"metadata": {
"foo": "bar"
},
"customer_id": "cust-b103fdf1-8b38-48c5-bbe4-8d70b6efc54r",
"description": "This is a description.",
"failure_code": null,
"reference_id": "ca9a047f-e808-4494-9980-0a49002ac2a2",
"payment_detail": null,
"payment_method": {
"id": "pm-19cc567e-4444-4214-9e77-e4d28f9b5050",
"card": null,
"type": "DIRECT_DEBIT",
"status": "EXPIRED",
"created": "2023-08-07T17:40:39.115295Z",
"ewallet": null,
"qr_code": null,
"updated": "2023-08-07T17:40:53.962941Z",
"metadata": null,
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "8f06b7dc684aa57a283adf49b2f67bdb11750ac04300f3996d97c7412ac5ca48",
"masked_bank_account_number": "XXX1631"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
}
},
"reference_id": "39d44d83-e41a-4639-b359-ab2071d7f13a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-1d72af2f-8bd7-45a8-8d12-7ab23170cf0c"
},
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Webhook Payment Failed Direct Debit One Time
Note: Make sure that you ONLY have a callback URL registered in the Payment Request
section in your Dashboard settings for payments. To prevent duplicate callbacks, DO NOT fill out product-specific sections.
Callback Payload
Example: Payment Failed Callback Payload
{
"created": "2023-08-07T17:49:26.242Z",
"business_id": "6396e6d48c59c18ca0e552555",
"event": "payment.failed",
"data": {
"id": "ddpy-0c3a5e88-11c5-4b94-a05d-93f8778e3756",
"items": null,
"amount": 11001,
"status": "FAILED",
"country": "PH",
"created": "2023-08-07T17:49:25.699261Z",
"updated": "2023-08-07T17:49:25.753596Z",
"currency": "PHP",
"metadata": {
"foo": "bar"
},
"customer_id": "cust-b103fdf1-8b38-48c5-bbe4-8d70b6e33333",
"description": "This is a description.",
"failure_code": "MAX_AMOUNT_LIMIT_ERROR",
"reference_id": "3aba1bc1-aa15-4145-3333-c985c5b3e2ce",
"payment_detail": null,
"payment_method": {
"id": "pm-c6646b5a-a09f-45f3-3333-a4c8394b47e9",
"card": null,
"type": "DIRECT_DEBIT",
"status": "EXPIRED",
"created": "2023-08-07T17:49:13.51121Z",
"ewallet": null,
"qr_code": null,
"updated": "2023-08-07T17:49:25.212213Z",
"metadata": null,
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "8f06b7dc684aa57a283adf49b2f67bdb11750ac04300f3996d97c7412ac5ca48",
"masked_bank_account_number": "XXX1631"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
}
},
"reference_id": "311ee56b-7a7a-4445-3333-ac553c970f54",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-f6b0802a-3333-45ee-8b3a-77f1d6d9fc27"
},
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.failed |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
ACCOUNT_NOT_ACTIVATED |
End-customer's account is not activated for payments. |
CHANNEL_UNAVAILABLE |
The partner channel cannot be reached or currently having a downtime |
CUSTOMER_UNREACHABLE |
The end-user's device cannot be reached at this moment by the partner channel |
DUPLICATE_ERROR |
There's an existing record of linking the same underlying account for the provided customer_id OR Virtual Account Number/Payment Code already exists |
INSUFFICIENT_BALANCE |
Source of funds has insufficient balance to complete the transaction |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the partner channel |
INVALID_PAYMENT_METHOD |
The provided payment method id has already expired or is inactive |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
MAX_AMOUNT_LIMIT_ERROR |
The transaction amount exceeds the partner channel's set limits |
MAX_OTP_ATTEMPTS_ERROR |
The maximum incorrect attempts allowed by the channel has been reached. |
PARTNER_CHANNEL_ERROR |
Error received from partner channel but no reasons provided |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_METHOD_ALREADY_EXISTS |
An active Payment Method with the same customer_id, channel_code for that merchant already exists. |
PAYMENT_EXPIRED |
If you are using Xendit-hosted OTP page, end-user needs to input their OTP within 15 minutes or else the payment will be expired. You may need to create a new payment. |
PAYMENT_STATUS_FAILED |
Payment has failed with no further information from channel. You may need to check before retrying. Recommended to wait ~30 minutes before retrying unless given further instruction. |
E-Wallets
Initiate One Time Payment
This endpoint provides the endpoint to create charge for Ewallet One time use. This scenario is suitable for Merchant who implement checkout case using Ewallet.
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"currency": "IDR",
"amount": 100000,
"payment_method": {
"type": "EWALLET",
"reusability": "ONE_TIME_USE",
"ewallet": {
"channel_code": "SHOPEEPAY",
"channel_properties": {
"success_return_url": "https://your-redirect-website.com/success"
}
}
},
"customer_id": "fc4c060b-3c41-4707-b7b2-df9c3376edde",
"metadata": {
"sku": "ABCDEFGH"
}
}' \
Header | 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. 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 Payment Request 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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
amountrequired |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer_id conditional |
string
|
ID of the customer object to which the account token will be linked to. Call Create Customer to generate Customer ID. A customer_id is required for all Ewallet payment methods if the customer object is null. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer optional |
object
|
A customer object to skip Create Customer URL endpoint process. This object is required if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
country conditional |
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 ). Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
payment_methodrequired |
object |
Note: Only one of payment_method{} or payment_method_id must be present.Respective Payment Method properties that corresponds to the chosen payment method type or channel. The request will apply the top-most values for customer_id , currency , and amount . The parameters to be set for the payment method object
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-8f9a5d3a-0f9f-47bf-8452-a4be9388b490",
"country": "ID",
"amount": 1500,
"currency": "IDR",
"business_id": "628db55f8378fa6f14db977f",
"reference_id": "bf90f78f-fd9f-4701-9143-ecea0c999af1",
"payment_method": {
"id": "pm-9690c507-0caf-4dec-877b-1a52304848f9",
"type": "EWALLET",
"reference_id": "d2878b0e-f2bb-4824-8c9c-be1273a446ea",
"description": null,
"created": "2023-07-18T02:01:02.620185557Z",
"updated": "2023-07-18T02:01:02.620185557Z",
"card": null,
"ewallet": {
"channel_code": "SHOPEEPAY",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff"
},
"account": {
"name": null,
"account_details": null,
"balance": null,
"point_balance": null
}
},
"direct_debit": null,
"direct_bank_transfer": null,
"over_the_counter": null,
"virtual_account": null,
"qr_code": null,
"metadata": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"province_state": null,
"street_line1": null,
"street_line2": null
},
"reusability": "ONE_TIME_USE",
"status": "ACTIVE"
},
"description": null,
"metadata": null,
"customer_id": null,
"capture_method": "AUTOMATIC",
"initiator": null,
"card_verification_results": null,
"created": "2023-07-18T02:01:02.646818745Z",
"updated": "2023-07-18T02:01:02.646818745Z",
"status": "REQUIRES_ACTION",
"actions": [
{
"action": "AUTH",
"url": "https://ewallet-mock-connector.xendit.co/v1/ewallet_connector/checkouts?token=ciqv4nkabidq0em86ofg",
"url_type": "DEEPLINK",
"method": "GET",
"qr_code": null
},
{
"action": "PRESENT_TO_CUSTOMER",
"url": null,
"url_type": null,
"method": null,
"qr_code": "test-qr-string"
}
],
"failure_code": null,
"channel_properties": null,
"shipping_information": null,
"items": null
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for the payment request. This has a prefix of pr- . Example: pr-8f9a5d3a-0f9f-47bf-8452-a4be9388b490 |
||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||
customer_idnullable |
string |
ID of the customer object to which the account token will be linked to | ||||||||||
reference_idnullable |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
||||||||||
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||||
amountnullable |
number |
Authorized amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment method will accept any amount as payment (open amount). (Applicable only for OVER_THE_COUNTER and VIRTUAL_ACCOUNT ) |
||||||||||
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 ). |
||||||||||
statusrequired |
string |
Status of the payment method. Possible values:
| ||||||||||
descriptionnullable |
string |
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||
payment_methodrequired |
object |
Corresponding Payment Method created or used for the Payment Method. Note: customer_id , currency , and amount are moved to the root level of the Payment Request object. |
||||||||||
actionsrequired |
object array |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to complete a payment. Only one of the provided actions is required to be fulfilled. If no further action is needed, this parameter will be an empty array [] . Each object will have the following properties:
|
||||||||||
failure_codenullable |
string |
If the status of the transaction is FAILED , this describes the reason for failure.Will be null if the transaction did not fail. See possible codes here. |
||||||||||
createdrequired |
string |
ISO 8601 Timestamp for Payment Request object creation. Timezone UTC+0 | ||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest Payment Request object update. Timezone UTC+0 | ||||||||||
metadatanullable |
object |
User defined object with JSON properties and values passed in during Payment Request creation. |
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_ACCOUNT_DETAILS400 |
The provided details were rejected by the partner channel due to incorrect information. |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
MAX_ACCOUNT_LINKING400 |
The direct debit account being attempted to be linked has reached the maximum linking allowed by the partner channel. |
PARTNER_CHANNEL_ERROR400 |
Error received from partner channel but no reasons provided |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
PROCESSOR_CONFIGURATION_ERROR 500 |
Payment declined due to a problem with the merchant configuration on the Card Processor. Contact Xendit to troubleshoot the issue. |
CHANNEL_UNAVAILABLE503 |
The payment channel requested is currently experiencing unexpected issues. The eWallet provider will be notified to resolve this issue |
PROCESSOR_ERROR 503 |
General system failure returned by the Card processor. Retry the request again after couple of minutes. |
INSUFFICIENT_BALANCE 400 |
Source of funds has insufficient balance to complete the transaction |
MAX_AMOUNT_LIMIT_ERROR 400 |
The transaction amount exceeds the partner channel's set limits |
INVALID_PAYMENT_METHOD400 |
The provided payment method id has already expired or is inactive |
ACCOUNT_NOT_ACTIVATED400 |
End-customer's account is not activated for payments. |
Webhook Payment Succeeded Ewallet One Time
Callback Payload
Example: Payment Succeeded Callback Payload
{
"created": "2023-05-31T08:18:13.473Z",
"business_id": "628db55f8378fa6f14db977f",
"event": "payment.succeeded",
"data": {
"id": "ewc_f545a7d9-482b-4eb0-b175-032252d3acca",
"items": null,
"amount": 1500,
"status": "SUCCEEDED",
"country": "ID",
"created": "2023-05-31T08:17:40.193463Z",
"updated": "2023-05-31T08:18:13.042335Z",
"currency": "IDR",
"metadata": null,
"customer_id": null,
"description": null,
"failure_code": null,
"reference_id": "8346c97c-6c16-4745-a1b4-69656f0b2d4e",
"payment_detail": {
"fund_source": "1_MONTH_INSTALLMENT",
"source": "Shopeepay"
},
"payment_method": {
"id": "pm-62e521fc-09bd-4d50-bc44-a190c482a1a5",
"card": null,
"type": "EWALLET",
"status": "EXPIRED",
"created": "2023-05-31T08:17:40.084679Z",
"ewallet": {
"account": {
"name": null,
"balance": null,
"point_balance": null,
"account_details": null
},
"channel_code": "SHOPEEPAY",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff"
}
},
"qr_code": null,
"updated": "2023-05-31T08:17:40.084679Z",
"metadata": null,
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": null,
"reference_id": "6c8ad38e-2925-44c4-95af-35003298eefa",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-dd5e558f-1001-4402-84c3-df4375c6b29f"
},
"api_version": null
}{
"created": "2023-05-31T08:18:13.473Z",
"business_id": "628db55f8378fa6f14db977f",
"event": "payment.succeeded",
"data": {
"id": "ewc_f545a7d9-482b-4eb0-b175-032252d3acca",
"items": null,
"amount": 1500,
"status": "SUCCEEDED",
"country": "ID",
"created": "2023-05-31T08:17:40.193463Z",
"updated": "2023-05-31T08:18:13.042335Z",
"currency": "IDR",
"metadata": null,
"customer_id": null,
"description": null,
"failure_code": null,
"reference_id": "8346c97c-6c16-4745-a1b4-69656f0b2d4e",
"payment_detail": {
"fund_source": "1_MONTH_INSTALLMENT",
"source": "Shopeepay"
},
"payment_method": {
"id": "pm-62e521fc-09bd-4d50-bc44-a190c482a1a5",
"card": null,
"type": "EWALLET",
"status": "EXPIRED",
"created": "2023-05-31T08:17:40.084679Z",
"ewallet": {
"account": {
"name": null,
"balance": null,
"point_balance": null,
"account_details": null
},
"channel_code": "SHOPEEPAY",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff"
}
},
"qr_code": null,
"updated": "2023-05-31T08:17:40.084679Z",
"metadata": null,
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": null,
"reference_id": "6c8ad38e-2925-44c4-95af-35003298eefa",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-dd5e558f-1001-4402-84c3-df4375c6b29f"
},
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Webhook Payment Failed Ewallet One Time
Note: Make sure that you ONLY have a callback URL registered in the Payment Request
section in your Dashboard settings for payments. To prevent duplicate callbacks, DO NOT fill out product-specific sections.
Callback Payload
Example: Payment Failed Callback Payload
{
"created": "2023-05-31T10:52:00.666Z",
"business_id": "628db55f8378fa6f14db9555",
"event": "payment.failed",
"data": {
"id": "ewc_df746164-4f3e-417e-84cd-fa78c1d6a555",
"items": null,
"amount": 20111,
"status": "FAILED",
"country": "ID",
"created": "2023-05-31T10:51:48.73712Z",
"updated": "2023-05-31T10:51:58.057377Z",
"currency": "IDR",
"metadata": null,
"customer_id": null,
"description": null,
"failure_code": "ACCOUNT_NOT_ACTIVATED",
"reference_id": "7ce8f500-1bad-4d46-a1eb-0879b13e1bba",
"payment_detail": {
"fund_source": "1_MONTH_INSTALLMENT",
"source": "Shopeepay"
},
"payment_method": {
"id": "pm-8bfd2cf3-6aca-4a10-ba48-d5c9e303b5df",
"card": null,
"type": "EWALLET",
"status": "EXPIRED",
"created": "2023-05-31T10:51:48.646147Z",
"ewallet": {
"account": {
"name": null,
"balance": null,
"point_balance": null,
"account_details": null
},
"channel_code": "SHOPEEPAY",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff"
}
},
"qr_code": null,
"updated": "2023-05-31T10:51:48.646147Z",
"metadata": null,
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": null,
"reference_id": "869776db-5e5a-48dd-b7b3-45b89737e599",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-63df12be-6dc2-4602-ab7a-78d851f0ee06"
},
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.failed |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
ACCOUNT_NOT_ACTIVATED |
End-customer's account is not activated for payments. |
CHANNEL_UNAVAILABLE |
The partner channel cannot be reached or currently having a downtime |
CUSTOMER_UNREACHABLE |
The end-user's device cannot be reached at this moment by the partner channel |
INSUFFICIENT_BALANCE |
Source of funds has insufficient balance to complete the transaction |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the partner channel |
INVALID_PAYMENT_METHOD |
The provided payment method id has already expired or is inactive |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
MAX_AMOUNT_LIMIT_ERROR |
The transaction amount exceeds the partner channel's set limits |
PARTNER_CHANNEL_ERROR |
Error received from partner channel but no reasons provided |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_EXPIRED |
If you are using Xendit-hosted OTP page, end-user needs to input their OTP within 15 minutes or else the payment will be expired. You may need to create a new payment. |
PAYMENT_STATUS_FAILED |
Payment has failed with no further information from channel. You may need to check before retrying. Recommended to wait ~30 minutes before retrying unless given further instruction. |
INVALID_ACCOUNT_DETAILS |
The provided details were rejected by the partner channel due to incorrect information. |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the partner channel |
Virtual Account
Virtual Account - Creation
This endpoint is provided to create random virtual account number or activate specified virtual account number.
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 10000,
"currency": "IDR",
"description": "description",
"payment_method": {
"reference_id": "reference_id-pm-level",
"reusability": "ONE_TIME_USE",
"type": "VIRTUAL_ACCOUNT",
"virtual_account": {
"channel_code": "BRI",
"channel_properties": {
"customer_name": "John Doe",
"virtual_account_number" : "9999171877",
"expires_at": "2023-08-11T17:00:00Z"
},
"alternative_display_types": [
"QR_STRING"
]
}
},
"reference_id": "reference_id-pr-level"
}' \
Header | 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. 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 Payment Request 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 | Description | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||||||||||||||||||||||
amountoptional |
number Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding virtual account will accept any amount as payment (open amount). |
||||||||||||||||||||||||||||||
reference_id optional |
string Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||||||||||||||||||||||
customer_id optional |
string ID of the customer object to which the account token will be linked to. Call Create Customer to generate Customer ID. |
||||||||||||||||||||||||||||||
customer optional |
object A customer object to skip Create Customer URL endpoint process. This object is only available if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||||||
country conditional |
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 ). Accepted values:
|
||||||||||||||||||||||||||||||
description optional |
string Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||||||
payment_methodconditional |
object Respective Payment Method properties that corresponds to the chosen payment method type or channel. The request will apply the top-most values for customer_id , currency , and amount . The details of parameters is shown here:
|
||||||||||||||||||||||||||||||
metadata optional |
object A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-1fe8d4e9-5d32-464b-8df1-1165faf9fa2e",
"country": "ID",
"amount": 10000,
"currency": "IDR",
"business_id": "628db55f8378fa6f14db977f",
"reference_id": "reference_id-pr-level",
"payment_method": {
"id": "pm-c19b6b05-fb0f-4af7-8029-5416d75f097c",
"type": "VIRTUAL_ACCOUNT",
"reference_id": "reference_id-pm-level",
"description": null,
"created": "2023-07-18T02:33:23.176204171Z",
"updated": "2023-07-18T02:33:23.176204171Z",
"card": null,
"ewallet": null,
"direct_debit": null,
"direct_bank_transfer": null,
"over_the_counter": null,
"virtual_account": {
"amount": 10000,
"currency": "IDR",
"channel_code": "BRI",
"channel_properties": {
"customer_name": "John Doe",
"virtual_account_number": "132819999171877",
"expires_at": "2023-08-11T17:00:00Z"
},
"alternative_displays": [
{
"type": "QR_STRING",
"data": "SAMPLE_QR_DATA"
}
]
},
"qr_code": null,
"metadata": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"province_state": null,
"street_line1": null,
"street_line2": null
},
"reusability": "ONE_TIME_USE",
"status": "PENDING"
},
"description": "description",
"metadata": null,
"customer_id": null,
"capture_method": "AUTOMATIC",
"initiator": null,
"card_verification_results": null,
"created": "2023-07-18T02:33:22.313192354Z",
"updated": "2023-07-18T02:33:22.313192354Z",
"status": "PENDING",
"actions": [],
"failure_code": null,
"channel_properties": null,
"shipping_information": null,
"items": null
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Body Parameter | Description |
---|---|
idrequired |
string Unique identifier for the payment request. This has a prefix of pr- . Example: pr-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 |
business_idrequired |
string Xendit-generated identifier for the business that owns the transaction |
customer_idnullable |
string ID of the customer object to which the account token will be linked to |
reference_idnullable |
string Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
currencyrequired |
string ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
amountnullable |
number Authorized amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment method will accept any amount as payment (open amount). (Applicable only for OVER_THE_COUNTER and VIRTUAL_ACCOUNT ) |
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 ). |
statusrequired |
string Status of the payment method. Possible values:
|
descriptionnullable |
string Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
payment_methodrequired |
object Corresponding Payment Method created or used for the Payment Method. Note: customer_id , currency , and amount are moved to the root level of the Payment Request object. |
createdrequired |
string ISO 8601 Timestamp for Payment Request object creation. Timezone UTC+0 |
updatedrequired |
string ISO 8601 Timestamp for latest Payment Request object update. Timezone UTC+0 |
metadatanullable |
object User defined object with JSON properties and values passed in during Payment Request creation. |
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_API_KEY401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
OPERATION_NOT_ALLOWED403 |
Operation being attempted is not supported for the provided payment method type or channel (eg. VA expiration date, VA suggested/expected amount, VA fixed amount) / Auth for the provided payment method ID is not supported . |
DUPLICATED_FIXED_PAYMENT_INSTRUMENT400 |
Fixed payment instrument is already in use. Please try again with another fixed payment instrument value. |
Webhook VA Activated Callback
This callback is triggered when the Virtual Account, QR string, or Fixed payment have has been successfully activated and can be used for payments.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Activated Callback Payload
{
"id": "pm-faa27710-5005-4d54-aedf-b2beecd2d68a",
"event": "payment_method.activated",
"business_id": "5ddb77c8f4177f1ef8a44939",
"created": "2023-05-26T09:02:03.038153416Z",
"data": {
"id": "pm-faa27710-5005-4d54-aedf-b2beecd2d68a",
"type": "VIRTUAL_ACCOUNT",
"country": "ID",
"business_id": "5ddb77c8f4177f1ef8a44939",
"customer_id": null,
"reference_id": "sample_test_payment_method",
"reusability": "ONE_TIME_USE",
"status": "ACTIVE",
"actions": [],
"description": null,
"created": "2023-05-26T09:02:02.573677Z",
"updated": "2023-05-26T09:02:02.857607606Z",
"metadata": null,
"billing_information": {
"country": "",
"street_line1": null,
"street_line2": null,
"city": null,
"province_state": null,
"postal_code": null
},
"failure_code": null,
"ewallet": null,
"direct_bank_transfer": null,
"direct_debit": null,
"card": null,
"over_the_counter": null,
"qr_code": null,
"virtual_account": {
"amount": 100000,
"currency": "IDR",
"channel_code": "BRI",
"channel_properties": {
"customer_name": "John Doe",
"virtual_account_number": "920019999153641",
"expires_at": "2054-05-25T17:00:00Z"
}
}
}
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
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 with status ACTIVE |
Simulate Virtual Account Payments (Test Mode)
Simulate Payments API allows you to emulate your customer behavior to pay to your payment request (i.e. Virtual Account, Over-the-counter / Retail Outlet, QR Code) in TEST
mode only.
A callback will be sent to your callback URL upon payment completion. Please refer to the callback section for further information about the callback that will be delivered.
Endpoint: Perform Capture Payment
POST https://api.xendit.co/v2/payment_methods/{id}/payments/simulate
Request Parameters
Example Perform Simulate Payment
curl https://api.xendit.co/v2/payment_methods/pm-b264541b-286d-4044-bac0-ace45b158bef/payments/simulate -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 507000
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. Note: Max 100 characters |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Payment Method ID. This starts with the prefix pm- . You will get this ID from payment request's response in the payment_method object. |
Body Parameter | Type | Description |
---|---|---|
amount required |
number
|
The amount that needs to be paid. For a close amount case, the amount must be the expected amount stated in the payment request. |
Response Parameters
Body Parameter | Type | Description |
---|---|---|
status required |
string
|
The status of the request. If it successfully being processed then the status will be PENDING . |
message required |
string
|
Additional information regarding the payment simulation process |
Example Simulate Payment Success Response
{
"status": "PENDING",
"message": "We're processing payment for payment method ID [pm-xxx] and will send you the result via callback. Please make sure you've set a callback URL in "Payment Succeeded" section in Callback settings in Xendit Dashboard. If you don't receive the callback within the next 5 minutes, please contact us."
}
Error Codes
Error Code | Description |
---|---|
INCORRECT_AMOUNT 400 |
Incorrect amount. The expected amount for this payment method is xxxx. |
INACTIVE_PAYMENT_METHOD 400 |
Could not pay callback {payment method} that is inactive |
API_VALIDATION_ERROR 400 |
There is invalid input in one of the required request fields |
PAYMENT_METHOD_NOT_SUPPORTED 400 |
Simulate Payment API supports VA, OTC, and QR Payment Method. Please try again using VA/OTC/QR Payment Method ID. |
REQUEST_FORBIDDEN_ERROR 403 |
Simulate Payment API cannot be accessed using Live API Key. Please try again using Test API Key and Payment Method ID. |
INVALID_API_KEY 401 |
API key format is invalid. |
DATA_NOT_FOUND 404 |
Provided payment_method_id is invalid, not found or access is unauthorized. |
SERVER_ERROR 500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
Webhook VA Payment Succeeded Callback
Callback Payload
Example: Payment Succeeded Callback Payload
{
"created": "2023-05-29T09:56:05.519Z",
"business_id": "5ddb77c8f4177f1ef8a44555",
"event": "payment.succeeded",
"api_version": null,
"data": {
"amount": 100000,
"channel_properties": null,
"country": "ID",
"created": "2023-05-29T09:56:01.205Z",
"currency": "IDR",
"customer_id": null,
"description": null,
"failure_code": null,
"id": "647476b1fe87ba392f68d5ec",
"items": null,
"metadata": {
"sku": "ABCDEFGH"
},
"payment_detail": null,
"payment_method": {
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"province_state": null,
"street_line1": null,
"street_line2": null
},
"card": null,
"created": "2023-05-29T09:52:35.963186Z",
"description": null,
"direct_bank_transfer": null,
"direct_debit": null,
"ewallet": null,
"id": "pm-56752735-91be-4af7-a52a-1d04ef6e0555",
"metadata": null,
"over_the_counter": null,
"qr_code": null,
"reference_id": "pm-level-39b161ee-9761-5555-b3a5-b8dfcddc3763",
"reusability": "ONE_TIME_USE",
"status": "EXPIRED",
"type": "VIRTUAL_ACCOUNT",
"updated": "2023-05-29T09:52:36.285346Z",
"virtual_account": {
"amount": 100000,
"channel_code": "BRI",
"channel_properties": {
"customer_name": "John Doe",
"expires_at": "2054-05-28T17:00:00Z",
"virtual_account_number": "920019999718932"
},
"currency": "IDR"
}
},
"payment_request_id": "pr-df1017d4-6247-5555-817e-f6140683c528",
"reference_id": "4c423b6a-2f9d-4b73-5555-a21c34106f8b",
"status": "SUCCEEDED",
"updated": "2023-05-29T09:56:01.205Z"
}
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Webhook VA Expired Callback
This callback is triggered when the Virtual Account has been expired and can no longer be used for payments.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Expired Callback Payload
{
"id": "pm-56752735-91be-4af7-a52a-1d04ef6e0de6",
"event": "payment_method.expired",
"business_id": "5ddb77c8f4177f1ef8a44939",
"created": "2023-05-29T09:56:05.653109662Z",
"data": {
"id": "pm-56752735-91be-4af7-a52a-1d04ef6e0de6",
"type": "VIRTUAL_ACCOUNT",
"country": "ID",
"business_id": "5ddb77c8f4177f1ef8a44939",
"customer_id": null,
"reference_id": "pm-level-39b161ee-9761-4d4e-b3a5-b8dfcddc3763",
"reusability": "ONE_TIME_USE",
"status": "EXPIRED",
"actions": [],
"description": null,
"created": "2023-05-29T09:52:35.963186Z",
"updated": "2023-05-29T09:56:05.424872798Z",
"metadata": null,
"billing_information": {
"country": "",
"street_line1": null,
"street_line2": null,
"city": null,
"province_state": null,
"postal_code": null
},
"failure_code": null,
"ewallet": null,
"direct_bank_transfer": null,
"direct_debit": null,
"card": null,
"over_the_counter": null,
"qr_code": null,
"virtual_account": {
"amount": 100000,
"currency": "IDR",
"channel_code": "BRI",
"channel_properties": {
"customer_name": "John Doe",
"virtual_account_number": "920019999718932",
"expires_at": "2054-05-28T17:00:00Z"
}
}
}
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.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 with status EXPIRED |
QR Code
QR Code Creation
This endpoint is provided to create QR instrument, hence your end customer is able to pay via QR code.
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 15000,
"currency": "IDR",
"payment_method": {
"type": "QR_CODE",
"reusability": "ONE_TIME_USE",
"qr_code": {
"channel_properties": {
"expires_at": "2023-10-25T00:00:00Z"
}
}
},
"description": "sample description",
"metadata": {
"foo": "bar"
}
}' \
Header | 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. 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 Payment Request 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 | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||||||||||||||||||
amountrequired |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
|
||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||||||||||||||||||
customer_id optional |
string
|
ID of the customer object to which the account token will be linked to. Call Create Customer to generate Customer ID. |
||||||||||||||||||||||||||
customer optional |
object
|
A customer object to skip Create Customer URL endpoint process. This object is only available if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||
country conditional |
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 ). Accepted values:
|
||||||||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||
payment_methodconditional |
object |
Note: Only one of payment_method{} or payment_method_id must be present.Respective Payment Method properties that corresponds to the chosen payment method type or channel. The request will apply the top-most values for customer_id , currency , and amount . The details of parameters is shown here:
|
||||||||||||||||||||||||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-5295461b-d129-4585-8fe7-4434ad402940",
"country": "ID",
"amount": 15000,
"currency": "IDR",
"business_id": "628db55f8378fa6f14db977f",
"reference_id": "7ce15f66-3766-497e-b337-9e861ad9655a",
"payment_method": {
"id": "pm-9f9b5f25-e655-4393-ac20-16fd8d8e394c",
"type": "QR_CODE",
"reference_id": "dd5c7f03-49f2-403f-91d3-c0bd2e205dc1",
"description": null,
"created": "2023-07-18T02:43:47.958973578Z",
"updated": "2023-07-18T02:43:47.958973578Z",
"card": null,
"ewallet": null,
"direct_debit": null,
"direct_bank_transfer": null,
"over_the_counter": null,
"virtual_account": null,
"qr_code": {
"amount": 15000,
"currency": "IDR",
"channel_code": "LINKAJA",
"channel_properties": {
"qr_string": "some-random-qr-string",
"expires_at": "2023-10-25T00:00:00Z"
}
},
"metadata": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"province_state": null,
"street_line1": null,
"street_line2": null
},
"reusability": "ONE_TIME_USE",
"status": "ACTIVE"
},
"description": "sample description",
"metadata": {
"foo": "bar"
},
"customer_id": null,
"capture_method": "AUTOMATIC",
"initiator": null,
"card_verification_results": null,
"created": "2023-07-18T02:43:47.923658935Z",
"updated": "2023-07-18T02:43:47.923658935Z",
"status": "PENDING",
"actions": [],
"failure_code": null,
"channel_properties": null,
"shipping_information": null,
"items": null
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Body Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique identifier for the payment request. This has a prefix of pr- . Example: pr-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 |
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction |
customer_idnullable |
string |
ID of the customer object to which the account token will be linked to |
reference_idnullable |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
amountnullable |
number |
Authorized amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment method will accept any amount as payment (open amount). (Applicable only for OVER_THE_COUNTER and VIRTUAL_ACCOUNT ) |
statusrequired |
string |
Status of the payment method. Possible values:
|
descriptionnullable |
string |
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
payment_methodrequired |
object |
Corresponding Payment Method created or used for the Payment Method. Note: customer_id , currency , and amount are moved to the root level of the Payment Request object. |
createdrequired |
string |
ISO 8601 Timestamp for Payment Request object creation. Timezone UTC+0 |
updatedrequired |
string |
ISO 8601 Timestamp for latest Payment Request object update. Timezone UTC+0 |
metadatanullable |
object |
User defined object with JSON properties and values passed in during Payment Request creation. |
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_API_KEY401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
OPERATION_NOT_ALLOWED403 |
Operation being attempted is not supported for the provided payment method type or channel (eg. VA expiration date, VA suggested/expected amount, VA fixed amount) / Auth for the provided payment method ID is not supported . |
Webhook QR Activated Callback
This callback is triggered when the Virtual Account, QR string, or Fixed payment have has been successfully activated and can be used for payments.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Activated Callback Payload
{
"id": "pm-c10989bf-87d8-4ac4-a20d-94ea40624d93",
"event": "payment_method.activated",
"business_id": "5ddb77c8f4177f1ef8a44939",
"created": "2023-05-31T07:22:47.287497139Z",
"data": {
"id": "pm-c10989bf-87d8-4ac4-a20d-94ea40624d93",
"type": "QR_CODE",
"country": "ID",
"business_id": "5ddb77c8f4177f1ef8a44939",
"customer_id": null,
"reference_id": "4a148603-b094-4e81-a3e4-5e4e77b6feac",
"reusability": "MULTIPLE_USE",
"status": "ACTIVE",
"actions": [],
"description": null,
"created": "2023-05-31T07:22:47.050186525Z",
"updated": "2023-05-31T07:22:47.050186525Z",
"metadata": null,
"billing_information": {
"country": "",
"street_line1": null,
"street_line2": null,
"city": null,
"province_state": null,
"postal_code": null
},
"failure_code": null,
"ewallet": null,
"direct_bank_transfer": null,
"direct_debit": null,
"card": null,
"over_the_counter": null,
"qr_code": {
"amount": null,
"currency": "IDR",
"channel_code": "LINKAJA",
"channel_properties": {
"qr_string": "some-random-qr-string",
"expires_at": "2023-10-25T00:00:00Z"
}
},
"virtual_account": null
}
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
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 with status ACTIVE |
Simulate QR Payment (Test Mode)
Simulate Payments API allows you to emulate your customer behavior to pay to your payment request (i.e. Virtual Account, Over-the-counter / Retail Outlet, QR Code) in TEST
mode.
A callback will be sent to your callback URL upon payment completion. Please refer to the callback section for further information about the callback that will be delivered.
Endpoint: Perform Capture Payment
POST https://api.xendit.co/v2/payment_methods/{id}/payments/simulate
Request Parameters
Example Perform Simulate Payment
curl https://api.xendit.co/v2/payment_methods/pm-b264541b-286d-4044-bac0-ace45b158bef/payments/simulate -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 507000
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. Note: Max 100 characters |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Payment Method ID. This starts with the prefix pm- . You will get this ID from payment request's response in the payment_method object. |
Body Parameter | Type | Description |
---|---|---|
amount required |
number
|
The amount that needs to be paid. For a close amount case, the amount must be the expected amount stated in the payment request. |
Response Parameters
Body Parameter | Type | Description |
---|---|---|
status required |
string
|
The status of the request. If it successfully being processed then the status will be PENDING . |
message required |
string
|
Additional information regarding the payment simulation process |
Example Simulate Payment Success Response
{
"status": "PENDING",
"message": "We're processing payment for payment method ID [pm-xxx] and will send you the result via callback. Please make sure you've set a callback URL in "Payment Succeeded" section in Callback settings in Xendit Dashboard. If you don't receive the callback within the next 5 minutes, please contact us."
}
Error Codes
Error Code | Description |
---|---|
INCORRECT_AMOUNT 400 |
Incorrect amount. The expected amount for this payment method is xxxx. |
INACTIVE_PAYMENT_METHOD 400 |
Could not pay callback {payment method} that is inactive |
API_VALIDATION_ERROR 400 |
There is invalid input in one of the required request fields |
PAYMENT_METHOD_NOT_SUPPORTED 400 |
Simulate Payment API supports VA, OTC, and QR Payment Method. Please try again using VA/OTC/QR Payment Method ID. |
REQUEST_FORBIDDEN_ERROR 403 |
Simulate Payment API cannot be accessed using Live API Key. Please try again using Test API Key and Payment Method ID. |
INVALID_API_KEY 401 |
API key format is invalid. |
DATA_NOT_FOUND 404 |
Provided payment_method_id is invalid, not found or access is unauthorized. |
SERVER_ERROR 500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
Webhook QR Payment Succeeded
Callback Payload
Example: Payment Succeeded Callback Payload
{
"created": "2023-05-31T07:38:58.373Z",
"business_id": "5ddb77c8f4177f1ef8a44939",
"event": "payment.succeeded",
"api_version": null,
"data": {
"amount": 15000,
"channel_properties": null,
"country": "ID",
"created": "2023-05-31T07:38:57.752591Z",
"currency": "IDR",
"customer_id": null,
"description": null,
"failure_code": null,
"id": "qrpy_cb762db3-d37d-4097-8716-d2a26d23f61d",
"items": null,
"metadata": {
"foo": "bar"
},
"payment_detail": {
"issuer_name": "DANA",
"receipt_id": ""
},
"payment_method": {
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"province_state": null,
"street_line1": null,
"street_line2": null
},
"card": null,
"created": "2023-05-31T07:22:47.050187Z",
"description": null,
"direct_bank_transfer": null,
"direct_debit": null,
"ewallet": null,
"id": "pm-c10989bf-87d8-4ac4-a20d-94ea40624d93",
"metadata": null,
"over_the_counter": null,
"qr_code": {
"amount": null,
"channel_code": "LINKAJA",
"channel_properties": {
"qr_string": "some-random-qr-string",
"expires_at": "2023-10-25T00:00:00Z"
},
"currency": "IDR"
},
"reference_id": "4a148603-b094-4e81-a3e4-5e4e77b6feac",
"reusability": "MULTIPLE_USE",
"status": "ACTIVE",
"type": "QR_CODE",
"updated": "2023-05-31T07:22:47.050187Z",
"virtual_account": null
},
"payment_request_id": "pr-4e96d8ab-4f5c-4a11-ab24-25e72ecd7901",
"reference_id": "4a148603-b094-4e81-a3e4-5e4e77b6feac",
"status": "SUCCEEDED",
"updated": "2023-05-31T07:38:57.752591Z"
}
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Webhook QR Expired Callback
This callback is triggered when the Virtual Account, QR string, or Fixed payment have has been successfully activated and can be used for payments.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Expired Callback Payload
{
"id": "pm-34b2ed73-7486-4848-8112-57546175e336",
"data": {
"id": "pm-34b2ed73-7486-4848-8112-57546175e336",
"card": null,
"type": "QR_CODE",
"status": "EXPIRED",
"actions": [],
"country": "ID",
"created": "2023-08-09T09:40:32.659773Z",
"ewallet": null,
"qr_code": {
"amount": 15000,
"currency": "IDR",
"channel_code": "DANA",
"channel_properties": {
"qr_string": "some-random-qr-string",
"expires_at": "2023-08-11T09:40:32.650188Z"
}
},
"updated": "2023-08-09T09:40:50.718860278Z",
"metadata": null,
"business_id": "628db55f8378fa6f14db977f",
"customer_id": null,
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": null,
"failure_code": null,
"reference_id": "e39c3914-eee3-49be-aa01-f8a7d91d2c75",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"event": "payment_method.expired",
"created": "2023-08-09T09:40:50.784698244Z",
"business_id": "628db55f8378fa6f14db977f"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.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 with status EXPIRED |
Over The Counter
Fixed Payment Code Creation
This endpoint is provided to create fixed payment code, hence your end customer is able to generate code to pay via retailer.
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 10000,
"currency": "IDR",
"country": "ID",
"payment_method": {
"type": "OVER_THE_COUNTER",
"reusability": "ONE_TIME_USE",
"over_the_counter": {
"channel_code": "ALFAMART",
"channel_properties": {
"customer_name": "John Doe"
}
}
},
"metadata": {
"foo": "bar"
}
}' \
Header | 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. 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 Payment Request 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 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||||||||||||||||||||
amountrequired |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
|
||||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||||||||||||||||||||
customer_id optional |
string
|
ID of the customer object to which the account token will be linked to. Call Create Customer to generate Customer ID. |
||||||||||||||||||||||||||||
customer optional |
object
|
A customer object to skip Create Customer URL endpoint process. This object is only available if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||||
country conditional |
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 ). Accepted values:
|
||||||||||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||||
payment_methodrequired |
object |
Note: Only one of payment_method{} or payment_method_id must be present.Respective Payment Method properties that corresponds to the chosen payment method type or channel. The request will apply the top-most values for customer_id , currency , and amount . The details of parameters is shown here:
|
optional
object
Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long.
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-ab565bdf-d506-4aaa-bd1d-e48a8bc83b70",
"country": "ID",
"amount": 10000,
"currency": "IDR",
"business_id": "628db55f8378fa6f14db977f",
"reference_id": "90392f42-d98a-49ef-a7f3-f3c0f4008a04",
"payment_method": {
"id": "pm-b4eff3d2-1fe2-41d3-867e-62cc5028438a",
"type": "OVER_THE_COUNTER",
"reference_id": "62c21e3e-9bef-40b0-bf2f-a42c4eaae770",
"description": null,
"created": "2023-07-18T02:45:30.940372554Z",
"updated": "2023-07-18T02:45:30.940372554Z",
"card": null,
"ewallet": null,
"direct_debit": null,
"direct_bank_transfer": null,
"over_the_counter": {
"amount": 10000,
"currency": "IDR",
"channel_code": "ALFAMART",
"channel_properties": {
"payment_code": "APAPMFQ5ERCG4",
"customer_name": "John Doe",
"expires_at": "2023-07-20T02:45:30Z"
}
},
"virtual_account": null,
"qr_code": null,
"metadata": {
"foo": "bar"
},
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"province_state": null,
"street_line1": null,
"street_line2": null
},
"reusability": "ONE_TIME_USE",
"status": "ACTIVE"
},
"description": null,
"metadata": {
"foo": "bar"
},
"customer_id": null,
"capture_method": "AUTOMATIC",
"initiator": null,
"card_verification_results": null,
"created": "2023-07-18T02:45:30.779418878Z",
"updated": "2023-07-18T02:45:30.779418878Z",
"status": "PENDING",
"actions": [],
"failure_code": null,
"channel_properties": null,
"shipping_information": null,
"items": null
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Body Parameter | Type | Description |
---|---|---|
idrequired |
string |
Unique identifier for the payment request. This has a prefix of pr- . Example: pr-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 |
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction |
customer_idnullable |
string |
ID of the customer object to which the account token will be linked to |
reference_idnullable |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
amountnullable |
number |
Authorized amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment method will accept any amount as payment (open amount). (Applicable only for OVER_THE_COUNTER and VIRTUAL_ACCOUNT ) |
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 ). |
statusrequired |
string |
Status of the payment method. Possible values:
|
descriptionnullable |
string |
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
payment_methodrequired |
object |
Corresponding Payment Method created or used for the Payment Method. Note: customer_id , currency , and amount are moved to the root level of the Payment Request object. |
createdrequired |
string |
ISO 8601 Timestamp for Payment Request object creation. Timezone UTC+0 |
updatedrequired |
string |
ISO 8601 Timestamp for latest Payment Request object update. Timezone UTC+0 |
metadatanullable |
object |
User defined object with JSON properties and values passed in during Payment Request creation. |
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_API_KEY401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
OPERATION_NOT_ALLOWED403 |
Operation being attempted is not supported for the provided payment method type or channel (eg. VA expiration date, VA suggested/expected amount, VA fixed amount) / Auth for the provided payment method ID is not supported . |
Webhook Fixed Payment Code Activated
This callback is triggered when the Virtual Account, QR string, or Fixed payment have has been successfully activated and can be used for payments.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Activated Callback Payload
{
"id": "pm-ce27c3ba-e854-414e-aec6-cb7aa8d82c0b",
"data": {
"id": "pm-ce27c3ba-e854-414e-aec6-cb7aa8d82c0b",
"card": null,
"type": "OVER_THE_COUNTER",
"status": "ACTIVE",
"actions": [],
"country": "PH",
"created": "2023-06-20T06:26:52.590918576Z",
"ewallet": null,
"qr_code": null,
"updated": "2023-06-20T06:26:52.590918576Z",
"metadata": {
"foo": "bar"
},
"business_id": "6396e6d48c59c18ca0e55218",
"customer_id": null,
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": null,
"failure_code": null,
"reference_id": "2200765f-303e-4345-af20-28e2e0aeb3e4",
"virtual_account": null,
"over_the_counter": {
"amount": 10000,
"currency": "PHP",
"channel_code": "CEBUANA",
"channel_properties": {
"expires_at": "2023-06-22T06:26:52Z",
"payment_code": "PHLTRA87887623535",
"customer_name": "John Doe"
}
},
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"event": "payment_method.activated",
"created": "2023-06-20T06:26:52.772429487Z",
"business_id": "6396e6d48c59c18ca0e55218"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
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 with status ACTIVE |
Simulate OTC Payment (Test Mode)
Simulate Payments API allows you to emulate your customer behavior to pay to your payment request (i.e. Virtual Account, Over-the-counter / Retail Outlet, QR Code) in TEST
mode.
A callback will be sent to your callback URL upon payment completion. Please refer to the callback section for further information about the callback that will be delivered.
Endpoint: Perform Capture Payment
POST https://api.xendit.co/v2/payment_methods/{id}/payments/simulate
Request Parameters
Example Perform Simulate Payment
curl https://api.xendit.co/v2/payment_methods/pm-b264541b-286d-4044-bac0-ace45b158bef/payments/simulate -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 507000
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. Note: Max 100 characters |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Payment Method ID. This starts with the prefix pm- . You will get this ID from payment request's response in the payment_method object. |
Body Parameter | Type | Description |
---|---|---|
amount required |
number
|
The amount that needs to be paid. For a close amount case, the amount must be the expected amount stated in the payment request. |
Response Parameters
Body Parameter | Type | Description |
---|---|---|
status required |
string
|
The status of the request. If it successfully being processed then the status will be PENDING . |
message required |
string
|
Additional information regarding the payment simulation process |
Example Simulate Payment Success Response
{
"status": "PENDING",
"message": "We're processing payment for payment method ID [pm-xxx] and will send you the result via callback. Please make sure you've set a callback URL in "Payment Succeeded" section in Callback settings in Xendit Dashboard. If you don't receive the callback within the next 5 minutes, please contact us."
}
Error Codes
Error Code | Description |
---|---|
INCORRECT_AMOUNT 400 |
Incorrect amount. The expected amount for this payment method is xxxx. |
INACTIVE_PAYMENT_METHOD 400 |
Could not pay callback {payment method} that is inactive |
API_VALIDATION_ERROR 400 |
There is invalid input in one of the required request fields |
PAYMENT_METHOD_NOT_SUPPORTED 400 |
Simulate Payment API supports VA, OTC, and QR Payment Method. Please try again using VA/OTC/QR Payment Method ID. |
REQUEST_FORBIDDEN_ERROR 403 |
Simulate Payment API cannot be accessed using Live API Key. Please try again using Test API Key and Payment Method ID. |
INVALID_API_KEY 401 |
API key format is invalid. |
DATA_NOT_FOUND 404 |
Provided payment_method_id is invalid, not found or access is unauthorized. |
SERVER_ERROR 500 |
An unexpected error occured. Our team has been notified and will troubleshoot the issue |
Webhook OTC Payment Succeeded
Callback Payload
Example: Payment Succeeded Callback Payload
{
"created": "2023-06-21T10:22:09.537Z",
"business_id": "628db55f8378fa6f14db977f",
"event": "payment.succeeded",
"data": {
"id": "pymt-6bd92321-1dd3-4007-ba6d-ba9778f78bf9",
"items": null,
"amount": 10000,
"status": "SUCCEEDED",
"country": "ID",
"created": "2023-06-21T10:22:06.894508924Z",
"updated": "2023-06-21T10:22:06.894508924Z",
"currency": "IDR",
"metadata": {
"foo": "bar"
},
"customer_id": null,
"description": null,
"failure_code": null,
"reference_id": "16439b4d-3bf3-4261-8bde-9c8f51621ff2",
"payment_detail": {
"remarks": "payment simulation"
},
"payment_method": {
"id": "pm-e4823b4d-02d8-4bac-b4d4-19a86e2201bb",
"card": null,
"type": "OVER_THE_COUNTER",
"status": "EXPIRED",
"created": "2023-06-21T10:21:45.42122Z",
"ewallet": null,
"qr_code": null,
"updated": "2023-06-21T10:22:09.477374419Z",
"metadata": {
"foo": "bar"
},
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": null,
"reference_id": "16439b4d-3bf3-4261-8bde-9c8f51621ff2",
"virtual_account": null,
"over_the_counter": {
"amount": 10000,
"currency": "IDR",
"channel_code": "ALFAMART",
"channel_properties": {
"expires_at": "2023-06-23T10:21:45Z",
"payment_code": "APAPM8788765223",
"customer_name": "John Doe"
}
},
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-2d95854f-fc29-40b6-89cc-acb8085b3b1b"
},
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Tokenized Payment Scenario
This payment method involves tokenization, where the process begins with the end user establishing an account link before proceeding to make subsequent payments.
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.
Tokenization
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 (in the form of payment_method_id
) are then used to create Cards payment requests. 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.
See our Tokenization Sample for an example implementation for web application. SDK implementations for mobile OS are in the works and are not available at the moment.
Multiple Use Tokens
Tokens can be created for multiple use. If you plan to save a card for future use, set reusability
to MUTLPLE_USE
(recommended). When tokenizing a card for multi-use, the amount
field is optional.
Once you completed the tokenization step using XenditJS, you will receive a payment method activated webhook. Do save the specified payment_method_id
(id
prefixed with pm-
) as it will be used in the payment request creation step.
Initiate Tokenized Payment
Using the payment_method_id
saved from the tokenization step, you can now create a payment request to proceed with charging.
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"reference_id": "merchant_internal_order_id",
"currency": "IDR",
"amount": 100000,
"payment_method_id": "pm-4cf0be16-6339-4f27-a62d-e71dc570268d",
"metadata": {
"sku": "ABCDEFGH"
}
}' \
Header | 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. 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 Payment Request 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 | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||||||||||||||||||
amountrequired |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
|
||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||||||||||||||||||
customer optional |
object
|
A customer object to skip Create Customer URL endpoint process. This object is required if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||
country conditional |
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 ). Accepted values:
|
||||||||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||
payment_method_idrequired |
string |
Unique identifier for the payment method. This has a prefix of pm- . When using XenditJS library on the client-side, this value will be generated by the createPaymentMethod function. Example: pm-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 |
||||||||||||||||||||||||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-a5b8c440-e32a-4556-baa6-0b3e7de362ea",
"country": "ID",
"amount": 15000,
"currency": "IDR",
"business_id": "666db55f3921fa6f14db977f",
"reference_id": "facbb1a8-b6ee-49b6-8f74-72021bdcd22a",
"payment_method": {
"id": "pm-4cf0be16-6332-4f27-a62d-e71dc322668d",
"type": "CARD",
"reference_id": "a7f7807b-b3c9-41b4-afd1-53dc58c2af88",
"description": "This is a description.",
"created": "2023-01-19T08:57:02.101083Z",
"updated": "2023-01-19T08:59:10.89757Z",
"card": {
"currency": "IDR",
"channel_properties": {
"skip_three_d_secure": false,
"success_return_url": "https://xendit.co/goodstuff",
"failure_return_url": "https://xendit.co/badstuff",
"cardonfile_type": "CUSTOMER_UNSCHEDULED"
},
"card_information": {
"token_id": "63c905dd8c4a98001b7c777a",
"masked_card_number": "666000XXXXXX1666",
"cardholder_name": "John Doe",
"expiry_month": "12",
"expiry_year": "2027",
"fingerprint": "61f632879e9e27001a8165b9",
"type": "CREDIT",
"network": "VISA",
"country": "ID",
"issuer": "BRI"
},
"card_verification_results": {
"address_verification_result": "MATCH",
"cvv_result": "MATCH",
"three_d_secure": {
"eci_code": "05",
"three_d_secure_flow": "CHALLENGE",
"three_d_secure_result": "AUTHENTICATED",
"three_d_secure_result_reason": null,
"three_d_secure_version": "2.1.0"
}
}
},
"ewallet": null,
"direct_debit": null,
"direct_bank_transfer": null,
"over_the_counter": null,
"virtual_account": null,
"qr_code": null,
"metadata": {
"foo": "bar"
},
"reusability": "MULTIPLE_USE",
"status": "ACTIVE"
},
"description": "This is a description.",
"metadata": {
"foo": "bar"
},
"customer_id": null,
"capture_method": "AUTOMATIC",
"initiator": "CUSTOMER",
"card_verification_results": null,
"created": "2023-01-19T16:43:05.960659909Z",
"updated": "2023-01-19T16:43:05.960659909Z",
"status": "REQUIRES_ACTION",
"actions": [
{
"action": "AUTH",
"url": "https://redirect.xendit.co/callbacks/v2/authorizations/ca_63c9731a54c8da001a01491f/authentication_redirect?api_key=xnd_public_development_xsvgZdan9aqY1w5Szfn8XxzDOv3UDZkBRdDT6fZuVpKLVNrvQvS00TDuSLhp",
"url_type": "WEB",
"method": "GET",
"qr_code": null
}
],
"failure_code": null,
"channel_properties": null,
"shipping_information": null,
"items": null
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Body Parameter | Type | Description | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for the payment request. This has a prefix of pr- . Example: pr-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 |
||||||||||||||||||||||
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 ). |
||||||||||||||||||||||
amountnullable |
number |
Authorized amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment method will accept any amount as payment (open amount). (Applicable only for OVER_THE_COUNTER and VIRTUAL_ACCOUNT ) |
||||||||||||||||||||||
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||||||||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||||||||||||||
reference_idnullable |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
||||||||||||||||||||||
payment_methodrequired |
object |
Corresponding Payment Method created or used for the Payment Method. Note: customer_id , currency , and amount are moved to the root level of the Payment Request object. |
||||||||||||||||||||||
descriptionnullable |
string |
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||
metadatanullable |
object |
User defined object with JSON properties and values passed in during Payment Request creation. | ||||||||||||||||||||||
customer_idnullable |
string |
ID of the customer object to which the account token will be linked to | ||||||||||||||||||||||
capture_methodnullable |
string |
Describes when the funds are captured. Defaults to AUTOMATIC Possible values:
|
||||||||||||||||||||||
initiatorrequired |
string |
Identifies whether the payment is initiated by the end-customer or the merchant. Defaults to CUSTOMER Possible values:
|
||||||||||||||||||||||
card_verification_resultsnullable |
object |
This is only applicable for CARD transactions. This contains the results of various checks done to verify the transaction such as CVV, and AVS.
|
||||||||||||||||||||||
createdrequired |
string |
ISO 8601 Timestamp for Payment Request object creation. Timezone UTC+0 | ||||||||||||||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest Payment Request object update. Timezone UTC+0 | ||||||||||||||||||||||
statusrequired |
string |
Status of the payment method. Possible values:
| ||||||||||||||||||||||
actionsrequired |
object array |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to complete a payment. Only one of the provided actions is required to be fulfilled. If no further action is needed, this parameter will be an empty array [] . Each object will have the following properties:
|
||||||||||||||||||||||
failure_codenullable |
string |
If the status of the transaction is FAILED , this describes the reason for failure.Will be null if the transaction did not fail. See possible codes here. |
||||||||||||||||||||||
channel_propertiesnullable |
object |
Specific settings applied to the payment request, overwriting the ones in the Payment Method object.For
|
Key | Value |
---|---|
skip_three_d_secure required |
boolean To indicate whether to perform 3DS on the payment requestDefaults to false
|
success_return_urlnullable |
string URL where the end-customer is redirected if the linking is successful.Required when skip_three_d_secure = false . This will be null if not applicable. |
failure_return_urlnullable |
string URL where the end-customer is redirected if the linking has failed.Required when skip_three_d_secure = false . This will be null if not applicable. |
nullable
object
Key | Value |
---|---|
countryrequired |
string 2-letter ISO 3166-2 country code for the customerโs shipping country |
street_line1nullable |
string Building name and apartment unit number |
street_line2nullable |
string Building street address |
citynullable |
string City, village or town as appropriate |
province_statenullable |
string Either one of (whichever is applicable):
|
postal_codenullable |
string Postal, zip or rural delivery code, if applicable |
nullable
array
Object parameters
Key | Value |
---|---|
typerequired |
string Type of itemDIGITAL_PRODUCT , PHYSICAL_PRODUCT , DIGITAL_SERVICE , PHYSICAL_SERVICE ,FEE ,DISCOUNT (Atome does not support DISCOUNT) |
reference_idrequired |
string Merchantโs identifier for specific item (ie. SKU, promotion code, etc)Format Special and alphanumericMax length 255 characters |
namerequired |
string Item nameFormat Special and alphanumericMax length 255 characters |
net_unit_amountrequired |
number Net amount to be charged per unit, please put negative amount for DISCOUNT (e.g. -1000000) |
quantityrequired |
number Number of units of this item in the basketMin 1 |
urlrequired |
string URL of the itemMust be HTTPS or HTTP |
categoryrequired |
string Merchant category for itemFormat Special and alphanumericMax length 255 characters |
subcategoryoptional |
string Merchant subcategory for itemFormat Special and alphanumericMax length 255 characters |
descriptionoptional |
string Item descriptionFormat Special and alphanumericMax length 255 characters |
metadataoptional |
object Additional object that may be used for additional item attributes |
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_ACCOUNT_DETAILS400 |
The provided details were rejected by the partner channel due to incorrect information. |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
MAX_ACCOUNT_LINKING400 |
The direct debit account being attempted to be linked has reached the maximum linking allowed by the partner channel. |
PARTNER_CHANNEL_ERROR400 |
Error received from partner channel but no reasons provided |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
PROCESSOR_CONFIGURATION_ERROR 500 |
Payment declined due to a problem with the merchant configuration on the Card Processor. Contact Xendit to troubleshoot the issue. |
CHANNEL_UNAVAILABLE503 |
The payment channel requested is currently experiencing unexpected issues. The eWallet provider will be notified to resolve this issue |
PROCESSOR_ERROR 503 |
General system failure returned by the Card processor. Retry the request again after couple of minutes. |
INSUFFICIENT_BALANCE 400 |
Source of funds has insufficient balance to complete the transaction |
MAX_AMOUNT_LIMIT_ERROR 400 |
The transaction amount exceeds the partner channel's set limits |
INVALID_PAYMENT_METHOD400 |
The provided payment method id has already expired or is inactive |
ACCOUNT_NOT_ACTIVATED400 |
End-customer's account is not activated for payments. |
CUSTOMER_UNREACHABLE400 |
The end-user's device cannot be reached at this moment |
Webhook Payment Succeeded Cards
Callback Payload
Example: Payment Succeeded Callback Payload
{
"created": "2023-05-31T08:18:13.473Z",
"business_id": "628db55f8378fa6f14db977f",
"event": "payment.succeeded",
"data": {
"id": "ca_f545a7d9-482b-4eb0-b175-032252d3acca",
"items": null,
"amount": 1500,
"status": "SUCCEEDED",
"country": "ID",
"created": "2023-05-31T08:17:40.193463Z",
"updated": "2023-05-31T08:18:13.042335Z",
"currency": "IDR",
"metadata": null,
"customer_id": null,
"description": null,
"failure_code": null,
"reference_id": "8346c97c-6c16-4745-a1b4-69656f0b2d4e",
"payment_detail": null,
"payment_method": {
"id": "pm-62e521fc-09bd-4d50-bc44-a190c482a1a5",
"type": "CARD",
"status": "EXPIRED",
"created": "2023-05-31T08:17:40.084679Z",
"card": {
"currency": "IDR",
"channel_properties": {
"skip_three_d_secure": false,
"success_return_url": "https://xendit.co/goodstuff",
"failure_return_url": "https://xendit.co/badstuff",
"cardonfile_type": "CUSTOMER_UNSCHEDULED"
},
"card_information": {
"token_id": "63c905dd8c4a98001b7c777a",
"masked_card_number": "666000XXXXXX1666",
"cardholder_name": "John Doe",
"expiry_month": "12",
"expiry_year": "2027",
"fingerprint": "61f632879e9e27001a8165b9",
"type": "CREDIT",
"network": "VISA",
"country": "ID",
"issuer": "BRI",
"cardholder_email": "johndoe@gmail.com",
"cardholder_phone_number": "628212223242526"
},
"card_verification_results": {
"address_verification_result": "MATCH",
"cvv_result": "MATCH",
"three_d_secure": {
"eci_code": "05",
"three_d_secure_flow": "CHALLENGE",
"three_d_secure_result": "AUTHENTICATED",
"three_d_secure_result_reason": null,
"three_d_secure_version": "2.1.0"
}
}
},
"ewallet": null,
"qr_code": null,
"updated": "2023-05-31T08:17:40.084679Z",
"metadata": null,
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": null,
"reference_id": "6c8ad38e-2925-44c4-95af-35003298eefa",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-dd5e558f-1001-4402-84c3-df4375c6b29f"
},
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Webhook Payment Failed Cards
Note: Make sure that you ONLY have a webhook URL registered in the Payment Request
section in your Dashboard settings for payments. To prevent duplicate webhooks, DO NOT fill out product-specific sections.
Webhook Payload
Example: Payment Failed Webhook Payload
{
"created": "2023-05-31T10:52:00.666Z",
"business_id": "628db55f8378fa6f14db9555",
"event": "payment.failed",
"data": {
"id": "ewc_df746164-4f3e-417e-84cd-fa78c1d6a555",
"items": null,
"amount": 20111,
"status": "FAILED",
"country": "ID",
"created": "2023-05-31T10:51:48.73712Z",
"updated": "2023-05-31T10:51:58.057377Z",
"currency": "IDR",
"metadata": null,
"customer_id": null,
"description": null,
"failure_code": "ACCOUNT_NOT_ACTIVATED",
"reference_id": "7ce8f500-1bad-4d46-a1eb-0879b13e1bba",
"payment_detail": null,
"payment_method": {
"id": "pm-8bfd2cf3-6aca-4a10-ba48-d5c9e303b5df",
"card": {
"currency": "IDR",
"channel_properties": {
"skip_three_d_secure": false,
"success_return_url": "https://xendit.co/goodstuff",
"failure_return_url": "https://xendit.co/badstuff",
"cardonfile_type": "CUSTOMER_UNSCHEDULED"
},
"card_information": {
"token_id": "63c905dd8c4a98001b7c777a",
"masked_card_number": "666000XXXXXX1666",
"cardholder_name": "John Doe",
"expiry_month": "12",
"expiry_year": "2027",
"fingerprint": "61f632879e9e27001a8165b9",
"type": "CREDIT",
"network": "VISA",
"country": "ID",
"issuer": "BRI"
},
"card_verification_results": {
"address_verification_result": "MATCH",
"cvv_result": "MATCH",
"three_d_secure": {
"eci_code": "05",
"three_d_secure_flow": "CHALLENGE",
"three_d_secure_result": "AUTHENTICATED",
"three_d_secure_result_reason": null,
"three_d_secure_version": "2.1.0"
}
}
},
"type": "EWALLET",
"status": "EXPIRED",
"created": "2023-05-31T10:51:48.646147Z",
"ewallet": null,
"qr_code": null,
"updated": "2023-05-31T10:51:48.646147Z",
"metadata": null,
"description": null,
"reusability": "ONE_TIME_USE",
"direct_debit": null,
"reference_id": "869776db-5e5a-48dd-b7b3-45b89737e599",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-63df12be-6dc2-4602-ab7a-78d851f0ee06"
},
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.failed |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
ACCOUNT_NOT_ACTIVATED |
End-customer's account is not activated for payments. |
CHANNEL_UNAVAILABLE |
The partner channel cannot be reached or currently having a downtime |
CUSTOMER_UNREACHABLE |
The end-user's device cannot be reached at this moment by the partner channel |
INSUFFICIENT_BALANCE |
Source of funds has insufficient balance to complete the transaction |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the partner channel |
INVALID_PAYMENT_METHOD |
The provided payment method id has already expired or is inactive |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
MAX_AMOUNT_LIMIT_ERROR |
The transaction amount exceeds the partner channel's set limits |
PARTNER_CHANNEL_ERROR |
Error received from partner channel but no reasons provided |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_EXPIRED |
If you are using Xendit-hosted OTP page, end-user needs to input their OTP within 15 minutes or else the payment will be expired. You may need to create a new payment. |
PAYMENT_STATUS_FAILED |
Payment has failed with no further information from channel. You may need to check before retrying. Recommended to wait ~30 minutes before retrying unless given further instruction. |
INVALID_ACCOUNT_DETAILS |
The provided details were rejected by the partner channel due to incorrect information. |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the partner channel |
Direct Debit
Account Linking (Direct Debit)
Account linking in direct debit enable you to abstract sources of funds, account authorizations and use them for making direct debit payments or recurring payments.
Endpoint: Create Payment Method
POST https://api.xendit.co/v2/payment_methods
Example 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": "DIRECT_DEBIT",
"direct_debit": {
"channel_code": "BPI",
"channel_properties": {
"success_return_url" : "https://redirect.me/goodstuff",
"failure_return_url" : "https://redirect.me/badstuff"
}
},
"reusability": "MULTIPLE_USE",
"customer_id": "cust-xxx"
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. 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 | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
type required |
string
|
Type of payment method For Direct debit:
|
||||||||||||||||||||||||||||||||||||||||
reusability required |
string
|
Describes whether or not the payment method can be reused for subsequent payments. For DIRECT_DEBIT , this determines whether or not authentication is performed again for subsequent payments. Accepted values for account linking: use MULTIPLE_USE as value for direct debit account linking. |
||||||||||||||||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment method. If none is provided, Xendit will randomly generate a unique reference_id . |
||||||||||||||||||||||||||||||||||||||||
customer_id conditional |
string
|
ID of the customer object to which the account token will be linked to. Call Create Customer to generate Customer ID. The value will always have prefix cust-xxx A customer_id is required for all DIRECT_DEBIT payment methods and if customer object is null. |
||||||||||||||||||||||||||||||||||||||||
customer optional |
object
|
A customer object to skip Create Customer URL endpoint process. This object is required only if customer_id is null The parameters to be set for the customer object
| ||||||||||||||||||||||||||||||||||||||||
country conditional |
string
|
2-letter ISO 3166-2 country code indicating country of transaction. Accepted values for Direct debit:
|
||||||||||||||||||||||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
||||||||||||||||||||||||||||||||||||||||
direct_debit conditional |
object
|
Required for type='DIRECT_DEBIT' , this contains the necessary information to describe a direct debit payment method.
|
Create Direct Debit Account Linking via Payment Method Response
Example Create Payment Method Success Response
{
"id": "pm-04340cfc-9a9d-437b-9046-80133cd2b265",
"type": "DIRECT_DEBIT",
"country": "PH",
"business_id": "6396e6d48c59c43843989",
"customer_id": "cust-675b65af-a3d6-4945-aafe-3899389",
"reference_id": "c3b17af5-16de-43bd-8165-22aa0c5c1bac",
"reusability": "MULTIPLE_USE",
"status": "REQUIRES_ACTION",
"actions": [
{
"action": "AUTH",
"url": "https://link-web-staging.xendit.co/oauth/lat-ae030303-5155-4962-ba09-ac3b3aa1cef4/confirm",
"url_type": "WEB",
"method": "GET"
}
],
"description": null,
"created": "2023-06-13T16:49:26.044862578Z",
"updated": "2023-06-13T16:49:26.044862578Z",
"metadata": null,
"billing_information": null,
"failure_code": null,
"ewallet": null,
"direct_bank_transfer": null,
"direct_debit": {
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
},
"type": "BANK_ACCOUNT",
"bank_account": {
"masked_bank_account_number": null,
"bank_account_hash": null
},
"debit_card": null
},
"card": null,
"over_the_counter": null,
"qr_code": null,
"virtual_account": null
}
A successful Payment Method creation returns a Payment Method Object with an HTTP 201
status code.
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 |
||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||
customer_idnullable |
string |
ID of the customer object to which the account token will be linked to | ||||||||||
reference_idnullable |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
||||||||||
reusabilityrequired |
string |
Describes whether or not the payment method can be reused for subsequent payments without going through the same linking process again. Possible value:
|
||||||||||
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. | ||||||||||
statusrequired |
string |
Status of the payment method. Possible values:
| ||||||||||
actionsrequired |
object array |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to activate a payment method. Only one of the provided actions is required to be fulfilled. If no further action is needed, this parameter will be an empty array [] . Each object will have the following properties:
|
||||||||||
typerequired |
string |
Type of payment method. Refer to the corresponding object to access further information Possible values:
|
||||||||||
direct_debitnullable |
object |
For type='DIRECT_DEBIT' , this contains the necessary information to describe a direct debit payment method. This will be null otherwise. Please refer to Direct debit Object for more parameter details. |
||||||||||
descriptionnullable |
string |
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||
createdrequired |
string |
ISO 8601 Timestamp for Payment Method object creation. Timezone UTC+0 | ||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest Payment Method object update. Timezone UTC+0 | ||||||||||
metadatanullable |
object |
User defined object with JSON properties and values passed in during Payment Method creation. |
Create Payment Method Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
INVALID_ACCOUNT_DETAILS400 |
The provided details were rejected by the partner channel due to incorrect information. |
MAX_ACCOUNT_LINKING400 |
The direct debit account being attempted to be linked has reached the maximum linking allowed by the partner channel. |
INVALID_API_KEY401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details. If you provide customer object request, the reference_id of customer object may already exist. |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 |
OTP_DELIVERY_ERROR 503 |
The partner channel has failed to send the OTP to the Customer |
Authorize Payment Method Direct Debit Tokenized
This endpoint only applies to BRI Direct Debit. This is used when an additional authorization (ex. OTP Validation) is required in order to successfully activate a payment method. This is equivalent to the POST - AUTH
action provided when a Payment Method has the status REQUIRES_ACTION
.
Endpoint: Account Linking - Authorize Payment Method
POST https://api.xendit.co/v2/payment_methods/:id/auth
Authorize Payment Method Request
Example Account Linking - Authorize Payment Method Request
curl https://api.xendit.co/v2/payment_methods/pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a/auth -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"auth_code": "356443"
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. 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 |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Primary identifier for the Payment Method object. This starts with the prefix pm- . |
Request Body Parameter | Type | Description |
---|---|---|
auth_code required |
string
|
The authorization code or OTP inputted by the end-customer. |
Authorize Payment Method Response
Example Account Linking - Authorize Payment Method Success Response
{
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "ID",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "DEBIT_CARD",
"debit_card": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "email@email.com"
},
"bank_account": null,
"channel_code": "BRI",
"channel_properties": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "test.email@xendit.co"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Returns a Payment Method Object with an HTTP 200
status code.
Authorize Payment Method Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
EXPIRED_OTP_ERROR400 |
The provided auth_code has expired |
INVALID_OTP_ERROR400 |
The provided auth_code is incorrect |
MAX_OTP_ATTEMPTS_ERROR400 |
The maximum attempts allowed by the channel has been reached |
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
DATA_NOT_FOUND404 |
The provided id did not match any of our records |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
PAYMENT_METHOD_ALREADY_ACTIVE409 |
Cannot proceed because the payment method is already active or has been activated |
PAYMENT_METHOD_ALREADY_FAILED409 |
Cannot proceed because the payment method has failed authorization and cannot be retried |
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 |
Webhook Account Linking Activated - Direct Debit
This callback activates when the end customer intends to connect their direct debit cards to your website for future payments.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Activated Callback Payload
{
"event": "payment_method.activated",
"data": {
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "PH",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null
},
"created": "2022-08-12T13:30:59.074277334Z",
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
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 with status ACTIVE |
Webhook Account Linking Failed - Direct Debit
This callback is triggered when a particular Payment Method has failed during authentication/authorization.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Failed Callback Payload
{
"id": "pm-343c8d96-0b69-4f02-85ae-110336241f7e",
"data": {
"id": "pm-343c8d96-0b69-4f02-85ae-110336241f7e",
"card": null,
"type": "DIRECT_DEBIT",
"status": "FAILED",
"actions": [],
"country": "PH",
"created": "2023-08-10T09:05:13.606327Z",
"ewallet": null,
"qr_code": null,
"updated": "2023-08-10T09:05:21.301664958Z",
"metadata": null,
"business_id": "6396e6d48c59c18ca0e55218",
"customer_id": "cust-19bfb7fd-6c8d-4332-8725-c14006090ea4",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": null,
"masked_bank_account_number": null
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
}
},
"failure_code": "PAYMENT_METHOD_ALREADY_EXISTS",
"reference_id": "195f7edd-7394-44f4-8395-01b983c2c80a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null
},
"event": "payment_method.failed",
"created": "2023-08-10T09:05:21.454587678Z",
"business_id": "6396e6d48c59c18ca0e55218"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.failed |
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 with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Payment Method Failure
This failure code will be delivered assynchronously with payment_methods.failed callback. Find details more in Payment Method Failed Callback
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
DUPLICATE_ERROR |
There's an existing record of linking the same underlying account for the provided customer_id OR Virtual Account Number/Payment Code already exists |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_METHOD_ALREADY_EXISTS |
An active Payment Method with the same customer_id, channel_code for that merchant already exists. |
Subsequent Payment (Direct Debit)
This scenario facilitates the subsequent payment functionality following the account linking process. Please kindly find the details of account linking steps here.
After making the following payment, the next task is to verify it using an OTP (One-Time Password). There are two options for OTP validation:
- Use the provided xendit hosted OTP from the action response parameter.
- or Create your own OTP validation page using the Authorize Payment endpoint
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 1500,
"currency": "PHP",
"payment_method_id": "pm-e677f3d7-15f5-4991-8c8c-1fba70c72684",
"description": "This is a description.",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff?custom=value",
"failure_return_url": "https://redirect.me/badstuff?custom=value"
},
"metadata": {
"foo": "bar"
}
}' \
Header | 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. 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 Payment Request 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 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||||||||||||||||||||
amountrequired |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
|
||||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||||||||||||||||||||
country conditional |
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 ). Accepted values:
|
||||||||||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||||
payment_method_idconditional |
object |
Note: Only one of payment_method{} or payment_method_id must be present.ID of the ACTIVE Payment Method to be used in the payment. |
||||||||||||||||||||||||||||
channel_propertiesoptional |
object |
Specific settings to be applied to the transaction. This also overwrites any common parameters with the Payment Method Object. For BRI Direct Debit:
For BPI, UBP, RCBC, CHINABANK, and FPX Channels under Direct Debit:
For SCB and BBL Direct Debit:
For KTB and BAY Direct Debit:
|
||||||||||||||||||||||||||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-8f9a5d3a-0f9f-47bf-8452-a4be9388b490",
"country": "PH",
"amount": 1500,
"currency": "PHP",
"business_id": "6396e6d48c59c18ca0e55218",
"reference_id": "464608e0-3fff-4ecc-83e9-ce57d2561b1c",
"payment_method": {
"id": "pm-e677f3d7-15f5-4991-8c8c-1fba70c72684",
"type": "DIRECT_DEBIT",
"reference_id": "80af8018-ec1b-48db-9ca2-a2bffc3fedf7",
"description": null,
"created": "2023-07-16T23:03:01.886251Z",
"updated": "2023-07-16T23:03:13.898886Z",
"card": null,
"ewallet": null,
"direct_debit": {
"channel_code": "BPI",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff",
"failure_return_url": "https://redirect.me/badstuff"
},
"type": "BANK_ACCOUNT",
"bank_account": {
"masked_bank_account_number": "XXX1631",
"bank_account_hash": "8f06b7dc684aa57a283adf49b2f67bdb11750ac04300f3996d97c7412ac5ca48"
},
"debit_card": null
},
"direct_bank_transfer": null,
"over_the_counter": null,
"virtual_account": null,
"qr_code": null,
"metadata": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"province_state": null,
"street_line1": null,
"street_line2": null
},
"reusability": "MULTIPLE_USE",
"status": "ACTIVE"
},
"description": "This is a description.",
"metadata": {
"foo": "bar"
},
"customer_id": "cust-d6bd4440-24b9-4199-bc09-b01c4eda049e",
"capture_method": "AUTOMATIC",
"initiator": null,
"card_verification_results": null,
"created": "2023-07-16T23:03:44.877239112Z",
"updated": "2023-07-16T23:03:44.877239112Z",
"status": "REQUIRES_ACTION",
"actions": [
{
"action": "AUTH",
"url": "https://direct-debit-web-dev.xendit.co/direct_debits/ddpy-4a33b665-80ca-4a93-a111-f52ba86ec7e3/checkout?failure_redirect_url=https%3A%2F%2Fredirect.me%2Fbadstuff%3Fcustom%3Dvalue&payment_redirect_delay=10",
"url_type": "WEB",
"method": "GET",
"qr_code": null
},
{
"action": "AUTH",
"url": "https://api.xendit.co/payment_requests/pr-8f9a5d3a-0f9f-47bf-8452-a4be9388b490/auth",
"url_type": "API",
"method": "POST",
"qr_code": null
}
],
"failure_code": null,
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff?custom=value",
"success_return_url": "https://redirect.me/goodstuff?custom=value"
},
"shipping_information": null,
"items": null
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_ACCOUNT_DETAILS400 |
The provided details were rejected by the partner channel due to incorrect information. |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
MAX_ACCOUNT_LINKING400 |
The direct debit account being attempted to be linked has reached the maximum linking allowed by the partner channel. |
PARTNER_CHANNEL_ERROR400 |
Error received from partner channel but no reasons provided |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
PROCESSOR_CONFIGURATION_ERROR 500 |
Payment declined due to a problem with the merchant configuration on the Card Processor. Contact Xendit to troubleshoot the issue. |
CHANNEL_UNAVAILABLE503 |
The payment channel requested is currently experiencing unexpected issues. The eWallet provider will be notified to resolve this issue |
OTP_DELIVERY_ERROR 503 |
The partner channel has failed to send the OTP to the Customer |
PROCESSOR_ERROR 503 |
General system failure returned by the Card processor. Retry the request again after couple of minutes. |
PROCESSOR_TEMPORARILY_UNAVAILABLE 503 |
The Card Processor appears to be temporarily unavailable. Wait for a couple minutes, then resend the request. If it fails again, Cardholder can try using a different card or other form of payment. |
PROCESSOR_TIMEOUT_ERROR 503 |
Request was received by the processor, but there was a server timeout. Wait for a couple minutes and then retry the request. |
INSUFFICIENT_BALANCE 400 |
Source of funds has insufficient balance to complete the transaction. |
MAX_AMOUNT_LIMIT_ERROR 400 |
The transaction amount exceeds the partner channel's set limits. |
FORBIDDEN 403 |
Provided API key does not have the correct permissions to perform the operation. |
Authorize Payment Request Direct Debit Tokenized
This is only applicable for select payment DIRECT_DEBIT
channels (BRI Direct Debit, BPI, RCBC, UBP, CHINABANK)
This is used when an additional authorization (ex. OTP Validation, PIN validation) is required in order to successfully activate a payment method. This is equivalent to the POST - AUTH
action provided when a Payment Method has the status REQUIRES_ACTION
.
Endpoint: Confirm Payment Request
POST https://api.xendit.co/payment_requests/:id/auth
Confirm Payment Request Request
Example Confirm Payment Request Request
curl https://api.xendit.co/payment_requests/pr-6e9778ea-7d62-40fe-8b25-a4d740754c5f/auth -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"auth_code": "123456"
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. 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 |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Primary identifier for the Payment Request object. This starts with the prefix pr- . |
Request Body Parameter | Type | Description |
---|---|---|
auth_code required |
string
|
The authorization code, OTP, or PIN inputted by the end-customer. |
Confirm Payment Request Response
Example Confirm Payment Request Response
{
"id": "pr-6e9778ea-7d62-40fe-8b25-a4d740754c5f",
"currency": "PHP",
"amount": 10000,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"business_id": "5f27a14a9bf05c73dd040bc8",
"status": "PENDING",
"reference_id": "a2c66ceb-2cbe-4541-bb69-9f50fd2040e0",
"payment_method": {
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "PH",
"ewallet": null,
"qr_code": null,
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"created": "2022-08-12T13:30:26.579048Z",
"updated": "2022-08-12T13:30:58.908220358Z"
},
"channel_properties": null,
"actions": [],
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "ABCDEFGH"
}
}
Returns a Payment Request Object with an HTTP 200
status code.
Confirm Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
EXPIRED_OTP_ERROR400 |
The provided auth_code has expired |
INVALID_OTP_ERROR400 |
The provided auth_code is incorrect |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
MAX_OTP_ATTEMPTS_ERROR400 |
The maximum attempts allowed by the channel has been reached |
PARTNER_CHANNEL_ERROR400 |
Error received from partner channel but no reasons provided |
INVALID_API_KEY401 |
API key format is invalid |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
The provided id did not match any of our records |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
PAYMENT_REQUEST_ALREADY_FAILED409 |
Cannot proceed because the payment method has already failed and cannot be retried. |
PAYMENT_REQUEST_ALREADY_PENDING409 |
Payment request ID already is processing and waiting for results from the partner channel. |
PAYMENT_REQUEST_ALREADY_SUCCEEDED409 |
Cannot proceed because the payment request has been successfully processed. |
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 |
Resend Auth for Payment Request Tokenized (Direct Debit )
This is only applicable for select payment DIRECT_DEBIT
channels (BPI, UBP, CHINABANK)
This is used when an additional authorization (ex. OTP Validation) is required in order to successfully activate a payment method. This is equivalent to the POST - AUTH
action provided when a Payment Method has the status REQUIRES_ACTION
.
Endpoint: Resend Auth for Payment Request
POST https://api.xendit.co/payment_requests/:id/auth/resend
Resend Auth for Payment Request Request
Example Resend Auth for Payment Request Request
curl https://api.xendit.co/payment_requests/pr-6e9778ea-7d62-40fe-8b25-a4d740754c5f/auth/resend -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. 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 |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Primary identifier for the Payment Request object. This starts with the prefix pr- . |
Resend Auth for Payment Request Response
Example Resend Auth for Payment Request Success Response
{
"id": "pr-6e9778ea-7d62-40fe-8b25-a4d740754c5f",
"currency": "PHP",
"amount": 10000,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"business_id": "5f27a14a9bf05c73dd040bc8",
"status": "REQUIRES_ACTION",
"reference_id": "a2c66ceb-2cbe-4541-bb69-9f50fd2040e0",
"payment_method": {
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "PH",
"ewallet": null,
"qr_code": null,
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"created": "2022-08-12T13:30:26.579048Z",
"updated": "2022-08-12T13:30:58.908220358Z"
},
"channel_properties": null,
"actions": [
{
"action": "AUTH",
"url_type": "API",
"url": "https://api.xendit.co/payment_requests/pr-6e9778ea-7d62-40fe-8b25-a4d740754c5f/auth",
"method": "POST"
}
],
"created": "2020-08-29T09:12:33.001Z",
"updated": "2020-08-29T09:12:33.001Z",
"metadata": {
"sku": "ABCDEFGH"
}
}
Returns a Payment Request Object with an HTTP 200
status code.
Resend Auth for Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
PARTNER_CHANNEL_ERROR400 |
Error received from partner channel but no reasons provided |
INVALID_API_KEY401 |
API key format is invalid |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DATA_NOT_FOUND404 |
The provided id did not match any of our records |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
PAYMENT_REQUEST_ALREADY_FAILED409 |
Cannot proceed because the payment method has already failed and cannot be retried. |
PAYMENT_REQUEST_ALREADY_PENDING409 |
Payment request ID already is processing and waiting for results from the partner channel. |
PAYMENT_REQUEST_ALREADY_SUCCEEDED409 |
Cannot proceed because the payment request has been successfully processed. |
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 |
Webhook Payment Succeeded Direct Debit Tokenized
This is also send for successful Payment Requests for EWALLET
, DIRECT_DEBIT
, and CARD
.
Callback Payload
Example: Payment Succeeded Callback Payload
{
"event": "payment.succeeded",
"data": {
"id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"amount": 1000,
"status": "SUCCEEDED",
"country": "PH",
"created": "2022-08-12T13:30:40.9209Z",
"updated": "2022-08-12T13:30:58.729373Z",
"currency": "PHP",
"metadata": {
"sku": "ABCDEFGH"
},
"customer_id": "c832697e-a62d-46fa-a383-24930b155e81",
"reference_id": "25cfd0f9-baee-44ca-9a12-6debe03f3c22",
"payment_method": {
"id": "pm-951b1ad9-1fbb-4724-a744-8956ab6ed17f",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:40.221525Z",
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"direct_bank_transfer": null
},
"description": null,
"failure_code": null,
"payment_detail": null,
"channel_properties": null,
"payment_request_id": "pr-5b26cae1-545b-49e9-855e-f85128f3e705"
},
"created": "2022-08-12T13:30:58.986Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Webhook Payment Failed Direct Debit Tokenized
This callback is sent when a pending EWALLET
, DIRECT_DEBIT
, and CARD
has failed.
Note: Make sure that you ONLY have a callback URL registered in the Payment Request
section in your Dashboard settings for payments. To prevent duplicate callbacks, DO NOT fill out product-specific sections.
Callback Payload
Example: Payment Failed Callback Payload
{
"event": "payment.failed",
"data": {
"id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"amount": 1000,
"status": "FAILED",
"country": "PH",
"created": "2022-08-12T13:30:40.9209Z",
"updated": "2022-08-12T13:30:58.729373Z",
"currency": "PHP",
"metadata": {
"sku": "ABCDEFGH"
},
"customer_id": "c832697e-a62d-46fa-a383-24930b155e81",
"reference_id": "25cfd0f9-baee-44ca-9a12-6debe03f3c22",
"payment_method": {
"id": "pm-951b1ad9-1fbb-4724-a744-8956ab6ed17f",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:40.221525Z",
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"direct_bank_transfer": null
},
"description": null,
"failure_code": "INSUFFICIENT_BALANCE",
"payment_detail": null,
"channel_properties": null,
"payment_request_id": "pr-5b26cae1-545b-49e9-855e-f85128f3e705"
},
"created": "2022-08-12T13:30:58.986Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.failed |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
ACCOUNT_NOT_ACTIVATED |
End-customer's account is not activated for payments. |
CHANNEL_UNAVAILABLE |
The partner channel cannot be reached or currently having a downtime |
CUSTOMER_UNREACHABLE |
The end-user's device cannot be reached at this moment by the partner channel |
DUPLICATE_ERROR |
There's an existing record of linking the same underlying account for the provided customer_id OR Virtual Account Number/Payment Code already exists |
INSUFFICIENT_BALANCE |
Source of funds has insufficient balance to complete the transaction |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the partner channel |
INVALID_PAYMENT_METHOD |
The provided payment method id has already expired or is inactive |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
MAX_AMOUNT_LIMIT_ERROR |
The transaction amount exceeds the partner channel's set limits |
MAX_OTP_ATTEMPTS_ERROR |
The maximum incorrect attempts allowed by the channel has been reached. |
PARTNER_CHANNEL_ERROR |
Error received from partner channel but no reasons provided |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_METHOD_ALREADY_EXISTS |
An active Payment Method with the same customer_id, channel_code for that merchant already exists. |
PAYMENT_EXPIRED |
If you are using Xendit-hosted OTP page, end-user needs to input their OTP within 15 minutes or else the payment will be expired. You may need to create a new payment. |
PAYMENT_STATUS_FAILED |
Payment has failed with no further information from channel. You may need to check before retrying. Recommended to wait ~30 minutes before retrying unless given further instruction. |
E-Wallets
Account Linking (E-Wallets)
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 account linking |
||||||||||||||||||||||||||
customer_id conditional |
string
|
ID of the customer object to which the account token will be linked to. Call Tokenized - Create Customer to generate Customer ID | ||||||||||||||||||||||||||
customer optional |
object
|
A customer object to skip Create Customer URL endpoint process. This object is required for all if the customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||
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 |
CUSTOMER_NOT_FOUND_ERROR400 |
Provided customer_id in the request parameters does not exist / owned by a different business / invalid format |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account to be linked has been blocked by the partner channel |
INVALID_ACCOUNT_DETAILS400 |
The provided details for account linking in incorrect or has been rejected by the partner channel |
FORBIDDEN403 |
Provided API key does not have the correct permissions to perform the operation |
IDEMPOTENCY_ERROR403 |
The request body does not match the body of the previous request with the same Idempotency key |
SERVER_ERROR403 |
An error occurred on Xendit's side |
Webhook Account Linking Activated (E-Wallets)
This callback is triggered when a particular Payment Method has been successfully created and can be used for payments.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Activated Callback Payload
{
"id": "pm-947ad717-c346-4fbd-8a30-c37ae3421a78",
"data": {
"id": "pm-947ad717-c346-4fbd-8a30-c37ae3421a78",
"card": null,
"type": "EWALLET",
"status": "ACTIVE",
"actions": [],
"country": "ID",
"created": "2023-05-31T09:37:53.643369Z",
"ewallet": {
"account": {
"name": "John Doe",
"balance": null,
"point_balance": null,
"account_details": "+62123456XXXX"
},
"channel_code": "OVO",
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
}
},
"qr_code": null,
"updated": "2023-05-31T09:38:04.697488975Z",
"metadata": {
"foo": "bar"
},
"business_id": "628db55f8378fa6f14db977f",
"customer_id": "cust-97400c09-714f-41a2-9a0a-1325ab4e9ab9",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": null,
"failure_code": null,
"reference_id": "b3155b96-c8bb-4a8b-96ae-75c21caab607",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null
},
"event": "payment_method.activated",
"created": "2023-05-31T09:38:04.930873409Z",
"business_id": "628db55f8378fa6f14db977f"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
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 with status ACTIVE |
Tokenized Payment E-Wallets
This endpoint provides the scenario where your End-customer want to have a linking scenario first then make a payment scenario subsequently. For this scenarion, Create Ewallet Account linking is required as pre-requisite, where the payment method ID (pm-xx) will be required for this create payment request.
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 1500,
"currency": "PHP",
"payment_method_id": "pm-04152d03-0f56-433c-994c-251f79b6074a",
"description": "This is a description.",
"metadata": {
"foo": "bar"
}
}' \
Header | 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. 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 Payment Request 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 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||
amountrequired |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
|
||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||
country conditional |
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 ). Accepted values:
|
||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||
payment_method_idrequired |
object |
Note: Only one of payment_method{} or payment_method_id must be present.ID of the ACTIVE Payment Method to be used in the payment. |
||||||||||
channel_propertiesoptional |
object |
Specific settings to be applied to the transaction. This also overwrites any common parameters with the Payment Method Object. For multiple use OVO, and SHOPEEPAY (ID & MY):
For GRABPAY (MY):
|
||||||||||
metadata optional |
object
|
A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-8f9a5d3a-0f9f-47bf-8452-a4be9388b490",
"country": "ID",
"amount": 1500,
"currency": "IDR",
"business_id": "628db55f8378fa6f14db977f",
"reference_id": "b7179cb7-33ed-4459-8482-42f1c2fb03aa",
"payment_method": {
"id": "pm-04152d03-0f56-433c-994c-251f79b6074a",
"type": "EWALLET",
"reference_id": "60288a67-6f0d-4399-8e29-cb5fd42b6a3b",
"description": null,
"created": "2023-07-18T02:17:06.916218Z",
"updated": "2023-07-18T02:19:37.110908Z",
"card": null,
"ewallet": {
"channel_code": "OVO",
"channel_properties": {
"cancel_return_url": "https://redirect.me/nostuff",
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
},
"account": {
"name": "John Doe",
"account_details": "+62123456XXXX",
"balance": 1000000,
"point_balance": 1000000
}
},
"direct_debit": null,
"direct_bank_transfer": null,
"over_the_counter": null,
"virtual_account": null,
"qr_code": null,
"metadata": {
"foo": "bar"
},
"reusability": "MULTIPLE_USE",
"status": "ACTIVE"
},
"description": "This is a description.",
"metadata": {
"foo": "bar"
},
"customer_id": "cust-bac23581-7fef-49e6-8074-c2aeb022df3b",
"capture_method": "AUTOMATIC",
"initiator": null,
"card_verification_results": null,
"created": "2023-07-18T02:23:57.5780025Z",
"updated": "2023-07-18T02:23:57.5780025Z",
"status": "REQUIRES_ACTION",
"actions": [
{
"action": "AUTH",
"url": "https://ewallet-mock-connector.xendit.co/v1/ewallet_connector/checkouts?token=ciqvffj78onc0bue8uig",
"url_type": "WEB",
"method": "GET",
"qr_code": null
},
{
"action": "AUTH",
"url": "https://ewallet-mock-connector.xendit.co/v1/ewallet_connector/checkouts?token=ciqvffj78onc0bue8uig",
"url_type": "MOBILE",
"method": "GET",
"qr_code": null
}
],
"failure_code": null,
"channel_properties": null,
"shipping_information": null,
"items": null
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_ACCOUNT_DETAILS400 |
The provided details were rejected by the partner channel due to incorrect information. |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
MAX_ACCOUNT_LINKING400 |
The direct debit account being attempted to be linked has reached the maximum linking allowed by the partner channel. |
PARTNER_CHANNEL_ERROR400 |
Error received from partner channel but no reasons provided |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
SERVER_ERROR500 |
An unexpected error occured, our team has been notified and will troubleshoot the issue |
PROCESSOR_CONFIGURATION_ERROR 500 |
Payment declined due to a problem with the merchant configuration on the Card Processor. Contact Xendit to troubleshoot the issue. |
CHANNEL_UNAVAILABLE503 |
The payment channel requested is currently experiencing unexpected issues. The eWallet provider will be notified to resolve this issue |
OTP_DELIVERY_ERROR 503 |
The partner channel has failed to send the OTP to the Customer |
PROCESSOR_ERROR 503 |
General system failure returned by the Card processor. Retry the request again after couple of minutes. |
PROCESSOR_TEMPORARILY_UNAVAILABLE 503 |
The Card Processor appears to be temporarily unavailable. Wait for a couple minutes, then resend the request. If it fails again, Cardholder can try using a different card or other form of payment. |
PROCESSOR_TIMEOUT_ERROR 503 |
Request was received by the processor, but there was a server timeout. Wait for a couple minutes and then retry the request. |
INSUFFICIENT_BALANCE 400 |
Source of funds has insufficient balance to complete the transaction |
MAX_AMOUNT_LIMIT_ERROR 400 |
The transaction amount exceeds the partner channel's set limits |
INVALID_PAYMENT_METHOD400 |
The provided payment method id has already expired or is inactive |
ACCOUNT_NOT_ACTIVATED400 |
End-customer's account is not activated for payments. |
CUSTOMER_UNREACHABLE400 |
The end-user's device cannot be reached at this moment |
Webhook Payment Succeeded Ewallet Tokenized
This is also send for successful Payment Requests for EWALLET
, DIRECT_DEBIT
, and CARD
.
Callback Payload
Example: Payment Succeeded Callback Payload
{
"created": "2023-05-31T09:38:35.559Z",
"business_id": "628db55f8378fa6f14db977f",
"event": "payment.succeeded",
"data": {
"id": "ewc_f7035bb6-5b62-4c43-b8d3-c80955554e01",
"items": null,
"amount": 1500,
"status": "SUCCEEDED",
"country": "ID",
"created": "2023-05-31T09:38:17.664697Z",
"updated": "2023-05-31T09:38:32.975311Z",
"currency": "IDR",
"metadata": {
"foo": "bar"
},
"customer_id": "cust-97400c09-714f-41a2-9a0a-1325ab4e9ab9",
"description": "This is a description.",
"failure_code": null,
"reference_id": "729308f7-741c-4e87-af84-6abc5e67f212",
"payment_detail": null,
"payment_method": {
"id": "pm-947ad717-c346-4fbd-8a30-c37ae3421a78",
"card": null,
"type": "EWALLET",
"status": "ACTIVE",
"created": "2023-05-31T09:37:53.643369Z",
"ewallet": {
"account": {
"name": "John Doe",
"balance": 1000000,
"point_balance": 1000000,
"account_details": "+62123456XXXX"
},
"channel_code": "OVO",
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
}
},
"qr_code": null,
"updated": "2023-05-31T09:38:04.697489Z",
"metadata": {
"foo": "bar"
},
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": null,
"reference_id": "b3155b96-c8bb-4a8b-96ae-75c21caab607",
"virtual_account": null,
"over_the_counter": null,
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-b89ff299-1c4a-454e-b9f0-a8435e6ddcf8"
},
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Webhook Payment Failed Ewallet Tokenized
Note: Make sure that you ONLY have a callback URL registered in the Payment Request
section in your Dashboard settings for payments. To prevent duplicate callbacks, DO NOT fill out product-specific sections.
Callback Payload
Example: Payment Failed Callback Payload
{
"created": "2023-05-31T10:11:02.966Z",
"business_id": "628db55f8378fa6f14db977f",
"event": "payment.failed",
"data": {
"id": "ewc_a34d616a-0885-49ff-a0d4-6ea3e3c974e2",
"items": null,
"amount": 20103,
"status": "FAILED",
"country": "ID",
"created": "2023-05-31T10:09:16.650076Z",
"updated": "2023-05-31T10:11:02.600413Z",
"currency": "IDR",
"metadata": null,
"customer_id": null,
"description": null,
"failure_code": "ACCOUNT_ACCESS_BLOCKED",
"reference_id": "fd6bec13-be0f-44c4-9f7b-cd5608dc1147",
"payment_detail": null,
"payment_method": {
"id": "pm-72e1e315-2455-4b57-b7ea-606a0e469c00",
"card": null,
"type": "EWALLET",
"status": "EXPIRED",
"created": "2023-05-31T10:09:16.560672Z",
"ewallet": {
"account": {
"name": null,
"balance": null,
"point_balance": null,
"account_details": null
},
"channel_code": "SHOPEEPAY",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff"
}
},
"qr_code": null,
"updated": "2023-05-31T10:09:16.560672Z",
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": null,
"reference_id": "90c17ae5-029b-4f14-bd90-8d0df6415cc1",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"channel_properties": null,
"payment_request_id": "pr-f436fdc8-8dbf-46ec-b498-baa6d714464f"
},
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.failed |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
ACCOUNT_NOT_ACTIVATED |
End-customer's account is not activated for payments. |
CHANNEL_UNAVAILABLE |
The partner channel cannot be reached or currently having a downtime |
CUSTOMER_UNREACHABLE |
The end-user's device cannot be reached at this moment by the partner channel |
DUPLICATE_ERROR |
There's an existing record of linking the same underlying account for the provided customer_id OR Virtual Account Number/Payment Code already exists |
INSUFFICIENT_BALANCE |
Source of funds has insufficient balance to complete the transaction |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the partner channel |
INVALID_PAYMENT_METHOD |
The provided payment method id has already expired or is inactive |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
MAX_AMOUNT_LIMIT_ERROR |
The transaction amount exceeds the partner channel's set limits |
MAX_OTP_ATTEMPTS_ERROR |
The maximum incorrect attempts allowed by the channel has been reached. |
PARTNER_CHANNEL_ERROR |
Error received from partner channel but no reasons provided |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_METHOD_ALREADY_EXISTS |
An active Payment Method with the same customer_id, channel_code for that merchant already exists. |
PAYMENT_EXPIRED |
If you are using Xendit-hosted OTP page, end-user needs to input their OTP within 15 minutes or else the payment will be expired. You may need to create a new payment. |
PAYMENT_STATUS_FAILED |
Payment has failed with no further information from channel. You may need to check before retrying. Recommended to wait ~30 minutes before retrying unless given further instruction. |
Webhook Account Linking Expired (E-Wallets)
This callback is triggered when a particular Payment Method has expired and will be unusable for payment transactions.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Expired Callback Payload
{
"id": "pm-62e521fc-09bd-4d50-bc44-a190c482a1a5",
"data": {
"id": "pm-62e521fc-09bd-4d50-bc44-a190c482a1a5",
"card": null,
"type": "EWALLET",
"status": "EXPIRED",
"actions": [],
"country": "ID",
"created": "2023-05-31T08:17:40.084679Z",
"ewallet": {
"account": {
"name": null,
"balance": null,
"point_balance": null,
"account_details": null
},
"channel_code": "SHOPEEPAY",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff"
}
},
"qr_code": null,
"updated": "2023-05-31T08:18:13.355204166Z",
"metadata": null,
"business_id": "628db55f8378fa6f14db977f",
"customer_id": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": null,
"failure_code": null,
"reference_id": "6c8ad38e-2925-44c4-95af-35003298eefa",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"event": "payment_method.expired",
"created": "2023-05-31T08:18:13.587592978Z",
"business_id": "628db55f8378fa6f14db977f"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.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 with status EXPIRED |
Link and Pay Scenario
This flow simplifies checkout payments for guest users, especially for direct debit cases, while also offering the option for the end customer to save the payment method for future use.
Direct Debit Link and Pay
Initiate Link and Pay (Direct Debit)
This flow is ideal for situations where you want to offer a checkout payment option, allowing your customers to save it for future payments.
After making the following payment, the next task is to verify it using an OTP (One-Time Password). For this flow, you may need to use xendit hosted OTP given in action parameter in the response.
Once the payment sucessful, then the payment method status will be Active
means the account has be linked and you can use the payment method ID as tokenized payment for the subsequent payment. The tokenized payment details can be found in here
Endpoint: Create Payment Request
POST https://api.xendit.co/payment_requests
Create Payment Request Request
Example Create Payment Request Request
curl https://api.xendit.co/payment_requests -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 500,
"currency": "PHP",
"payment_method": {
"type": "DIRECT_DEBIT",
"direct_debit": {
"channel_code": "BPI",
"channel_properties": {
"success_return_url" : "https://redirect.me/goodstuff",
"failure_return_url" : "https://redirect.me/badstuff"
}
},
"reusability": "MULTIPLE_USE"
},
"customer_id": "cust-1e68806c-38d7-4109-b1cd-4f10ef4cf99b",
"description": "This is a description.",
"metadata": {
"foo": "bar"
}
}' \
Header | 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. 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 Payment Request 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. |
Parameter | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
amountrequired |
number |
Expected and accepted amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
reference_id optional |
string
|
Merchant-provided identifier for this payment request. If none is provided, Xendit will randomly generate a unique reference_id . Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer_id conditional |
string
|
ID of the customer object to which the account token will be linked to. Call Create Customer to generate Customer ID. A customer_id is required for all DIRECT_DEBIT payment methods and if the customer object is null. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
customer conditional |
object
|
A customer object to skip Create Customer URL endpoint process. This object only available if customer_id is null.The parameters to be set for the customer object
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
country optional |
string
|
2-letter ISO 3166-2 country code indicating country of transaction. Accepted values:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
description optional |
string
|
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
payment_methodconditional |
object |
Note: Only one of payment_method{} or payment_method_id must be present.Respective Payment Method properties that corresponds to the chosen payment method type or channel. The request will apply the top-most values for customer_id , currency , and amount .The parameters to be set for the payment method object
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
metadata optional |
object |
object A free-format JSON for additional information that you may use. Object can be up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. |
Create Payment Request Response
Example Create Payment Request Response
{
"id": "pr-8f9a5d3a-0f9f-47bf-8452-a4be9388b490",
"country": "PH",
"amount": 500,
"currency": "PHP",
"business_id": "6396e6d48c59c18ca0e55218",
"reference_id": "eeaf6501-dea4-4103-bb7e-8ee706ce04f6",
"payment_method": {
"id": "pm-02318afc-9810-4044-b8b4-d0eacb0a77a8",
"type": "DIRECT_DEBIT",
"reference_id": "54ee6999-a032-40c6-b731-dcc7f6d26040",
"description": null,
"created": "2023-07-16T22:38:13.474210828Z",
"updated": "2023-07-16T22:38:13.474210828Z",
"card": null,
"ewallet": null,
"direct_debit": {
"channel_code": "BPI",
"channel_properties": {
"success_return_url": "https://redirect.me/goodstuff",
"failure_return_url": "https://redirect.me/badstuff"
},
"type": "BANK_ACCOUNT",
"bank_account": {
"masked_bank_account_number": null,
"bank_account_hash": null
},
"debit_card": null
},
"direct_bank_transfer": null,
"over_the_counter": null,
"virtual_account": null,
"qr_code": null,
"metadata": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"province_state": null,
"street_line1": null,
"street_line2": null
},
"reusability": "MULTIPLE_USE",
"status": "PENDING"
},
"description": "This is a description.",
"metadata": {
"foo": "bar"
},
"customer_id": "cust-bf61e185-da02-4223-a594-5da05c45218e",
"capture_method": "AUTOMATIC",
"initiator": null,
"card_verification_results": null,
"created": "2023-07-16T22:38:13.231458108Z",
"updated": "2023-07-16T22:38:13.231458108Z",
"status": "REQUIRES_ACTION",
"actions": [
{
"action": "AUTH",
"url": "https://link-web-staging.xendit.co/oauth/lat-17702cc1-31c8-4791-b243-8699a3575146/confirm",
"url_type": "WEB",
"method": "GET",
"qr_code": null
}
],
"failure_code": null,
"channel_properties": null,
"shipping_information": null,
"items": null
}
A successful Payment Request creation returns a Payment Request Object with an HTTP 201
status code.
Listen to the payment.*
callbacks for the final status of the transaction.
Body Parameter | Type | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired |
string |
Unique identifier for the payment request. This has a prefix of pr- . Example: pr-6d1c8be4-f4d9-421c-9f0b-ab3b2b6bbc39 |
||||||||||
business_idrequired |
string |
Xendit-generated identifier for the business that owns the transaction | ||||||||||
customer_idnullable |
string |
ID of the customer object to which the account token will be linked to | ||||||||||
reference_idnullable |
string |
Identifier provided by the merchant or automatically generated by Xendit if it was not provided. Maximum length: 255 characters |
||||||||||
currencyrequired |
string |
ISO 4217 three-letter code of the transaction's currency. Will be auto-filled based on the channel_code if not provided. Possible values:
|
||||||||||
amountnullable |
number |
Authorized amount of the transaction in the actual value in the provided currency . Decimal places support varies per currency:
If amount is not provided, the corresponding payment method will accept any amount as payment (open amount). (Applicable only for OVER_THE_COUNTER and VIRTUAL_ACCOUNT ) |
||||||||||
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 ). |
||||||||||
statusrequired |
string |
Status of the payment method. Possible values:
| ||||||||||
descriptionnullable |
string |
Free-text field for any additional information regarding the payment method. Maximum length: 255 characters |
||||||||||
payment_methodrequired |
object |
Corresponding Payment Method created or used for the Payment Method. Note: customer_id , currency , and amount are moved to the root level of the Payment Request object. |
||||||||||
actionsrequired |
object array |
If status=REQUIRES_ACTION , this contains objects that detail the possible next steps in order to complete a payment. Only one of the provided actions is required to be fulfilled. If no further action is needed, this parameter will be an empty array [] . Each object will have the following properties:
|
||||||||||
failure_codenullable |
string |
If the status of the transaction is FAILED , this describes the reason for failure.Will be null if the transaction did not fail. See possible codes here. |
||||||||||
createdrequired |
string |
ISO 8601 Timestamp for Payment Request object creation. Timezone UTC+0 | ||||||||||
updatedrequired |
string |
ISO 8601 Timestamp for latest Payment Request object update. Timezone UTC+0 | ||||||||||
metadatanullable |
object |
User defined object with JSON properties and values passed in during Payment Request creation. |
Create Payment Request Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
CUSTOMER_NOT_FOUND_ERROR400 |
The provided customer_id does not exist. |
CUSTOMER_PAYMENT_METHOD_MISMATCHED400 |
Error due to the customer_id provided does not have access to the provided payment method information |
INVALID_ACCOUNT_DETAILS400 |
The provided details were rejected by the partner channel due to incorrect information. |
INVALID_PAYMENT_METHOD400 |
The provided payment_method_id has already expired or is inactive |
MAX_ACCOUNT_LINKING400 |
The direct debit account being attempted to be linked has reached the maximum linking allowed by the partner channel. |
PARTNER_CHANNEL_ERROR400 |
Error received from partner channel but no reasons provided |
INVALID_API_KEY401 |
API key format is invalid |
INVALID_MERCHANT_CREDENTIALS401 |
API key format is invalid |
CHANNEL_NOT_ACTIVATED403 |
Request failed because this specific payment channel has not been activated through Xendit. Please activate via Xendit dashboard or our customer service |
FEATURE_NOT_ACTIVATED403 |
A certain feature being accessed has not yet activated. Please reach out to our customer service for further assistance. |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
DUPLICATE_ERROR409 |
There's an already existing record with the provided details |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
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 provider will be notified to resolve this issue |
OTP_DELIVERY_ERROR 503 |
The partner channel has failed to send the OTP to the Customer |
PROCESSOR_ERROR 503 |
General system failure returned by the Card processor. Retry the request again after couple of minutes. |
INSUFFICIENT_BALANCE 400 |
Source of funds has insufficient balance to complete the transaction. |
MAX_AMOUNT_LIMIT_ERROR 400 |
The transaction amount exceeds the partner channel's set limits. |
FORBIDDEN 403 |
Provided API key does not have the correct permissions to perform the operation. |
Validate OTP Link and Pay
This endpoint only applies to BRI Direct Debit. This is used when an additional authorization (ex. OTP Validation) is required in order to successfully activate a payment method. This is equivalent to the POST - AUTH
action provided when a Payment Method has the status REQUIRES_ACTION
.
Endpoint: Account Linking - Authorize Payment Method
POST https://api.xendit.co/v2/payment_methods/:id/auth
Authorize Payment Method Request
Example Account Linking - Authorize Payment Method Request
curl https://api.xendit.co/v2/payment_methods/pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a/auth -X POST \
--user xnd_development_LoReMIPman+ZPGT+ZZ9b3ooF4w3Dn+R1k+LoReMIPman: \
--header 'Content-Type: application/json' \
--data-raw '{
"auth_code": "356443"
}' \
Header | Type | Description |
---|---|---|
idempotency-key optional |
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. 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 |
Path Parameter | Type | Description |
---|---|---|
id required |
string
|
Primary identifier for the Payment Method object. This starts with the prefix pm- . |
Request Body Parameter | Type | Description |
---|---|---|
auth_code required |
string
|
The authorization code or OTP inputted by the end-customer. |
Authorize Payment Method Response
Example Account Linking - Authorize Payment Method Success Response
{
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "ID",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "DEBIT_CARD",
"debit_card": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "email@email.com"
},
"bank_account": null,
"channel_code": "BRI",
"channel_properties": {
"mobile_number": "+62818555988",
"card_last_four": "8888",
"card_expiry": "06/24",
"email": "test.email@xendit.co"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null,
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Returns a Payment Method Object with an HTTP 200
status code.
Authorize Payment Method Errors
Error Code | Description |
---|---|
API_VALIDATION_ERROR 400 |
There is invalid input in one of the request fields or a required field was not filled out |
ACCOUNT_ACCESS_BLOCKED400 |
Access to the underlying account or card has been blocked by the partner channel or the issuer. |
EXPIRED_OTP_ERROR400 |
The provided auth_code has expired |
INVALID_OTP_ERROR400 |
The provided auth_code is incorrect |
MAX_OTP_ATTEMPTS_ERROR400 |
The maximum attempts allowed by the channel has been reached |
INVALID_API_KEY401 |
API key format is invalid |
REQUEST_FORBIDDEN_ERROR403 |
The API key is forbidden to perform this request |
FEATURE_NOT_SUPPORTED403 |
A certain feature being accessed is not supported |
DATA_NOT_FOUND404 |
The provided id did not match any of our records |
IDEMPOTENCY_ERROR409 |
The same Idempotency-key was provided with a different payload |
PAYMENT_METHOD_ALREADY_ACTIVE409 |
Cannot proceed because the payment method is already active or has been activated |
PAYMENT_METHOD_ALREADY_FAILED409 |
Cannot proceed because the payment method has failed authorization and cannot be retried |
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 |
Webhook Account Linking Activated for Direct Debit Link and Pay
This callback is triggered when a particular Payment Method has been successfully created and can be used for payments.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Activated Callback Payload
{
"event": "payment_method.activated",
"data": {
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"actions": [],
"country": "PH",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null
},
"created": "2022-08-12T13:30:59.074277334Z",
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
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 with status ACTIVE |
Webhook Account Linking Expired for Direct Debit Link and Pay
This callback is triggered when a particular Payment Method has expired and will be unusable for payment transactions.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Expired Callback Payload
{
"event": "payment_method.expired",
"data": {
"id": "pm-6ff0b6f2-f5de-457f-b08f-bc98fbae485a",
"card": null,
"type": "DIRECT_DEBIT",
"status": "EXPIRED",
"actions": [],
"country": "PH",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:58.908220358Z",
"metadata": null,
"customer_id": "e2878b4c-d57e-4a2c-922d-c0313c2800a3",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"failure_code": null,
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"billing_information": null,
"direct_bank_transfer": null
},
"created": "2022-08-12T13:30:59.074277334Z",
"business_id": "5f27a14a9bf05c73dd040bc8"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.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 with status EXPIRED |
Webhook Account Linking Failed for Direct Debit Link and Pay
This callback is triggered when a particular Payment Method has failed during authentication/authorization.
Note: Make sure that you have a callback URL registered in the Payment Method field in your Dashboard settings.
Callback Payload
Example: Payment Method Failed Callback Payload
{
"id": "pm-02aa112e-ac69-448a-bab9-0f216fc512d0",
"data": {
"id": "pm-02aa112e-ac69-448a-bab9-0f216fc512d0",
"card": null,
"type": "DIRECT_DEBIT",
"status": "FAILED",
"actions": [],
"country": "PH",
"created": "2023-08-10T10:48:38.600369Z",
"ewallet": null,
"qr_code": null,
"updated": "2023-08-10T10:48:50.389414006Z",
"metadata": null,
"business_id": "6396e6d48c59c18ca0e55218",
"customer_id": "cust-5d360bbb-3aa7-4cc0-8d8f-c9e58af2be81",
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": null,
"masked_bank_account_number": null
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://redirect.me/badstuff",
"success_return_url": "https://redirect.me/goodstuff"
}
},
"failure_code": "PAYMENT_METHOD_ALREADY_EXISTS",
"reference_id": "34d9cfd0-726a-40ef-be00-7f010e9b1a28",
"virtual_account": null,
"over_the_counter": null,
"billing_information": {
"city": null,
"country": "",
"postal_code": null,
"street_line1": null,
"street_line2": null,
"province_state": null
},
"direct_bank_transfer": null
},
"event": "payment_method.failed",
"created": "2023-08-10T10:48:50.5388319Z",
"business_id": "6396e6d48c59c18ca0e55218"
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment_method.failed |
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 with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
CHANNEL_UNAVAILABLE |
The partner channel cannot be reached or currently having a downtime |
DUPLICATE_ERROR |
There's an existing record of linking the same underlying account for the provided customer_id OR Virtual Account Number/Payment Code already exists |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_METHOD_ALREADY_EXISTS |
An active Payment Method with the same customer_id, channel_code for that merchant already exists. |
Webhook Payment Succeeded Direct Debit Link and Pay
Callback Payload
Example: Payment Succeeded Callback Payload
{
"event": "payment.succeeded",
"data": {
"id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"amount": 1000,
"status": "SUCCEEDED",
"country": "PH",
"created": "2022-08-12T13:30:40.9209Z",
"updated": "2022-08-12T13:30:58.729373Z",
"currency": "PHP",
"metadata": {
"sku": "ABCDEFGH"
},
"customer_id": "c832697e-a62d-46fa-a383-24930b155e81",
"reference_id": "25cfd0f9-baee-44ca-9a12-6debe03f3c22",
"payment_method": {
"id": "pm-951b1ad9-1fbb-4724-a744-8956ab6ed17f",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:40.221525Z",
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"direct_bank_transfer": null
},
"description": null,
"failure_code": null,
"payment_detail": null,
"channel_properties": null,
"payment_request_id": "pr-5b26cae1-545b-49e9-855e-f85128f3e705"
},
"created": "2022-08-12T13:30:58.986Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.succeeded |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status SUCCEEDED |
Webhook Payment Failed Direct Debit Link and Pay
This callback is sent when a pending EWALLET
, DIRECT_DEBIT
, or CARD
has failed.
Note: Make sure that you ONLY have a callback URL registered in the Payment Request
section in your Dashboard settings for payments. To prevent duplicate callbacks, DO NOT fill out product-specific sections.
Callback Payload
Example: Payment Failed Callback Payload
{
"event": "payment.failed",
"data": {
"id": "ddpy-3cd658ae-25b9-4659-aa36-596ae41a809f",
"amount": 1000,
"status": "FAILED",
"country": "PH",
"created": "2022-08-12T13:30:40.9209Z",
"updated": "2022-08-12T13:30:58.729373Z",
"currency": "PHP",
"metadata": {
"sku": "ABCDEFGH"
},
"customer_id": "c832697e-a62d-46fa-a383-24930b155e81",
"reference_id": "25cfd0f9-baee-44ca-9a12-6debe03f3c22",
"payment_method": {
"id": "pm-951b1ad9-1fbb-4724-a744-8956ab6ed17f",
"card": null,
"type": "DIRECT_DEBIT",
"status": "ACTIVE",
"created": "2022-08-12T13:30:26.579048Z",
"ewallet": null,
"qr_code": null,
"updated": "2022-08-12T13:30:40.221525Z",
"metadata": null,
"description": null,
"reusability": "MULTIPLE_USE",
"direct_debit": {
"type": "BANK_ACCOUNT",
"debit_card": null,
"bank_account": {
"bank_account_hash": "b4dfa99c9b60c77f2e3962b73c098945",
"masked_bank_account_number": "XXXXXX1234"
},
"channel_code": "BPI",
"channel_properties": {
"failure_return_url": "https://your-redirect-website.com/failure",
"success_return_url": "https://your-redirect-website.com/success"
}
},
"reference_id": "620b9df4-fe69-4bfd-b9d4-5cba6861db8a",
"virtual_account": null,
"over_the_counter": null,
"direct_bank_transfer": null
},
"description": null,
"failure_code": "INSUFFICIENT_BALANCE",
"payment_detail": null,
"channel_properties": null,
"payment_request_id": "pr-5b26cae1-545b-49e9-855e-f85128f3e705"
},
"created": "2022-08-12T13:30:58.986Z",
"business_id": "5f27a14a9bf05c73dd040bc8",
"api_version": null
}
Header Parameters
Header Parameter | Type | Description |
---|---|---|
x-callback-tokenrequired |
string |
Your Xendit unique callback token to verify the origin of the callback |
webhook-idrequired |
string |
A unique identifier of every webhook to help you to handle double callback 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 webhook |
Body Parameter | Type | Description |
---|---|---|
eventrequired |
string |
Identifies the event that triggered a notification to the merchant - payment.failed |
business_idrequired |
string |
Business ID of the merchant |
createdrequired |
string |
ISO 8601 Timestamp for callback notification creation. Timezone UTC+0. |
dataoptional |
object |
Payment Object with status FAILED . See the Failure Code table below to see the possible values of failure_code . |
Failure Code | Description |
---|---|
ACCOUNT_ACCESS_BLOCKED |
End customer bank account has been blocked, end user should contact the bank for resolution. |
ACCOUNT_NOT_ACTIVATED |
End-customer's account is not activated for payments. |
CHANNEL_UNAVAILABLE |
The partner channel cannot be reached or currently having a downtime |
CUSTOMER_UNREACHABLE |
The end-user's device cannot be reached at this moment by the partner channel |
DUPLICATE_ERROR |
There's an existing record of linking the same underlying account for the provided customer_id OR Virtual Account Number/Payment Code already exists |
INSUFFICIENT_BALANCE |
Source of funds has insufficient balance to complete the transaction |
INVALID_MERCHANT_CREDENTIALS |
Merchant credentials met with an error with the partner channel |
INVALID_PAYMENT_METHOD |
The provided payment method id has already expired or is inactive |
MAX_ACCOUNT_LINKING |
Partner channel blocked the linking because the underlying account has been linked to the maximum number allowed by the channel. |
MAX_AMOUNT_LIMIT_ERROR |
The transaction amount exceeds the partner channel's set limits |
MAX_OTP_ATTEMPTS_ERROR |
The maximum incorrect attempts allowed by the channel has been reached. |
PARTNER_CHANNEL_ERROR |
Error received from partner channel but no reasons provided |
SERVER_ERROR |
An unexpected error occured. Our team has been notified and will troubleshoot the issue. |
PAYMENT_METHOD_ALREADY_EXISTS |
An active Payment Method with the same customer_id, channel_code for that merchant already exists. |
PAYMENT_EXPIRED |
If you are using Xendit-hosted OTP page, end-user needs to input their OTP within 15 minutes or else the payment will be expired. You may need to create a new payment. |
PAYMENT_STATUS_FAILED |
Payment has failed with no further information from channel. You may need to check before retrying. Recommended to wait ~30 minutes before retrying unless given further instruction. |