With UPI, funds can be transferred instantly to any bank account through NPCI's real-time payment system. Collect DeepLinks, which conform to NPCI specifications, allow merchants to enable their customers to directly access UPI apps with prefilled payment information.

#Who is a Merchant?

A merchant, in this context, refers to any business aiming to receive payments for goods or services provided to customers using UPI DeepLinks.

#What can I do with this product?

Generate deep links that work across all supported UPI apps and provide payment details. Any UPI app, such as PhonePe or GPay, can be used by your customers to make payments.

Share the payment link anywhere—WhatsApp, SMS, as QR codes, or as part of reminders and push notifications.

Time to integrate: 2 hours to 2 days.

Time to go live: 1 to 14 days.


#How it works

  • (Website Name) receives payment details from the Merchant and sends a unique payment link to the Customer.
  • A Customer clicks the payment link, chooses preferred UPI app and enters mPIN to make a successful payment.
  • Upon successful payment, (Website Name) triggers a webhook notification, which the merchant can use to update the transaction status.
  • (Website Name) settles the amount to the Merchant according to the settlement timeline configured.

Was this page helpful?

#UPI Quickstart

If you haven't already done so, sign up on The Bridge, if you haven’t already. This is where you can create product configurations and add configuration details. Read more on this here and watch this quick video on how to create a test merchant configuration.

You will also find some other details below that will help you get started. We will reach out to you if you encounter any issues.


API URLs
  • Sandbox https://uat.(Website Name).co/api
  • Production https://prod.(Website Name).co/api

Please note that if you are using **OAuth** as your preferred authentication method, the API URL will need to be updated. The sandbox URL would becomehttps://uat.(Website Name).co/api/v2 https://uat.(Website Name).co/api/v2https://prod.(Website Name).co/api/v2


Header

These will be applicable to all APIs you call, unless specified otherwise—

  • X-(Website Name)-Product-Instance-ID—this is a unique identifier for your merchant configuration set up on the Bridge. Look for the “Merchant ID” on the top left, inside your merchant configuration.
  • authorization—Bearer <insert_token_here>. Generate this token using OAuth or JWT.
  • Content-Type—will be application/json. This will not be present in the header for Check link status API.

List of APIs
  • Create UPI payment link
  • Add credit (mock a payment in Sandbox)
  • Get notified via webhook (by exposing an endpoint)
  • Check link status (optional)
  • Expire Bill (optional)
API Name Path HTTP Method Authentication API documentation
Create payment link /payment-links POST OAuth or JWT Read
Add credit /triggers/funds/addCredit POST OAuth or JWT Read
Get notified via webhook <merchants-callback-URL>/notifications POST As set by merchant Read
Check link status /payment-links/<platformBillId> GET OAuth or JWT Read
Expire bill /utilities/bills/<platformBillId>/expire POST OAuth or JWT Read
Create refund /refund/batch POST OAuth or JWT Read
Check batch or individual refund status /refund/:batchID or /refund/:refundID GET OAuth or JWT Batch refund,

Individual refund

#Start integration

Step 1 — Create a merchant configuration

See this quick video on how to create a merchant configuration on The Bridge Sandbox.


Step 2 — Add configuration details

Under the “Configuration” tab—

Add URL endpoint

callbackURL—used by (Website Name) to send payment and settlement notifications. Read more about notifications if you want to implement this..

Please note, Website Name will add /notifications at the end of this URL.


Configure authentication details as per your preference to expose callbackURL. If needed, add details about The Bridge and contact (Website Name)'s team. Depending on your needs, you can also add multiple callback URLs.

Add settlement account(s)

A settlement account has to be added to allow mock settlements while making test transactions. Any dummy value could be added here

Any changes to the Production configuration require approval from a (Website Name) admin. The changes will not go live until they are approved. This maker-checker process exists to ensure that there are no accidental updates to the configurations of live products.


#Guide to using all APIs

Create a UPI payment link
Method POST
Path /payment-links
Header X-(Website Name)-Product-Instance-ID

Authorization: Bearer <insert_token_here>. Generate this token using OAuth or JWT.

Content-Type—will be application/json
Sample request

Let’s create a payment link for INR 100. This is what the request and response would look like.

{
"billerBillID":"EB-1123-345324",
"amount":{
"value":10000,
"currencyCode":"INR"
},
"amountExactness":"EXACT",//ENUM values—EXACT | EXACT_DOWN | ANY
"name":"Merchant name",//specify this optionallly
"transactionNote":"Payment for ABC bill",//optional
"additionalInfo":{
"UUID":"b6b6f173-8649-4b2e-9c22-f78e9195a23e",
"tags":"electricity"
}
}

In the above request:

  • billerBillID is an identifier for this link in merchant’s system which they will later look up or reconcile against.
  • amount.value is the value in paise of the amount needed to be collected from the user, expressed as data type integer
  • amount.currencyCode would always be INR.
  • amountExactness allows flexibility in the amount being paid by the customer, as per merchant specification.
    • Specifying EXACT will allow your customer to pay only the exact amount specified by you in the create link API.
    • Specifying ANY will simply allow your customer to pay any amount above INR 1.
    • Specifying EXACT_DOWN will only allow the paid amount to be more than INR 1 and less than the amount specified in the Create bill API.

Note that UPI does not recognise a “maximum allowed amount” and any payment value above INR 1 will be successful with EXACT_DOWN.

However, paying more than the amount specified in the Create bill API will fail (Website Name)’s validation, and will be refunded to your customer.Validations below.

amountExactness is not honoured consistently across UPI apps. As explained above, failure against the amountExactness logic on (Website Name) may cause a successful payment to trigger a refund for the customer. Hence, we recommend setting EXACT for amountExactness, for higher predictability.


  • Thename parameter is optional and allows you to specify the payee's name during payment, with the default being the merchant's name set up on the Bridge.
  • FortransactionNote, an optional parameter, you can set a message for UPI payments made by customers. The default transaction note is "Payment for {your billerBillID}”.
  • additionalInfo an optional object, enables you to pass key-value pairs that (Website Name) will include in the payment successful notification. This feature is useful for defining details not received in the notification.

The request for link generation is flexible, accommodating various use cases. Refer to the API documentation for details on all parameters. here.

Validations

You may additionally set up checks for transaction to be considered successful.

Validations can be set for successful transactions. Two supported types are:

  • Amount based check—Specify an acceptable payment amount range using the AMOUNT_EXACTNESS condition explained above.
  • Source account check—Set a flag during integration to specify an expected bank account for customer payments. If chosen, mention the expected bank account in thesourceAccounts object as part of the Create payment link API.

Refunds for unmet validations are detailed in our documentation.

Sample response
{
"status":200,
"success":true,
"data":{
"name":"Test Link generator",
"paymentLink":{
"shortURL":"https://bills.pe/yH9c9",
"upiID":"test464618891939677612@kaypay",
"upiLink":"upi://pay?pa=test464618891939677612@kaypay&pn=Test+Link+generator&am=100.00&tr=EB-1123-345324&tn=Payment+for+EB-1123-345324&cu=INR"
},
"platformBillID":"464618891939677612"
}
}

In the above response:

  • shortURLis directly shareable with customers through a communication channel.
  • upiLink can be used as an Android button target (what is typically known as an intent trigger) or to generate a QR code that can be scanned with any UPI enabled app.
  • WhileupiID is generally unnecessary, a merchant might resort to sharing this ID directly with the customer as a last option if neither of the two methods mentioned above proves effective. However, note that the user experience for this method may not be optimal.
  • platformBillID is a unique identifier linked to the generated link, allowing for later tracking purposes.

Add credit (mock a payment in Sandbox)

A mock payment against a link can be triggered to recreate a successful payment by a customer.

(Website Name) recommends using this via Postman and to not waste resources on integrating this in code, unless there is a specific requirement to do so (such as automations and tests at your end).


Method POST
Path /triggers/funds/addCredit
Header X-(Website Name)-Product-Instance-ID

Authorization: Bearer <insert_token_here>. Generate this token using OAuth or JWT.

Content-Type—will be application/json
Sample request
{
"amount":100,
"type":"UPI",
"destinationAccount":{
"accountID":"test464618891939677612@kaypay"
},
"sourceAccount":{
"accountID":"dummy_customer@vpa"
},
"transactionReference":"464618891939677612"
}

In the above request:

  • amount is the value in rupees of the amount the link was generated for, expressed as data type float or double
  • destinationAccount.accountID is the upiID generated above.
  • sourceAccount.accountID is the VPA from which the payment is made - any dummy value can be used here, which is in a valid VPA format.
  • transactionReference is the platformBillID from the Create Link response.

The response would simply be 200 OK without any body.


Get notified via webhook

When a customer makes a successful payment (or mocks a payment), (Website Name) triggers a near-realtime notification via webhooks (also referred to as callback).

For this to work, (Website Name) expects the merchant to expose an API endpoint URL ending in /notifications. Once this URL is configured on (Website Name), the merchant starts receiving notifications.

Sample notification
{
"partnerDetails":{
"appID":"string",// your unique app ID in Website Name system, this is constant
"productInstanceID":"string"// your unique product instance ID in Website Name system, this is constant
},
"events":[
{
"data":{
"amountPaid":{// amount paid by the user in paisa
"currencyCode":"INR",
"value":10000
},
"billerBillID":"EB-1123-345324",// same as the billerBillID set by you when creating the link
"platformBillID":"string",// same as the platformBillID received by you when creating the link
"amountExactness":"EXACT",
"additionalInfo":{// same as values defined when creating the link
"UUID":"b6b6f173-8649-4b2e-9c22-f78e9195a23e",
"tags":"electricity"
},
"status":"PAYMENT_SUCCESSFUL",
"payerVpa":"string",
"transactionId":"string",
},
"timeStamp":1595325201265,
"type":"BILL_FULFILMENT_STATUS",
"id":"fc4d3128-b6f4-46a5-8275-f5c05e0025b4"
}
]
}

In the above request:

  • partnerDetails are unique IDs corresponding to the merchant.
  • events is an array of events, which will usually contain only a single event.
  • events.type is the event type - where the relevant type would beBILL_FULFILMENT_STATUS.
  • events.timestamp is the epoch timestamp of the event.
  • events.id is unique callback ID for every event, used for logging, debugging and tracking.

The response should simply be 200 OK without any body.


Check link status (optional)

This API does a status check on payment done against a link. It should not be used for polling but only for specific use cases.

For example, if someone waiting for a customer to pay within 5 minutes (300 seconds) doesn’t receive a callback within that time—they can use this API to check payment status and mark link as “invalid”, so that it is not used again.

Method GET
Path /payment-links/<platformBillId>

The request should simply be the API URL with platformBillID appended to the path appropriately <base_url>/payment-links/<platformBillId>. Read more.
Header X-(Website Name)-Product-Instance-ID

Authorization: Bearer <insert_token_here>. Generate this token using OAuth or JWT.
Sample response
{
"status":200,
"success":true,
"data":{
"amountPaid":{
"currencyCode":"INR",
"value":100
},
"createdAt":"2020-09-17T11:21:25.000Z",
"expiresAt":"2020-10-17T11:21:25.000Z",
"name":"test-bill",
"payerVpa":"ramesh@okaxis",
"paymentLink":{
"upiID":"test456457682191123757@kaypay",
"upiLink":"upi://pay?pa=test456457682191123757@kaypay&pn=test-bill&am=1.00&tr=test-bill-1&tn=Payment+for+test-bill-1&cu=INR"
},
"platformBillID":"string",
"billerBillID":"string",
"receipt":{
"date":"2020-09-17T05:52:04.587Z",
"id":"04abb833-2e83-4960-bd69-4000a0ea48eb"
},
"status":"PAYMENT_SUCCESSFUL",
"additionalInfo":{
"UUID":"a48f0c3f-1b50-40a9-9506-d775b9f9f5d9"
}
}
}

In the above response:

  • amountPaid.value is the amount paid by the customer in paise.

  • createdAt and expiresAt represent the link creation and validity timestamps, respectively. The validity is set to 45 days 0 hours (meaning the time will be same as for link creation) by default, but can be customised.

  • paymentLink contains the same info as in Create UPI payment link API’s response.

  • status represents the status of the link.

    Status Meaning
    BILL_CREATED The UPI link is created.
    PAYMENT_SUCCESSFUL User has made a successful payment.
    PAYMENT_FAILED User has made a payment but it failed due to some validation reasons or bank side issue (rare scenario).
    CREDIT_RECEIVED The money is received by (Website Name).
    SETTLEMENT_SUCCESSFUL The money is settled to merchant account.
    SETTLEMENT_FAILED The attempt to settle money to merchant account has failed - generally we would either resolve this internally with next batch of settlement or reach out to you in case there is some additional info required.
    BILL_EXPIRED The UPI link has expired either by the default timeline or the timeline set by customer.
  • A UPI link can take multiple paths depending on the success and failure at different steps. Accordingly, the status journeys of a UPI link can be mapped as follows.

    • An ideal status flow (where user pays successfully and money is settled to merchant account) for a UPI payment link is: BILL_CREATED > PAYMENT_SUCCESSFUL > CREDIT_RECEIVED > SETTLEMENT_SUCCESSFUL

    • In case a user doesn't pay or the payment is unsuccessful due to any reason between user's UPI app and user's bank: BILL_CREATED > BILL_EXPIRED

    • In case payment fails due to an error on (Website Name) (such as amount validation):BILL_CREATED > PAYMENT_FAILED

    • In case of settlement related issues: BILL_CREATED > PAYMENT_SUCCESSFUL > CREDIT_RECEIVED > SETTLEMENT_FAILED


Expire Bill (optional)

Use the expire bill API to assign the BILL_EXPIRED status to the bill associated with your link. An expiry here refers to 2 things:

  • Setting the bill state to BILL_EXPIRED in (Website Name)'s system
  • Expiring the shortlink associated with the bill

platformBillID is a unique identifier for a bill on (Website Name)'s system and has to be provided to expire the bill. This is made available in the Create Payment Link API's response.

Method POST
Path /utilities/bills/<platformBillId>/expire
Header X-(Website Name)-Product-Instance-ID

Authorization: Bearer <insert_token_here>. Generate this token using OAuth or JWT.

Content-Type—will be application/json
Success
{
"status":200,
"success":true
}
Failure

In case the platformBillID provided is incorrect, (Website Name) will respond with 404 resource not found error—

{
status:404,
success:false,
error:{
code:"bill-not-found",
title:"Bill not found",
detail:"Provided billId not found. Please re-check the billId.",
docUrl:"",
traceId:"XXXX"
}
}

If a bill has expired, a payment by a customer should not be allowed if a payment app returns an error.

However, if the customer makes a payment without making the verify VPA call, the payment will go through but be refunded.


Create refund and check refund status (optional)

You can initiate refunds yourself or set validations to automate them by visiting the Refunds page



Was this page helpful?

#Go Live

The Bridge Sandbox environment allows you to test your integration with sample transactions before going live and accepting actual payments.

In case you face an issue with any of the following steps, raise a support ticket and our team will reach out to you.


#Step 1 — Create configuration on Production

This quick video shows how to create a Merchant configuration on The Bridge's Production environment. You can also copy your Sandbox configuration to Production. See video reference.


#Step 2 — Add configuration details

Click on the “Configuration” tab. Here are the details needed—

  • If you wish to receive settlement notifications from (Website Name), provide the callbackURL.
  • Details of the settlement account to which your customers' payments will be deposited.

Note that you cannot edit the account number and IFSC code once your account has been marked as CERTIFIED.


#Step 3 — Add KYC details

Click on the “KYC” tab to see the list of details you need to add.

Depending on your business category, our team may also contact you separately to collect a few more details.


#Step 4 — Submit for review

Navigate to the "Review" tab and select "Submit for review." (Website Name)'s Admin team will verify the details you've provided and conduct integration testing before your system goes live. Upon approval, you'll receive notification from our team, and the "Review" tab will show the message, "Your latest configuration is live in production," with the configuration status changing to "LIVE." Transactions will be visible once your customers make payments using the links you've generated.


A note on editing configuration after having gone live

You can make modifications to the configuration and re-submit by selecting "Submit for review" again. Upon submission, you'll receive a confirmation stating, "You have submitted for review," and the revised details will be displayed on the "Review" tab.

Expect (Website Name) admin to review your configuration within 2-3 days after submission. Upon successful review, the new configuration details will be activated in production, and the "Review" tab will display the message, "Your latest configuration is live in production."

Until (Website Name) approves the new details, your older configuration will remain functional.


How to access reports for live transactions and settlements

See this quick video to see and download reports.

You should switch to the Production environment to view transactions against LIVE configurations.


Also, you can opt to use our Reports APIs to get available transaction and settlement data, which gives you more flexibility in consuming the data.

Was this page helpful?

#Third party verification (TPV)

A merchant can use TPV to validate the account from which a customer makes a payment. Use cases include paying for mutual funds, stocks etc., where regulation mandates that the customer has to make payment only from their own account.

TPV validates the source account ifsc and account number against the values provided by the merchant.


TPV is an additional service provided by (Website Name) and is enabled only upon request by the merchant.


TPV can be done in two ways—

  • TPV check by (Website Name)
  • TPV check by merchant

#TPV check by (Website Name)

The merchant must provide the ifsc and the account number when creating the payment link for (Website Name) to perform TPV.

When the customer makes the payment, (Website Name) checks the source account IFSC and account number In the event that they do not match, then the transaction is marked as PAYMENT_FAILED, with reason as TPV check failed and the amount will be refunded in the next settlement cycle.

Payments links created with TPV check are charged for both TPV successful and TPV failed cases.


Creating a payment link with TPV check by (Website Name)
Method POST
Path /payment-links
Header X-(Website Name)-Product-Instance-ID

Authorization: Bearer <insert_token_here>. Generate this token using OAuth or JWT.

Content-Type—will be application/json
Sample request
{
"amount":{
"currencyCode":"INR",
"value":2000
},
"amountExactness":"EXACT",
"billerBillID":"918147077472",
"name":"Website Name Payment Links Test",
"validationRules":{
"sourceAccounts":[
{
"number":"9009120939129",
"ifsc":"(website name)"
}
]
},
"additionalInfo":{
"UUID":"b6b6f173-8649-4b2e-9c22-f78e9195a23e",
"tags":"electricity"
}
}
Sample response
{
"status":200,
"success":true,
"data":{
"name":"Website Name Payment Links Test",
"paymentLink":{
"shortURL":"https://sandbox.bills.pe/Srmjne3",
"upiID":"(website name)868062282653893900@kaypay",
"upiLink":"upi://pay?pa=(website name)868062282653893900@kaypay&pn=(website name)%20Payment%20Links%20TEst&am=20.00&tr=868062282653893900&tn=Payment%20for%20918147077472&cu=INR&mode=04"
},
"platformBillID":"868062282653893900"
}
}
Sample bill fulfillment notification
{
"partnerDetails":{
"appID":"867480814940587229",
"productInstanceID":"867480814940587229"
},
"events":[
{
"data":{
"Reason":"TPV check failed",
"amountPaid":{
"currencyCode":"INR",
"value":2000
},
"payerVpa":"saainithil97@icici",
"sourceAccount":{
"ifsc":"(website name)0000012",
"number":"9009120939129"
},
"status":"PAYMENT_FAILED",
"transactionId":"6603274139532736",
"transactionNote":"Payment for 918147077472"
},
"timeStamp":1649389668226,
"type":"BILL_FULFILMENT_STATUS",
"id":"3f545cad-c179-4360-b0c7-1faad9737571",
"additionalInfo":{// same as values defined when creating the link
"UUID":"b6b6f173-8649-4b2e-9c22-f78e9195a23e",
"tags":"electricity"
},
}
]
}

#TPV check by merchant

The merchant creates the payment link without any source account information.

When TPV is enabled for the merchant, the source account IFSC and account number are passed on to the merchant, in the bill fulfillment notification. (Website Name) will process the transaction without any checks. Merchant can then carry out the validation on their end and initiate refund as needed, using the Create refund API.

Sample bill fulfillment notification with TPV enabled
{
"partnerDetails":{
"appID":"867480814940587229",
"productInstanceID":"867480814940587229"
},
"events":[
{
"data":{
"Reason":"",
"amountPaid":{
"currencyCode":"INR",
"value":2000
},
"billerBillID":"918147077472",
"payerVpa":"saainithil97@icici",
"platformBillID":"868066686043948303",
"sourceAccount":{
"ifsc":"(website name)0000012",
"number":"9009120939129"
},
"status":"PAYMENT_SUCCESSFUL",
"transactionId":"3407080294420161",
"transactionNote":"Payment for 918147077472"
},
"timeStamp":1649389505287,
"type":"BILL_FULFILMENT_STATUS",
"id":"481b642f-de67-4cd7-a025-ae3e28329118",
"additionalInfo":{// same as values defined when creating the link
"UUID":"b6b6f173-8649-4b2e-9c22-f78e9195a23e",
"tags":"electricity"
},
}
]
}

Was this page helpful?

#Refunds

(Website Name) offers refund functionality for UPI payments. (Website Name) can self-initiate refunds for predefined scenarios or merchants can initiate refunds voluntarily.

The refund will appear in the customer's account within 1 to 9 business days after it has been initiated. Within 170 days of the transaction date, refunds can be requested.


Refunds are initiated in batches, along with merchant bill settlements. In the present settlement, the amount to be refunded is adjusted if it has already been settled to the merchant in a previous settlement.


#Types of refunds

Refunds are of three types, based on the reason for initiation—

  • (Website Name) initiated refunds — (Website Name) automatically refunds a transaction in cases where the transaction is not properly routed through the UPI eco-system and cannot be reconciled. Whenever the amount exactness validation rules for the payment link fail, (Website Name) initiates refunds automatically.
  • Merchant initiated refunds — Merchants can request a refund for one or more transactions. Reasons could include return of goods and services and more.
  • Third party verification (TPV) refunds — If the account used by the customer for making payment does not match what the merchant is expecting, a refund can be initiated. TPV is enabled by (Website Name) only upon request from the merchant.

#(Website Name) initiated refunds

When a transaction is facilitated within the UPI ecosystem, it undergoes a complex flow across multiple points. Errors occurring at any juncture in this process can lead to scenarios where (Website Name) is unable to reconcile the transaction. Consequently, (Website Name) initiates automatic refunds to the customer's source VPA (Virtual Payment Address). Various situations prompting such automatic refunds include:

  • Missing orderID
  • Incorrect orderID
  • Missed notification from bank

(Website Name) also initiates refunds in these situations—


(Website Name) initiated refund process

For transactions that come under (Website Name) initiated refunds, the bill fulfillment notification for that particular transaction will have PAYMENT_FAILED as the status.

(Website Name) will later notify the merchant about the refund initiation, in the next settlement cycle. See refund notifications.

In cases where the orderID is missing or invalid, (Website Name) cannot identify the merchant and hence will not provide any refund notification to the merchant. However, the refund will still be processed to the customer's VPA.

(Website Name) initiated refunds are credited to the customer's source VPA in 1 to 9 business days — no intervention from the merchant is needed.



#Merchant initiated refunds

A merchant can choose to refund a payment to the customer after the payment is complete or settled. Refunds have to be initiated within 60 days from the date of transaction.

Create and check refund status with the following APIs.


#Create refund API

Create a refund request for one or more transactions.

Method POST
Path /refund/batch
Header X-(Website Name)-Product-Instance-ID

Authorization: Bearer <insert_token_here>. Generate this token using OAuth or JWT.

Content-Type—will be application/json
Sample request (when original transaction has no split instructions)
{
"refunds":[
{
"seqNo":1,
"identifier":"1099309092570138096",
"identifierType":"BILL_ID",
"refundType":"FULL"
},
{
"seqNo":2,
"identifier":"1099309493419771390",
"identifierType":"BILL_ID",
"refundType":"PARTIAL",
"refundAmount":{
"currencyCode":"INR",
"value":1500
}
}
]
}
Sample request (when original transaction has split instructions)
{
"refunds":[
{
"seqNo":1,
"identifier":"896458251304961390",
"identifierType":"BILL_ID",
"refundType":"FULL",
"deductions":[
{
"account":{
"id":"Biller-External-001",
"ifsc":"KKBK0000001",
"name":"External-biller-Acc-1"
},
"split":{
"unit":"INR",
"value":20000
}
},
{
"account":{
"id":"Biller-External-002",
"ifsc":"KKBK0000001",
"name":"External-biller-Acc-2"
},
"split":{
"unit":"INR",
"value":10000
}
}
]
}
]
}
Sample response
{
"status":200,
"success":true,
"data":{
"batchID":"ca1l9e1bnsesi098pbn0",
"refunds":[
{
"amount":{
"currencyCode":"INR",
"value":20000
},
"billID":"896458251304961389",
"deductions":[
{
"account":{
"id":"Biller-External-001",
"ifsc":"KKBK0000001",
"name":"External-biller-Acc-1"
},
"split":{
"unit":"INR",
"value":20000
}
}
],
"id":"896458511922234749",
"status":"Created",
"transactionRefID":"8127920116918371",
"seqNo":1,
"success":true
},
{
"amount":{
"currencyCode":"INR",
"value":5000
},
"billID":"896458450802836853",
"deductions":[
{
"account":{
"id":"Biller-External-001",
"ifsc":"KKBK0000001",
"name":"External-biller-Acc-1"
},
"split":{
"unit":"INR",
"value":5000
}
}
],
"id":"896458511980955006",
"status":"Created",
"transactionRefID":"6004660259904990",
"seqNo":2,
"success":true
}
]
}
}

The API returns a batchID for the refund, which can be used to check the status of the refund.


#Check refund batch status API

Check status of refunds created against a particular batchID.

Method GET
Path /refund/batch/:batchID
Header X-(Website Name)-Product-Instance-ID

Authorization: Bearer <insert_token_here>. Generate this token using OAuth or JWT.

Content-Type—will be application/json
Sample response
{
"status":200,
"success":true,
"data":{
"refunds":[
{
"amount":{
"currencyCode":"INR",
"value":1500
},
"billID":"1099299575895688621",
"createdAt":"2023-02-21T04:44:10.082Z",
"deductions":[
{
"account":{
"id":"50100221813167",
"ifsc":"HDFC0000839",
"name":"Santosh-Test"
},
"split":{
"unit":"INR",
"value":1500
}
}
],
"id":"1099299900383823287",
"initiatedAt":"2023-02-21T04:44:50.461Z",
"status":"Initiated",// ENUM — Created, Pending, Initiated
"transactionRefID":"2092666374742383",
"type":"MerchantInitiated"
}
]
}
}
What are the different types of refund statuses?

Created: This marks the point at which the merchant initiates a refund request through APIs or The Bridge ((Website Name) dashboard). At this stage, neither the refund nor its processing has occurred.

Initiated: This status indicates that the refund request has been communicated to the banking partner and the actual refund process has commenced. This serves as the final status for a refund since NPCI does not disclose information about when a refund reflects in the customer's bank account.

Pending: This status applies when refunds are awaiting reconciliation or have completed reconciliation but remain unprocessed for reasons such as:

  • Insufficient funds: If the settlement amount is inadequate to cover a specific refund request, the refund stays in a Pending state. For instance, if a merchant, say X, has a daily settlement amount of ₹850 and creates 10 refunds of ₹100 each, totaling ₹1000 in the same timeframe, only the first 8 will be refunded and move to an initiated state. The callback notification will contain the first 8 refunds in the initiated block and the rest in thePending block.

    Example: If the total settlement amount for the day for Merchant X is ₹850 and the merchant has created 10 refunds of ₹100 each totalling ₹1000 in the same duration, only the first 8 will get refunded and move to an initiated state. The callback notification sent to the merchant will contain the first 8 refunds in the initiated block and the remaining in the pending block.

  • No Active Transactions: A refund request remains Pending if there are no active transactions, meaning no settlements to the merchant's account from which the refund amount can be deducted and returned to the customer. For example, if Merchant Y has not conducted any transactions for one or more days and has created refund requests, the refunds would stay in a pending status with the reason "No Active Transactions."

    Example: Merchant Y has not transacted for 1 or more days and has created Refund requests. Since there are no active transactions, the refunds would remain in Pending status with the reason No Active Transactions

Rejected: This status is reserved for exceptional scenarios where a merchant wishes to halt the processing of a previously requested refund. The merchant must request the (Website Name) team to reject the refund, and this request is handled offline.


#Check individual refund status API

Check status of a specific refund with the refund id.

Method GET
Path /refund/:refundId
refundId is the id provided in the refunds array of Create refund API
Header X-(Website Name)-Product-Instance-ID

Authorization: Bearer <insert_token_here>. Generate this token using OAuth or JWT.

Content-Type—will be application/json
Sample response
{
"status":200,
"success":true,
"data":{
"amount":{
"currencyCode":"INR",
"value":1500
},
"billID":"1099299575895688621",
"createdAt":"2023-02-21T04:44:10.082Z",
"deductions":[
{
"account":{
"id":"50100221813167",
"ifsc":"HDFC0000839",
"name":"Santosh-Test"
},
"split":{
"unit":"INR",
"value":1500
}
}
],
"id":"1099299900383823287",
"initiatedAt":"2023-02-21T04:44:50.461Z",
"status":"Initiated",// ENUM — Created, Pending, Initiated
"transactionRefID":"2092666374742383",
"type":"MerchantInitiated"
}
}

#Refund notifications

Check out refund notifications ↗


Was this page helpful?

#Reports API

The (Website Name) Reports API provides you with access to transaction and settlement data. This can be consumed to automate your reconcilliation process.

The request format is detailed below—

URL Production: https://bifrost.(Website Name).co/bifrost/collect/reports
Sandbox: https://uat-bifrost.(Website Name).co/bifrost/collect/reports
Method POST
Headers Content-Type: application/json

x-(Website Name)-partner-id: Can be found under Organization settings on The Bridge.

x-(Website Name)-env:: Test/ Live. This corresponds to the Sandbox and Production environment on The Bridge.

Authorization: Bearer (insert_token_here). Generate this token using OAuth or JWT.

#Transaction Report

Request
{
"filters":{
"paymentStartDate":"2019-12-31T18:30:00.000Z",// ISO-8601 timestamp in UTC
"paymentEndDate":"2020-12-10T18:29:59.999Z",// ISO-8601 timestamp in UTC
"settlementStartDate":"2019-12-31T18:30:00.000Z",// ISO-8601 timestamp in UTC
"settlementEndDate":"2020-12-10T18:29:59.999Z",// ISO-8601 timestamp in UTC
// payment modes you want to filter, we recommend skipping this parameter
"paymentMode":[
"UPI",
"CASH",
"NEFT",
"RTGS",
"IMPS",
"IFT",
"CC",
"DC",
"Prepaid",
"Internet Banking",
"Debit Card",
"Credit Card",
"Cash",
"Wallet",
"Prepaid Card",
"AEPS",
"Account Transfer",
"Bharat QR",
"USSD"
],
"platformBillStatus":[// bill statuses you want to filter, we recommend using only "SETTLEMENT_SUCCESSFUL" for exact reconciliation
"PAYMENT_SUCCESSFUL",
"PAYMENT_FAILED",
"CREDIT_RECEIVED",
"SETTLEMENT_SUCCESSFUL",
"SETTLEMENT_FAILED",
"BILL_EXPIRED"
]
},
"pagination":{// set your pagination limit for large number of records
"cursor":"",// use "nextCursor" value as returned by API response, as an input to subsequent API call to move the cursor ahead
"limit":100// min 100 max 500
},
"productIds":[// list of all product IDs for which you want to fetch the records for
"374024227163997852"
],
"reportType":"transaction"
}
Response
{
"status":200,// http status
"success":true,// success status of API request
"data":{// data in case of success
"metadata":{// metadata about records that match the request
"totalRecords":2,// total number of matching records
"filters":{},// filters applied
"previousCursor":"",// updated cursor position after this call
"nextCursor":""// next cursor position for use with next iteration of pagination
},
"records":[// array of records
{
"platformBillID":"517002663317996567",// (website name)'s unique ID for every bill
"billerBillID":"fb0e9146-466a-40f1-9bd6-e8d01d4940e2",// biller's ID associated with this bill
"billerMCC":"Loans",// category of business
"platformBillStatus":"CREDIT_RECEIVED",// status of the transaction, read here to know more: https://support.(website name).co/support/solutions/articles/81000385479
"amountTotal":1992,// bill amount
"deemedStatus":"NOT_DEEMED",// whether this bill was deemed success (upcoming feature)
"currencyCode":"INR",
"amountPaid":200000,// amount paid by the customer
"paymentInstrument":"UPI",// payment method used by the customer
"paymentDate":"2020-12-10T05:43:30+05:30",// ISO-8601 timestamp for payment
"paymentReferenceID":"517002663317996567",// unique payment ID as shared by customer app
"paymentReceipt":"dceeb285-c4ab-49e4-a7f0-d37bdef3b906",// receipt generated against the payment
"settlementDate":"2020-12-12T10:54:30+05:30",// ISO-8601 timestamp for settlement
"settlementUtr":"CMS201022000BLO",// bank Unique Transaction Reference number for the settlement
"primaryAccountNumber":"XXXXXXXX060510",// primary bank account associated with the biller
"primaryAccountIfsc":"KKBK0000431",// primary bank IFSC associated with the biller
"primaryAccountName":"John Wick",// primary bank account holder name associated with the biller
"primaryAccountSettlementAmount":198384,// settlement amount sent to primary bank account
"split":"YES",// indicates if settlement has been split into parts
"splitSettlements":[// array with objects describing each part of the split in settlement
{
"date":"2020-10-22T10:54:30+05:30",
"utr":"CMS201023000BLO",
"name":"The Manager",
"id":"XXXXXXXX060511",
"ifsc":"KKBK0000431",
"amount":1144
}
],
"bpcTotal":400,// bill payment charge deducted by (website name)
"bpcPercentage":0,// percentage on the basis of which the bill payment charge is calculated
"bpcFlat":400,// flat fee as part of bill payment charge
"gstTotal":72,// GST charged on bill payment charge
"gstPercentage":18,// percentage fee on the basis of which the GST is calculated
"gstFlat":0// flat fee as part of GST
},
{
...
}
]
}
}

#Refund Report

Request
{
"filters":{
"createdAtEndDate":"2022-08-10T11:15:41.631Z",// ISO-8601 timestamp in UTC
"createdAtStartDate":"2022-08-06T18:30:00.000Z"// ISO-8601 timestamp in UTC
"payeeVPA":"anothersample@okbank",
"payerVPA":"sample@okbank",
"paymentReferenceID":"1234567890",
"refundReason":[
"Order ID invalid in credit alert",
"Duplicate payment made against bill",
"Payment amount validation failure",
"Credit alert received after bill expiry",
"Credit alert not received from bank",
"Initiated by merchant",
"Source account info missing from credit alert",
"TPV check failure"
],
"refundStatus":[
"Created",
"MarkedForRefund",
"QueuedForRefund",
"Rejected",
"Initiated"
]
},
"pagination":{// set your pagination limit for large number of records
"cursor":"",// use "nextCursor" value as returned by API response, as an input to subsequent API call to move the cursor ahead
"limit":100// min 100 max 500
},
"productIds":[// list of all product IDs for which you want to fetch the records for
"374024227163997852"
],
"reportType":"refund"
}
Response
{
"status":200,
"success":true,
"data":{
"metadata":{
"totalRecords":39,
"filters":{
"createdAtEndDate":"2022-08-10T11:15:41.631Z",// ISO-8601 timestamp in UTC
"createdAtStartDate":"2022-08-06T18:30:00.000Z",// ISO-8601 timestamp in UTC
"paymentMode":null,
"platformBillStatus":null,
"productTypes":null,
"refundReason":[
"Order ID invalid in credit alert",
"Duplicate payment made against bill",
"Payment amount validation failure",
"Credit alert received after bill expiry",
"Credit alert not received from bank",
"Initiated by merchant",
"Source account info missing from credit alert",
"TPV check failure"
],
"refundStatus":[
"Created",
"MarkedForRefund",
"QueuedForRefund",
"Rejected",
"Initiated"
]
},
"previousCursor":"",
"nextCursor":""
},
"records":[
{
"actorID":"1234567890",
"amount":1234,
"batchID":"cbpobt817cjflqbfl5r0",
"createdAt":"2022-08-10T15:48:29+05:30",
"initiatedAt":"",
"payerVPA":"sample@okbank",
"payeeVPA":"anothersample@okbank",
"paymentReferenceID":"222234971910",
"paymentTransactionID":"PTMDCWAAD8A02F7412B90DE8C32236D0494",
"platformBillID":"958135084945245239",
"refundReason":"Initiated by merchant",
"refundID":"958136906271525795",
"refundStatus":"Created",
"type":"MerchantInitiated",
"deductions":[
{
"account":{
"name":"",
"id":"0566102000016463",
"ifsc":"IBKL0002536"
},
"split":{
"value":1234,
"unit":"INR"
},
"UTR":""
}
]
},
{
...
}
]
}
}

Was this page helpful?

#Notifications

#Outgoing event alerts sent by (Website Name) to partners.

Currently, there are two types of events— BILL_FULFILMENT_STATUS and BILL_SETTLEMENT_STATUS, which triggers a notification for the following events.


#Bill fulfilment status

After (Website Name) receives a callback from the bank for a particular payment, we send a PAYMENT_SUCCESSFUL or PAYMENT_FAILED or PAYMENT_ATTEMPT_FAILED notification to the merchant.


#Payment successful notification

{
"partnerDetails":{
"appID":"861023031961584801",
"productInstanceID":"861023031961584801"
},
"events":[
{
"data":{
"Reason":"",
"amountPaid":{
"currencyCode":"INR",
"value":100
},
"billerBillID":"918147077472",
"payerVpa":"saainithil97@icici",
"platformBillID":"896444053527201086",
"receiptId":"292cdeff-f4c6-4684-b266-43586f5234d0",
"sourceAccount":{// this is the account from which the payment was made and will only be sent for TPV-enabled merchants
"ifsc":"(website name)0000012",
"name":"Noresh",
"number":"9009120939129"
},
"status":"PAYMENT_SUCCESSFUL",
"transactionId":"260843001102590",
"transactionNote":"Payment for 918147077472",
"additionalInfo":{// same as values defined when creating the link
"UUID":"b6b6f173-8649-4b2e-9c22-f78e9195a23e",
"tags":"electricity"
},
},
"timeStamp":1652772351636,
"type":"BILL_FULFILMENT_STATUS",
"id":"edead767-1584-4177-bd45-7ac9cd201c28"
}
]
}

#Payment failed notification

A payment can fail for multiple reasons as explained below:

Reason When does this happen?
Amount validation failed If the payment amount does not satisfy the amountExactness condition specified during payment link creation.
Payment link has expired If the payment was made after the expiryDate set during payment link creation.
Missed credit alert In rare scenarios, the bank system does not send us a credit alert in real time. But when we process all transactions in the following settlement cycle, and if delayed processing configuration is disabled for the merchant, the bill is marked as PAYMENT_FAILED and notification is sent.
Payment address inactive When a customer makes multiple payments using the same payment link, only the first one is honoured. For all others, a failure notification is sent.
TPV check failed If TPV check by (Website Name) is enabled and account validation fails. Read more about TPV here.

{
"partnerDetails":{
"appID":"861023031961584801",
"productInstanceID":"861023031961584801"
},
"events":[
{
"data":{
"Reason":"Amount validation failed",
"amountPaid":{
"currencyCode":"INR",
"value":200
},
"billerBillID":"918147077472",
"payerVpa":"saainithil97@icici",
"platformBillID":"896445757228320073",
"receiptId":"774cbd68-0106-4635-b861-986d4a5c9792",
"status":"PAYMENT_FAILED",
"transactionId":"6917454577784936",
"transactionNote":"Payment for 918147077472",
"additionalInfo":{// same as values defined when creating the link
"UUID":"b6b6f173-8649-4b2e-9c22-f78e9195a23e",
"tags":"electricity"
},
},
"timeStamp":1652772555905,
"type":"BILL_FULFILMENT_STATUS",
"id":"e41d9f2a-eb66-4be0-8dec-f04806656274"
}
]
}

#Payment attempt failed notification

Merchants receive notifications if a payment attempt fails due to incorrect UPI MPIN, insufficient balance, network errors, or other reasons. These failures are indicated bynpciStatusCode and npciStatusReason. Full list of status codes, reasons and descriptions are provided below.

List of all payment attempt failed notification statuses

NPCI status code NPCI status reason Website Name Description Next Steps for merchants
U30 DEBIT HAS BEEN FAILED The customer's debit attempt failed. Inform the customer and ask them to try again or use a different payment method.
U09 REQAUTH TIME OUT FOR PAY Payment authorization took too long. Ask the customer to try again. If it continues, reach out to Website Name support.
U90 REMITTER BANK DEEMED HIGH RESPONSE TIME CHECK DECLINE The customer's bank is taking too long to respond. Ask the customer to contact their bank or try a different payment method.
U67 DEBIT TIMEOUT The debit process took too long. Ask the customer to try again or use a different payment method.
U88 CONNECTION TIMEOUT IN REQPAY CREDIT Connection timed out during the credit request process. Try processing the transaction again. If the issue persists, contact Website Name support.
U16 RISK THRESHOLD EXCEEDED The transaction exceeds the risk threshold. Review the transaction for potential issues or ask the customer to use a different payment method.
U28 REMITTER BANK NOT AVAILABLE The customer's bank is unavailable. Inform the customer and suggest trying again later or using a different bank or payment method.
XQ Transaction not permitted to cardholder (beneficiary) This transaction isn't permitted for the beneficiary. Inform the customer and suggest using a different payment method.
U85 CONNECTION TIMEOUT IN REQPAY DEBIT Connection timed out during the debit request process. Try processing the transaction again. If the issue persists, contact Website Name support.
HS3 HSM communication error A communication error occurred with the security module. Retry the transaction or contact Website Name support if the problem persists.
U66 DEVICE FINGERPRINT MISMATCH Device fingerprint mismatch detected. Inform the customer, ask them to verify their device, and retry the transaction.
U91 BENEFICIARY BANK DEEMED HIGH RESPONSE TIME CHECK DECLINE Beneficiary bank response time is too high. Inform the customer and suggest they contact their bank or use a different payment method.
U03 NET DEBIT CAP IS EXCEEDED The total debit amount exceeded the set limit. Ask the customer to try a different payment method or contact their bank.
U54 TRANSACTION ID OR AMOUNT IN CREDENTIAL BLOCK DOES NOT MATCH WITH THAT IN REQPAY Transaction details mismatch. Verify the transaction details and retry, or contact Website Name support if needed.
U86 REMITTER BANK THROTTLING DECLINE The customer's bank declined due to throttling. Inform the customer and ask them to contact their bank or use a different payment method.
XK REQUESTED FUNCTION NOT SUPPORTED (BENEFICIARY) The requested function is not supported for the beneficiary. Ask the customer to try a different payment method.
U14 ENCRYPTION ERROR An encryption error occurred in the transaction. Retry the transaction or contact Website Name support if the problem persists.
XC INVALID TRANSACTION OR IF MEMBER IS NOT ABLE TO FIND ANY APPROPRIATE RESPONSE CODE (BENEFICIARY) Invalid transaction or response code issue. Contact Website Name support for assistance.
U47 REQUEST DEBIT IS NOT FOUND The debit request was not found. Retry the transaction or contact Website Name support if needed.
BT ACQUIRER/BENEFICIARY UNAVAILABLE(TIMEOUT) Receiver/beneficiary is not available, causing a timeout. Inform the customer and suggest trying again later or using a different payment method.
94 Unknown Error An unknown error occurred. Retry the transaction or contact Website Name support if the problem persists.
U53 PSP REQUEST PAY DEBIT ACKNOWLEDGEMENT NOT RECEIVED The debit acknowledgement was not received. Retry the transaction or contact Website Name support if needed.
HS2 HSM Time out A timeout occurred with the security module. Retry the transaction or contact Website Name support if the problem persists.
S99 Graceful decline The transaction was stopped without a specific reason. Ask the customer to try a different payment method or contact Website Name support if needed.
U01 THE REQUEST IS DUPLICATE Duplicate transaction request. Confirm that the transaction was processed only once and contact Website Name support if necessary.

The bill created won’t expire, allowing customers to retry the payment.

{
"partnerDetails":{
"appID":"1115232834412348749",
"productInstanceID":"1115232834412348749"
},
"events":[
{
"data":{
"Reason":"",
"amountPaid":{
"currencyCode":"INR",
"value":5000
},
"npciStatusCode":"U30",
"npciStatusReason":"DEBIT HAS BEEN FAILED",
"payeeVpa":"fortest@kaypay",
"payerVpa":"saainithil97@icici",
"paymentChannel":"UPI",
"paymentReferenceNumber":"9921837467033533",
"platformBillID":"1217499640581064416",
"(website name)Description":"The customer's debit attempt failed.",
"status":"PAYMENT_ATTEMPT_FAILED",
"transactionDate":"2023-08-03 12:16:12",
"transactionId":"615436a8-434c-43db-8a57-dd4cf11dff3e"
},
"timeStamp":1691045172577,
"type":"PAYMENT_ATTEMPT_FAILED",
"id":"e48bdd28-c34f-4237-bebd-ccb37f174b8a"
}
]
}

#Bill settlement status


#Bill settled notification

A SETTLEMENT_SUCCESSFUL notification is sent to the merchant after successful payments from (Website Name) to the merchant. This depends on the settlement frequency agreed upon between (Website Name) and the merchant.

{
"partnerDetails":{
"appID":"string",// your unique app ID in Website Name system, this is constant
"productInstanceID":"string"// your unique product instance ID in Website Name system, this is constant
},
"events":[
{
"data":{
"amountSettled":{
// amount settled by (website name), in paisa
"currencyCode":"INR",
"value":1084
},
"platformBillIds":[
// list of platform bill IDs that are processed in this settlement
405884202257482938,
...
],
"status":"SETTLEMENT_SUCCESSFUL",
"transactionId":"string"// bank utr number
},
"id":"f3b41c8f-72fc-485d-b39a-cf497787a039",// unique callback ID for every request, used for logging, debugging and tracking
"timeStamp":1594293083984,// epoch timestamp
"type":"BILL_SETTLEMENT_STATUS"
}
]
}

#Refund status


#Refund initiated notification

Refunds are initiated in batch, along with settlements. A batch notification is sent for all processed refunds, once our partner bank initiates refund of the amount, which can be determined by "type" : "REFUND_STATUS".

The refunds array in the notification provides the details of all transactions for which refund is initiated.

{
"partnerDetails":{
"appID":"799310436687152247",
"productInstanceID":"799310436687152247"
},
"events":[{
"data":{
"amountRefunded":{
"currencyCode":"INR",
"value":1500
},
"refunds":{
"Initiated":[{
"amount":{
"currencyCode":"INR",
"value":1500
},
"batchID":"cfq51rppcne0a46h51k0",
"billID":"1099309493419771390",
"reason":"Initiated by merchant",
"transactionID":"7019851224174158",
"type":"MerchantInitiated"
}],
"Pending":[{
"amount":{
"currencyCode":"INR",
"value":3000
},
"batchID":"cfq51rppcne0a46h51k0",
"billID":"1099309092570138096",
"reason":"Initiated by merchant",
"transactionID":"8271601534619864",
"type":"MerchantInitiated"
}],
"Rejected":[]
}
},
"timeStamp":1676955892641,
"type":"REFUND_STATUS",
"id":"f042a983-d1d5-4ea6-9ef9-aa6826728839"
}]
}

#Refund successful notification

(Website Name) does not have a refund successful notification yet, since this information is not available over APIs.


As next steps, you can start your internal reconciliation process or consume our Report APIs ↗ to get detailed settlement reports.


Was this page helpful?

#OAuth 2.0

It works over HTTPS and is an open standard for authorisation. (Website Name) uses it to authorize API requests with access tokens. Read more abouthere ↗.

In (Website Name) products, OAuth keys provide a lot of flexibility—you can use a single set of keys to authorize requests for multiple configurations, or authorise requests for a single configuration using multiple sets of keys.


#Calling (Website Name)-hosted APIs

Merchants use (Website Name) hosted APIs for creating payment links, checking link status, and fetching reports. Merchants can use OAuth keys to generate an access token and authorise such API requests with the generate token API explained below.

Note on JWT authentication

Only OAuth keys can be used to generate tokens with the generate token API. We recommend upgrading to OAuth soon if you are using JWT authentication to access (Website Name) hosted APIs. We support JWT auth but will not build any further features for it.

Change of URLs for OAuth

Using OAuth requires a change to the (Website Name) API endpoints you call. For eg, if the given endpoint is https://prod.(Website Name).co/api/(path), it would change tohttps://prod.(Website Name).co/api/v2/(path)—notice the /v2 added before the(path).


#How to get OAuth keys

Step 1—Login to The Bridge and head to Org settings

If you are an Admin for your Bridge account, you should be able to see the API keys card under “Org settings” in the left panel. Click the OAuth keys card to view keys for all your product configs.


Step 2—Configure key details

On clicking “Generate new key”, you should see a simple form

Select environment—A key can exist only in one environment. Sandbox keys access only sandbox configs, and production keys access only production configs.

Key name—This is for you to easily identify a key later and tell what a particular key can access.

Add products—Here's where you can select the product configurations that this key can access.

Generate new key

Step 3—Generate key

Once all fields have been filled out, the "Generate key" button will appear. You should see the clientID and secret for this key when you click it.

And done! You can now use this key to make API requests to (Website Name). Read more ↗ on supported features for OAuth keys.


#Generate Token API

Tokens are used to authorise any other API requests made to (Website Name). This API works with OAuth keys only.

Request
URL Sandbox: https://uat.(Website Name).co/api/v2/auth/token
Production: https://prod.(Website Name).co/api/v2/auth/token
Method POST
Header Content-Type: application/json

Request body
{
"clientID":"c0a411d5-b6f9-4bfd-a342-7cb01935ed43",
"secret":"b2b3e650-a31b-47a3-acf6-c96c9c5c282d",
}

Response

Success

A new token is provided by (Website Name) in the success response, along with an expiresIn param, which specifies the validity of the token in seconds (the default value is 1800 seconds or 30 minutes). You may store and keep reusing the same token till it expires.

{
"status":200,
"success":true,
"data":{
"expiresIn":1800,//seconds
"token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJsaWJ6NGFNaE4yUk5xMlpyVk9QaFhaMXpoMjA0V2gtdTdhT21LX2huRVQ4In0.eyJleHAiOjE2MTM5OTQzMTIsImlhdCI6MTYxMzk5NDAxMiwianRpIjoiZmZhZjM2ZTUtZmI3Mi00NTY2LTljOGYtY2U5N2I5MjY2Y2E4IiwiaXNzIjoiaHR0cHM6Ly9hdXRoLWRldi5zZXR1LmNvL2F1dGgvcmVhbG1zL2NvbGxlY3QiLCJzdWIiOiJhZGE1MTNhMS0xYjVhLTQ1NGQtYTk2Ny05OGI3YTYwNjY3MTAiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJjZDRlYTM5OC03YWIzLTQ3ZGUtYWE1MC03YzNiOWIzZjBhMjYiLCJzZXNzaW9uX3N0YXRlIjoiYmYxYjJjZjgtNTgzZC00Y2MwLWIwN2QtNmI5YWQyNmZiNGI0IiwiYWNyIjoiMSIsInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiY2xpZW50SWQiOiJjZDRlYTM5OC03YWIzLTQ3ZGUtYWE1MC03YzNiOWIzZjBhMjYiLCJjbGllbnRIb3N0IjoiMTA2LjUxLjE1LjI1MCIsIlgtU2V0dS1Qcm9kdWN0LUluc3RhbmNlLUlEIjoiNTYyNDMzODMwNDMwOTY2OTk4IiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2VydmljZS1hY2NvdW50LWNkNGVhMzk4LTdhYjMtNDdkZS1hYTUwLTdjM2I5YjNmMGEyNiIsImNsaWVudEFkZHJlc3MiOiIxMDYuNTEuMTUuMjUwIn0.QfEzImuN1P9jwTBJTcJ6ozP_gC3J-FOJp0D0va2AfXUUw8d5HLA5zqojCd6BnE6ApqKWnVU1aB0YWFwDbgHaVA3Netr-hmGadElLMhGiHah2UaLO0Bk86pZpyxNxtdx9u6YjfVYT6TSvUsqO4lISegFTJRTqFZxuBFv4WoKJPPD0JwEMYGH71LyOiCJA2sAq4YbOMKOvRrj2X_ipkSqvsrgEZicJ3lTY4vWyoGJ8wps0VW6k4vFSdX1qRKrAz_7XVKr8MKz_H1ng91h5XlZqsUh6BPz3WW0atWjt0RbAtXR32iB0zaB204IECxwriNmka1FxA9PZq94NvPwANDznhQ"
}
}

Failure

If incorrect clientID and secret details are provided, (Website Name) could respond with the following error—

{
"status":400,
"success":false,
"error":{
"code":"invalid-api-key",
"detail":"API key invalid [cd4ea398-7ab3-47de-aa50-7c3b9b3f0a21], please recheck your credentials.",
"docURL":"",
"title":"AUTHENTICATION_ERROR"
"traceID":"8b7bd233-5231-4bdd-8d48-aa4c0dae07b9"
"errors":[],
}
}
  • The traceID in the above response is dynamic and can be shared with (Website Name) support team, if further debugging is required.

#How to use the token

Once you have a valid token available against product configuration(s), you can store it and use it to authorise an API call made to (Website Name), by setting the authorization request header as Bearer <token-value>.

On expiry

Implement a workflow to generate new token when the old one expires. The general (Website Name)p might look something like this—

  • Store clientID and secret.
  • Generate new token with stored clientID and secret when token has expired. If the API you call returns 401 unauthorized, it could be an indication that the token has expired.
  • Store the newly generated token and use for subsequent API calls.

Was this page helpful?

#JWT basics

The JWT is sent as part of the authorisation header of every API request. Typically it looks like this—

// Auth header format
Authorization: Bearer <JWT_TOKEN>
// Sample JWT encoded
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiI4ZjQ3ZTQxYy00Njg0LTRhZjEtYjFiOC0yNDZjODMxMTIwMzMiLCJpYXQiOjE1NzI0OTMzNTYsImp0aSI6ImM1MzQ0N2UzLTk5M2EtNDRhZS05Yzc4LTMxZjQ1YzNjMDgyZSJ9.xfYii9lfWMHtMBgjK5U6NFN_6_Q9jw8UMQu8Jnvftbs

The JWT in itself has three parts— Aheader, payload, and a signature. (Website Name) uses the following format—

// JWT format
urlsafe_base64(<JWT_HEADER>).urlsafe_base64(<JWT_PAYLOAD>).urlsafe_base64(<SIGNATURE>)
// Sample JWT decoded
{
"alg":"HS256",
"typ":"JWT"
},
{
"aud":"8f47e41c-4684-4af1-b1b8-246c83112033",// This is the schemeID
"iat":1572493356,
"jti":"c53447e3-993a-44ae-9c78-31f45c3c082e"
}

This means that—

header : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
payload : eyJhdWQiOiI4ZjQ3ZTQxYy00Njg0LTRhZjEtYjFiOC0yNDZjODMxMTIwMzMiLCJpYXQiOjE1NzI0OTMzNTYsImp0aSI6ImM1MzQ0N2UzLTk5M2EtNDRhZS05Yzc4LTMxZjQ1YzNjMDgyZSJ9
signature : xfYii9lfWMHtMBgjK5U6NFN_6_Q9jw8UMQu8Jnvftbs

Header

This is a base64 encoded value. It contains details about the algorithm used to calculate the signature. This could have values such as HMAC SHA256 or RSA. For example—

// Sample JWT header
{
"alg":"HS256",
"typ":"JWT"
}
// is encoded to
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload

The value is also encoded in base64 encoded value.In this part of the JWT, you will find details about the entity and the request made (also called "claims"). For example—

// Sample JWT payload
{
"aud":"8f47e41c-4684-4af1-b1b8-246c83112033",// This is the schemeID
"iat":1572493356,
"jti":"c53447e3-993a-44ae-9c78-31f45c3c082e"
}
// is encoded to
eyJhdWQiOiI4ZjQ3ZTQxYy00Njg0LTRhZjEtYjFiOC0yNDZjODMxMTIwMzMiLCJpYXQiOjE1NzI0OTMzNTYsImp0aSI6ImM1MzQ0N2UzLTk5M2EtNDRhZS05Yzc4LTMxZjQ1YzNjMDgyZSJ9
  • The JWT includes aud as the scheme_id This value is shared between the entity sending the API response and the entity initiating API requests. (Website Name) provides this value in the credentials for calling (Website Name) APIs. Ensure you configure and share this value with (Website Name) to facilitate (Website Name)'s API calls to your system.
  • Theiat  represents the epoch timestamp in seconds when the request was issued. Requests older than 30 seconds are considered stale and will be rejected.
  • Thejti serves as a unique ID for each request, offering identification for logging, debugging, and tracking purposes. Given its uniqueness for every request, avoid reusing or repeating the same JWT token for different requests.

Signature

The signature is constructed using the algorithm specified in the header, along with the encoded header, encoded payload, and secret:

HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)

The secret is a private key shared between (Website Name) and you, used to sign the token to verify the sender of the JWT, ie, if the claims are coming from the aud that they claim to be coming from. The request is authenticated based on both the validity of the signature, and also the verification of each claim individually. For example—

Input string : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiI4ZjQ3ZTQxYy00Njg0LTRhZjEtYjFiOC0yNDZjODMxMTIwMzMiLCJpYXQiOjE1NzI0OTMzNTYsImp0aSI6ImM1MzQ0N2UzLTk5M2EtNDRhZS05Yzc4LTMxZjQ1YzNjMDgyZSJ9
Secret : 7c2e036c-908f-48ba-abe3-cd8745a6fa99
HA256 Signaure : xfYii9lfWMHtMBgjK5U6NFN_6_Q9jw8UMQu8Jnvftbs

You can try this on your command line by running—

echo -n "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiI4ZjQ3ZTQxYy00Njg0LTRhZjEtYjFiOC0yNDZjODMxMTIwMzMiLCJpYXQiOjE1NzI0OTMzNTYsImp0aSI6ImM1MzQ0N2UzLTk5M2EtNDRhZS05Yzc4LTMxZjQ1YzNjMDgyZSJ9.xfYii9lfWMHtMBgjK5U6NFN_6_Q9jw8UMQu8Jnvftbs"| openssl dgst -sha256 -hmac BBzKUWAZeAS2tBsk0FtJT4ep -binary|openssl base64 -e -A |sed s/+/-/ |sed -E s/=+$//

Read more about how we arrived at this command here ↗


# JWT authentication for (Website Name) APIs

The JSON Web Token mechanism is used for securely communicating with (Website Name). It is an open standard for representing claims securely between two parties.

The JWT website ↗ covers the basics of how it works and the concepts involved. This guide provides a simple description of how JWT is implemented at (Website Name).

For (Website Name) products, JWT keys have a one-to-one mapping with individual product configurations. Essentially, each product configuration comes with its own JWT key that a merchant can use to authorise API requests.

While we support JWT auth, we recommend using the more secureOAuth keys, which come with features like the ability to access multiple products with the same key, or regenerate and delete keys as needed and so on.


# Calling (Website Name)-hosted APIs

A merchant will call (Website Name) APIs for creating payment links, checking link status, for fetching reports etc and can use JWT to authenticate such requests with (Website Name).

If you are an Admin for your Bridge account, you should be able to see the API keys card under “Org settings” in the left panel. Click the JWT keys card to view keys for all your product configs. Read more ↗


#Sample code

As a result, you don't need to worry about encoding and decoding JWTs.

A lot of third party libraries exist that can do this for you easily —you can take a look at all the available libraries in most of the programming languages at Libraries for Token Signing/Verification section here ↗.

When the JWT format is recognized, i.e., the signature is valid and the payload is verified, (Website Name) / partner can accept a request as legitimate. Requests can be rejected if—

More than two minutes have passed since the token was generated.

  1. The aud claim is not verified.
  2. The signature is invalid.

Below here are some samples in popular languages.


Python
## pyjwt==1.7.1
import jwt
import datetime
import uuid
scheme_id ="8f47e41c-4684-4af1-b1b8-246c83112033"
secret ="7c2e036c-908f-48ba-abe3-cd8745a6fa99"
payload ={
"aud": scheme_id,
"iat": datetime.datetime.utcnow(),
"jti":str(uuid.uuid1())
}
// generate a token like this
token = jwt.encode(payload, secret, algorithm="HS256")
// And to decode the token and verify the aud claim—
try:
# verified claim
jwt.decode(token, secret, audience=scheme_id)
print("Verified token")
except jwt.PyJWTError:
# unverified claim
print("Token error")

PHP
<?php
require __DIR__.'/vendor/autoload.php';
use FirebaseJWTJWT;
$key = "7c2e036c-908f-48ba-abe3-cd8745a6fa99";
$aud = "8f47e41c-4684-4af1-b1b8-246c83112033";
// create token
$token = array(
"aud" => $aud,
"iat" => 1572493356,
"jti" => "c53447e3-993a-44ae-9c78-31f45c3c082e"
);
$jwt = JWT::encode($token, $key);
print_r($jwt);
echo '<br/>';
// Decode Logic
/**
* You can add a leeway to account for when there is a clock skew times between
* the signing and verifying servers. It is recommended that this leeway should
* not be bigger than a few minutes.
*
* Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef
*/
JWT::$leeway = 60; // $leeway in seconds
$decoded = JWT::decode($jwt, $key, array('HS256'));
$audClaimInToken = $decoded -> aud;
print_r($audClaimInToken);
echo '<br/>';
if($audClaimInToken == $aud){
echo "Success";
}
else{
echo "Fail";
}
?>

C#
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
public class JwtAuthManager
{
static string SecretKey ="ReallyLongSecret";// this should come from your configuration file
static string audience ="YourAudClaim";// this should come from your configuration file
public string GenerateJWTToken()
{
byte[] symmetricKey = Encoding.ASCII.GetBytes(JwtAuthManager.SecretKey);
var token_Handler = new JwtSecurityTokenHandler();
var now = DateTime.UtcNow;
var securitytokenDescriptor = new SecurityTokenDescriptor
{
Audience = JwtAuthManager.audience,
IssuedAt = now,
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(symmetricKey), SecurityAlgorithms.HmacSha256)
};
var stoken = token_Handler.CreateToken(securitytokenDescriptor);
var token = token_Handler.WriteToken(stoken);
return token;
}
public bool ValidateToken(string token)
{
var simplePrinciple = JwtAuthManager.GetPrincipal(token);
Console.WriteLine(simplePrinciple);
if(simplePrinciple == null)
return false;
// You can implement more validation to check whether username exists in your DB or not or something else.
return true;
}
public static ClaimsPrincipal GetPrincipal(string token)
{
try
{
var jwtTokenHandler = new JwtSecurityTokenHandler();
var jwtToken = jwtTokenHandler.ReadToken(token) as JwtSecurityToken;
if(jwtToken == null)
return null;
byte[] symmetricKey = Encoding.ASCII.GetBytes(JwtAuthManager.SecretKey);
var validationParameters = new TokenValidationParameters()
{
ValidateAudience = true,
RequireExpirationTime = false,
ValidateIssuer = false,
ValidAudience = JwtAuthManager.audience,
IssuerSigningKey = new SymmetricSecurityKey(symmetricKey)
};
SecurityToken securityToken;
var principal = jwtTokenHandler.ValidateToken(token, validationParameters, out securityToken);
Console.WriteLine("Principle");
Console.WriteLine(principal);
return principal;
}
catch(Exception e)
{
Console.WriteLine(e);
return null;
}
}
}

Java
packagecom.(website name).helpers;
importcom.auth0.jwt.JWT;
importcom.auth0.jwt.JWTVerifier;
importcom.auth0.jwt.algorithms.Algorithm;
importcom.auth0.jwt.exceptions.JWTVerificationException;
importcom.auth0.jwt.interfaces.DecodedJWT;
importjava.util.Date;
importjava.util.UUID;
publicclass(website name)JwtHelper{
privateString schemedId;
privateString secret;
public(website name)JwtHelper(String secret,String schemedId){
this.schemedId = schemedId;
this.secret = secret;
}
publicvoidsetSchemedId(String schemedId){
this.schemedId = schemedId;
}
publicvoidsetSecret(String secret){
this.secret = secret;
}
publicStringyieldBearerToken(){
Algorithm algorithm =Algorithm.HMAC256(this.secret);
String token = JWT.create()
.withAudience(this.schemedId)
.withIssuedAt(newDate())
.withClaim("jti", UUID.randomUUID().toString())
.sign(algorithm);
return"Bearer "+ token;
}
publicvoid verifyBearerToken (String bearerToken)throwsJWTVerificationException{
bearerToken = bearerToken.replace("Bearer ","");
Algorithm algorithm =Algorithm.HMAC256(this.secret);
JWTVerifier verifier = JWT.require(algorithm)
.acceptLeeway(10)
.withAudience(this.schemedId)
.build();//Reusable verifier instance
DecodedJWT jwt = verifier.verify(bearerToken);
}
}

Was this page helpful?

#Settlement object

(Website Name) bill objects can contain instructions on how to settle a collected bill amount, as shown in the sample code snippet.

The settlement object contains the following details—

  • Which bank account(s) the settlement should be deposited to.
  • What is the split applied on the amount when making the settlement.
  • "data":{
    "customer":{
    "name":"Shailesh"
    },
    "billDetails":{
    "billFetchStatus":"AVAILABLE",
    "bills":[
    {
    "generatedOn":"2020-06-04T06:59:04Z"// bill generation / fee start date,
    "dueDate":"2020-06-04T06:59:04Z"// last date for fee payment,
    "recurrence":"ONE_TIME",
    "amountExactness":"EXACT",
    "billerBillID":"string",// bill identifier, sent with each payment
    "customerAccount":{},
    "amount":{},//amount against the bill
    "items":[],// array of line items
    "aggregates":{},// details on final amount that the customer needs to pay
    "settlement":{
    // details about the settlement instructions for this bill
    "primaryAccount":{},
    "parts":[]
    }
    }
    ]
    }
    }

    #When to use the settlement object

    Below are some common use cases for the settlement object.

    It is an optional parameter. If the settlement object is not present in bill object, we will settle the full amount to the primary bank account set as part of the merchant configuration on The Bridge.


    Case 1 — Redirect entire funds to a different account

    In the absence of settlement instructions, all funds are settled to a primary account by default. On The Bridge, only one account can be marked as primary.

    You can specify the preferred settlement account as the primaryAccount inside the settlement object if you wish to redirect funds away from this account. This specifies the settlement account to be changed only for this bill, other settlements will continue to happen to your primary account.

    The primary account you specify in the settlement object must already be CERTIFIED on The Bridge. Otherwise, the settlement would fail.


    Case 2 — Split funds into different accounts

    In some business use cases, a bill needs to be split and settled to multiple bank accounts. Some examples could be—

    • Different collection accounts for different heads
    • Different line items belong to different parts of the organization (departments, sub organizations, business entities, etc)
    • Splits to vendor/partner accounts
    • We support upto 5 splits on a single bill.


      By using (Website Name)'s settlement object in the merchant's fetch API, merchants can pass on their bill settlement preference to (Website Name), and (Website Name) will take care of the rest.

      Splits work only if amountExactness which means the customer can pay the exact amount or more. Extra money will be settled to the primary account specified in the settlement object if the paid amount exceeds the bill amount.


      #Settlement object structure

      The settlement JSON object consists of 2 objects—

      • parts—contains the split rules for settlement
      • primaryAccount—money is transferred to this account after all splits have been settled
      {
      "settlement":{
      "parts":[],
      "primaryAccount":{},
      },
      }

      Parts

      Parts is an array of objects that defines the split and account to which that split should be settled.

      "parts":[
      {
      "account":{
      "id":"string",
      "ifsc":"string",
      "name":"string"//optional
      },
      "split":{
      "unit":"INR",
      "value": int,// in paise
      }
      "remarks":"string"//optional
      }
      ]

      Descriptions

      • account.id Bank account number for the settlement of this particular split
      • account.ifsc Bank IFSC for the settlement of desired split part
      • account.name Name that appears against the bank account account
      • split.unit Unit by which the split part is calculated. The supported value is INR or Indian National Rupee.
      • split.value Value of the split relative to the mentioned unit, INR accepts integer values and treats them as amount in paise. Please note that we expect only values converted to paise, for simplicity of calculations.
      • remarks Description of the split that will appear in the settlement report.

      Primary account

      A primary account defines the bank account where the balance amount is settled after calculating and settling all splits. Here is what it looks like.

      "primaryAccount":{
      "id":"string",
      "ifsc":"string",
      "name":"string"//optional
      }
      }

      Only one bank account can be specified here, otherwise the settlement will be rejected.


      Descriptions

      • account.id Bank account number for the primary account
      • account.ifsc Bank IFSC for the primary account
      • account.name Name against primary account. This is optional.

      #Split calculation method

      The splits are always calculated by secondary accounts, that is, accounts that are not marked as primaryAccount in the settlement object. Based on the following descriptions, you can set your business logic to allow for proper splits that are accepted by (website name).


      Split by fixed amount value(s)

      Enter the exact amount of the split(s) in paise. The total of split parts should either add up to the total bill settlement amount or be less than that.

      The splits are always calculated by secondary accounts, that is, accounts that are not marked as primaryAccounts in the settlement object. Using the following descriptions, you can set your business logic so that (Website Name) accepts proper splits.

      Settlement will be rejected in case the total of splits exceeds the bill settlement amount.


      Example scenario— For a bill of ₹100, a merchant wants ₹20 for itself and the remaining balance has to be settled to a vendor bank account. For this scenario, the settlement object would look like—

      {
      "primaryAccount":{
      "account":{
      "id":"vendor-bank-account-number",
      "ifsc":"vendor-bank-ac-ifsc"
      }
      },
      "parts":[
      {
      "account":{
      "id":"biller-bank-ac-number",
      "ifsc":"biller-bank-ac-ifsc"
      },
      "split":{
      "unit":"INR",
      "value":2000// in paise
      }
      }
      ]
      }

      Split settlement example

      Take the following scenario—

      Amount to settle: 200000 (₹2000), which is the amount actually paid by customer, in paise

      {
      "primaryAccount":{
      "account":{
      "id":"TUITION-FEE-ACCOUNT",
      "ifsc":"string"
      }
      },
      "parts":[
      {
      "account":{
      "id":"BUS_FEE_ACCOUNT",
      "ifsc":"string"
      },
      "split":{
      "value":60000,
      "unit":"INR"
      },
      "remarks":"Sports fee"
      },
      {
      "account":{
      "id":"SPORTS-FEE-ACCOUNT",
      "ifsc":"string"
      },
      "split":{
      "value":40000,
      "unit":"INR"
      },
      "remarks":"Sports fee"
      }
      ]
      }

      The resulting settlement happens as follows, with the values in paise

      1. ₹600 for the bus fee account: 60000
      2. ₹400 for the sports fee account: 40000
      3. Balance of ₹1000 for the tuition fee account: 100000

      Was this page helpful?

Fetch auth token

https://uat.(Website Name).co/api/v2/auth/token

Fetch token to be used to authorize all (Website Name) APIs


Request

Body

clientID

string

clientID from the V2 API key pair

secret

string

secret from the V2 API key pair

Response

Body

data

object

Required

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request POST \
--url https://uat.(website name).co/api/v2/auth/token \
--header 'content-type: application/json'\
--data '{
"clientID": "string",
"secret": "string"
}'
200 Success

Response sample


{
"data":{
"expiresIn":0,
"token":"token"
},
"status":200,
"success":true
}

Create a payment link

https://uat.(Website Name).co/api/v2/payment-links


Request

Header parameters

X-(website name)-Product-Instance-ID

string

Required

Identifier for product instance. Required for authorisation.

Authorization

string

Required

OAuth token. Required for authorisation.


Body

additionalInfo

object

amount

object

Amount to be refunded

amountExactness

string

Required

Exactness of the bill amount. "ANY" means customer can pay any amount. "EXACT" means customer can pay only the amount specified in the bill. "EXACT_UP" means customer must pay at least the specified amount or more, and "EXACT_DOWN" means customer can pay any amount upto the specified amount. "RANGE" means the customer can pay any amount between amountMin and amountMax specified in the validationRules.

Valid values:

ANYEXACTEXACT_UPEXACT_DOWNRANGE

billerBillID

string

Required

Unique bill identifier provided by the biller. For GST, it is the CPIN.

campaignID

string

This can be used to group payment links.

expiryDate

string<date-time>

Expiry date of the paymentLink in the ISO 8601 format, upto seconds precision.

name

string

Payee name to be populated in the Payment Link.

settlement

object

Contains the settlement configuration for the bill.

transactionNote

string
<= 80 chars

Used to show a note on payer app

validationRules

object

Bill validation rules

Response

Body

data

object

Required

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request POST \
--url https://uat.(website name).co/api/v2/payment-links \
--header 'Authorization: SOME_STRING_VALUE'\
--header 'X-(website name)-Product-Instance-ID: SOME_STRING_VALUE'\
--header 'content-type: application/json'\
--data '{
"amount": {
"currencyCode": "INR",
"value": 20000
},
"amountExactness": "EXACT",
"billerBillID": "918147077472",
"expiryDate": "2022-05-15T12:23:50Z",
"name": "Website Name Payment Links Test",
"settlement": {
"parts": [
{
"account": {
"id": "Biller-External-002",
"ifsc": "KKBK0000001"
},
"remarks": "EXACT sample split",
"split": {
"unit": "INR",
"value": 10000
}
}
],
"primaryAccount": {
"id": "Biller-External-001",
"ifsc": "KKBK0000001"
}
}
}'
200 Success

Response sample


{
"data":{
"name":"Website Name Payment Links Test",
"paymentLink":{
"shortURL":"https://sandbox.bills.pe/8tA2TQd",
"upiID":"nareshlocal@kaypay",
"upiLink":"upi://pay?pa=nareshlocal@kaypay&pn=(website name)%20Payment%20Links%20Test&am=200.00&tr=875621444531258946&tn=Payment%20for%20918147077472&cu=INR&mode=04"
},
"platformBillID":"875621444531258946"
},
"status":200,
"success":true
}

Check payment status

GET https://uat.(Website Name).co/api/v2/payment-links/{platformBillId}

Returns the status of the payment for the supplied bill id.


Request

Path parameters

platformBillId

string

Required

The unique identifier for a payment link in (website name).


Header parameters

X-(website name)-Product-Instance-ID

string

Required

Identifier for product instance. Required for authorisation.

Authorization

string

Required

OAuth token. Required for authorisation.


Response

Body

data

object

Required

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request GET \
--url https://uat.(website name).co/api/v2/payment-links/{platformBillId}\
--header 'Authorization: SOME_STRING_VALUE'\
--header 'X-(website name)-Product-Instance-ID: SOME_STRING_VALUE'
200 Success

Response sample


{
"data":{
"amountPaid":{
"currencyCode":"INR",
"value":20000
},
"billerBillID":"918147077472",
"createdAt":"2022-04-18T13:55:00.000Z",
"expiresAt":"2022-05-15T12:23:50.000Z",
"name":"Website Name Payment Links Test",
"payerVpa":"saainithil97@icici",
"paymentLink":{
"upiID":"nareshlocal@kaypay",
"upiLink":"upi://pay?pa=nareshlocal@kaypay&pn=(website name)%20Payment%20Links%20Test&am=200.00&tr=875621444531258946&tn=Payment%20for%20918147077472&cu=INR&mode=04"
},
"platformBillID":"875621444531258946",
"receipt":{
"date":"2022-04-18T13:55:41.000Z",
"id":"2801283953906381"
},
"status":"PAYMENT_SUCCESSFUL",
"transactionNote":"Payment for 918147077472"
},
"status":200,
"success":true
}

Initiate Batch Refund

https://uat.(Website Name).co/api/v2/refund/batch

Initiate a batch of several refunds at once


Request

Header parameters

X-(website name)-Product-Instance-ID

string

Required

Identifier for product instance. Required for authorisation.

Authorization

string

Required

OAuth token. Required for authorisation.


Body

refunds

array

Required

Contains individual transactions to refund.

Response

Body

data

object

Required

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request POST \
--url https://uat.(website name).co/api/v2/refund/batch \
--header 'Authorization: SOME_STRING_VALUE'\
--header 'X-(website name)-Product-Instance-ID: SOME_STRING_VALUE'\
--header 'content-type: application/json'\
--data '{
"refunds": [
{
"seqNo": 0,
"deductions": [
{
"account": {
"id": "string",
"ifsc": "string",
"name": "string"
},
"split": {
"unit": "INR",
"value": 0
}
}
],
"identifier": "string",
"identifierType": "BILL_ID",
"refundAmount": {
"currencyCode": "string",
"value": 0
},
"refundType": "FULL"
}
]
}'
200 Success

Response sample


{
"data":{
"refunds":[
{
"seqNo":0,
"success":true,
"amount":{
"currencyCode":"currencyCode",
"value":0
},
"billID":"billID",
"deductions":[
{
"account":{
"id":"id",
"ifsc":"ifsc",
"name":"name"
},
"split":{
"unit":"INR",
"value":0
}
}
],
"id":"id",
"initiatedAt":"2023-11-20T10:44:51.693Z",
"status":"status",
"transactionRefID":"transactionRefID",
"code":"code",
"detail":"detail",
"title":"title"
}
],
"batchID":"batchID"
},
"status":200,
"success":true
}

Get status of a refund batch

https://uat.(Website Name).co/api/v2/refund/{refundID}

Returns details a specified refund


Request

Path parameters

batchID

string

Required

ID corresponding to refund batch


Header parameters

X-(website name)-Product-Instance-ID

string

Required

Identifier for product instance. Required for authorisation.

Authorization

string

Required

OAuth token. Required for authorisation.


Response

Body

data

object

Required

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request GET \
--url https://uat.(website name).co/api/v2/refund/batch/{batchID}\
--header 'Authorization: SOME_STRING_VALUE'\
--header 'X-(website name)-Product-Instance-ID: SOME_STRING_VALUE'
200 Success

Response sample


{
"data":{
"refunds":[
{
"amount":{
"currencyCode":"currencyCode",
"value":0
},
"billID":"billID",
"deductions":[
{
"account":{
"id":"id",
"ifsc":"ifsc",
"name":"name"
},
"split":{
"unit":"INR",
"value":0
}
}
],
"id":"id",
"initiatedAt":"2023-11-20T10:45:20.051Z",
"status":"status",
"transactionRefID":"transactionRefID"
}
],
"batchID":"batchID"
},
"status":200,
"success":true
}

Get status of a refund

https://uat.(website name).co/api/v2/refund/{refundID}

Returns details a specified refund


Request

Path parameters

refundID

string

Required

ID corresponding to a specific refund request


Header parameters

X-(website name)-Product-Instance-ID

string

Required

Identifier for product instance. Required for authorisation.

Authorization

string

Required

OAuth token. Required for authorisation.


Response

Body

data

object

Required

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request GET \
--url https://uat.(website name).co/api/v2/refund/{refundID}\
--header 'Authorization: SOME_STRING_VALUE'\
--header 'X-(website name)-Product-Instance-ID: SOME_STRING_VALUE'
200 Success

Response sample


{
"data":{
"amount":{
"currencyCode":"currencyCode",
"value":0
},
"billID":"billID",
"deductions":[
{
"account":{
"id":"id",
"ifsc":"ifsc",
"name":"name"
},
"split":{
"unit":"INR",
"value":0
}
}
],
"id":"id",
"initiatedAt":"2023-11-20T10:45:48.189Z",
"status":"status",
"transactionRefID":"transactionRefID"
},
"status":200,
"success":true
}

Request

https://uat.(Website Name).co/api/v2/utilities/bills/{platformBillId}/expire

Used to expire a bill.


Request

Path parameters

platformBillId

string

Required

The unique identifier for a bill in (website name).


Header parameters

X-(website name)-Product-Instance-ID

string

Required

Identifier for product instance. Required for authorisation.

Authorization

string

Required

OAuth token. Required for authorisation.


Response

Body

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request POST \
--url https://uat.(website name).co/api/v2/utilities/bills/{platformBillId}/expire \
--header 'Authorization: SOME_STRING_VALUE'\
--header 'X-(website name)-Product-Instance-ID: SOME_STRING_VALUE'
200 Success

Response sample


{
"status":200,
"success":true
}

Request

https://partner-base-api-url.com/notifications


Request

Header parameters

Authorization

string

Required

OAuth token. Required for authorisation.


Body

events

array

Required

Array of events.

partnerDetails

object

Required

Details about the partner.

Response

Body

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request POST \
--url https://partner-base-api-url.com/notifications \
--header 'Authorization: SOME_STRING_VALUE'\
--header 'content-type: application/json'\
--data '{
"events": [
{
"data": {},
"id": "string",
"timeStamp": 0,
"type": "string"
}
],
"partnerDetails": {
"appID": "string",
"productInstanceID": "string"
}
}'
200 If the payment is successful

Response sample


{
"status":200,
"success":true
}

Retrieve reports

https://uat-bifrost.(Website Name).co/bifrost/collect/reports

Used to retrieve a report from the (Website Name) system.


Request

Header parameters

X-(website name)-Product-Instance-ID

string

Required

Identifier for product instance. Required for authorisation.

Authorization

string

Required

OAuth token. Required for authorisation.


Body

filters

object

Payload containing the filters to be applied.

productInstanceIDOfReport

string

Required

The unique identifier of the product instance in app for which the report is fetched.

Response

Body

data

object

Required

Report response data

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request POST \
--url https://uat-bifrost.(website name).co/bifrost/collect/reports \
--header 'Authorization: SOME_STRING_VALUE'\
--header 'X-(website name)-Product-Instance-ID: SOME_STRING_VALUE'\
--header 'content-type: application/json'\
--data '{
"filters": {},
"productInstanceIDOfReport": "string"
}'
200 Success

Response sample


{
"data":{
"metadata":{},
"records":[
{}
],
"reportDetails":{}
},
"status":200,
"success":true
}

Trigger mock payment

https://uat.(Website Name).co/api/v2/triggers/funds/addCredit

To trigger a mock credit for testing purposes. To test your integration, you can use this in your sandbox. This is not available in production.


Request

Header parameters

Authorization

string

Required

OAuth token. Required for authorisation.


Body

amount

number<double>

Required

Amount for the mock credit.

destinationAccount

object

Required

sourceAccount

object

Required

transactionReference

string

platformBillID from Create Link response

type

string

Valid values:

UPIACCOUNT

Response

Body

data

object

Required

status

integer

Required

HTTP status code for the response.

success

boolean

Required

Indicator to denote whether the request is successful.

Language

curl

Node

Python

Go

Request sample


curl --request POST \
--url https://uat.(website name).co/api/v2/triggers/funds/addCredit \
--header 'Authorization: SOME_STRING_VALUE'\
--header 'content-type: application/json'\
--data '{
"amount": 200,
"destinationAccount": {
"accountID": "nareshlocal@kaypay"
},
"sourceAccount": {
"accountID": "saainithil97@icici"
},
"transactionReference": "875621444531258946",
"type": "UPI"
}'
200 Success

Response sample


{
"data":{
"utr":"utr"
},
"status":200,
"success":true
}

Trigger mock settlement

https://uat.(Website Name).co/api/v2/triggers/funds/mockSettlement

A mock settlement is used for testing purposes. To test your integration, you can use this in your sandbox. This is not available in production.


Request

Header parameters

Authorization

string

Required

OAuth token. Required for authorisation.


Body

transactions

array

Required

Response

Body

200 Success

Language

curl

Node

Python

Go

Request sample


curl --request POST \
--url https://uat.(website name).co/api/v2/triggers/funds/mockSettlement \
--header 'Authorization: SOME_STRING_VALUE'\
--header 'content-type: application/json'\
--data '{
"transactions": [
{
"utr": "string"
}
]
}'
200 Success

Response sample


{}