This guide is for payment aggregators located outside India that want to collect payments from Indian buyers—individuals or businesses—on behalf of merchants located outside India.
Xflow currently supports collections only for invoices denominated in INR.
This guide explains how to collect payments through Xflow's hosted checkout using the following payment methods:
Support for bank transfers and direct API integrations for cards and UPI will be added in a future release.
Your merchants are represented as connected users on Xflow.
Before collecting payments for a connected user, you must:
The following information is currently required to enable Cards and UPI collections for a connected user:
Connected user onboarding is currently managed by Xflow's operations team. Submit the required information to support@xflowpay.com. After verifying the information, Xflow will create the connected user account and initiate its activation. APIs for connected user onboarding will be introduced in a future release.
Once the connected user is activated, you will receive its account ID.
Let's say the connected-user account ID is account_xxx_connected_user.
The parent account ID of the connected user is your Xflow account ID (let's say account_xxx_aggregator).
When making an API call on behalf of this connected user, include the following header in your request:
-H 'Xflow-Account: "account_xxx_connected_user"'
The Xflow-Account header identifies the connected user account for which the API call is being made.
The first step for receiving a payment is to create a Partner.
A Partner represents the payer, i.e. the connected user's customer in India who will make the payment using UPI or Cards. To create a Partner, you must create an account with type = partner.
You need the following basic information to create and activate a Partner. This information is used for regulatory reporting, screening, and verification.
PAN, i.e. Permanent Account Number will be required if we get a sanctions hit against the Partner.
You may or may not have all the information about the Partner at the time of creating the Partner. Both scenarios are covered below.
In this scenario, create the Partner account by passing the required information as shown below.
curl -L -X POST 'https://api.xflowpay.com/v1/accounts' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-H 'Content-Type: application/json' \
-d '{
"business_details": {
"legal_name": "Acme India Pvt Ltd",
"physical_address": {
"country": "IN",
"postal_code": "560025"
},
"type": "business"
},
"type": "partner"
}'
{
"address": "activated",
"business_details": {
"date_of_incorporation": null,
"dba": null,
"email": null,
"estimated_monthly_volume": null,
"ids": null,
"legal_name": "Acme India Pvt Ltd",
"merchant_category_code": null,
"merchant_size": null,
"physical_address": {
"city": null,
"country": "IN",
"line1": null,
"line2": null,
"postal_code": "560025",
"state": null
},
"product_category": null,
"product_description": null,
"type": "business",
"website": null
},
"capability": null,
"created": 1689499166,
"id": "account_xxx_partner",
"link": null,
"livemode": false,
"logo_id": null,
"metadata": null,
"nickname": null,
"object": "account",
"parent_account_id": "account_xxx_connected_user",
"purpose_code": null,
"status": "draft",
"sub_type": null,
"supporting_documentation": null,
"system_message": null,
"tos_acceptance": null,
"type": "partner"
}
Explaining some of the key fields above.
type: When you create a Partner, you are creating an account of type = partner.
business_details.legal_name: This is the legal name of your Partner. The legal name must match the Bill To entity on the invoice that you provide later.
business_details.type: This indicates whether the Partner is a business or an individual.
business_details.physical_address.country: This should be IN for Partners paying from India.
business_details.physical_address.postal_code: This is the postal code of the Partner’s registered address for businesses, or residential address for individuals.
business_details.ids.tax: This is the Partner’s PAN. PAN is conditionally required for screening and verification.
account.status: When the Partner account is first created, it is created in draft status.
Once the Partner is created, you must submit the Partner for activation.
curl -L -X POST 'https://api.xflowpay.com/v1/accounts/account_xxx_partner/activate' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-H 'Content-Type: application/json'
This will move the Partner account from draft to verifying status.
Calling the activate endpoint is equivalent to submitting the Partner information to Xflow for verification.
Xflow screens the Partner for sanctions and other regulatory checks.
In most cases, the Partner account will move from verifying to activated almost instantly.
Once the Partner is activated, you can initiate checkout for that Partner.
In some scenarios, Xflow may require the Partner’s PAN before activating the account.
In this case, the Partner account will move to input_required status.
When this happens, update the business_details.ids.tax field with the Partner’s PAN and call the activate endpoint again.
curl -L -X POST 'https://api.xflowpay.com/v1/accounts/account_xxx_partner' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-H 'Content-Type: application/json' \
-d '{
"business_details": {
"ids": {
"tax": "ABCDE1234F"
}
}
}'
Alternatively, you can initiate checkout and the Partner will be asked to provide their PAN during the checkout flow.
Once the Partner provides PAN, the account transitions to verifying and then eventually to activated.
In rare scenarios, if your Partner is a sanctioned entity or individual, the account will move to hold status.
You will not be able to receive payments from a Partner in hold status.
If you need to update Partner details while the account is still in draft status, use the Update Account API as shown below.
The below example updates the Partner's city from Bangalore to Mumbai.
You can optionally store any key-value pair in the metadata field to store additional information on an object.
curl -L -X POST 'https://api.xflowpay.com/v1/accounts/account_xxx_partner' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-H 'Content-Type: application/json' \
-d '{
"business_details": {
"physical_address": {
"city": "Mumbai"
},
},
"metadata": {
"change_log": "Changed city from Bangalore to Mumbai"
}
}'
Partner account status transitions are communicated over webhooks. Listen to account.status.* events, where status can include activated, input_required, or hold.
The legal name provided on the Partner account must match the Bill To Entity on the invoice that you provide later. If PAN is provided, the legal name on the Partner account should also match the name associated with the PAN.
If you do not have all the required Partner information, you can still create a Partner account with partial information or no information.
You can then initiate the checkout flow. In this scenario, Xflow will collect the required information from the Partner during checkout.
Xflow will also try to verify this information during the checkout flow. If verification is completed successfully, the Partner account will transition to activated. If the Partner is rejected due to sanctions or fraud screening, the account will transition to hold.
In most cases, the Partner may remain in verifying status during checkout and then transition to either activated or hold after the transaction is completed. The hold status is rare and applies only to sanctioned or fraudulent entities or individuals.
After you create the Partner account, save the account.id in your system and map it to your own customer ID.
When you initiate checkout for an existing Partner, reuse the same account.id instead of creating a new Partner account. This helps Xflow identify the Partner and avoids collecting the same information again during checkout.
Once you have created a Partner, the next step is to create a Receivable.
A Receivable represents the invoice that your Partner is paying for. In simple terms, it tells Xflow what the payment is for, how much needs to be collected, and which invoice the payment should be mapped to.
The Receivable currency must be INR.
To confirm a Receivable, you will need the following information:
account_id: The Xflow account ID of the Partner against whom the invoice is being raised, or who will make the payment.account.purpose_code[].You may or may not have all of this information before initiating the checkout flow. Both paths are explained below.
If you have all the information required to create the Receivable, follow the steps below.
First, upload the digital copy of the invoice using the Files API. The invoice must be a .jpeg, .pdf, or .png file.
curl -L -X POST 'https://api.xflowpay.com/v1/files' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-F file=@"sample_invoice.pdf" \
-F payload='{
"purpose": "finance_document"
}'
{
"created": 1675153265,
"file_name": "sample_invoice.pdf",
"id": "file_xxx_invoice",
"livemode": false,
"metadata": null,
"object": "file",
"purpose": "finance_document",
"size": 493117,
"type": "pdf",
"url": "https://api.xflowpay.com/v1/files/file_xxx_invoice/contents"
}
Once you have the file.id from the response, create the Receivable as shown below. The file ID is passed in invoice.document.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json' \
-d '{
"amount_maximum_reconcilable": "1000.00",
"currency": "INR",
"invoice": {
"amount": "1000.00",
"creation_date": "2022-08-02",
"currency": "INR",
"document": "file_xxx_invoice",
"due_date": "2022-10-02",
"reference_number": "INV-35/1"
},
"account_id": "account_xxx_partner",
"purpose_code": "S0101",
"transaction_type": "goods"
}'
{
"account_id": "account_xxx_partner",
"amount_locked": "0.00",
"amount_maximum_reconcilable": "1000.00",
"amount_reconcilable": "1000.00",
"amount_reconciled": "0.00",
"amount_reconciled_not_settled": "0.00",
"amount_settled_payouts": "0.00",
"created": 1666079293,
"currency": "INR",
"deposit_ids_amount_locked": [],
"description": null,
"hsn_code": null,
"id": "receivable_xxx",
"invoice": {
"amount": "1000.00",
"creation_date": "2022-08-02",
"currency": "INR",
"document": "file_xxx_invoice",
"due_date": "2022-10-02",
"reference_number": "INV-35/1"
},
"livemode": false,
"metadata": null,
"object": "receivable",
"purpose_code": "S0101",
"purpose_code_description":null,
"status": "draft",
"supporting_documentation": null,
"system_message": [],
"transaction_type": "goods"
}
In the above request:
account_id is the Xflow Partner account ID.invoice.document is the file ID returned by the Files API.invoice.reference_number is the invoice number.invoice.amount is the invoice amount.amount_maximum_reconcilable is the amount the connected user wants to collect from the payer.description is a short description of the invoice or payment obligation.purpose_code explains the commercial purpose of the payment.transaction_type identifies whether the transaction is for goods, services, or another supported category.currency must be INR.Ensure that amount_maximum_reconcilable, invoice.amount, and
checkout.amount(covererd later in this guide) are the same.
After creating the Receivable, you must confirm it. Confirming a Receivable submits it to Xflow for verification and changes the Receivable status to verifying.
Xflow verifies the Receivable online and, in most cases, transitions it to activated almost instantly. In rare scenarios, Xflow may require additional information from you. In such cases, the Receivable will move to input_required.
You can listen to receivable.status.* events to track status changes.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables/receivable_xxx/confirm' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-H 'Content-Type: application/json'
Once the Receivable is created, you can use the receivable.id to create the Checkout as shown in the next section.
The Receivable currency must be INR.
A Receivable remains in draft status until it is confirmed. You must confirm the Receivable before Xflow can verify and activate it.
Listen to receivable.status.* webhook events to track Receivable status changes such as verifying, activated, and input_required.
If you do not have the required information, you can create an empty Receivable against the Partner you created in the first step.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-H 'Content-Type: application/json' \
-d '{
"account_id": "account_xxx_partner"
}'
Once you have the receivable.id from the response, you can create the Checkout as shown in the next section.
At this stage, the Receivable is in draft status.
Once checkout is completed the Receivable will have been updated with the partner address and name.
You must update the receivable with all mandatory fields before Xflow can process the payment for you.
You can do this after your Partner completes the payment in the checkout flow.
Once you have created a Partner and a Receivable, the next step is to create a Checkout.
The Checkout is the payment experience that your Partner sees. It allows the Partner to choose how they want to pay. Currently, Xflow supports UPI and Cards on the hosted checkout.
The Checkout request should include the following fields:
amount: The amount to be collected from the Partner.currency: The currency of the Checkout. This must be INR.from.account_id: The Xflow account ID of the Partner.receivables[0].id: The Receivable against which the payment is being collected.payment_methods: The payment methods that should be shown to the Partner.redirect_url: The URL where the Partner should be redirected after completing or exiting the payment flow.metadata: Optional. You can use this to pass your internal order ID, transaction ID, or reference ID.Currently, a Checkout can be used for only one Receivable. This means each Checkout should be treated as a single-invoice, single-payment collection session.
To create a Checkout, call the Create Checkout API as shown below.
curl -L -X POST 'https://api.xflowpay.com/v1/checkouts' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-H 'Content-Type: application/json' \
-d '{
"amount": "1000.00",
"currency": "INR",
"from": {
"account_id": "account_xxx_partner"
},
"receivables": [
{
"id": "receivable_xxx"
}
],
"payment_methods": ["cards", "upi"],
"redirect_url": "https://merchant.example.com/payments/return",
"metadata": {
"order_id": "ORD-1001"
},
"type": "payment"
}'
Xflow will return a Checkout object.
{
"amount": "1000.00",
"created": 1682224000,
"currency": "INR",
"effective_transaction": null,
"expires_at": 1682225800,
"from": {
"account_id": "account_xxx_partner"
},
"gross_amount": "1000.00",
"id": "checkout_xxx",
"livemode": false,
"metadata": {
"order_id": "ORD-1001"
},
"object": "checkout",
"payment_methods": ["cards", "upi"],
"receivables": [
{
"id": "receivable_xxx"
}
],
"redirect_url": "https://merchant.example.com/payments/return",
"status": "initialized",
"to": {
"account_id": "account_xxx_connected_user"
},
"type": "payment"
}
Save the checkout.id in your system. You will need this ID to open the hosted checkout experience using the Xflow SDK, and to track the payment status later.
You should also map the checkout.id to your internal transaction ID or order ID.
The Checkout object is created in initialized status. The Partner can make one or more payment attempts during the checkout session.
The checkout session is valid for 30 minutes. After 30 minutes, the Checkout will move to a terminal state based on whether a payment attempt was completed or the session expired without payment.
To open the hosted checkout experience, complete the prerequisites below and then initialize the Xflow Checkout SDK.
You need to add the Checkout SDK to your website, and update your Content Security Policy.
Add the Xflow Checkout SDK script to your website.
<script src="https://assets.xflowpay.com/v1/checkout.js"></script>
Once the script is loaded, the Xflow object will be available on the browser window.
To render the Xflow hosted checkout inside your application, add the following Xflow domains to your Content Security Policy.
script-src: https://assets.xflowpay.com/
frame-src: https://checkout.xflowpay.com/
This allows your application to load the Xflow SDK and display the hosted checkout page.
Use the checkout.id returned by the Create Checkout API to initialize the Xflow SDK on your website.
const xflowSdk = new window.Xflow({
checkoutId: checkoutId,
onClose: closeHandler,
});
The onClose callback is optional. You can use it to handle cases where the Partner closes the hosted checkout modal before completing the payment.
To open the checkout experience, call:
xflowSdk.open();
This opens the Xflow hosted checkout, where the Partner can choose a payment method and complete the payment.
Once the payment is completed, the Partner will be redirected to the redirect_url that was provided while creating the Checkout.
On the redirected URL, Xflow will include the checkout.id as a query parameter. Use this ID to fetch the latest Checkout object using the Get Checkout API.
You should poll the Checkout object until the payment status reaches a terminal state. The latest payment status can be checked using effective_transaction.status.
Use this status to show the right experience to the Partner on your redirected page.
For example:
The redirect flow should be used only for the Partner-facing experience. For backend payment confirmation, reconciliation, and settlement workflows, rely on Xflow APIs and webhooks.
If you used an activated Receivable to create the Checkout, you can skip this step. If you created the Checkout using a draft Receivable, you must update and confirm the Receivable after the payment is completed.
Upload the invoice using the Files API as covered earlier in this guide. You will need the file.id returned by the Files API to update the Receivable.
Once the invoice has been uploaded, update the Receivable with the invoice and commercial details.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables/receivable_xxx' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-H 'Content-Type: application/json' \
-d '{
"amount_maximum_reconcilable": "1000.00",
"currency": "INR",
"invoice": {
"amount": "1000.00",
"creation_date": "2022-08-02",
"currency": "INR",
"document": "file_xxx_invoice",
"due_date": "2022-10-02",
"reference_number": "INV-35/1"
},
"purpose_code": "S0101",
"transaction_type": "goods"
}'
After you have updated all mandatory fields, confirm the Receivable using the Confirm Receivable API.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables/receivable_f0A_1666079293438_eDQAH_000/confirm' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json'
Confirming the Receivable tells Xflow that the invoice and commercial details are final and ready for reconciliation, settlement, and payout.
A Receivable cannot be edited after it has been confirmed.
Once Xflow receives settlement from card or UPI schemes, the activated Receivable is reconciled with the incoming funds.
After reconciliation, a Payout object is created in initialized status.
{
"amount": null,
"arrival_date": null,
"automatic": true,
"created": 1666160776,
"currency": "USD",
"id": "payout_xxx",
"livemode": true,
"metadata": null,
"object": "payout",
"payment_method": "global_wire",
"payment_method_details": null,
"payout_confirmation": null,
"statement_descriptor": "XFLOW PAYOUT F0A-1666160776922-J2uic-000",
"status": "initialized",
"to": {
"account_id": "account_xxx_aggregator",
"address_id": "address_xxx_aggregator"
},
"tracking_info": null,
"unique_transaction_reference": null
}
The value of the Payout object keeps increasing as more funds are received and reconciled.
For example, assume you are on a weekly payout cycle and your payout day is Monday. In this case, all successful transactions between Wednesday of the previous week and Tuesday of the current week are accumulated into a single Payout object.
On Wednesday, the Payout object is locked and moves to processing status. This is when Xflow submits the transactions to its banking partner for verification and processing.
Once all transactions are verified, the banking partner initiates the payout to your bank account on Monday. At this stage, the Payout object moves to settled status.
Payout timelines depend on your configured payout cycle and banking partner processing timelines.
The amount field on the Payout object represents the amount that will be paid out in your chosen payout currency.
To view the INR amount that contributed to the Payout, fetch the Payment object of type = payout linked to the Payout object.
You can do this by passing the Payout ID in the linked_id query parameter.
curl -L -X GET 'https://api.xflowpay.com/v1/payments?linked_id=payout_xxx' \
-H 'Authorization: Bearer sk_your_key'
On the Payment object, the INR amount is available in from.amount.
{
"created": 1666160776,
"fee_plan_id": "fee_plan_xxx",
"from": {
"amount": "830000.00",
"currency": "INR"
},
"id": "payment_xxx_payout",
"is_exchange_rate_applicable": true,
"linked_id": "payout_xxx",
"linked_object": "payout",
"linked_payments": [],
"linked_payments_file_id": "file_xxx_linked_payments_payout",
"livemode": true,
"object": "payment",
"payout_eligible_at": null,
"to": {
"amount": null,
"currency": null
},
"type": "payout"
}
Once the Payout moves to settled status and Xflow receives wire transfer confirmation from its banking partner, the amount field on the Payout object is updated.
At this point, an Exchange Rate object is attached to the Payment object of type = payout linked to the Payout object.
You can listen to the exchange_rate.created webhook event to know when the exchange rate has been created.
Use the Payment object of type = payout linked to the Payout object to track
the INR source amount and exchange rate details.
At Xflow, the underlying real world money movement is modelled via the Payment objects of different types.
You can understand which Partner payments contributed to a Payout by following the backward linking chain across Payment objects.
`payout` --> `transfer` (gives you the connected user) -->`funds_debit` (gives Receivable ID) --> `reconcile` (gives reconcile events).
You have already fetched the Payment object of type = payout linked to the Payout object.
This Payment object is backward linked to Payment objects of type = transfer.
The linked_payments_file_id field on the Payment object of type = payout contains a file with all the transfer Payment objects that contributed to the Payout.
curl -L -X GET 'https://api.xflowpay.com/v1/payments/payment_xxx_transfer' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
{
"created": 1666160776,
"fee_plan_id": "fee_plan_xxx",
"from": {
"amount": "830000.00",
"currency" : "INR"
},
"id": "payment_xxx_transfer",
"is_exchange_rate_applicable": false,
"linked_id": "transfer_xxx",
"linked_object": "transfer",
"linked_payments": [
{
"account_id": "account_xxx_connected_user",
"payment_id": "payment_xxx_funds_debit",
"payment_type": "funds_debit"
}
],
"linked_payments_file_id": null,
"livemode": true,
"object": "payment",
"payout_eligible_at": null,
"to": {
"amount": "830000.00",
"currency" : "INR"
},
"type": "transfer"
}
This transfer has top-level linked_object of type Transfer. From the Transfer object, you will get the connected user’s account (field: from.account_id).
Now let's focus on the linked_payments hash on the transfer payment.
You will see that the linked_payments.payment_id is of type funds_debit.
Since there is 1:1 relationship between transfer and funds_debit, the linkage is directly provided on the object itself.
Let’s fetch this funds_debit payment
curl -L -X GET 'https://api.xflowpay.com/v1/payments/payment_xxx_funds_debit' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
{
"created": 1666160776,
"fee_plan_id": "fee_plan_xxx",
"from": {
"amount": "830000.00",
"currency": "INR"
},
"id": "payment_xxx_funds_debit",
"is_exchange_rate_applicable": false,
"linked_id": "receivable_xxx",
"linked_object": "receivable",
"linked_payments": [
{
"account_id": "account_xxx_connected_user",
"payment_id": "payment_xxx_reconcile",
"payment_type": "reconcile"
}
],
"linked_payments_file_id": null,
"livemode": true,
"object": "payment",
"payout_eligible_at": null,
"to": {
"amount": "830000.00",
"currency": "INR"
},
"type": "funds_debit"
}
The linked_id on the funds_debit object will provide you the receivable that was reconciled.
This way, you will be able to get all the receivables that contributed to the payout.
Each funds_debit Payment object provides the Receivable ID in the linked_id field. Since each Receivable is linked to an invoice, you can use this chain to identify which invoices were paid and included in the Payout.
Before we explain the fees being charged at the transaction level, let's understand where the agreed upon fees are configured.
Your fees are configured on the FeePlan object.
There are 2 types of FeePlan objects associated with your account.
type = account_fees_passthrough : This FeePlan object holds the fees that will be applied on every transaction of your connected users. Think about this fee as a Collection fee which is payment method specific. Some payment methods may not have any collection fee. The fees are organised under the hash deposit on the feePlan object, and will be payment method specific. This FeePlan is inherited as-is on your connected user’s account for processing the transaction. The FeePlan on your connected user’s account is of type = account_fees. You cannot edit the FeePlans on your account or your connected user’s account.
type = account_fees : This FeePlan object holds the fees that will be applied while making payouts to you. In essence, these fees are charged per payout, and not per connected user transaction. This fee is called a Payout fee, and is configured under payout hash. The FeePlan cannot be edited.
Now, let’s look at understanding fees charged on your payout.
Collection fee: When a deposit received via card or UPI payment (or any payment method that carries a collection fee) is reconciled against a receivable, Payment of type = processing_fee is created. This payment is linked to Payment of type = reconcile. As explained earlier, Payment of type = reconcile is linked to Payment of type = funds_credit. The linked_object on reconcile payment is the Receivable (so you will know for which receivable the fee was charged), and the linked_object for funds_credit payment is Deposit object. The deposit object has the payment method (how the partner paid), and this should help you understand why a specific collection fee was charged on a receivable.
Payout fee: When your Payout goes into processing, we create a Payment of type = payout_fee which is linked to the Payment of type = payout whose linked Object is the Payout being made to you. The payout_fee will help you understand the fees being charged for your Payout.
In rare scenarios when our banking partner rejects a specific connected user transaction, we may adjust (reduce) your Payout Fee. Note that the collection fee is not adjusted or refunded because Xflow has already incurred the collection fee.
The exact fee values depends on your commercial agreement with Xflow.
The following example shows the structure of a FeePlan object. The fee arrays populated in the object depend on your commercial configuration.
{
"created": 1666077553,
"deposit": [],
"id": "fee_plan_xxx_aggregator",
"linked_id": "account_xxx_aggregator",
"linked_object": "account",
"livemode": true,
"metadata": null,
"object": "fee_plan",
"payout": [
{
"destination_currency": "*",
"fixed": "0.00",
"minimum": "0.00",
"source_currency": "*",
"variable": "0.00"
},
{
"destination_currency": "USD",
"fixed": "0.00",
"minimum": "50.00",
"source_currency": "INR",
"variable": "0.50"
}
],
"payout_fx": [],
"receivable_reconcile": [],
"status": "activated",
"transfer_fx": [],
"type": "account_fees",
"validity": {
"from": 1683072939,
"to": null
}
}
{
"created": 1666077553,
"deposit": [
{
"destination_currency": "*",
"payment_method": "*",
"variable": "2.00"
},
{
"destination_currency": "INR",
"payment_method": "cards",
"variable": "2.00"
},
{
"destination_currency": "INR",
"payment_method": "upi",
"variable": "1.00"
}
],
"id": "fee_plan_xxx_aggregator",
"linked_id": "account_xxx_aggregator",
"linked_object": "account",
"livemode": true,
"metadata": null,
"object": "fee_plan",
"payout": [],
"payout_fx": [],
"receivable_reconcile": [],
"status": "activated",
"transfer_fx": [],
"type": "account_fees_passthrough",
"validity": {
"from": 1683072939,
"to": null
}
}
This section is relevant only for goods transactions. You can skip this section if you are collecting payments for software or services transactions.
When a goods Receivable is reconciled, the supporting_documentation.status on the Receivable object moves to pending.
You must submit the required shipping document within 10 business days to complete regulatory requirements. This document can be an airway bill, bill of lading, or any other document that provides evidence of shipping.
Supporting documents are modeled as File objects. Create a File object as shown earlier in this guide, with file.purpose = transactional_document.
Once the File object is created, use the returned file.id to update the relevant Receivable.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables/receivable_xxx' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Xflow-Account: "account_xxx_connected_user"' \
-H 'Content-Type: application/json' \
-d '{
"supporting_documentation": {
"documents": [
{
"file_id": "file_xxx_shipping_document",
"reconcile_id": "payment_xxx_reconcile",
"type": "shipping"
}
]
}
}'
In the above request:
file_id is the ID of the File object created for the shipping document.reconcile_id is the ID of the Payment object of type = reconcile.type identifies the type of supporting document being submitted. For shipping documents, use shipping.Supporting documentation is required only for goods transactions.
For goods transactions, shipping documentation must be submitted within 10 business days after the Receivable is reconciled.
This integration guide is for direct merchants located outside India, who want to collect payments from Indian buyers (individuals and businesses) for their products or services located outside India. Please note that currently Xflow supports collections for only INR invoices.
In this integration guide, we will provide step by step instructions on collecting payments via a hosted checkout experience with two payment methods : (i) cards (ii) Unified Payments Interface or UPI.
The first step for receiving a payment is to create a Partner.
A Partner represents the payer, i.e. your customer in India who will make the payment using UPI or Cards. To create a Partner, you must create an account with type = partner.
You need the following basic information to create and activate a Partner. This information is used for regulatory reporting, screening, and verification.
PAN, i.e. Permanent Account Number will be required if we get a sanctions hit against the Partner.
You may or may not have all the information about your customer at the time of creating the Partner. Both scenarios are covered below.
In this scenario, create the Partner account by passing the required information as shown below.
curl -L -X POST 'https://api.xflowpay.com/v1/accounts' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json' \
-d '{
"business_details": {
"legal_name": "Acme India Pvt Ltd",
"physical_address": {
"country": "IN",
"postal_code": "560025"
},
"type": "business"
},
"type": "partner"
}'
{
"address": "activated",
"business_details": {
"date_of_incorporation": null,
"dba": null,
"email": null,
"estimated_monthly_volume": null,
"ids": null,
"legal_name": "Acme India Pvt Ltd",
"merchant_category_code": null,
"merchant_size": null,
"physical_address": {
"city": null,
"country": "IN",
"line1": null,
"line2": null,
"postal_code": "560025",
"state": null
},
"product_category": null,
"product_description": null,
"type": "business",
"website": null
},
"capability": null,
"created": 1689499166,
"id": "account_F0A_1689499166365_wvmFu_000",
"link": null,
"livemode": false,
"logo_id": null,
"metadata": null,
"nickname": null,
"object": "account",
"parent_account_id": null,
"purpose_code": null,
"status": "draft",
"sub_type": null,
"supporting_documentation": null,
"system_message": null,
"tos_acceptance": null,
"type": "partner"
}
Explaining some of the key fields above.
type: When you create a Partner, you are creating an account of type = partner.
business_details.legal_name: This is the legal name of your Partner. The legal name must match the Bill To entity on the invoice that you provide later.
business_details.type: This indicates whether the Partner is a business or an individual.
business_details.physical_address.country: This should be IN for Partners paying from India.
business_details.physical_address.postal_code: This is the postal code of the Partner’s registered address for businesses, or residential address for individuals.
business_details.ids.tax: This is the Partner’s PAN. PAN is conditionally required for screening and verification.
account.status: When the Partner account is first created, it is created in draft status.
Once the Partner is created, you must submit the Partner for activation.
curl -L -X POST 'https://api.xflowpay.com/v1/accounts/account_F0A_1689499166365_wvmFu_000/activate' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json'
{
"address": "activated",
"business_details": {
"date_of_incorporation": null,
"dba": null,
"email": null,
"estimated_monthly_volume": null,
"ids": null,
"legal_name": "Acme India Pvt Ltd",
"merchant_category_code": null,
"merchant_size": null,
"physical_address": {
"city": null,
"country": "IN",
"line1": null,
"line2": null,
"postal_code": "560025",
"state": null
},
"product_category": null,
"product_description": null,
"type": "business",
"website": null
},
"capability": null,
"created": 1689499166,
"id": "account_F0A_1689499166365_wvmFu_000",
"link": null,
"livemode": false,
"logo_id": null,
"metadata": null,
"nickname": null,
"object": "account",
"parent_account_id": "account_F0A_1689499162690_90FiL_000",
"purpose_code": null,
"status": "verifying",
"sub_type": null,
"supporting_documentation": null,
"system_message": null,
"tos_acceptance": null,
"type": "partner"
}
Calling the activate endpoint is equivalent to submitting the Partner information to Xflow for verification. Xflow screens the Partner for sanctions and other regulatory checks.
In most cases, the Partner account will move from verifying to activated almost instantly. Once the Partner is activated, you can initiate checkout for that Partner.
In some scenarios, Xflow may require the Partner’s PAN before activating the account. In this case, the Partner account will move to input_required status. When this happens, update the business_details.ids.tax field with the Partner’s PAN and call the activate endpoint again.
curl -L -X POST 'https://api.xflowpay.com/v1/accounts/account_F0A_1689499166365_wvmFu_000' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json' \
-d '{
"business_details": {
"ids": {
"tax": "ABCDE1234F"
}
}
}'
Alternatively, you can initiate checkout and your payer will be asked to provide their PAN during the checkout flow. Once the Partner provides PAN, the account transitions to verifying and then eventually to activated.
In rare scenarios, if your Partner is a sanctioned entity or individual, the account will move to hold status. You will not be able to receive payments from a Partner in hold status.
If you need to update Partner details while the account is still in draft status, use the Update Account API as shown below.
curl -L -X POST 'https://api.xflowpay.com/v1/accounts/account_F0A_1689499166365_wvmFu_000' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json' \
-d '{
"business_details": {
"product_description": "I am changing the description in draft state"
},
"metadata": {
"internal_name": "Acme India Pvt Ltd"
}
}'
Partner account status transitions are communicated over webhooks. Listen to account.status.* events, where status can include activated, input_required, or hold.
The legal name provided on the Partner account must match the Bill To entity on the invoice that you provide later. If PAN is provided, the legal name on the Partner account should also match the name associated with the PAN.
If you do not have all the required Partner information, you can still create a Partner account with partial information or no information.
You can then initiate the checkout flow. In this scenario, Xflow will collect the required information from the Partner during checkout.
Xflow will also try to verify this information during the checkout flow.If verification is completed successfully, the Partner account will transition to activated. If the Partner is rejected due to sanctions or fraud screening, the account will transition to hold.
In most cases, the Partner may remain in verifying status during checkout and then transition to either activated or hold after the transaction is completed. The hold status is rare and applies only to sanctioned or fraudulent entities or individuals.
After you create the Partner account, save the account.id in your system and map it to your own customer ID.
When you initiate checkout for an existing Partner, reuse the same account.id instead of creating a new Partner account. This helps Xflow identify the Partner and avoids collecting the same information again during checkout.
Once you have created a Partner, the next step is to create a Receivable.
A Receivable represents the invoice that your Partner is paying for. In simple terms, it tells Xflow what the payment is for, how much needs to be collected, and which invoice the payment should be mapped to.
The Receivable currency must be INR.
To confirm a Receivable, you will need the following information:
account_id: The Xflow account ID of the Partner against whom the invoice is being raised, or who will make the payment.account.purpose_code[].You may or may not have all of this information before initiating the checkout flow. Both paths are explained below.
If you do not have the required information, you can create an empty Receivable against the Partner you created in the first step.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json' \
-d '{
"account_id": "account_F0A_1689499166365_wvmFu_000"
}'
{
"account_id": "account_F0A_1689499166365_wvmFu_000",
"amount_locked": "0.00",
"amount_maximum_reconcilable": null,
"amount_reconcilable": null,
"amount_reconciled": "0.00",
"amount_reconciled_not_settled": "0.00",
"amount_settled_payouts": "0.00",
"created": 1666079293,
"currency": null,
"deposit_ids_amount_locked": [],
"description": null,
"hsn_code": null,
"id": "receivable_f0A_1666079293438_eDQAH_000",
"invoice": null,
"livemode": true,
"metadata": null,
"object": "receivable",
"purpose_code": null,
"purpose_code_description": null,
"status": "draft",
"supporting_documentation": null,
"system_message": [],
"transaction_type": null
}
Once you have the receivable.id from the response, you can create the Checkout as shown in the next section.
At this stage, the Receivable is in draft status. You must update it with all mandatory fields before Xflow can process the payment for you. You can do this after your Partner completes the payment in the checkout flow.
This is covered later in Update a Receivable.
If you have all the information required to create the Receivable, follow the steps below.
First, upload the digital copy of the invoice using the Files API. The invoice must be a .jpeg, .pdf, or .png file.
curl -L -X POST 'https://api.xflowpay.com/v1/files' \
-H 'Authorization: Bearer sk_your_key' \
-F file=@"sample_invoice.pdf" \
-F payload='{
"purpose": "finance_document"
}'
{
"created": 1675153265,
"file_name": "sample_invoice.pdf",
"id": "file_F0A_1675153265850_IREzx_000",
"livemode": false,
"metadata": null,
"object": "file",
"purpose": "finance_document",
"size": 493117,
"type": "pdf",
"url": "https://api.xflowpay.com/v1/files/file_F0A_1675153265850_IREzx_000/contents"
}
Once you have the file.id from the response, create the Receivable as shown below. The file ID is passed in invoice.document.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json' \
-d '{
"amount_maximum_reconcilable": "1000.00",
"currency": "INR",
"invoice": {
"amount": "1000.00",
"creation_date": "2022-08-02",
"currency": "INR",
"document": "file_F0A_1675153265850_IREzx_000",
"due_date": "2022-10-02",
"reference_number": "INV-35/1"
},
"account_id": "account_F0A_1689499166365_wvmFu_000",
"purpose_code": "S0101",
"transaction_type": "goods"
}'
{
"account_id": "account_F0A_1689499166365_wvmFu_000",
"amount_locked": "0.00",
"amount_maximum_reconcilable": "1000.00",
"amount_reconcilable": "1000.00",
"amount_reconciled": "0.00",
"amount_reconciled_not_settled": "0.00",
"amount_settled_payouts": "0.00",
"created": 1666079293,
"currency": "INR",
"deposit_ids_amount_locked": [],
"description": null,
"hsn_code": null,
"id": "receivable_f0A_1666261130393_wuH6k_000",
"invoice": {
"amount": "1000.00",
"creation_date": "2022-08-02",
"currency": "INR",
"document": "file_F0A_1675153265850_IREzx_000",
"due_date": "2022-10-02",
"reference_number": "INV-35/1"
},
"livemode": false,
"metadata": null,
"object": "receivable",
"purpose_code": "S0101",
"purpose_code_description": "Advance payment against imports made to countries other than Nepal and Bhutan.",
"status": "draft",
"supporting_documentation": null,
"system_message": [],
"transaction_type": "goods"
}
After creating the Receivable, you must confirm it. Confirming a Receivable submits it to Xflow for verification and changes the Receivable status to verifying.
Xflow verifies the Receivable online and, in most cases, transitions it to activated almost instantly. In rare scenarios, Xflow may require additional information from you. In such cases, the Receivable will move to input_required.
You can listen to receivable.status.* events to track status changes.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables/receivable_f0A_1666261130393_wuH6k_000/confirm' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json'
Once the Receivable is created, you can use the receivable.id to create the Checkout as shown in the next section.
The Receivable currency must be INR.
A Receivable remains in draft status until it is confirmed. You must confirm the Receivable before Xflow can verify and activate it.
Listen to receivable.status.* webhook events to track Receivable status changes such as verifying, activated, and input_required.
Once you have created a Partner and a Receivable, the next step is to create a Checkout.
The Checkout is the payment experience that your Partner sees. It allows the Partner to choose how they want to pay. Currently, Xflow supports UPI and Cards on the hosted checkout.
The Checkout request should include the following fields:
amount: The amount to be collected from the Partner.currency: The currency of the Checkout. This must be INR.from.account_id: The Xflow account ID of the Partner.receivables[0].id: The Receivable against which the payment is being collected.payment_methods: The payment methods that should be shown to the Partner.redirect_url: The URL where the Partner should be redirected after completing or exiting the payment flow.metadata: Optional. You can use this to pass your internal order ID, transaction ID, or reference ID.Currently, a Checkout can be used for only one Receivable. This means each Checkout should be treated as a single-invoice, single-payment collection session.
To create a Checkout, call the Create Checkout API as shown below.
curl -L -X POST 'https://api.xflowpay.com/v1/checkouts' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"currency": "INR",
"from": {
"account_id": "account_xxx"
},
"metadata": {"order_id": "ORD-1001"},
"payment_methods": [
"cards",
"upi"
],
"receivables": [
{ "id": "receivable_xxx" }
],
"redirect_url": "https://test.xflowpay.com/handle-redirect",
"type": "payment",
}'
Xflow will return a Checkout object.
{
"amount": "1000.00",
"created": 1682224000,
"currency": "INR",
"effective_transaction": null,
"expires_at": 1682225800,
"from": {
"account_id": "account_F0A_1689499166365_wvmFu_000"
},
"gross_amount": "1000.00",
"id": "checkout_f0A_1682224000000_abCDx_000",
"livemode": false,
"metadata": {
"order_id": "ORD-1001"
},
"object": "checkout",
"payment_methods": [
"cards",
"upi"
],
"receivables": [
{
"id": "receivable_xxx"
}
],
"redirect_url": "https://merchant.example.com/payments/return",
"status": "initialized",
"to": {
"account_id": "account_F0A_1689499162690_90FiL_000"
},
"type": "payment"
}
Save the checkout.id in your system. You will need this ID to open the hosted checkout experience using the Xflow SDK, and to track the payment status later.
You should also map the checkout.id to your internal transaction ID or order ID.
The Checkout object is created in initialized status. The Partner can make one or more payment attempts during the checkout session.
The checkout session is valid for 30 minutes. After 30 minutes, the Checkout will move to a terminal state based on whether a payment attempt was completed or the session expired without payment.
To open the hosted checkout experience, complete the prerequisites below and then initialize the Xflow Checkout SDK.
Add the Xflow Checkout SDK script to your frontend.
<script src="https://assets.xflowpay.com/v1/checkout.js"></script>
Once the script is loaded, the Xflow object will be available on the browser window.
To render the Xflow hosted checkout inside your application, add the following Xflow domains to your Content Security Policy.
script-src: https://assets.xflowpay.com/
frame-src: https://checkout.xflowpay.com/
This allows your application to load the Xflow SDK and display the hosted checkout page.
Use the checkout.id returned by the Create Checkout API to initialize the Xflow SDK on your frontend.
const xflowSdk = new window.Xflow({
checkoutId: checkoutId,
onClose: closeHandler
});
The onClose callback is optional. You can use it to handle cases where the Partner closes the hosted checkout modal before completing the payment.
To open the checkout experience, call:
xflowSdk.open();
This opens the Xflow hosted checkout, where the Partner can choose a payment method and complete the payment.
Once the payment is completed, the Partner will be redirected to the redirect_url that was provided while creating the Checkout.
On the redirected URL, Xflow will include the checkout.id as a query parameter. Use this ID to fetch the latest Checkout object using the Get Checkout API.
You should poll the Checkout object until the payment status reaches a terminal state. The latest payment status can be checked using effective_transaction.status.
Use this status to show the right experience to the Partner on your redirected page.
For example:
The redirect flow should be used only for the Partner-facing experience. For backend payment confirmation, reconciliation, and settlement workflows, rely on Xflow APIs and webhooks.
If you used an activated Receivable to create the Checkout, you can skip this step.
If you created the Checkout using a draft Receivable, you must update and confirm the Receivable after the payment is completed.
Upload the invoice using the Files API as covered earlier in Upload file.
Once the invoice has been uploaded, update the Receivable with the invoice and commercial details.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables/receivable_f0A_1666079293438_eDQAH_000' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json' \
-d '{
"account_id": "account_F0A_1689499166365_wvmFu_000",
"amount_maximum_reconcilable": "1000.00",
"currency": "INR",
"description": "Invoice FY 2022-23-038",
"invoice": {
"amount": "1000.00",
"creation_date": "2022-10-18",
"currency": "INR",
"document": "file_F0A_1666079283600_ffoLd_000",
"due_date": "2022-11-07",
"reference_number": "Invoice FY 2022-23-038"
},
"purpose_code": "S0102",
"transaction_type": "goods"
}'
In the above request:
account_id is the Xflow Partner account ID.invoice.document is the file ID returned by the Files API.invoice.reference_number is the invoice number.invoice.amount is the invoice amount.amount_maximum_reconcilable is the maximum amount that can be reconciled against this Receivable.description is a short description of the invoice or payment obligation.purpose_code explains the commercial purpose of the payment.transaction_type identifies whether the transaction is for goods, services, or another supported category.currency must be INR.Ensure that amount_maximum_reconcilable, invoice.amount, and checkout.amount are the same.
After you have updated all mandatory fields, confirm the Receivable using the Confirm Receivable API.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables/receivable_f0A_1666079293438_eDQAH_000/confirm' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json'
Confirming the Receivable tells Xflow that the invoice and commercial details are final and ready for reconciliation, settlement, and payout.
A Receivable cannot be edited after it has been confirmed.
Once Xflow receives settlement from card or UPI schemes, the activated Receivable is reconciled with the incoming funds.
After reconciliation, a Payout object is created in initialized status.
{
"amount": null,
"arrival_date": null,
"automatic": true,
"created": 1666160776,
"currency": "USD",
"id": "payout_f0A_1666160776922_Q1hjW_000",
"livemode": true,
"metadata": null,
"object": "payout",
"payment_method": "global_wire",
"payment_method_details": null,
"payout_confirmation": null,
"statement_descriptor": "XFLOW PAYOUT F0A-1666160776922-J2uic-000",
"status": "initialized",
"to": {
"account_id": "account_F0A_1666077553446_41Hgq_000",
"address_id": "address_f0A_1666160723235_fJSRH_000"
},
"tracking_info": null,
"unique_transaction_reference": null
}
The value of the Payout object keeps increasing as more funds are received and reconciled.
For example, assume you are on a weekly payout cycle and your payout day is Monday. In this case, all successful transactions between Wednesday of the previous week and Tuesday of the current week are accumulated into a single Payout object.
On Wednesday, the Payout object is locked and moves to processing status. This is when Xflow submits the transactions to its banking partner for verification and processing.
Once all transactions are verified, the banking partner initiates the payout to your bank account on Monday. At this stage, the Payout object moves to settled status.
Payout timelines depend on your configured payout cycle and banking partner processing timelines.
The amount field on the Payout object represents the amount that will be paid out in your chosen payout currency.
To view the INR amount that contributed to the Payout, fetch the Payment object of type = payout linked to the Payout object.
You can do this by passing the Payout ID in the linked_id query parameter.
curl -L -X GET 'https://api.xflowpay.com/v1/payments?linked_id=payout_f0A_1666160776922_Q1hjW_000' \
-H 'Authorization: Bearer sk_your_key'
On the Payment object, the INR amount is available in from.amount.
{
"created": 1666160776,
"fee_plan_id": "fee_plan_F0A_1666077553446_a8sn4_000",
"from": {
"amount": "830000.00",
"currency": "INR"
},
"id": "payment_f0A_1666160776922_DkBou_000",
"is_exchange_rate_applicable": true,
"linked_id": "payout_f0A_1666160776922_Q1hjW_000",
"linked_object": "payout",
"linked_payments": [],
"linked_payments_file_id": "file_F0A_1666078140654_lQm8l_000",
"livemode": true,
"object": "payment",
"payout_eligible_at": null,
"to": {
"amount": null,
"currency": null
},
"type": "payout"
}
Once the Payout moves to settled status and Xflow receives wire transfer confirmation from its banking partner, the amount field on the Payout object is updated.
At this point, an Exchange Rate object is attached to the Payment object of type = payout linked to the Payout object.
You can listen to the exchange_rate.created webhook event to know when the exchange rate has been created.
Use the Payment object of type = payout linked to the Payout object to track the INR source amount and exchange rate details.
You can understand which Partner payments contributed to a Payout by following the backward linking chain across Payment objects.
payout → funds_debit → reconcile → funds_credit
The logical money movement can be understood as follows:
payout: Linked to the Payout object.funds_debit: Linked to the Receivable.reconcile: Linked to the Receivable.funds_credit: Linked to the Deposit.You have already fetched the Payment object of type = payout linked to the Payout object.
This Payment object is backward linked to Payment objects of type = funds_debit. The linked_payments_file_id field on the Payment object of type = payout contains a file with all the funds_debit Payment objects that contributed to the Payout.
Each funds_debit Payment object provides the Receivable ID in the linked_id field. Since each Receivable is linked to an invoice, you can use this chain to identify which invoices were paid and included in the Payout.
Fees depend on the pricing plan configured for you by Xflow’s sales team.
In general, card and UPI collection fees are charged when your Receivable is reconciled with incoming funds.
These fees are attached to the Payment object of type = reconcile.
You can use the backward linking chain explained above to identify the relevant reconcile Payment object.
Once you have the id of reconcile payment, search for Payment object of type = processing_fee with linked_payment as the reconcile payment
Fees depend on the pricing plan configured for you by Xflow’s sales team.
The exact fee structure depends on your commercial agreement with Xflow.
This section is relevant only for goods transactions.
You can skip this section if you are collecting payments for software or services transactions.
When a goods Receivable is reconciled, the supporting_documentation.status on the Receivable object moves to pending.
You must submit the required shipping document within 10 business days to complete regulatory requirements. This document can be an airway bill, bill of lading, or any other document that provides evidence of shipping.
Supporting documents are modeled as File objects. Create a File object as shown earlier in this guide, with file.purpose = transactional_document.
Once the File object is created, use the returned file.id to update the relevant Receivable.
curl -L -X POST 'https://api.xflowpay.com/v1/receivables/receivable_f0A_1727427046725_mjXJy_000' \
-H 'Authorization: Bearer sk_your_key' \
-H 'Content-Type: application/json' \
-d '{
"supporting_documentation": {
"documents": [
{
"file_id": "file_F0A_1666078140654_lQm8l_000",
"reconcile_id": "payment_f0A_1666160779999_PQCou_000",
"type": "shipping"
}
]
}
}'
In the above request:
file_id is the ID of the File object created for the shipping document.reconcile_id is the ID of the Payment object of type = reconcile.type identifies the type of supporting document being submitted. For shipping documents, use shipping.Supporting documentation is required only for goods transactions.
For goods transactions, shipping documentation must be submitted within 10 business days after the Receivable is reconciled.
You can use test mode to test your checkout integration before moving real money.
Test mode works like live mode, but no actual payment is processed and no real funds are moved. This allows you to safely check whether your integration is working as expected before you go live.
If your checkout flow works correctly in test mode, you can be confident that the same flow will work in live mode once you enable real payments.
Data from test mode is not carried over to live mode. Use test mode to validate the full checkout flow, including checkout creation, hosted checkout rendering, payment status handling, redirection, and webhook processing.
In test mode, the hosted checkout page shows options to simulate different payment outcomes.
You can use these options to test scenarios such as:
This allows you to verify how your integration handles both successful and unsuccessful checkout attempts.