Endpoint
Base URLs
| Environment | Base URL |
|---|---|
| Production | https://merchant-api.sabpaisa.in |
| Staging | https://staging-sb-merchant-api.sabpaisa.in |
Full URL example (Production): POST https://merchant-api.sabpaisa.in/api/v2/payments/s2s
Authentication Headers
| Header | Required | Description |
|---|---|---|
X-Api-Key | Yes | Your API key (provided during onboarding) |
X-Merchant-Id | Yes | Your merchant code (e.g., “LPSD1”) |
Content-Type | Yes | Must be application/json |
X-Idempotency-Key | No | Unique key to prevent duplicate payments on retries |
S2S_NOT_ENABLED error, contact SabPaisa support to activate server-to-server payments.Request Examples
UPI QR — Generate QR Code for Customer to Scan
Use paymentMode: "UPI_QR" to generate a QR code string. Display it on your payment page for the customer to scan with any UPI app.
1{
2 "merchantId": "LPSD1",
3 "merchantTxnId": "ORDER_20260317_001",
4 "amount": 50000,
5 "currency": "INR",
6 "customerName": "Rahul Sharma",
7 "customerEmail": "[email protected]",
8 "customerPhone": "9876543210",
9 "paymentMode": "UPI_QR",
10 "timestamp": 1742198400,
11 "checksum": "a1b2c3d4e5f6...64_hex_chars"
12}UPI Intent — Open Customer's UPI App Directly
Use paymentMode: "UPI_INTENT" to get an intent URL that opens the customer's UPI app directly on mobile.
1{
2 "merchantId": "LPSD1",
3 "merchantTxnId": "ORDER_20260317_002",
4 "amount": 50000,
5 "currency": "INR",
6 "customerName": "Rahul Sharma",
7 "customerEmail": "[email protected]",
8 "customerPhone": "9876543210",
9 "paymentMode": "UPI_INTENT",
10 "timestamp": 1742198400,
11 "checksum": "a1b2c3d4e5f6...64_hex_chars"
12}Request Fields
Required Fields
| Field | Type | Constraint | Description |
|---|---|---|---|
merchantId | String | max 50 chars | Your merchant code |
merchantTxnId | String | max 100, alphanumeric + _ - | Your unique order/transaction ID |
amount | Long | 100 – 100000000 | Amount in paise (50000 = ₹500) |
currency | String | INR | Currency code |
customerName | String | 2 – 100 chars | Customer's full name |
customerEmail | String | valid email, max 255 | Customer's email address |
customerPhone | String | max 20 chars | Customer's phone number |
paymentMode | String | UPI_QR or UPI_INTENT | Payment mode |
checksum | String | exactly 64 hex chars | HMAC-SHA256 signature |
Optional Fields
| Field | Type | Constraint | Default | Description |
|---|---|---|---|---|
timestamp | Long | Unix seconds | — | Request timestamp (replay protection) |
description | String | max 500 chars | — | Payment description |
upiExpiryMinutes | Integer | — | 5 | QR / intent link expiry in minutes |
metadata | Object | max 50 keys | — | Custom key-value pairs |
udf1 – udf20 | String | max 255 each | — | User-defined fields (echoed in webhook) |
udf1 – udf20) are echoed back in webhook callbacks. Use them to pass your internal reference data.Checksum Generation
The checksum ensures request integrity in transit. It is an HMAC-SHA256 signature that produces a 64-character lowercase hex string.
Steps
- Build the base string:
merchantId|merchantTxnId|amount|currency|timestamp - Sign with HMAC-SHA256 using your secret key.
- Output is a 64-character lowercase hex string.
Example
Base string: "LPSD1|ORDER_001|50000|INR|1742198400"
Secret key: "your_secret_key_here"
Algorithm: HMAC-SHA256
Output: "a1b2c3d4e5f6a1b2c3d4e5f6..."
1String baseString = merchantId + "|" + merchantTxnId + "|"
2 + amount + "|" + currency + "|" + timestamp;
3Mac mac = Mac.getInstance("HmacSHA256");
4mac.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));
5String checksum = Hex.encodeHexString(mac.doFinal(baseString.getBytes()));Success Responses
Returns a upiQrString that you use to generate a QR code for the customer to scan.
1{
2 "success": true,
3 "paymentId": "sppay_abc123xyz",
4 "txnId": "SP_12345",
5 "merchantTxnId": "ORDER_20260317_001",
6 "status": "PROCESSING",
7 "amount": 50000,
8 "currency": "INR",
9 "paymentMode": "UPI_QR",
10 "upiQrString": "upi://pay?pa=merchant@upi&pn=MerchantName&am=500.00",
11 "intentUrl": null,
12 "message": "Payment initiated",
13 "traceId": "abc-def-123"
14}What to do
- Use
upiQrStringto generate a QR code and display on your payment page - Customer scans with any UPI app (GPay, PhonePe, Paytm, etc.)
- Wait for webhook callback for final status
Returns an intentUrl that opens the customer's UPI app directly on their device.
1{
2 "success": true,
3 "paymentId": "sppay_def456uvw",
4 "txnId": "SP_67890",
5 "merchantTxnId": "ORDER_20260317_002",
6 "status": "PROCESSING",
7 "amount": 50000,
8 "currency": "INR",
9 "paymentMode": "UPI_INTENT",
10 "upiQrString": null,
11 "intentUrl": "upi://pay?pa=merchant@upi&pn=MerchantName&am=500.00&tr=SP_67890",
12 "message": "Payment initiated",
13 "traceId": "def-ghi-456"
14}What to do
- Redirect the customer to
intentUrlon mobile - Customer's UPI app opens and they approve the payment
- Wait for webhook callback for final status
Error Responses
Invalid API key or merchant ID.
1{
2 "success": false,
3 "errorCode": "UNAUTHORIZED",
4 "errorMessage": "Invalid API key or merchant ID"
5}Fix: Verify your X-Api-Key and X-Merchant-Id headers.
S2S payments not activated for your merchant account.
1{
2 "success": false,
3 "errorCode": "S2S_NOT_ENABLED",
4 "errorMessage": "S2S payments are not enabled for this merchant"
5}Fix: Contact SabPaisa support to enable S2S payments for your account.
Timestamp is missing or in the future.
1{
2 "success": false,
3 "errorCode": "INVALID_TIMESTAMP",
4 "errorMessage": "Timestamp is missing or in the future"
5}Fix: Ensure your server clock is synced (NTP) and the timestamp is current Unix seconds.
Timestamp is older than 5 minutes.
1{
2 "success": false,
3 "errorCode": "REQUEST_EXPIRED",
4 "errorMessage": "Request timestamp is older than 5 minutes"
5}Fix: Generate a fresh timestamp for each request. Requests older than 5 minutes are rejected.
Checksum verification failed.
1{
2 "success": false,
3 "errorCode": "INVALID_SIGNATURE",
4 "errorMessage": "Checksum verification failed"
5}Fix: Verify your base string format is merchantId|merchantTxnId|amount|currency|timestamp and you are using the correct secret key.
Unrecognized paymentMode value.
1{
2 "success": false,
3 "errorCode": "INVALID_PAYMENT_MODE",
4 "errorMessage": "Invalid payment mode: NEFT. Currently supported: UPI_QR, UPI_INTENT"
5}Fix: Use UPI_QR or UPI_INTENT.
A required field is missing or has an invalid value.
1{
2 "success": false,
3 "errorCode": "VALIDATION_ERROR",
4 "errorMessage": "customerName: size must be between 2 and 100"
5}Fix: Check field constraints in the Request Fields section above.
A payment with the same merchantTxnId already exists.
1{
2 "success": false,
3 "errorCode": "DUPLICATE_TRANSACTION",
4 "errorMessage": "Transaction already exists with ID: ORDER_001"
5}Fix: Use a unique merchantTxnId for each payment. For retries, use the X-Idempotency-Key header.
Same X-Idempotency-Key sent with a different request body.
1{
2 "success": false,
3 "errorCode": "IDEMPOTENCY_MISMATCH",
4 "errorMessage": "Request body differs from original request with same idempotency key"
5}Fix: Use a new idempotency key for different requests.
Payment could not be initiated by the banking system.
1{
2 "success": false,
3 "errorCode": "PAYMENT_FAILED",
4 "errorMessage": "Payment could not be processed. Please try again.",
5 "traceId": "abc-123"
6}Fix: Retry the payment. If the issue persists, contact support with the traceId.
Payment service is temporarily unavailable or timed out.
1{
2 "success": false,
3 "errorCode": "SERVICE_UNAVAILABLE",
4 "errorMessage": "Payment service is temporarily unavailable. Please try again later.",
5 "traceId": "abc-123"
6}Fix: Retry after a few seconds. If the issue persists, contact support with the traceId.
Error Code Quick Reference
| Error Code | HTTP | Description | Action |
|---|---|---|---|
UNAUTHORIZED | 401 | Invalid credentials | Check API key and merchant ID |
S2S_NOT_ENABLED | 403 | S2S not enabled | Contact SabPaisa support |
VALIDATION_ERROR | 400 | Invalid request fields | Check field constraints |
INVALID_TIMESTAMP | 400 | Timestamp missing or future | Sync server clock |
REQUEST_EXPIRED | 400 | Timestamp older than 5 min | Use current timestamp |
INVALID_SIGNATURE | 400 | Checksum failed | Check base string + secret key |
INVALID_PAYMENT_MODE | 400 | Mode not recognized | Use UPI_QR or UPI_INTENT |
DUPLICATE_TRANSACTION | 400 | merchantTxnId reused | Use unique transaction ID |
IDEMPOTENCY_MISMATCH | 400 | Key reused, body changed | Use new idempotency key |
PAYMENT_FAILED | 400 | Payment rejected | Retry or contact support |
SERVICE_UNAVAILABLE | 400 | Service temporarily down | Retry after a few seconds |
PROCESSING_ERROR | 400 | Processing error | Retry or contact support |
UPI QR vs UPI Intent — When to Use
| Aspect | UPI QR | UPI Intent |
|---|---|---|
| Best for | Desktop / web checkout | Mobile app checkout |
| How it works | Customer scans QR with phone | UPI app opens on same device |
| Cross-device | Yes (QR on laptop, scan from phone) | No (same device only) |
| UPI app choice | Customer picks any app | Customer picks from installed apps |
| Your implementation | Generate QR from upiQrString | Redirect to intentUrl |
| Response field | upiQrString | intentUrl |
Post-Payment Flow
Customer Completes Payment
- UPI QR: Generate QR from
upiQrStringand display. Customer scans and pays. - UPI Intent: Customer approves payment in the redirected UPI app.
Webhook Callback
S2S UPI uses the same webhook system as the standard checkout flow. Your webhook URL receives a POST with the final payment status.
1{
2 "paymentId": "sppay_abc123xyz",
3 "merchantTxnId": "ORDER_20260317_001",
4 "status": "SUCCESS",
5 "amount": 50000,
6 "currency": "INR",
7 "paymentMode": "UPI_QR",
8 "udf1": "...",
9 "udf15": "..."
10}Possible status values: SUCCESS FAILED EXPIRED
View full Webhook documentation (signature verification, retry policy, events)Idempotency — Safe Retries
If your request times out or you're unsure whether it succeeded, retry with the same X-Idempotency-Key:
1POST /api/v2/payments/s2s
2X-Idempotency-Key: order-001-attempt-1| Scenario | Result |
|---|---|
| Same key + same body | Returns original response (no duplicate) |
| Same key + different body | Returns IDEMPOTENCY_MISMATCH error |
| Different key | Creates a new payment |
merchantTxnId as the idempotency key.Integration Checklist
- 1Obtain API key, merchant ID, and secret key from SabPaisa
- 2Confirm S2S is enabled for your account
- 3Implement HMAC-SHA256 checksum generation
- 4Set up webhook endpoint to receive payment callbacks
- 5Test UPI QR flow on staging (generate QR → scan → verify webhook)
- 6Test UPI Intent flow on staging (redirect → approve → verify webhook)
- 7Handle all error codes listed in the Error Code Reference
- 8Implement idempotency for safe retries
- 9Switch to production base URL
- 10Run end-to-end test on production
We're Here to Help
Running into an issue? Our integration support team is happy to assist. Please include:
- Your merchant ID
- The
traceIdfrom the error response - Full request and response (excluding checksum and
X-Api-Key)