UroPay does not offer payment aggregation services or UPI accounts. UroPay only provides generation of QR Code and reading UPI credit SMS for UPI Payments using the UroPay companion Android app. Please review the terms before use.
UroPay lets the registered user accept UPI payments directly to their bank account without a payment aggregator. The pre-requisite is to have the UroPay companion app continuously running on the Android phone where the user will get the UPI credit SMS. The app will read the UPI credit SMS and send the transaction details to the UroPay API. No other SMS, like OTP etc, are processed and they are ignored on the server with no storage whatsoever.
To keep things simple to implement, there are only 3 endpoints - /order/generate, /order/update and /order/status.
There is only 1 API url and it is the device which determines the TEST or PRODUCTION environments. You can login into the dashboard to change the environment.
API URL: https://api.uropay.me
All requests must include the following headers (optional headers are marked):
Content-Type: application/jsonAccept: application/jsonX-API-KEY: YOUR_API_KEY_ASSIGNED_BY_UROPAYAuthorization: Bearer `${sha512(YOUR_SECRET_ASSIGNED_BY_UROPAY)}` sha512 hashed secretAccept-Encoding: gzip, deflate, br (optional)Authentication is done via API keys. Include your API key in the header of each request:
X-API-KEY: YOUR_API_KEY_ASSIGNED_BY_UROPAY
Authorization: Bearer `${sha512(YOUR_SECRET_ASSIGNED_BY_UROPAY)}` sha512 hashed secret
DO NOT SEND PLAIN SECRET IN THE REQUEST BODY OR IN THE HEADER OF THE REQUEST
You can get an API KEY and SECRET after you login in your dashboard on https://app.uropay.me/ .
Code Examples for generating the hashed secret:
//nodejs const crypto = require('crypto'); const secret = 'YOUR_SECRET_ASSIGNED_BY_UROPAY'; const sha512 = crypto.createHash('sha512'); sha512.update(secret); const hashedSecret = sha512.digest('hex'); console.log(hashedSecret);//php $secret = 'YOUR_SECRET_ASSIGNED_BY_UROPAY'; $sha512 = hash('sha512', $secret); echo $sha512;
Generates an order and returns a QR Code and an identifier for the order to be used later.
| Parameter | Type | Required | Description |
|---|---|---|---|
| vpa | string | Yes | The VPA which will be used to receive the payment. |
| vpaName | string | Yes | The name to be shown for the VPA |
| amount | number | Yes | The amount in paise. For example, if the amount is ₹ 150/-, the amount should be 15000. The amount should be in RUPEES only. |
| merchantOrderId | string | Yes | The order id provided by the merchant |
| customerName | string | Yes | Customer name who will pay the money |
| customerEmail | string | Yes | Customer email who will pay the money and who will receive a confirmation email from UroPay's side |
| transactionNote | string | No | An optional field which is shown in the UPI app. It can be an identifier or a small description |
| notes | JSON | No | a key value pair JSON object. This is only for internal use |
curl -X POST https://api.uropay.me/order/generate \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'X-API-KEY: YOUR_API_KEY_ASSIGNED_BY_UROPAY' \
-H 'Accept-Encoding: gzip, deflate, br' \
-H 'Authorization: Bearer `${sha512(YOUR_SECRET_ASSIGNED_BY_UROPAY)}`' \
-d '{
"vpa": "abc@icici",
"vpaName": "John Doe",
"amount": 15000,
"merchantOrderId": "ORDER1247",
"transactionNote": "For ORDER1247",
"customerName": "Jane Doe",
"customerEmail": "jane@gmail.com",
"notes": {
"key1": "value1",
"key2": "value2"
}
}'
{
"code": 200,
"status": "success",
"message": "Order created successfully",
"data": {
"uroPayOrderId": "india-bharat-united",
"orderStatus": "CREATED",
"upiString": "upi://pay?pa=abc@icici&pn=John%20Doe&am=150&cu=INR&tn=For%20ORDER1247&tr=india-bharat-united",
"qrCode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhAQMAAAAEfUA5AAAABlBMVEX///8AAABVwtN+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACAElEQVRYhdWYsW3EMAxFKbhwqRE0ijY7aTSP4hFcqjDM8H/6HAQXXC2qCGw9F8eI/PyUyNfVFEvWo+i1DKkdr/xju5PSF394wks6pWx4Lf3iblC6qG7N4hXxLR15l8t3A9OkR9nSudrh4TB7fIpIq57rXvW//8Zs1LNuZOTdKDyuj5wMRV0ZjO41Id5+gv7VjVj0WdA6xQmq7h86HYki3q1xiznZddiH6bT4+6z0JSj4y9SsyoJYrO3YwmOLSZtlWfUeio7jaqb+YVQqeRMvG7gCtffd9brFpNC6qnfHoSuAMtj7o4TzUTuNwyrGUg/AisfCMoo60pj0tYy8NXSYCknDwWQlRdZFpFhQtUefzc5Y1p0ZpiYkNXcpaDOYCPghHs0VZNe6KSmdjFzIuouivKCE9JSn9qNRKx72UJ/LTBlAkYXFTzAexdSiODGLl1vwz43+WYJS6zAK9WazYfzsoQefJ6Xoj52zpK8Fx4Wse/xzMOpTjDsZHe5khCKNrAtKPeswXmIuW5B1b30OSeEK9H0nI/TPhaNMnZb6ohez6ZhZaB0HdVQ1JmUd+XQMek/HUDPX53j0riPUDW4vf+MtYanfjPnV0rh9juekzk4xwJBSn9N9URGYIkKfYjj/i+S4lFmHeM0/r/vdU6HPW1B6KwN8TlJex4h3nOcOKhr9un4AxDa+W6YafgEAAAAASUVORK5CYII=",
"amountInRupees": "150.00"
}
}
Once the customer pays for the order, the developer needs to ask the customer for the UPI Reference Number to update UroPay else the system will not be able to call your webhook on your server to update the payment status.
| Parameter | Type | Required | Description |
|---|---|---|---|
| uroPayOrderId | string | Yes | The order id provided by UroPay to the merchant when the order was generated in the generate order api endpoint. |
| referenceNumber | string | Yes | The UPI Reference Number provided by the customer after they have paid for the order. This needs to be unique across TEST and LIVE environments. |
| orderStatus | string | No | You can update the order status if you need. Values allowed: CREATED | UPDATED | COMPLETED | FAILED | PENDING | CANCELLED. |
curl -X PUT https://api.uropay.me/order/update \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'X-API-KEY: YOUR_API_KEY_ASSIGNED_BY_UROPAY' \
-H 'Accept-Encoding: gzip, deflate, br' \
-H 'Authorization: Bearer `${sha512(YOUR_SECRET_ASSIGNED_BY_UROPAY)}`' \
-d '{
"uroPayOrderId": "india-bharat-united",
"referenceNumber": "280836361135"
}'
{
"code": 200,
"status": "success",
"message": "UPI referenceNumber in order: india-bharat-united updated successfully",
"data": {
"uroPayOrderId": "india-bharat-united",
"orderStatus": "UPDATED"
}
}
No need to update the order when the customer does not pay. In this scenario, the order will remain in CREATED state in your account.
This endpoint can be polled at regular intervals to get the status of the order by using uroPayOrderId
| Parameter | Type | Required | Description |
|---|---|---|---|
| uroPayOrderId | string | Yes | The order id provided by UroPay to the merchant when the order was generated in the generate order api endpoint. |
curl -X GET 'https://api.uropay.me/order/status/india-bharat-united' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'X-API-KEY: YOUR_API_KEY_ASSIGNED_BY_UROPAY' \
-H 'Accept-Encoding: gzip, deflate, br'
Important: You do not need to send the authorisation header. This endpoint can be used in client side code.
{
"code": 200,
"status": "success",
"message": "Order status is PENDING" or "COMPLETED",
"data": {
"uroPayOrderId": "india-bharat-united",
"orderStatus": "PENDING" or "COMPLETED"
}
}
| Code | Description |
|---|---|
| 400 | Bad Request - The request was invalid. |
| 401 | Unauthorized - Authentication failed or not provided. |
| 403 | Forbidden - You don't have permission to access this resource. |
| 404 | Not Found - The specified resource was not found. |
| 429 | Too Many Requests - Rate limit exceeded. |
| 500 | Internal Server Error - Something went wrong on our end. |
The API has a rate limit of 60 requests per minute (one request every 1 second) per API key. If you exceed this limit, you'll receive a 429 Too many requests. response.
The response will include the following headers:
RateLimit-Policy: The rate limit time windowRateLimit-Limit: The maximum number of requests allowed per time windowRateLimit-Remaining: The remaining number of requests allowed per time windowOnce the UPI credit SMS arrives at the device, the UroPay companion Android app will read the SMS and send the SMS to the UroPay API. No other SMS, like OTP etc, are processed, and they are ignored on the server with no storage whatsoever.
Once the transaction details are extracted from the SMS, the SMS is discarded and the transaction details are forwarded to the Webhook or Webhooks which the user has defined in the dashboard. The server will forward a JSON object as POST http request to the webhook.
Along with JSON object, the server will also forward headers which can be used to validate the request.
| Header | Value | Description | Code Sample |
|---|---|---|---|
| Content-Type | application/json | The content type of the request | |
| X-Uropay-Environment | TEST or PRODUCTION | Based on the device associated with the environment set in the dashboard, the value will be TEST or PRODUCTION. | |
| X-Uropay-Webhook-Id | base 64 encoded string | A unique id for each webhook so that the duplicate calls can be handled. | |
| X-Uropay-Signature | Signature = HMAC-SHA-256(hashed-secret, JSON.stringify(transactionData + environment)) | A unique hash which is generated using HMAC SHA-256 algorithm. This identifies that the webhook call is genuine and generated by UroPay. You need to check this signature before processing the webhook call at your end. Important: The secret should be sha512 hashed before using it. Check "Authentication" section. | For consistent signature, the transaction data should be sorted before generating the signature. For example:
const sortedData = Object.fromEntries(
Object.entries(data).sort(([a], [b]) => a.localeCompare(b))
);
const payload = {...sortedData, environment: environment};
|
Following is the JSON object you will receive in the webhook call. from and vpa keys are optional and will contain null if not present.
Every value is a STRING to keep it flexible. You need to typecase it to the required type at your end.
IMPORTANT: The webhook call will happen more than once. First, it will happen as soon as your device receives the UPI credit SMS, and the second one will happen when you update the order with UPI Reference Number. Please handle multiple webhook calls accordingly.
If you do not have UroPay Companion App installed, then the `amount` key will be `empty or 0`.
{
"amount': "150.00",
"referenceNumber": "430686551035",
"from": "Gaurav Chandra",
"vpa": "abc@icici"
}
You can use referenceNumber key to match the payment in your system.
Important: Your webhook URL must respond with HTTP STATUS 200 OK else that webhook call will be marked as FAILED. Also, you can define as many webhooks you want, and UroPay will call them in sequence.
Contact at gaurav@uropay.me if you have any queries or suggestions.