Integrate UPI Reserve Pay
Integrate UPI Reserve Pay (SBMD) APIs to block and debit funds using a single customer authorisation.
UPI Reserve Pay APIs use the single-block, multiple-debit (SBMD) framework to manage scheduled or recurring transactions. With a single customer authorisation, this system allows businesses to block a specific sum from the customer's account. This reserved fund can then be debited automatically multiple times, eliminating the need for further customer approvals and ensuring a smoother, more reliable payment flow.
Example
A customer using the Acme Quick Commerce app authorises a one-time UPI block of ₹2,000 for future purchases. When they place a ₹400 order on Monday and a ₹600 order on Wednesday, both amounts are automatically debited from that reserved fund. The customer never has to enter a PIN at checkout, making their repeat orders completely frictionless.
To create an authorisation transaction using the Razorpay APIs, you need to:
Razorpay links recurring tokens to customers using a unique identifier generated through the Customer API.
The following endpoint creates a customer.
name
string The name of the customer. For example, John Smith.
string The email address of the customer. For example, john.smith@example.com.
contact
string The phone number of the customer. For example, +11234567890.
fail_existing
optional
string The request throws an exception by default if a customer with the exact details already exists. You can pass an additional parameter fail_existing to get the existing customer's details in the response. Possible values:
1(default): If a customer with the same details already exists, throws an error.0: If a customer with the same details already exists, fetches details of the existing customer.
notes
optional
object Key-value pair that can be used to store additional information about the entity. Maximum 15 key-value pairs, 256 characters (maximum) each. For example, "note_key": "Beam me up Scotty”.
id
string Unique identifier of the customer. For example, cust_1Aa00000000004.
entity
optional
string Indicates the type of entity.
name
string Customer's name. Alphanumeric, with period (.), apostrophe ('), forward slash (/), at (@) and parentheses allowed. The name must be between 3-50 characters in length.
contact
string The customer's phone number. A maximum length of 15 characters including country code.
string The customer's email address. A maximum length of 64 characters.
gstin
string GST number linked to the customer. For example, 29XAbbA4369J1PA.
notes
json object This is a key-value pair that can be used to store additional information about the entity. It can hold a maximum of 15 key-value pairs, 256 characters (maximum) each. For example, "note_key": "Beam me up Scotty”.
created_at
integer UNIX timestamp, when the customer was created. For example, 1234567890.
Use the
to create a unique Razorpayorder_id that is associated with the authorisation transaction for a one time mandate. To create a one-time mandate, pass the value of the frequency parameter as one_time. The following endpoint creates an order.
amount
mandatory
integer Amount in currency subunits. The maximum amount that can be blocked is ₹15,000.
currency
mandatory
string The 3-letter ISO currency code for the payment. Currently, we only support INR.
customer_id
mandatory
string The unique identifier of the customer. For example, cust_4xbQrmEoA5WJ01.
method
mandatory
string The authorisation method. Here, it is upi.
receipt
optional
string A user-entered unique identifier of the order. For example, Receipt No. 1. You should map this parameter to the order_id sent by Razorpay.
notes
optional
object Key-value pair that can be used to store additional information about the entity. Maximum 15 key-value pairs, 256 characters each. For example, "note_key": "Beam me up Scotty”.
token
object Details related to the authorisation such as max amount, frequency and expiry information.
max_amount
mandatory
integer The maximum amount that can be debited is ₹15,000.
expire_at
mandatory
integer The Unix timestamp that indicates when the authorisation transaction must expire. The default and the maximum value allowed is 90 days.
frequency
mandatory
string The frequency at which you can charge your customer. The value should be as_presented.
type
mandatory
string Indicates the type of payment. Here, the possible value is single_block_multiple_debit.
id
string The unique identifier of the order.
amount
integer The amount for which the order was created, in currency subunits.
entity
string Name of the entity. Here, it is order.
amount_paid
integer The amount paid against the order.
amount_due
integer The amount pending against the order.
currency
string ISO code for the currency in which you want to accept the payment. The default length is 3 characters.
receipt
string Receipt number that corresponds to this order.
status
string The status of the order. Possible values:
created: When you create an order it is in thecreatedstate. It stays in this state till a payment is attempted on it.attempted: An order moves fromcreatedtoattemptedstate when a payment is first attempted on it. It remains in theattemptedstate till one payment associated with that order is captured.paid: After the successful capture of the payment, the order moves to thepaidstate. No further payment requests are permitted once the order moves to thepaidstate. The order stays in thepaidstate even if the payment associated with the order is refunded.
attempts
integer The number of payment attempts, successful and failed, that have been made against this order.
notes
json object Key-value pair that can be used to store additional information about the entity. Maximum 15 key-value pairs, 256 characters (maximum) each. For example, "note_key": "Beam me up Scotty”.
created_at
integer Indicates the Unix timestamp when this order was created.
Use this API endpoint to initiate UPI mandate authorisation via intent flow. This step creates a pending token. The customer approves the mandate in their TPAP app.
curl -u <YOUR_KEY_ID>:<YOUR_KEY_SECRET> \-X POST https://api.razorpay.com/v1/orders \-H "Content-Type: application/json" \-d '{"amount": 200,"contact": "9123456780","currency": "INR","customer_id": "cust_RtNzXmWrRe0Edr","email": "gaurav.kumar@example.com","method": "upi","order_id": "order_RtP3VPM5YrzXr8","recurring": true,"upi": {"flow": "intent"}}'
amount
integer The amount you want to charge your customer. This should be the same as the order amount. The maximum amount that can be blocked is ₹15,000.
currency
string The 3-letter ISO currency code for the payment.
order_id
string The unique identifier of the order created.
customer_id
string The unique identifier of the customer you want to charge.
upi.flow
string The UPI payment flow for the transaction. Here, the value must be intent.
recurring
string Determines whether recurring payment is enabled or not.
true: Recurring payment is enabled.false: Recurring payment is not enabled.
contact
string The customer's phone number.
string The customer's email address.
notes
object Key-value pair you can use to store additional information about the entity. Maximum of 15 key-value pairs, 256 characters each.
description
string A user-entered description for the payment.
razorpay_payment_id
string The unique identifier of the payment created. For example, pay_RtP3bnk51QvOF9.
next
array A list of action objects describing the next steps to complete the payment.
next.action
string The type of action to perform. Possible values:
intent: Redirects the customer to their TPAP app to approve the mandate.poll: Used to poll the payment status.
next.url
string The URL corresponding to the action. For intent, this is a UPI deep link. For poll, this is the Razorpay API endpoint to check payment status.
Given below is a list of possible errors you may face while making the authorisation payment.
- Description: Payment was unsuccessful as the bank linked to this UPI ID is temporarily unavailable. Any amount deducted will be refunded within 5-7 working days.
- Next Steps: Retry after some time.
- Description: Payment was unsuccessful due to a temporary issue at your bank. Any amount deducted will be refunded within 5-7 working days.
- Next Steps: Retry after some time.
- Description: Payment was unsuccessful as it was declined by your bank. Any amount deducted will be refunded within 5-7 working days.
- Next Steps: Retry after some time.
- Description: Payment processing failed due to error at bank or wallet gateway.
- Next Steps: Retry after some time.
- Description: Payment was unsuccessful due to a temporary issue. Any amount deducted will be refunded within 5-7 working days.
- Next Steps: Retry after some time.
- Description: Payment processing failed due to error at bank or wallet gateway.
- Next Steps: Retry after some time.
- Description: Payment was unsuccessful as it was declined by your bank. Any amount deducted will be refunded within 5-7 working days.
- Next Steps: Ask the customer to retry with other account.
- Description: Payment was unsuccessful due to a temporary issue. Any amount deducted will be refunded within 5-7 working days.
- Next Steps: Retry after some time.
- Description: Payment was unsuccessful as it was declined by your bank. Any amount deducted will be refunded within 5-7 working days.
- Next Steps: Retry after some time.
- Description: Payment failed because Transaction amount limit has exceeded.
- Next Steps: Reach out to the customer to collect the amount.
In a Single Block Multiple Debit (SBMD) flow, the Token represents the unique mandate or authorisation.
You can retrieve the token_id using the Dashboard or the APIs given below.
A customer can have multiple tokens and these tokens can be used to create subsequent payments for multiple products or services.
Watch Out!
- This endpoint will not fetch the details of expired and unused tokens.
- The UPI tokens are not populated in the API response if the
save_vpafeature is not enabled in your account. Please raise a request with our to get this activated.
The following endpoint retrieves tokens linked to a customer.
entity
string The name of the entity. Here, it is collection.
count
integer The total number of tokens returned in the response.
items
array A list of token objects associated with the customer.
id
string The unique identifier of the token. For example, token_RtOSr9o9lZwv5C.
entity
string The name of the entity. Here, it is token.
token
string The token value used to identify the mandate.
bank
string The bank associated with the token. Returns null for UPI tokens.
wallet
string The wallet associated with the token. Returns null for UPI tokens.
method
string The payment method associated with the token. Here, it is upi.
vpa
json object Details of the customer's UPI VPA linked to the token.
username
string The username part of the customer's UPI
handle
string The handle (bank or PSP) part of the customer's UPI For example, upi.
name
string The account holder's name as registered with the bank. Returns null if not available.
status
string The status of the For example, valid. Returns null if not yet validated.
received_at
integer Unix timestamp at which the VPA was received.
recurring
boolean Indicates whether the token is enabled for recurring payments. Possible values:
true: Token is enabled for recurring payments.false: Token us not enabled for recurring payments.
recurring_details
json object Details of the recurring mandate associated with the token.
status
string The status of the recurring mandate. For example, confirmed.
failure_reason
string The reason for mandate failure, if applicable. Returns null if there is no failure.
amount_blocked
integer The amount blocked against the mandate, in currency subunits.
amount_debited
integer The amount debited against the mandate so far, in currency subunits.
auth_type
string The authentication type used. Returns null if not applicable.
mrn
string The mandate reference number. Returns null if not yet assigned.
used_at
integer Unix timestamp at which the token was last used. Returns null if unused.
created_at
integer Unix timestamp at which the token was created.
start_time
integer Unix timestamp at which the mandate validity begins.
notes
array Key-value pairs used to store additional information. Returns an empty array if no notes are added.
error_description
string Description of the error, if any. Returns null for successful mandates.
entity_id
string The identifier of the entity linked to the token. Returns null if not applicable.
dcc_enabled
boolean Indicates whether Dynamic Currency Conversion (DCC) is enabled. Possible values:
true: DCC is enabled.false: DCC is not enabled.
max_amount
integer The maximum amount that can be debited per transaction, in currency subunits.
expired_at
integer Unix timestamp at which the token expires.
The following endpoint fetches the token_id using a payment_id.
id
string The unique identifier of the payment. For example, pay_RtP3bnk51QvOF9.
entity
string The name of the entity. Here, it is payment.
amount
integer The payment amount in currency subunits.
currency
string The ISO currency code for the payment. For example, INR.
status
string The status of the payment.
order_id
string The unique identifier of the order associated with the payment.
invoice_id
string The unique identifier of the invoice associated with the payment. Returns null if not applicable.
international
boolean Indicates whether the payment is an international transaction. Possible values:
true: It is an international payment.false: It is a domestic payment.
method
string The payment method used. Here, it is upi.
amount_refunded
integer The amount refunded for the payment, in currency subunits.
refund_status
string The refund status of the payment. Returns null if no refund has been initiated.
captured
boolean Indicates whether the payment has been captured. Possible values:
true: It is captured.false: It is not captured.
description
string A description for the payment. Returns null if not provided.
card_id
string The unique identifier of the card used for the payment. Returns null for UPI payments.
bank
string The bank associated with the payment. Returns null for UPI payments.
wallet
string The wallet used for the payment. Returns null for UPI payments.
vpa
string The customer's virtual payment address (VPA). Returns null until the mandate is confirmed.
string The customer's email address.
contact
string The customer's phone number.
customer_id
string The unique identifier of the customer.
token_id
string The unique identifier of the token created for the recurring payment mandate.
notes
json object Key-value pair used to store additional information about the entity. Maximum 15 key-value pairs, 256 characters each.
fee
integer The fee charged by Razorpay for the payment, in currency subunits. Returns null if not yet captured.
tax
integer The tax charged on the Razorpay fee. Returns null if not yet captured.
error_code
string The error code if the payment failed. Returns null for successful payments.
error_description
string The description of the error. Returns null for successful payments.
error_source
string The source of the error. Returns null for successful payments.
error_step
string The step at which the error occurred. Returns null for successful payments.
error_reason
string The reason for the error. Returns null for successful payments.
acquirer_data
json object Acquirer-specific data for the payment.
acquirer_data.rrn
string The retrieval reference number (RRN) assigned by the bank. Returns null until the payment is processed.
created_at
integer Unix timestamp at which the payment was created.
upi
json object UPI details.
vpa
string The customer's UPI Returns null until the mandate is confirmed.
flow
string The UPI payment flow used. Here, it is intent.
Handy Tips
You can also retrieve the token_id via the
Use this API to fetch token details using token_id and customer_id as path parameters.
curl -u <YOUR_KEY_ID>:<YOUR_KEY_SECRET> \-X GET https://api.razorpay.com/v1/customers/cust_RtNzXmWrRe0Edr/tokens/token_RtOSr9o9lZwv5C
id
string The unique identifier of the token. For example, token_RtOSr9o9lZwv5C.
entity
string The name of the entity. Here, it is token.
token
string The token value used to identify the mandate.
bank
string The bank associated with the token. Returns null for UPI tokens.
wallet
string The wallet associated with the token. Returns null for UPI tokens.
method
string The payment method associated with the token. Here, it is upi.
vpa
json object Details of the customer's UPI VPA linked to the token.
username
string The username part of the customer's UPI
handle
string The handle (bank or PSP) part of the customer's UPI For example, upi.
name
string The account holder's name as registered with the bank.
status
string The status of the For example, valid.
received_at
integer Unix timestamp at which the VPA was received.
recurring
boolean Indicates whether the token is enabled for recurring payments. Possible values: true, false.
recurring_details
json object Details of the recurring mandate associated with the token.
status
string The status of the recurring mandate. For example, confirmed.
failure_reason
string The reason for mandate failure, if applicable.
amount_blocked
integer The amount blocked against the mandate, in currency subunits.
amount_debited
integer The amount debited against the mandate so far, in currency subunits.
auth_type
string The authentication type used. Returns null if not applicable.
mrn
string The mandate reference number. Returns null if not yet assigned.
used_at
integer Unix timestamp at which the token was last used.
created_at
integer Unix timestamp at which the token was created.
start_time
integer Unix timestamp at which the mandate validity begins.
notes
array Key-value pairs used to store additional information. Returns an empty array if no notes are added.
error_description
string Description of the error, if any. Returns null for successful mandates.
entity_id
string The identifier of the entity linked to the token. Returns null if not applicable.
dcc_enabled
boolean Indicates whether Dynamic Currency Conversion (DCC) is enabled. Possible values:
true: DCC is enabled.false: DCC is not enabled.
max_amount
integer The maximum amount that can be debited per transaction, in currency subunits.
expired_at
integer Unix timestamp at which the token expires.
Once the initial amount block is authorised, you can execute debits against the mandate. For each debit, you need to:
Handy Tips
Before initiating a debit, it is good practice to check the remaining funds available under the mandate to avoid payment failures. See
.You have to create a new order to charge a one time mandate. This order is different from the one created during the authorisation transaction.
The following endpoint creates an order.
amount
mandatory
integer Amount in currency subunits.
currency
mandatory
string The 3-letter ISO currency code for the payment.
receipt
optional
string A user-entered unique identifier for the order. For example, Receipt No. 1. You should map this parameter to the order_id sent by Razorpay.
notes
optional
object Key-value pair you can use to store additional information about the entity. Maximum of 15 key-value pairs, 256 characters each. For example, "note_key": "Beam me up Scotty”.
payment_capture
mandatory
boolean Determines whether the payment status should be changed to captured automatically or not. Possible values:
true: Payments are captured automatically.false: Payments are not captured automatically. You can manually capture payments using the .
id
string The unique identifier of the order. For example, order_1Aa00000000002.
entity
string The name of the entity. Here, it is order.
amount
integer The amount for which the order was created, in currency subunits.
amount_paid
integer The amount paid against the order, in currency subunits.
amount_due
integer The amount pending against the order, in currency subunits.
currency
string The ISO currency code for the order. For example, INR.
receipt
string The receipt number corresponding to the order.
offer_id
string The unique identifier of the offer applied to the order. Returns null if no offer is applied.
status
string The status of the order.
attempts
integer The number of payment attempts made against this order.
notes
json object Key-value pairs used to store additional information about the entity. Maximum 15 key-value pairs, 256 characters each.
created_at
integer Unix timestamp at which the order was created.
Use the following endpoint to create a payment against the blocked amount.
curl -u [YOUR_KEY_ID]:[YOUR_KEY_SECRET] \-X POST https://api.razorpay.com/v1/payments/create/json-H "Content-Type: application/json" \-d '{"amount": 100,"currency": "INR","order_id": "order_RtOeB96x8bofcC","customer_id": "cust_RtNzXmWrRe0Edr","token": "token_RtOSr9o9lZwv5C","recurring": true,"contact": "9876543210","email":"gaurav.kumar@example.com","notes": {"note_key 1": "note_key","note_key 2": "Beam me up Scotty"},"description": "Creating recurring payment for Gaurav Kumar"}'
amount
integer The amount you want to charge your customer. This should be the same as the order amount.
currency
string The 3-letter ISO currency code for the payment.
order_id
string The unique identifier of the order created.
customer_id
string The unique identifier of the customer you want to charge.
token
string The token_id generated when the customer successfully completes the authorisation payment.
recurring
string Determines whether recurring payment is enabled or not.
true: Recurring payment is enabled.false: Recurring payment is not enabled.
contact
string The customer's phone number.
string The customer's email address.
notes
object Key-value pair you can use to store additional information about the entity. Maximum of 15 key-value pairs, 256 characters each.
description
string A user-entered description for the payment.
Is this integration guide useful?
ON THIS PAGE