#Collect UPI DeepLinks
#What is Collect UPI DeepLinks?
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 beapplication/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 | < |
POST |
As set by merchant | Read |
Check link status | /payment-links/< |
GET |
OAuth or JWT | Read |
Expire bill | /utilities/bills/< |
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 typeinteger
amount.currencyCode
would always beINR
.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.
- Specifying
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.
- The
name
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. - For
transactionNote
, an optional parameter, you can set a message for UPI payments made by customers. The default transaction note is "Payment for {yourbillerBillID
}”. 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 the
sourceAccounts
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:
shortURL
is 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.- While
upiID
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 typefloat
ordouble
destinationAccount.accountID
is theupiID
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 theplatformBillID
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/< The request should simply be the API URL with platformBillID appended to the path appropriately < . 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
andexpiresAt
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/< |
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—
- Amount exactness validation failure
- Duplicate payment for the same bill
- Expired bill
(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 the
Pending
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 thepending
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 settlement405884202257482938,...],"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.
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
andsecret
. - Generate new token with stored
clientID
andsecret
when token has expired. If the API you call returns401 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 formatAuthorization: Bearer <JWT_TOKEN>// Sample JWT encodedAuthorization: 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 formaturlsafe_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 : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9payload : eyJhdWQiOiI4ZjQ3ZTQxYy00Njg0LTRhZjEtYjFiOC0yNDZjODMxMTIwMzMiLCJpYXQiOjE1NzI0OTMzNTYsImp0aSI6ImM1MzQ0N2UzLTk5M2EtNDRhZS05Yzc4LTMxZjQ1YzNjMDgyZSJ9signature : 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 toeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
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 toeyJhdWQiOiI4ZjQ3ZTQxYy00Njg0LTRhZjEtYjFiOC0yNDZjODMxMTIwMzMiLCJpYXQiOjE1NzI0OTMzNTYsImp0aSI6ImM1MzQ0N2UzLTk5M2EtNDRhZS05Yzc4LTMxZjQ1YzNjMDgyZSJ9
- The JWT includes
aud
as thescheme_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. - The
iat
represents the epoch timestamp in seconds when the request was issued. Requests older than 30 seconds are considered stale and will be rejected. - The
jti
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.eyJhdWQiOiI4ZjQ3ZTQxYy00Njg0LTRhZjEtYjFiOC0yNDZjODMxMTIwMzMiLCJpYXQiOjE1NzI0OTMzNTYsImp0aSI6ImM1MzQ0N2UzLTk5M2EtNDRhZS05Yzc4LTMxZjQ1YzNjMDgyZSJ9Secret : 7c2e036c-908f-48ba-abe3-cd8745a6fa99HA256 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.
- The aud claim is not verified.
- The signature is invalid.
Below here are some samples in popular languages.
Python
## pyjwt==1.7.1import jwtimport datetimeimport uuidscheme_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 thistoken = jwt.encode(payload, secret, algorithm="HS256")// And to decode the token and verify the aud claim—try:# verified claimjwt.decode(token, secret, audience=scheme_id)print("Verified token")except jwt.PyJWTError:# unverified claimprint("Token error")
PHP
<?phprequire __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 filestatic string audience ="YourAudClaim";// this should come from your configuration filepublic 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 instanceDecodedJWT 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.
- 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
parts
—contains the split rules for settlementprimaryAccount
—money is transferred to this account after all splits have been settledaccount.id
Bank account number for the settlement of this particular splitaccount.ifsc
Bank IFSC for the settlement of desired split partaccount.name
Name that appears against the bank account accountsplit.unit
Unit by which the split part is calculated. The supported value isINR
or Indian National Rupee.split.value
Value of the split relative to the mentioned unit,INR
acceptsinteger
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.account.id
Bank account number for the primary accountaccount.ifsc
Bank IFSC for the primary accountaccount.name
Name against primary account. This is optional.- ₹600 for the bus fee account: 60000
- ₹400 for the sports fee account: 40000
- Balance of ₹1000 for the tuition fee account: 100000
"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—
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—
{"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
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
#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—
Was this page helpful?
(website name) Collect APIs
Base URL
https://uat.(Website Name).co/api/v2
Description
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
objectRequired
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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"}'
Response sample
{"data":{"expiresIn":0,"token":"token"},"status":200,"success":true}
Request
Header parameters
X-(website name)-Product-Instance-ID
stringRequired
Identifier for product instance. Required for authorisation.
Authorization
stringRequired
OAuth token. Required for authorisation.
Body
additionalInfo
objectamount
object
Amount to be refunded
amountExactness
stringRequired
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:
ANY
EXACT
EXACT_UP
EXACT_DOWN
RANGE
billerBillID
stringRequired
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
objectRequired
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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"}}}'
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
stringRequired
The unique identifier for a payment link in (website name).
Header parameters
X-(website name)-Product-Instance-ID
stringRequired
Identifier for product instance. Required for authorisation.
Authorization
stringRequired
OAuth token. Required for authorisation.
Response
Body
data
objectRequired
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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'
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
Request
Header parameters
X-(website name)-Product-Instance-ID
stringRequired
Identifier for product instance. Required for authorisation.
Authorization
stringRequired
OAuth token. Required for authorisation.
Body
refunds
arrayRequired
Contains individual transactions to refund.
Response
Body
data
objectRequired
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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"}]}'
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
Request
Path parameters
batchID
stringRequired
ID corresponding to refund batch
Header parameters
X-(website name)-Product-Instance-ID
stringRequired
Identifier for product instance. Required for authorisation.
Authorization
stringRequired
OAuth token. Required for authorisation.
Response
Body
data
objectRequired
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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'
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
Request
Path parameters
refundID
stringRequired
ID corresponding to a specific refund request
Header parameters
X-(website name)-Product-Instance-ID
stringRequired
Identifier for product instance. Required for authorisation.
Authorization
stringRequired
OAuth token. Required for authorisation.
Response
Body
data
objectRequired
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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'
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
Request
Path parameters
platformBillId
stringRequired
The unique identifier for a bill in (website name).
Header parameters
X-(website name)-Product-Instance-ID
stringRequired
Identifier for product instance. Required for authorisation.
Authorization
stringRequired
OAuth token. Required for authorisation.
Response
Body
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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'
Response sample
{"status":200,"success":true}
Request
Header parameters
Authorization
stringRequired
OAuth token. Required for authorisation.
Body
events
arrayRequired
Array of events.
partnerDetails
objectRequired
Details about the partner.
Response
Body
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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"}}'
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
stringRequired
Identifier for product instance. Required for authorisation.
Authorization
stringRequired
OAuth token. Required for authorisation.
Body
filters
object
Payload containing the filters to be applied.
productInstanceIDOfReport
stringRequired
The unique identifier of the product instance in app for which the report is fetched.
Response
Body
data
objectRequired
Report response data
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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"}'
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
stringRequired
OAuth token. Required for authorisation.
Body
amount
number<double>Required
Amount for the mock credit.
destinationAccount
objectRequired
sourceAccount
objectRequired
transactionReference
string
platformBillID from Create Link response
type
stringValid values:
UPI
ACCOUNT
Response
Body
data
objectRequired
status
integerRequired
HTTP status code for the response.
success
booleanRequired
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"}'
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
stringRequired
OAuth token. Required for authorisation.
Body
transactions
arrayRequired
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"}]}'
Response sample
{}