AEPS — On Behalf of Your Merchants
Every AEPS endpoint below is a real, callable route — POST {baseUrl}/process/aeps/<route> — encrypted with your partner API key (see Authentication & Security). Generated and cross-checked against BucksBox-Vendor.postman_collection.json.
Base URLs
| Environment | Base URL |
|---|---|
| Production | https://api.bucksbox.in/gateway |
| Staging | https://api.bucksbox.in/gateway-stage |
e.g. production Withdrawal is POST https://api.bucksbox.in/gateway/process/aeps/withdrawal.
merchantId is required on every call
paymentSystem resolves the acting merchant as req.user?.merchantId ?? req.body.merchantId. Your partner API key resolves only req.vendorId — never req.merchantId — so every request body below carries "merchantId" to say which of your merchants the call is for. Omit it and the call fails (merchant not found) rather than silently succeeding against the wrong account. paymentSystem also verifies server-side that the merchantId you send actually belongs to your partner account before processing anything.
All bodies below are the plaintext you AES-256-GCM-encrypt into { "payload": "..." } — see Authentication & Security for the encryption/checksum steps, headers, and response decryption.
Onboarding
One-time device/agent onboarding, in order.
1. Initialize
POST https://api.bucksbox.in/gateway/process/aeps/initialize
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123" }
{ "merchantId": "MERCHANT123", "service": "AEPS" }
Creates the AEPS Service-KYC record for this merchant if one doesn't exist. Note this specific response is not wrapped in the usual {statusCode, message, data} envelope — it returns merchantId/service directly on success (falls back to the standard envelope on failure).
2. Onboarding
POST https://api.bucksbox.in/gateway/process/aeps/onboarding
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123" }
{ "statusCode": "00", "otp_status": true, "otp_reqid": "OTPREQ-...", "...": "remaining fields are NSDL's own onboarding response, passed through" }
Requires merchant.merchantinfo to already exist. Triggers NSDL onboarding and auto-requests the first OTP.
3. Request OTP
POST https://api.bucksbox.in/gateway/process/aeps/request_otp
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123" }
{ "statusCode": "00", "message": "success", "data": { "otpreqid": "OTPREQ-..." } }
Re-sends the onboarding OTP if the one from Onboarding expired.
4. Validate OTP
POST https://api.bucksbox.in/gateway/process/aeps/validate_otp
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123", "otp": "123456", "otpreqid": "OTPREQ-..." }
{ "statusCode": "00", "message": "success" }
5. Verify PAN
POST https://api.bucksbox.in/gateway/process/aeps/verify_pan
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123", "pan": "ABCDE1234F", "name": "Ramesh Kumar", "dob": "1990-01-15" }
{ "statusCode": "00", "message": "success", "data": { "...": "NSDL PAN-verification response, passed through" } }
6. Update UID (Aadhaar)
POST https://api.bucksbox.in/gateway/process/aeps/update_UID
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123", "aadhaarno": "999999999999" }
{ "statusCode": "00", "message": "success" }
7. Update Biodetail
POST https://api.bucksbox.in/gateway/process/aeps/updatebiodetail
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123", "PidData": "<PidData XML from the RD service>", "aadhaarno": "999999999999" }
{ "statusCode": "00", "message": "success" }
8. Submit
POST https://api.bucksbox.in/gateway/process/aeps/submit
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123" }
{ "statusCode": "00", "message": "success", "data": { "...": "NSDL confirmation response, passed through" } }
Finalizes onboarding with NSDL, using the merchant's own appid as the reference.
9. Status Check
GET https://api.bucksbox.in/gateway/process/aeps/statusCheck
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123" }
{ "statusCode": "00", "message": "success", "data": { "...": "NSDL onboarding-status response, passed through" } }
GET, but still sent with an encrypted body — the gateway forwards GET /process/* with a body intact for exactly this route.
10. Get Agent Detail
POST https://api.bucksbox.in/gateway/process/aeps/GetAgentDetail
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123", "agentId": "" }
{ "statusCode": "00", "message": "success", "data": { "...": "NSDL agent-detail response, passed through" } }
agentId optional — empty string defaults to the merchant's own terminal MID.
Transactions
All five share one request shape and one response envelope. BankName is the receiving bank's NSDL IIN — see Banks below for valid values.
11. Withdrawal
POST https://api.bucksbox.in/gateway/process/aeps/withdrawal
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{
"merchantId": "MERCHANT123",
"AadharNo": "999999999999",
"TxnAmount": 1000,
"Latitude": "19.0760",
"Longitude": "72.8777",
"CustomerName": "Ramesh Kumar",
"PidData": "<PidData XML from the RD service>",
"BankName": "918152"
}
{
"statusCode": "00",
"message": "Transaction successful",
"data": {
"ResponseCode": "00",
"ResponseStatus": "SUCCESS",
"Balance": "15230.00",
"STAN": "011032",
"RetailerReferenceNumber": "RRN-...",
"ReferenceNo": "...",
"AuthCode": "cdcf3f268b87422f859e0b10676bfde8",
"AadharNo": "********4821"
}
}
Balance here is the balance after the withdrawal. ResponseCode "00" = success, anything else = failed. No response at all (NSDL network timeout) is treated as pending, not failed — paymentSystem records the attempt with a generated reference (AEPS-NR-<timestamp>) for later reconciliation.
12. Balance Enquiry
POST https://api.bucksbox.in/gateway/process/aeps/balance
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{
"merchantId": "MERCHANT123",
"AadharNo": "999999999999",
"TxnAmount": 0,
"Latitude": "19.0760",
"Longitude": "72.8777",
"CustomerName": "Ramesh Kumar",
"PidData": "<PidData XML from the RD service>",
"BankName": "918152"
}
{
"statusCode": "00",
"message": "Transaction successful",
"data": { "ResponseCode": "00", "ResponseStatus": "SUCCESS", "Balance": "15230.00", "STAN": "011033", "RetailerReferenceNumber": "RRN-...", "AadharNo": "********4821" }
}
TxnAmount is still required by the backend validator even though a balance enquiry has no amount — send 0.
13. Mini Statement
POST https://api.bucksbox.in/gateway/process/aeps/minstatement
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{
"merchantId": "MERCHANT123",
"AadharNo": "999999999999",
"TxnAmount": 0,
"Latitude": "19.0760",
"Longitude": "72.8777",
"CustomerName": "Ramesh Kumar",
"PidData": "<PidData XML from the RD service>",
"BankName": "918152"
}
{
"statusCode": "00",
"message": "Transaction successful",
"data": {
"ResponseCode": "00",
"ResponseStatus": "SUCCESS",
"Ministatement": "02/06 POS/D/5017000018 C 100.00\n01/06 POS/W/5017000017 D 500.00",
"STAN": "011034",
"AadharNo": "********4821"
}
}
Ministatement is a single \n-delimited string (one line per transaction) — NSDL's own format, passed through as-is, not a JSON array.
14. Req Auth (daily agent authentication)
POST https://api.bucksbox.in/gateway/process/aeps/reqAuth
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{
"merchantId": "MERCHANT123",
"AadharNo": "999999999999",
"TxnAmount": 0,
"Latitude": "19.0760",
"Longitude": "72.8777",
"CustomerName": "Ramesh Kumar",
"PidData": "<PidData XML from the RD service>",
"BankName": "918152"
}
{ "statusCode": "00", "message": "Transaction successful", "data": { "ResponseCode": "00", "ResponseStatus": "SUCCESS", "STAN": "011030" } }
One-time (24h) NSDL agent authentication — also run automatically on the first transaction of the day if you skip it. No Balance/Ministatement field; this is a pure auth handshake.
15. Purchase (Aadhaar Pay)
POST https://api.bucksbox.in/gateway/process/aeps/purchase
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{
"merchantId": "MERCHANT123",
"AadharNo": "999999999999",
"TxnAmount": 350,
"Latitude": "19.0760",
"Longitude": "72.8777",
"CustomerName": "Ramesh Kumar",
"PidData": "<PidData XML from the RD service>",
"BankName": "918152"
}
{
"statusCode": "00",
"message": "Transaction successful",
"data": { "ResponseCode": "00", "ResponseStatus": "SUCCESS", "STAN": "011035", "RetailerReferenceNumber": "RRN-...", "ReferenceNo": "...", "AuthCode": "9f1c2a3b4d5e6f708192a3b4c5d6e7f8", "AadharNo": "********4821" }
}
Merchant-assisted debit at the point of sale — same shape as Withdrawal, minus Balance (there's no "balance after" for a purchase).
16. Auth Status
GET https://api.bucksbox.in/gateway/process/aeps/authStatus
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{ "merchantId": "MERCHANT123" }
{ "statusCode": "00", "data": { "authenticated": true, "tid": "TID001", "authenticatedAt": "2026-07-04T09:00:00Z", "expiresAt": "2026-07-05T09:00:00Z" } }
Read-only — checks whether a Req Auth session already exists for this merchant's terminal. Never calls NSDL.
17. Banks (IIN list)
GET https://api.bucksbox.in/gateway/process/aeps/banks
X-Client-Id: <your apiKey>
Plaintext body — encrypt with AES-256-GCM using your SaltAESKey (64-char hex or 44-char base64, both decode to 32 bytes) before sending as { "payload": "..." }:
{}
{ "statusCode": "00", "message": "success", "data": [ { "iin": "918152", "bankName": "State Bank of India" }, { "iin": "607086", "bankName": "Axis Bank" } ] }
No merchantId needed — static reference list. BankName on every transaction above must be one of these iin values.
Cash Deposit is not implemented yet
The checksum layer has a CD (Cash Deposit) transaction-type constant defined, but there's no /aeps/* route or controller function behind it — don't build against it as if it exists.
Supported Biometric (RD Service) Devices
PidData in every transaction body above comes from your merchant's locally-running RD (Registered Device) service — the same UIDAI-certified Intent contract regardless of which physical scanner is plugged in, so any UIDAI-certified device should work. In practice, one vendor has actually been built and tested against; the rest are named in the codebase but not yet confirmed on real hardware.
| Vendor | Status | Notes |
|---|---|---|
| Mantra | ✅ Verified | Fingerprint (MFS100) confirmed working end to end. RD service on 127.0.0.1:11100. Iris capture defaults to DeviceMake: "MANTRAIRIS" server-side when not overridden. |
| Morpho / Idemia | ⚠️ Listed, not verified | Config placeholder port 11101 — not tested against a live device. |
| Startek | ⚠️ Listed, not verified | Config placeholder port 11103 — not tested against a live device. |
| SecuGen | ⚠️ Listed, not verified | Config placeholder port 11102 — not tested against a live device. |
| Precision, Evolute | ⚠️ Named only | Appear only as UIDAI-certified vendor names in a source comment — no port, no integration code, no testing evidence. |
Since a vendor's terminal is what actually runs the RD service and captures PidData — not anything on your side of the API — this table matters most if you're the one instructing merchants which scanner to buy, or debugging a PidData capture failure a merchant reports. The API call shape (AadharNo, TxnAmount, Latitude, Longitude, CustomerName, PidData, BankName) is identical no matter which device produced the PidData XML. Full detail on the Intent contract itself is on Merchant API → AEPS → RD Service Integration.