diff --git a/api-references/payments/upi-issuance.json b/api-references/payments/upi-issuance.json new file mode 100644 index 00000000..c2349072 --- /dev/null +++ b/api-references/payments/upi-issuance.json @@ -0,0 +1,4427 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Setu UPI Issuance — TPAP API", + "description": "TPAP-facing APIs for the Setu UPI Issuance switch (closed-stack PPI issuer). Phase 1: onboarding / device binding.", + "version": "1.0" + }, + "servers": [ + { + "url": "https://upi-issuance-qa.setu.co" + } + ], + "paths": { + "/api/v1/onboarding/binding-token": { + "post": { + "tags": [ + "Device binding" + ], + "summary": "Generate a binding token", + "description": "Generate a device-binding token: returns the VMN and the ready-to-send silent-SMS body, and starts onboarding for the user's mobile number.", + "operationId": "onboarding#requestBindingToken", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequestBindingTokenRequestBody" + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "os": "android", + "otpRequired": true + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BindingTokenResponse" + }, + "example": { + "smsBody": "VERIFY SETqxf8aemkxxdrhbifd4n4zldq7guvxb2k", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vmn": "919900000001" + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "429": { + "description": "Too many requests: Too Many Requests response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-binding-cap-exceeded", + "mobile-binding-cap-exceeded" + ], + "example": "device-binding-cap-exceeded" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-binding-cap-exceeded", + "message": "Too many binding attempts for this device.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/binding-status": { + "post": { + "tags": [ + "Device binding" + ], + "summary": "Poll binding status", + "description": "Poll a user's device-binding status. Returns the user object in its current state.", + "operationId": "onboarding#pollBindingStatus", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PollBindingStatusRequestBody" + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BindingStatusResponse" + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "user": { + "deviceId": "device-abc-123", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "mobile": "919999999999", + "status": "active" + } + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "binding-not-found" + ], + "example": "binding-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "binding-not-found", + "message": "No binding for this device.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/otp/request": { + "post": { + "tags": [ + "OTP verification" + ], + "summary": "Request an OTP", + "description": "Request the user-presence OTP SMS — include the vpa to verify a new VPA (new onboarding / new VPA); omit the vpa for a device change (SIM re-binding). Asynchronous: returns 202; the OTP SMS is sent shortly after.", + "operationId": "onboarding#requestOTP", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequestOTPRequestBody" + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "vpa": "919999999999-alice@setu" + } + } + } + }, + "responses": { + "202": { + "description": "Accepted response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OTPRequestResponse" + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found", + "vpa-not-found" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "429": { + "description": "Too many requests: Too Many Requests response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "otp-cap-exceeded" + ], + "example": "otp-cap-exceeded" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "otp-cap-exceeded", + "message": "Too many OTP requests.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/otp/verify": { + "post": { + "tags": [ + "OTP verification" + ], + "summary": "Verify an OTP", + "description": "Verify the OTP the user entered. Activates what it was requested for — a new VPA (new onboarding / new VPA, vpa in the body) or the user (a device change, no vpa).", + "operationId": "onboarding#verifyOTP", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VerifyOTPRequestBody" + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "otp": "123456", + "vpa": "919999999999-alice@setu" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OTPVerifyResponse" + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "user": { + "deviceId": "device-abc-123", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "mobile": "919999999999", + "status": "active" + }, + "vpa": { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + } + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request", + "missing-parameter" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked", + "invalid-otp" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "410": { + "description": "Gone: Gone response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "otp-expired-or-exhausted" + ], + "example": "otp-expired-or-exhausted" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "otp-expired-or-exhausted", + "message": "No live OTP to verify.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/vpa/check": { + "post": { + "tags": [ + "VPA management" + ], + "summary": "Check VPA availability", + "description": "Check whether a chosen VPA prefix is available. A taken prefix is not an error.", + "operationId": "onboarding#checkVPA", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CheckVPARequestBody" + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VpaCheckResponse" + }, + "example": { + "available": true, + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu" + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request", + "invalid-program", + "missing-parameter", + "invalid-vpa", + "invalid-handle" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/create-vpa": { + "post": { + "tags": [ + "VPA management" + ], + "summary": "Create a VPA", + "description": "Create a VPA over the user's chosen account. Requires an active user. With otpRequired, the VPA is created pending-verification until an OTP activates it.", + "operationId": "onboarding#createVPA", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateVPARequestBody" + }, + "example": { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "defaultCredit": true, + "defaultDebit": true, + "deviceId": "device-abc-123", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "otpRequired": false, + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateVPAResponse" + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + } + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request", + "invalid-program", + "missing-parameter", + "invalid-vpa", + "invalid-handle" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state", + "vpa-taken" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/get-vpa": { + "post": { + "tags": [ + "VPA management" + ], + "summary": "Get a VPA", + "description": "Fetch one of the user's VPAs by its VPA string.", + "operationId": "onboarding#getVPA", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetVPARequestBody" + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "vpa": "919999999999-alice@setu" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateVPAResponse" + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + } + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request", + "missing-parameter", + "invalid-vpa", + "invalid-handle" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found", + "vpa-not-found" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/list-vpas": { + "post": { + "tags": [ + "VPA management" + ], + "summary": "List VPAs", + "description": "List the user's live VPAs (active and pending-verification), newest-added first, keyset-paginated.", + "operationId": "onboarding#listVPAs", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListVPAsRequestBody" + }, + "example": { + "cursor": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "deviceId": "device-abc-123", + "limit": 20, + "mobile": "919999999999" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VpaListResponse" + }, + "example": { + "nextCursor": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpas": [ + { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + }, + { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + } + ] + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/vpa/deregister": { + "post": { + "tags": [ + "VPA management" + ], + "summary": "Deregister a VPA", + "description": "Deregister one of the user's VPAs (soft delete; the entry is preserved for audit and re-registration). Idempotent for an already-deregistered VPA.", + "operationId": "onboarding#deregisterVPA", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetVPARequestBody" + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "vpa": "919999999999-alice@setu" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateVPAResponse" + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + } + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request", + "missing-parameter", + "invalid-vpa", + "invalid-handle" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found", + "vpa-not-found" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/programs": { + "post": { + "tags": [ + "Programs" + ], + "summary": "Create a program", + "description": "Create a program — an engagement channel that VPAs are created under — and return its programId.", + "operationId": "onboarding#createProgram", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProgramRequestBody" + }, + "example": { + "amountLimit": 500000, + "code": "ACME", + "isCreditAllowed": true, + "isDebitAllowed": true, + "name": "Acme Wallet" + } + } + } + }, + "responses": { + "201": { + "description": "Created response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProgramResponse" + }, + "example": { + "program": { + "amountLimit": 500000, + "code": "ACME", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "isCreditAllowed": true, + "isDebitAllowed": true, + "name": "Acme Wallet", + "status": "active" + }, + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request", + "missing-parameter" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/programs/{programId}": { + "patch": { + "tags": [ + "Programs" + ], + "summary": "Update a program", + "description": "Update a program's configuration. Only the fields supplied in the body are changed.", + "operationId": "onboarding#updateProgram", + "parameters": [ + { + "name": "programId", + "in": "path", + "description": "The program to update (ULID).", + "required": true, + "schema": { + "type": "string", + "description": "The program to update (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProgramRequestBody" + }, + "example": { + "amountLimit": 500000, + "code": "ACME", + "isCreditAllowed": true, + "isDebitAllowed": false, + "name": "Acme Wallet", + "status": "inactive" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProgramResponse" + }, + "example": { + "program": { + "amountLimit": 500000, + "code": "ACME", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "isCreditAllowed": true, + "isDebitAllowed": true, + "name": "Acme Wallet", + "status": "active" + }, + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request", + "missing-parameter" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "program-not-found" + ], + "example": "program-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "program-not-found", + "message": "No program with that id.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/block-vpa": { + "post": { + "tags": [ + "Payee blocklist" + ], + "summary": "Block a payee VPA", + "description": "Block an external payee VPA for the user. Idempotent; requires an active user.", + "operationId": "onboarding#blockPayeeVPA", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlockPayeeVPARequestBody" + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "payeeVpa": "merchant@otherbank" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PayeeBlockResponse" + }, + "example": { + "blockedPayee": { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request", + "missing-parameter", + "invalid-vpa" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/unblock-vpa": { + "post": { + "tags": [ + "Payee blocklist" + ], + "summary": "Unblock a payee VPA", + "description": "Unblock a previously-blocked payee VPA (soft flip; the entry is preserved). Idempotent for an already-unblocked payee; requires an active user.", + "operationId": "onboarding#unblockPayeeVPA", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlockPayeeVPARequestBody" + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "payeeVpa": "merchant@otherbank" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PayeeBlockResponse" + }, + "example": { + "blockedPayee": { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request", + "missing-parameter", + "invalid-vpa" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found", + "payee-not-blocked" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + }, + "/api/v1/onboarding/list-blocked-vpas": { + "post": { + "tags": [ + "Payee blocklist" + ], + "summary": "List blocked payee VPAs", + "description": "List the user's currently-blocked payee VPAs, newest first, keyset-paginated.", + "operationId": "onboarding#listBlockedPayeeVPAs", + "parameters": [ + { + "name": "idempotencyKey", + "in": "header", + "description": "Optional client-generated idempotency key for safe retries.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional client-generated idempotency key for safe retries.", + "example": "req-8f3a2b1c" + }, + "example": "req-8f3a2b1c" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListVPAsRequestBody" + }, + "example": { + "cursor": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "deviceId": "device-abc-123", + "limit": 20, + "mobile": "919999999999" + } + } + } + }, + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlockedPayeeListResponse" + }, + "example": { + "blockedPayees": [ + { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + } + ], + "nextCursor": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "400": { + "description": "Bad request: Bad Request response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-request" + ], + "example": "invalid-request" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-request", + "message": "The request could not be parsed.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "401": { + "description": "Unauthorized: Unauthorized response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "device-not-linked" + ], + "example": "device-not-linked" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "device-not-linked", + "message": "This device is not bound for this user.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "404": { + "description": "Not found: Not Found response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "user-not-found" + ], + "example": "user-not-found" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "user-not-found", + "message": "No user for this mobile number.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "409": { + "description": "Conflict: Conflict response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "invalid-user-state" + ], + "example": "invalid-user-state" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "invalid-user-state", + "message": "The user is not in a valid state for this operation.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + }, + "500": { + "description": "Internal server error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "traceId", + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "enum": [ + "internal-error" + ], + "example": "internal-error" + }, + "message": { + "type": "string", + "description": "Human-readable description of the error." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID)." + } + } + }, + "example": { + "code": "internal-error", + "message": "Something went wrong on Setu's side.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "BadRequestError": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code from the published dictionary.", + "example": "invalid-request", + "enum": [ + "invalid-request", + "missing-parameter", + "invalid-program", + "invalid-vpa", + "invalid-handle" + ] + }, + "message": { + "type": "string", + "description": "Human-readable description of the error.", + "example": "A required parameter is missing or invalid." + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + }, + "example": { + "code": "invalid-request", + "message": "A required parameter is missing or invalid.", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "required": [ + "traceId", + "code", + "message" + ] + }, + "BindingStatusResponse": { + "type": "object", + "properties": { + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "user": { + "$ref": "#/components/schemas/UserView" + } + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "user": { + "deviceId": "device-abc-123", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "mobile": "919999999999", + "status": "active" + } + }, + "required": [ + "traceId", + "user" + ] + }, + "BindingTokenResponse": { + "type": "object", + "properties": { + "smsBody": { + "type": "string", + "description": "The ready-to-send silent-SMS body. The app sends this verbatim to the VMN; the token is embedded here and is never returned separately.", + "example": "VERIFY SETqxf8aemkxxdrhbifd4n4zldq7guvxb2k" + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "vmn": { + "type": "string", + "description": "The Virtual Mobile Number to send the SMS to.", + "example": "919900000001" + } + }, + "example": { + "smsBody": "VERIFY SETqxf8aemkxxdrhbifd4n4zldq7guvxb2k", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vmn": "919900000001" + }, + "required": [ + "traceId", + "vmn", + "smsBody" + ] + }, + "BlockPayeeVPARequestBody": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code (e.g. 919999999999).", + "example": "919999999999" + }, + "payeeVpa": { + "type": "string", + "description": "The external payee VPA to block or unblock (prefix@handle; any handle).", + "example": "merchant@otherbank" + } + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "payeeVpa": "merchant@otherbank" + }, + "required": [ + "deviceId", + "mobile", + "payeeVpa" + ] + }, + "BlockedPayeeListResponse": { + "type": "object", + "properties": { + "blockedPayees": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BlockedPayeeView" + }, + "description": "This page of the user's currently-blocked payee VPAs (newest-added first); empty when none.", + "example": [ + { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + } + ] + }, + "nextCursor": { + "type": "string", + "description": "Cursor for the next page; absent on the last page.", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + }, + "example": { + "blockedPayees": [ + { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + } + ], + "nextCursor": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "required": [ + "traceId", + "blockedPayees" + ] + }, + "BlockedPayeeView": { + "type": "object", + "properties": { + "blockedAt": { + "type": "string", + "description": "When the payee was most recently blocked (RFC3339).", + "example": "2026-07-09T12:00:00Z" + }, + "id": { + "type": "string", + "description": "The blocklist entry id (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "payeeVpa": { + "type": "string", + "description": "The blocked payee VPA (prefix@handle).", + "example": "merchant@otherbank" + }, + "status": { + "type": "string", + "description": "blocked or unblocked.", + "example": "blocked" + }, + "unblockedAt": { + "type": "string", + "description": "When the payee was unblocked (RFC3339); absent while blocked.", + "example": "2026-07-09T12:30:00Z" + } + }, + "example": { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + "required": [ + "id", + "payeeVpa", + "status" + ] + }, + "CheckVPARequestBody": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code (e.g. 919999999999).", + "example": "919999999999" + }, + "programId": { + "type": "string", + "description": "Optional program id (ULID). Validated when supplied.", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "vpa": { + "type": "string", + "description": "The full VPA to check (prefix@handle, e.g. 919999999999-alice@setu). Its prefix must start with the user's mobile number.", + "example": "919999999999-alice@setu" + } + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu" + }, + "required": [ + "deviceId", + "mobile", + "vpa" + ] + }, + "CreateProgramRequestBody": { + "type": "object", + "properties": { + "amountLimit": { + "type": "integer", + "description": "Per-transaction cap, in paise. Omit for no cap.", + "example": 500000, + "format": "int64" + }, + "code": { + "type": "string", + "description": "The program's short code — its channel identifier.", + "example": "ACME" + }, + "isCreditAllowed": { + "type": "boolean", + "description": "May wallets on this program receive incoming UPI? Defaults true.", + "example": true + }, + "isDebitAllowed": { + "type": "boolean", + "description": "May wallets on this program pay outgoing UPI? Defaults true.", + "example": true + }, + "name": { + "type": "string", + "description": "The program's display name.", + "example": "Acme Wallet" + } + }, + "example": { + "amountLimit": 500000, + "code": "ACME", + "isCreditAllowed": true, + "isDebitAllowed": true, + "name": "Acme Wallet" + }, + "required": [ + "name", + "code" + ] + }, + "CreateVPARequestBody": { + "type": "object", + "properties": { + "accountName": { + "type": "string", + "description": "The account-holder name.", + "example": "Alice Doe" + }, + "accountNo": { + "type": "string", + "description": "The wallet / pool account number.", + "example": "99887766554433" + }, + "accountProviderId": { + "type": "string", + "description": "The account-provider id. Optional when a TPAP default is configured.", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "defaultCredit": { + "type": "boolean", + "description": "Make this VPA the user's default credit account.", + "example": true + }, + "defaultDebit": { + "type": "boolean", + "description": "Make this VPA the user's default debit account.", + "example": true + }, + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "ifsc": { + "type": "string", + "description": "The IFSC of the account. Optional when a TPAP default is configured.", + "example": "SETU0000001" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code (e.g. 919999999999).", + "example": "919999999999" + }, + "otpRequired": { + "type": "boolean", + "description": "Whether OTP verification is needed to activate the new VPA — set true for Android, false for iOS. When true, the VPA is created pending-verification until an OTP activates it; false (default) creates it active.", + "example": false + }, + "programId": { + "type": "string", + "description": "Optional program id (ULID) — the program this VPA belongs to. Validated when supplied.", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "vpa": { + "type": "string", + "description": "The full VPA to create (prefix@handle, e.g. 919999999999-alice@setu). Its prefix must start with the user's mobile number.", + "example": "919999999999-alice@setu" + } + }, + "example": { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "defaultCredit": true, + "defaultDebit": true, + "deviceId": "device-abc-123", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "otpRequired": false, + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu" + }, + "required": [ + "deviceId", + "mobile", + "accountNo", + "vpa", + "accountName" + ] + }, + "CreateVPAResponse": { + "type": "object", + "properties": { + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "vpa": { + "$ref": "#/components/schemas/VpaView" + } + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + } + }, + "required": [ + "traceId", + "vpa" + ] + }, + "GetVPARequestBody": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code (e.g. 919999999999).", + "example": "919999999999" + }, + "vpa": { + "type": "string", + "description": "The full VPA to fetch (prefix@handle, e.g. 919999999999-alice@setu). Its prefix must start with the user's mobile number.", + "example": "919999999999-alice@setu" + } + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "vpa": "919999999999-alice@setu" + }, + "required": [ + "deviceId", + "mobile", + "vpa" + ] + }, + "ListVPAsRequestBody": { + "type": "object", + "properties": { + "cursor": { + "type": "string", + "description": "The nextCursor from the previous page. Omit for the first page.", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "limit": { + "type": "integer", + "description": "Max entries to return this page. Omitted or non-positive defaults to 20; clamped to 100.", + "example": 20, + "format": "int64" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code (e.g. 919999999999).", + "example": "919999999999" + } + }, + "example": { + "cursor": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "deviceId": "device-abc-123", + "limit": 20, + "mobile": "919999999999" + }, + "required": [ + "deviceId", + "mobile" + ] + }, + "OTPRequestResponse": { + "type": "object", + "properties": { + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "required": [ + "traceId" + ] + }, + "OTPVerifyResponse": { + "type": "object", + "properties": { + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "user": { + "$ref": "#/components/schemas/UserView" + }, + "vpa": { + "$ref": "#/components/schemas/VpaView" + } + }, + "example": { + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "user": { + "deviceId": "device-abc-123", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "mobile": "919999999999", + "status": "active" + }, + "vpa": { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + } + }, + "required": [ + "traceId" + ] + }, + "PayeeBlockResponse": { + "type": "object", + "properties": { + "blockedPayee": { + "$ref": "#/components/schemas/BlockedPayeeView" + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + }, + "example": { + "blockedPayee": { + "blockedAt": "2026-07-09T12:00:00Z", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "unblockedAt": "2026-07-09T12:30:00Z" + }, + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "required": [ + "traceId", + "blockedPayee" + ] + }, + "PollBindingStatusRequestBody": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code (e.g. 919999999999).", + "example": "919999999999" + } + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999" + }, + "required": [ + "deviceId", + "mobile" + ] + }, + "ProgramResponse": { + "type": "object", + "properties": { + "program": { + "$ref": "#/components/schemas/ProgramView" + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + } + }, + "example": { + "program": { + "amountLimit": 500000, + "code": "ACME", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "isCreditAllowed": true, + "isDebitAllowed": true, + "name": "Acme Wallet", + "status": "active" + }, + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "required": [ + "traceId", + "program" + ] + }, + "ProgramView": { + "type": "object", + "properties": { + "amountLimit": { + "type": "integer", + "description": "Per-transaction cap, in paise; absent when there is no cap.", + "example": 500000, + "format": "int64" + }, + "code": { + "type": "string", + "description": "The program's short code.", + "example": "ACME" + }, + "id": { + "type": "string", + "description": "The program id (ULID); pass it as programId on onboarding calls.", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "isCreditAllowed": { + "type": "boolean", + "description": "May wallets on this program receive incoming UPI?", + "example": true + }, + "isDebitAllowed": { + "type": "boolean", + "description": "May wallets on this program pay outgoing UPI?", + "example": true + }, + "name": { + "type": "string", + "description": "The program's display name.", + "example": "Acme Wallet" + }, + "status": { + "type": "string", + "description": "active or inactive.", + "example": "active" + } + }, + "example": { + "amountLimit": 500000, + "code": "ACME", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "isCreditAllowed": true, + "isDebitAllowed": true, + "name": "Acme Wallet", + "status": "active" + }, + "required": [ + "id", + "name", + "isCreditAllowed", + "isDebitAllowed", + "status" + ] + }, + "RequestBindingTokenRequestBody": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code (e.g. 919999999999).", + "example": "919999999999" + }, + "os": { + "type": "string", + "description": "The device OS: android or ios.", + "example": "android" + }, + "otpRequired": { + "type": "boolean", + "description": "Set true for the device-change case where an OTP is needed after SIM binding (e.g. Android). Set false for iOS, or for the new-onboarding / new-VPA case where the OTP happens after VPA creation (gate it on create-vpa's otpRequired instead).", + "example": true + } + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "os": "android", + "otpRequired": true + }, + "required": [ + "deviceId", + "mobile", + "os", + "otpRequired" + ] + }, + "RequestOTPRequestBody": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code (e.g. 919999999999).", + "example": "919999999999" + }, + "vpa": { + "type": "string", + "description": "Include the VPA to verify a new VPA (new onboarding / new VPA); omit for a device-change OTP (SIM re-binding).", + "example": "919999999999-alice@setu" + } + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "vpa": "919999999999-alice@setu" + }, + "required": [ + "deviceId", + "mobile" + ] + }, + "UpdateProgramRequestBody": { + "type": "object", + "properties": { + "amountLimit": { + "type": "integer", + "description": "Per-transaction cap, in paise. Omit for no cap.", + "example": 500000, + "format": "int64" + }, + "code": { + "type": "string", + "description": "The program's short code.", + "example": "ACME" + }, + "isCreditAllowed": { + "type": "boolean", + "description": "May wallets on this program receive incoming UPI?", + "example": true + }, + "isDebitAllowed": { + "type": "boolean", + "description": "May wallets on this program pay outgoing UPI?", + "example": false + }, + "name": { + "type": "string", + "description": "The program's display name.", + "example": "Acme Wallet" + }, + "status": { + "type": "string", + "description": "active or inactive.", + "example": "inactive" + } + }, + "example": { + "amountLimit": 500000, + "code": "ACME", + "isCreditAllowed": true, + "isDebitAllowed": false, + "name": "Acme Wallet", + "status": "inactive" + } + }, + "UserView": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "id": { + "type": "string", + "description": "The user id (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code.", + "example": "919999999999" + }, + "status": { + "type": "string", + "description": "binding-pending | device-bound | otp-pending | active.", + "example": "active" + } + }, + "example": { + "deviceId": "device-abc-123", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "mobile": "919999999999", + "status": "active" + }, + "required": [ + "id", + "status" + ] + }, + "VerifyOTPRequestBody": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "The user's device id.", + "example": "device-abc-123" + }, + "mobile": { + "type": "string", + "description": "The user's mobile number, with country code (e.g. 919999999999).", + "example": "919999999999" + }, + "otp": { + "type": "string", + "description": "The OTP the user entered.", + "example": "123456" + }, + "vpa": { + "type": "string", + "description": "Include the VPA to verify a new VPA (new onboarding / new VPA); omit for a device-change OTP (SIM re-binding).", + "example": "919999999999-alice@setu" + } + }, + "example": { + "deviceId": "device-abc-123", + "mobile": "919999999999", + "otp": "123456", + "vpa": "919999999999-alice@setu" + }, + "required": [ + "deviceId", + "mobile", + "otp" + ] + }, + "VpaCheckResponse": { + "type": "object", + "properties": { + "available": { + "type": "boolean", + "description": "false means the VPA is already taken by another user's active VPA. A taken VPA is not an error.", + "example": true + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "vpa": { + "type": "string", + "description": "The full VPA that was checked (prefix@handle).", + "example": "919999999999-alice@setu" + } + }, + "example": { + "available": true, + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu" + }, + "required": [ + "traceId", + "vpa", + "available" + ] + }, + "VpaListResponse": { + "type": "object", + "properties": { + "nextCursor": { + "type": "string", + "description": "Cursor for the next page; absent on the last page.", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "traceId": { + "type": "string", + "description": "Trace handle for this call (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "vpas": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VpaView" + }, + "description": "This page of the user's live VPAs (newest-added first); empty when none.", + "example": [ + { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + }, + { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + }, + { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + } + ] + } + }, + "example": { + "nextCursor": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpas": [ + { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + }, + { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + }, + { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + } + ] + }, + "required": [ + "traceId", + "vpas" + ] + }, + "VpaView": { + "type": "object", + "properties": { + "accountName": { + "type": "string", + "description": "The account-holder name.", + "example": "Alice Doe" + }, + "accountNo": { + "type": "string", + "description": "The wallet / pool account number.", + "example": "99887766554433" + }, + "accountProviderId": { + "type": "string", + "description": "The account-provider id.", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "accountType": { + "type": "string", + "description": "The account type (e.g. PPIWALLET).", + "example": "PPIWALLET" + }, + "id": { + "type": "string", + "description": "The VPA id (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "ifsc": { + "type": "string", + "description": "The IFSC of the account.", + "example": "SETU0000001" + }, + "mobile": { + "type": "string", + "description": "The owner's mobile number, with country code.", + "example": "919999999999" + }, + "programId": { + "type": "string", + "description": "The program the VPA belongs to (ULID).", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" + }, + "status": { + "type": "string", + "description": "active | pending-verification | deregistered.", + "example": "active" + }, + "vpa": { + "type": "string", + "description": "The full VPA, prefix@handle.", + "example": "919999999999-alice@setu" + } + }, + "example": { + "accountName": "Alice Doe", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountType": "PPIWALLET", + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "vpa": "919999999999-alice@setu" + }, + "required": [ + "id", + "vpa" + ] + } + } + }, + "tags": [ + { + "name": "Device binding" + }, + { + "name": "OTP verification" + }, + { + "name": "VPA management" + }, + { + "name": "Programs" + }, + { + "name": "Payee blocklist" + } + ] +} \ No newline at end of file diff --git a/content/endpoints.json b/content/endpoints.json index 08d01f1c..07ac07b2 100644 --- a/content/endpoints.json +++ b/content/endpoints.json @@ -38,6 +38,12 @@ "path": "umap", "order": 7, "visible_in_sidebar": true + }, + { + "name": "UPI Issuance", + "path": "upi-issuance", + "order": 8, + "visible_in_sidebar": true } ] }, diff --git a/content/menuItems.json b/content/menuItems.json index 46aa7ca7..28bfd573 100644 --- a/content/menuItems.json +++ b/content/menuItems.json @@ -1 +1 @@ -{"home":[{"name":"Payments","path":"payments","order":0,"visible_in_sidebar":true,"api_reference":true,"children":[{"name":"BBPS BillCollect","path":"bbps","order":0,"visible_in_sidebar":true,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"BBPS API reference","path":"api-reference","order":9},{"name":"Axis BBPS","visible_in_sidebar":false,"page_title":"Axis BBPS API Approach Document","path":"axis","order":10},{"name":"Bill Structure","visible_in_sidebar":true,"page_title":"BBPS - Bill Structure","path":"bill-structure","order":5,"children":[{"name":"Special cases","visible_in_sidebar":true,"page_title":"BBPS - Bill Structure special cases","path":"special-cases","order":1}]},{"name":"Go live","visible_in_sidebar":true,"page_title":"BBPS - Go live","path":"go-live","order":3},{"name":"Notifications","visible_in_sidebar":true,"page_title":"BBPS - Notifications","path":"notifications","order":4},{"name":"Overview","visible_in_sidebar":true,"page_title":"BBPS - Overview","path":"overview","order":1},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS - Quickstart","path":"quickstart","order":2,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"BBPS - API integration","path":"api-integration","order":2},{"name":"No-code CSV","visible_in_sidebar":true,"page_title":"BBPS - No-code CSV","path":"no-code-integration","order":1},{"name":"Share bills","visible_in_sidebar":false,"page_title":"BBPS - Share bills","path":"share-biils","order":1}]},{"name":"Reports API","visible_in_sidebar":true,"page_title":"BBPS - Reports API","path":"reports","order":6},{"name":"Additional resources","visible_in_sidebar":true,"page_title":"BBPS - Additional Resources","path":"resources","order":8,"children":[{"name":"Errors","visible_in_sidebar":true,"page_title":"BBPS error codes","path":"errors","order":4},{"name":"JWT authentication","visible_in_sidebar":true,"page_title":"UPI Deeplinks JWT authentication","path":"jwt","order":2},{"name":"OAuth 2.0","visible_in_sidebar":true,"page_title":"BBPS OAuth 2.0","path":"oauth","order":1},{"name":"Settlement object","visible_in_sidebar":true,"page_title":"UPI Deeplinks settlement object","path":"settlement-object","order":3}]}]},{"name":"BBPS BillPay","path":"billpay","order":1,"versions":["v1","v2"],"default_version":"v2","visible_in_sidebar":true,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"BBPS Billpay API integration","path":"api-integration","order":1,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"COU Direct Connectivity API reference","path":"api-reference","order":10},{"name":"List of APIs","visible_in_sidebar":true,"page_title":"BBPS COU - List of APIs","path":"apis","order":2},{"name":"FX Retail","visible_in_sidebar":true,"page_title":"BBPS COU - FX Retail (Forex category)","path":"fx-retail","order":8},{"name":"API encryption (optional)","visible_in_sidebar":true,"page_title":"BBPS COU - API payload encryption (Dynamic IV)","path":"api-encryption","order":9},{"name":"Harmonization of TAT","visible_in_sidebar":true,"page_title":"Harmonization Of TAT (Disputes API)","path":"harmonization_of_tat","order":6},{"name":"Objects","visible_in_sidebar":true,"page_title":"BBPS COU - Objects","path":"objects","order":11},{"name":"Paying Bills","visible_in_sidebar":true,"page_title":"Paying Bills","path":"paying-bills","order":4,"children":[{"name":"Paying for options","visible_in_sidebar":true,"page_title":"Paying for alternative options","path":"bill-payment-options","order":4},{"name":"Passing CCF","visible_in_sidebar":true,"page_title":"Customer Convenience Fee (CCF) Integration Guide","path":"customer-convenience-fee","order":3},{"name":"Paying multiple bills","visible_in_sidebar":true,"page_title":"Paying for multiple bills","path":"multi-bill-processing","order":5},{"name":"Paying for plans","visible_in_sidebar":true,"page_title":"Paying for plans","path":"plan-mdm-integration","order":6},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS Bill Payment Integration Guide","path":"quickstart","order":1},{"name":"Remitter Details","visible_in_sidebar":true,"page_title":"Passing Remitter Details","path":"remittance_flows_guide","order":2}]},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS COU - API integration","path":"quickstart","order":1},{"name":"Integrating with UPMS","visible_in_sidebar":true,"page_title":"BBPS COU - Integrating with UPMS","path":"upms","order":7},{"name":"Migration Guide to v2","visible_in_sidebar":true,"page_title":"BBPS COU - Migration Guide to v2","path":"v2-migration","order":5},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"BBPS COU - Webhooks","path":"webhooks","order":3}]},{"name":"API reference","visible_in_sidebar":false,"page_title":"BillPay API reference","path":"api-reference","order":5},{"path":"mcp","children":[{"name":"Integration Guide","visible_in_sidebar":false,"page_title":"MCP Server for Bill Payments - Integration Guide","path":"integration-guide","order":1},{"name":"Tools and Prompts","visible_in_sidebar":false,"page_title":"MCP Server for Bill Payments - Tools and Prompts","path":"tools-and-prompts","order":2}]},{"name":"Prepaid Recharge","visible_in_sidebar":true,"page_title":"BBPS Billpay Prepaid Recharge APIs","path":"mobile-prepaid-recharge","order":3,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Mobile Prepaid Recharge API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Mobile Prepaid Recharge quickstart","path":"quickstart","order":1},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"Mobile Prepaid Recharge Webhooks","path":"webhooks","order":3}]},{"name":"Overview","visible_in_sidebar":true,"page_title":"BBPS Billpay Overview","path":"overview","order":0},{"name":"Pre-built screens","visible_in_sidebar":true,"page_title":"BBPS Billpay pre-built screens","path":"pre-built-screens","order":2,"children":[{"name":"API reference","visible_in_sidebar":false,"page_title":"BBPS Billpay API reference","path":"api-reference-wl","order":4},{"name":"API reference","visible_in_sidebar":true,"page_title":"BBPS Billpay API reference","path":"api-reference","order":5},{"name":"Custom payment","visible_in_sidebar":true,"page_title":"BBPS Billpay custom payment","path":"custom-payment","order":2,"children":[{"name":"Android","visible_in_sidebar":true,"page_title":"BBPS Billpay android integration for custom payment","path":"android","order":3},{"name":"Required APIs","visible_in_sidebar":true,"page_title":"BBPS Billpay APIs for custom payment","path":"apis","order":1},{"name":"Cross platform","visible_in_sidebar":true,"page_title":"BBPS Billpay cross-platform integration for custom payment","path":"cross-platform","order":3},{"name":"iOS","visible_in_sidebar":true,"page_title":"BBPS Billpay iOS integration for custom payment","path":"iOS","order":4},{"name":"Website","visible_in_sidebar":true,"page_title":"BBPS Billpay website integration for custom payment","path":"website","order":2}]},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS Billpay Quickstart","path":"quickstart","order":1,"children":[{"name":"Android","visible_in_sidebar":true,"page_title":"BBPS Billpay Android integration","path":"android","order":2},{"name":"API","visible_in_sidebar":true,"page_title":"BBPS Billpay API","path":"api","order":2},{"name":"Cross platform","visible_in_sidebar":true,"page_title":"BBPS Billpay cross platform integration","path":"cross-platform","order":4},{"name":"iOS","visible_in_sidebar":true,"page_title":"BBPS Billpay iOS integration","path":"iOS","order":3},{"name":"Website","visible_in_sidebar":true,"page_title":"BBPS Billpay website","path":"website","order":1}]},{"name":"Remitter Details","visible_in_sidebar":true,"page_title":"Remitter Details For Bill Payments Integration Guide","path":"remitter-details","order":4},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"BBPS Billpay webhooks","path":"webhooks","order":2}]},{"path":"v1","children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"BBPS Billpay API integration","path":"api-integration","order":1,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"COU Direct Connectivity API reference","path":"api-reference","order":5},{"name":"List of APIs","visible_in_sidebar":true,"page_title":"BBPS COU - List of APIs","path":"apis","order":2},{"name":"Deprecated APIs","visible_in_sidebar":false,"page_title":"BBPS COU - API integration (deprecated)","path":"deprecated","order":4,"children":[{"name":"Mock environment","visible_in_sidebar":false,"page_title":"BBPS Billpay Mock environment","path":"mock-environment","order":2},{"name":"Polling","visible_in_sidebar":false,"page_title":"BBPS Billpay polling","path":"polling","order":2}]},{"name":"Objects","visible_in_sidebar":true,"page_title":"BBPS COU - Objects","path":"objects","order":3},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS COU - API integration","path":"quickstart","order":1},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"BBPS COU - Webhooks","path":"webhooks","order":4}]},{"name":"API reference","visible_in_sidebar":false,"page_title":"BillPay API reference","path":"api-reference","order":5},{"name":"Overview","visible_in_sidebar":true,"page_title":"BBPS Billpay Overview","path":"overview","order":0},{"name":"Pre-built screens","visible_in_sidebar":true,"page_title":"BBPS Billpay pre-built screens","path":"pre-built-screens","order":2,"children":[{"name":"API reference","visible_in_sidebar":false,"page_title":"BBPS Billpay API reference","path":"api-reference-wl","order":4},{"name":"API reference","visible_in_sidebar":true,"page_title":"BBPS Billpay API reference","path":"api-reference","order":4},{"name":"Custom payment","visible_in_sidebar":true,"page_title":"BBPS Billpay custom payment","path":"custom-payment","order":2,"children":[{"name":"Android","visible_in_sidebar":true,"page_title":"BBPS Billpay android integration for custom payment","path":"android","order":3},{"name":"Required APIs","visible_in_sidebar":true,"page_title":"BBPS Billpay APIs for custom payment","path":"apis","order":1},{"name":"Cross platform","visible_in_sidebar":true,"page_title":"BBPS Billpay cross-platform integration for custom payment","path":"cross-platform","order":3},{"name":"iOS","visible_in_sidebar":true,"page_title":"BBPS Billpay iOS integration for custom payment","path":"iOS","order":4},{"name":"Website","visible_in_sidebar":true,"page_title":"BBPS Billpay website integration for custom payment","path":"website","order":2}]},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS Billpay Quickstart","path":"quickstart","order":1,"children":[{"name":"Android","visible_in_sidebar":true,"page_title":"BBPS Billpay Android integration","path":"android","order":2},{"name":"API","visible_in_sidebar":true,"page_title":"BBPS Billpay API","path":"api","order":2},{"name":"Cross platform","visible_in_sidebar":true,"page_title":"BBPS Billpay cross platform integration","path":"cross-platform","order":4},{"name":"iOS","visible_in_sidebar":true,"page_title":"BBPS Billpay iOS integration","path":"iOS","order":3},{"name":"Website","visible_in_sidebar":true,"page_title":"BBPS Billpay website","path":"website","order":1}]},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"BBPS Billpay webhooks","path":"webhooks","order":2}]}]}]},{"name":"WhatsApp Collect","path":"whatsapp-collect","order":3,"visible_in_sidebar":true,"children":[{"name":"API Integration","visible_in_sidebar":true,"page_title":"WhatsApp Collect API Integration","path":"api-integration","order":3},{"name":"API reference","visible_in_sidebar":true,"page_title":"WhatsApp Collect API reference","path":"api-reference","order":5},{"name":"Error codes","visible_in_sidebar":true,"page_title":"WhatsApp Collect error codes","path":"errors","order":4},{"name":"Collection journey","visible_in_sidebar":true,"page_title":"WhatsApp Collect Journey","path":"journey","order":1},{"name":"Overview","visible_in_sidebar":true,"page_title":"WhatsApp Collect Overview","path":"overview","order":0},{"name":"Collection reminders","visible_in_sidebar":true,"page_title":"WhatsApp Collect reminders","path":"reminders","order":2}]},{"name":"UPI DeepLinks","path":"upi-deeplinks","order":4,"visible_in_sidebar":true,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"UPI Deeplinks API reference","path":"api-reference","order":8},{"name":"Notifications","visible_in_sidebar":true,"page_title":"UPI Deeplinks Notifications","path":"notifications","order":6},{"name":"Overview","visible_in_sidebar":true,"page_title":"UPI Deeplinks Overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"UPI Deeplinks quickstart","path":"quickstart","order":1,"children":[{"name":"Go Live","visible_in_sidebar":true,"page_title":"UPI Deeplinks go live","path":"go-live","order":1}]},{"name":"Refunds","visible_in_sidebar":true,"page_title":"UPI Deeplinks Refunds","path":"refunds","order":4},{"name":"Reports API","visible_in_sidebar":true,"page_title":"UPI Deeplinks Reports API","path":"reports","order":5},{"name":"Additional resources","visible_in_sidebar":true,"page_title":"UPI Deeplinks additonal resources","path":"resources","order":6,"children":[{"name":"JWT authentication","visible_in_sidebar":true,"page_title":"UPI Deeplinks JWT authentication","path":"jwt","order":2},{"name":"OAuth 2.0","visible_in_sidebar":true,"page_title":"UPI Deeplinks OAuth 2.0","path":"oauth","order":1},{"name":"Settlement object","visible_in_sidebar":true,"page_title":"UPI Deeplinks settlement object","path":"settlement-object","order":3}]},{"name":"SDKs","visible_in_sidebar":true,"page_title":"UPI Deeplinks SDKs","path":"sdks","order":3},{"name":"Third party verification","visible_in_sidebar":true,"page_title":"UPI Deeplinks third party verification","path":"third-party-verification","order":3}]},{"name":"UPI Setu","path":"umap","order":7,"visible_in_sidebar":true,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"UPI Setu - API integration","path":"api-integration","order":2,"children":[{"name":"Aggregators","visible_in_sidebar":true,"page_title":"UPI Setu - API integration for aggregators","path":"aggregators","order":1},{"name":"Merchants","visible_in_sidebar":true,"page_title":"UPI Setu - API integration for merchants","path":"merchants","order":2}]},{"name":"API reference","visible_in_sidebar":true,"page_title":"UPI Setu - API reference","path":"api-reference","order":8},{"name":"UPI mandates","visible_in_sidebar":true,"page_title":"UPI mandates","path":"mandates","order":4,"children":[{"name":"Mandate operations","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Mandate operations","path":"generic","order":5,"children":[{"name":"Pause","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Pause","path":"pause","order":3},{"name":"Revoke","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Revoke","path":"revoke","order":2},{"name":"Unpause","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Unpause","path":"unpause","order":4},{"name":"Update","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Update","path":"update","order":1}]},{"name":"OneShot","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - OneShot","path":"one-shot","order":1,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Check payment status","path":"check-status","order":4},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Create One Time Mandate","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Execute One Time Mandate","path":"execute","order":3},{"name":"Pre Debit Notify","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Send One Time Mandate Pre Debit Notification","path":"pre-debit-notify","order":2}]},{"name":"Recur","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Recur","path":"recur","order":3,"children":[{"name":"Check payment status","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Check payment status","path":"check-status","order":4},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Create recurring mandate","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Execute mandate","path":"execute","order":3},{"name":"Pre Debit Notify","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Send Recurring Mandate Pre Debit Notification","path":"pre-debit-notify","order":2}]},{"name":"Reserve","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Reserve","path":"reserve","order":2,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Check payment status","path":"check-status","order":4},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Create Reserve Mandate","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Execute Reserve Mandate","path":"execute","order":3}]},{"name":"ReservePlus","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - ReservePlus","path":"reserve-plus","order":4,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Check payment status","path":"check-status","order":3},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Create single block multi-debit","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Execute single block multi-debit","path":"execute","order":2}]}]},{"name":"Merchant on-boarding","visible_in_sidebar":true,"page_title":"UPI Setu - Merchant onboarding","path":"merchant-onboarding","order":2,"children":[{"name":"Check VPA availability","visible_in_sidebar":true,"page_title":"UPI Setu - Merchant on-boarding - Check VPA availability","path":"check-vpa-availability-api","order":2},{"name":"Setup a merchant","visible_in_sidebar":true,"page_title":"UPI Setu - Merchant on-boarding - Setup merchant","path":"create-merchant-api","order":1},{"name":"Registering VPA","visible_in_sidebar":true,"page_title":"UPI Setu - Merchant on-boarding - Registering a VPA","path":"create-vpa-api","order":3}]},{"name":"Notifications and alerts","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts","path":"notifications","order":7,"children":[{"name":"VPA verification","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Customer VPA verification","path":"customer-vpa-verification","order":6},{"name":"Mandates","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Mandates","path":"mandates","order":3,"children":[{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Creation of mandate","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Mandate execution","path":"execute","order":7},{"name":"Notify","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Mandate pre-debit notifications","path":"notify","order":6},{"name":"Pause","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Pausing mandate","path":"pause","order":4},{"name":"Revoke","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Revoking mandate","path":"revoke","order":3},{"name":"Unpause","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Unpausing mandate","path":"unpause","order":5},{"name":"Update","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Updating mandate","path":"update","order":2}]},{"name":"Payments","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Payments","path":"payments","order":2},{"name":"Refunds","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Refunds","path":"refunds","order":4},{"name":"Verify signature","visible_in_sidebar":true,"page_title":"UMAP - Events and notifications","path":"verify-signature","order":1}]},{"name":"Overview","visible_in_sidebar":true,"page_title":"UPI Setu - Overview","path":"overview","order":0},{"name":"UPI payments","visible_in_sidebar":true,"page_title":"UPI payments","path":"payments","order":3,"children":[{"name":"Collect","visible_in_sidebar":true,"page_title":"UPI payments - Collect","path":"collect","order":2,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu payments - Collect request - Check payment status","path":"check-status","order":3},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu payments - Create collect request","path":"create-collect-request","order":2},{"name":"Verify customer VPA","visible_in_sidebar":true,"page_title":"UPI Setu payments - Verify customer VPA","path":"verify-customer-vpa-api","order":1}]},{"name":"Flash","visible_in_sidebar":true,"page_title":"UPI payments - Flash","path":"flash","order":1,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu payments - Intent/QR - Check payment status","path":"check-status","order":2},{"name":"Dynamic QR","visible_in_sidebar":true,"page_title":"UPI Setu payments - Create Dynamic QR","path":"create-dqr","order":1},{"name":"Static QR","visible_in_sidebar":true,"page_title":"UPI Setu payments - Create Static QR","path":"create-sqr","order":1}]},{"name":"TPV","visible_in_sidebar":true,"page_title":"UPI payments - TPV","path":"tpv","order":3,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Payments - TPV - Check payment status","path":"check-status","order":2},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Payments - Create TPV API","path":"create-tpv","order":1},{"name":"Payments","visible_in_sidebar":true,"page_title":"UMAP - Notifications and alerts - Payments","path":"life-cycle","order":1}]}]},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"UPI Setu - Quickstart","path":"quickstart","order":1,"children":[{"name":"Aggregators","visible_in_sidebar":true,"page_title":"UPI Setu - Quickstart for aggregators","path":"aggregators","order":1},{"name":"Merchants","visible_in_sidebar":true,"page_title":"UPI Setu - Quickstart for merchants","path":"merchants","order":2}]},{"name":"Refunds and disputes","visible_in_sidebar":true,"page_title":"UPI Setu - Refunds and disputes","path":"refunds-disputes","order":6,"children":[{"name":"Check refund status","visible_in_sidebar":true,"page_title":"UPI Setu - Refunds and disputes - Check refund status API","path":"check-refund-status-api","order":2},{"name":"Create refund","visible_in_sidebar":true,"page_title":"UPI Setu - Refunds and disputes - Create refund API","path":"create-refund-api","order":1},{"name":"Fetch dispute","visible_in_sidebar":true,"page_title":"UPI Setu - Refunds and disputes - Fetch dispute API","path":"fetch-dispute-api","order":3}]},{"name":"Transaction Monitoring","visible_in_sidebar":false,"page_title":"UPI Setu - Transaction Monitoring","path":"transaction-monitoring","order":5,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Transaction monitoring - Check status API","path":"check-status-api","order":1},{"name":"Check status history","visible_in_sidebar":true,"page_title":"UPI Setu - Transaction monitoring - Check status sistory API","path":"check-status-history-api","order":2},{"name":"Fetch payment","visible_in_sidebar":true,"page_title":"UPI Setu - Transaction monitoring - Fetch payment API","path":"fetch-payment-api","order":3}]}]}]},{"name":"Data","path":"data","order":1,"visible_in_sidebar":true,"children":[{"name":"KYC","path":"kyc","order":0,"visible_in_sidebar":true,"children":[{"name":"Secure Data Add-On","visible_in_sidebar":true,"page_title":"Setu Encrypted APIs","path":"encryption","order":2},{"name":"Overview","visible_in_sidebar":true,"page_title":"Setu KYC Overview","path":"overview","order":1}]},{"name":"PAN verification","path":"pan","order":0,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"PAN verification API reference","path":"api-reference","order":1},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"PAN verification quickstart","path":"quickstart","order":0}]},{"name":"Aadhaar eSign","path":"esign","order":2,"visible_in_sidebar":true,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Aadhaar eSign API reference","path":"api-reference","order":9},{"name":"Error codes","visible_in_sidebar":true,"page_title":"Aadhaar eSign error codes","path":"error-codes","order":8},{"name":"eStamp overview","visible_in_sidebar":true,"page_title":"eStamp overview","path":"estamp","order":2},{"name":"Flexible eSign guide","visible_in_sidebar":true,"page_title":"Integration guide with flexible signature coordinates","path":"flexi-esign","order":4},{"name":"eSign Name Match","visible_in_sidebar":true,"page_title":"Aadhaar eSign Name Match","path":"name-match","order":6},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Aadhaar eSign Notifications","path":"notifications","order":7},{"name":"Overview","visible_in_sidebar":true,"page_title":"Aadhaar eSign overview","path":"overview","order":1},{"name":"PDF templates","visible_in_sidebar":true,"page_title":"Integration guide with pdf templating API's","path":"pdf-templating","order":5},{"name":"Integration guide","visible_in_sidebar":true,"page_title":"Aadhaar eSign integration guide","path":"quickstart","order":3}]},{"name":"DigiLocker","path":"digilocker","order":3,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Digilocker API reference","path":"api-reference","order":3},{"name":"Error codes","visible_in_sidebar":true,"page_title":"DigiLocker error codes","path":"error-codes","order":4},{"name":"Overview","visible_in_sidebar":true,"page_title":"Digilocker overview","path":"overview","order":0},{"name":"Integration guide","visible_in_sidebar":true,"page_title":"Digilocker quickstart","path":"quickstart","order":1}]},{"name":"AA Gateway","path":"account-aggregator","order":4,"versions":["v1","v2"],"default_version":"v2","visible_in_sidebar":true,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Account Aggregator API integration","path":"api-integration","order":3,"children":[{"name":"Account Availability","visible_in_sidebar":true,"page_title":"Account Aggregator Account Availability","path":"account-availability-apis","order":5},{"name":"Consent flow","visible_in_sidebar":true,"page_title":"Account Aggregator Consent flow","path":"consent-flow","order":1},{"name":"Data flow","visible_in_sidebar":true,"page_title":"Account Aggregator Data flow","path":"data-apis","order":2},{"name":"Active FIPs","visible_in_sidebar":true,"page_title":"Account Aggregator Active FIPs","path":"fip-apis","order":4},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Account Aggregator Notifications","path":"notifications","order":3}]},{"name":"API reference","visible_in_sidebar":true,"page_title":"Account Aggregator API reference","path":"api-reference","order":10},{"name":"Consent object","visible_in_sidebar":true,"page_title":"Account Aggregator consent object","path":"consent-object","order":4},{"name":"Embed Setu screens","visible_in_sidebar":true,"page_title":"Account Aggregator Embed Setu screens","path":"embed-setu-aa","order":7},{"name":"FI data types","visible_in_sidebar":true,"page_title":"Account Aggregator FI data types","path":"fi-data-types","order":5},{"name":"Licenses and go live","visible_in_sidebar":true,"page_title":"Account Aggregator license and go live process","path":"licenses-and-go-live","order":8,"children":[{"name":"Go live","visible_in_sidebar":true,"page_title":"FIU go live process","path":"go-live","order":2},{"name":"Licenses","visible_in_sidebar":true,"page_title":"Licenses required to participate in AA","path":"licenses","order":1},{"name":"Participants in AA","visible_in_sidebar":true,"page_title":"Participants in AA","path":"participants-in-aa","order":0}]},{"name":"Multi AA gateway","visible_in_sidebar":true,"page_title":"Account Aggregator multi-AA gateway","path":"multi-aa-gateway","order":2},{"name":"Overview","visible_in_sidebar":true,"page_title":"Account Aggregator overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Account Aggregator quickstart","path":"quickstart","order":1},{"path":"v1","children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Account Aggregator API integration","path":"api-integration","order":3,"children":[{"name":"Consent flow","visible_in_sidebar":true,"page_title":"Account Aggregator Consent flow","path":"consent-flow","order":1},{"name":"Data flow","visible_in_sidebar":true,"page_title":"Account Aggregator Data flow","path":"data-apis","order":2},{"name":"Active FIPs","visible_in_sidebar":true,"page_title":"Account Aggregator Active FIPs","path":"fip-apis","order":4},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Account Aggregator Notifications","path":"notifications","order":3}]},{"name":"API reference","visible_in_sidebar":true,"page_title":"Account Aggregator API reference","path":"api-reference","order":10},{"name":"Consent object","visible_in_sidebar":true,"page_title":"Account Aggregator Consent object","path":"consent-object","order":4},{"name":"Embed Setu screens","visible_in_sidebar":true,"page_title":"Account Aggregator Embed Setu screens","path":"embed-setu-aa","order":7},{"name":"End-to-end encryption","visible_in_sidebar":false,"page_title":"Account Aggregator End-to-end encryption","path":"encryption","order":1},{"name":"FI data types","visible_in_sidebar":true,"page_title":"Account Aggregator FI data types","path":"fi-data-types","order":5},{"name":"Get started","visible_in_sidebar":false,"page_title":"Account Aggregator getting started","path":"get-started","order":0},{"name":"Licenses and go live","visible_in_sidebar":true,"page_title":"Account Aggregator license and go live process","path":"licenses-and-go-live","order":8,"children":[{"name":"Go live","visible_in_sidebar":true,"page_title":"FIU go live process","path":"go-live","order":2},{"name":"Licenses","visible_in_sidebar":true,"page_title":"Licenses required to participate in AA","path":"licenses","order":1},{"name":"Participants in AA","visible_in_sidebar":true,"page_title":"Participants in AA","path":"participants-in-aa","order":0}]},{"name":"Migration guide","visible_in_sidebar":true,"page_title":"Account Aggregator Migration Guide","path":"migration-guide","order":6,"children":[{"name":"Consent flow","visible_in_sidebar":true,"page_title":"Account Aggregator Consent flow","path":"consent-flow","order":1},{"name":"Data flow","visible_in_sidebar":true,"page_title":"Account Aggregator Data flow","path":"data-flow","order":2},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Account Aggregator Notifications","path":"notifications","order":3}]},{"name":"Overview","visible_in_sidebar":true,"page_title":"Account Aggregator overview","path":"overview","order":0},{"name":"Postman integration","visible_in_sidebar":true,"page_title":"Account Aggregator Postman integration","path":"postman","order":2},{"name":"Quickstart","visible_in_sidebar":false,"page_title":"Account Aggregator quickstart","path":"quickstart-v1","order":1},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Account Aggregator quickstart","path":"quickstart","order":1},{"name":"Request signing","visible_in_sidebar":false,"page_title":"Account Aggregator Request signing","path":"request-signing","order":1}]}]},{"name":"Bank account verification","path":"bav","order":5,"visible_in_sidebar":false,"children":[{"name":"Bundled BAV","visible_in_sidebar":true,"page_title":"Bundled Bank Account Verification","path":"bundled-bav","order":2,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Bundled BAV API integration","path":"api-integration","order":2},{"name":"API reference","visible_in_sidebar":true,"page_title":"Bundled BAV API reference","path":"api-reference","order":3},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Quickstart for Bundled BAV","path":"quickstart","order":1}]},{"name":"Penny drop","visible_in_sidebar":true,"page_title":"BAV using penny drop","path":"penny-drop","order":1,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"BAV API integration","path":"api-integration","order":1,"children":[{"name":"Async API","visible_in_sidebar":true,"page_title":"BAV Async API integration","path":"async","order":2},{"path":"bav-codes"},{"name":"Sync API","visible_in_sidebar":true,"page_title":"BAV Sync API integration","path":"sync","order":1}]},{"name":"API reference","visible_in_sidebar":true,"page_title":"BAV API reference","path":"api-reference","order":3},{"name":"Notifications","visible_in_sidebar":true,"page_title":"BAV Async Penny drop Notifications","path":"notifications","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BAV quickstart","path":"quickstart","order":0}]},{"name":"Penny drop + PennyLess","visible_in_sidebar":true,"page_title":"Bank account verification using Penny drop + PennyLess","path":"pennydrop-pennyless","order":2,"children":[{"name":"API Integration","visible_in_sidebar":true,"page_title":"Penny drop + PennyLess API Integration","path":"api-integration","order":1},{"name":"API reference","visible_in_sidebar":true,"page_title":"Pennydrop-pennyless API reference","path":"api-reference","order":3},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Penny drop + PennyLess Notifications","path":"notifications","order":2}]},{"name":"PennyLess Drop","visible_in_sidebar":true,"page_title":"BAV using PennyLess Drop API","path":"pennyless-drop","order":4,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"BAV Pennyless API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Quickstart for PennyLess drop API","path":"quickstart","order":1}]},{"name":"Reverse Penny drop","visible_in_sidebar":true,"page_title":"BAV using reverse penny drop","path":"reverse-penny-drop","order":3,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"RPD API integration","path":"api-integration","order":2},{"name":"API reference","visible_in_sidebar":true,"page_title":"BAV RPD API reference","path":"api-reference","order":4},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Quickstart for reverse penny drop","path":"quickstart","order":1},{"name":"Webhook Auth","visible_in_sidebar":true,"page_title":"Webhook Authentication","path":"webhook-authentication","order":3}]}]},{"name":"Insights","path":"insights","order":5,"versions":["v1","v2","v3"],"default_version":"v3","visible_in_sidebar":true,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Setu Insights API reference","path":"api-reference","order":4},{"name":"Error codes","visible_in_sidebar":true,"page_title":"Setu Insights error codes","path":"error-code","order":5},{"name":"List of insights","visible_in_sidebar":true,"page_title":"All Setu insights","path":"insights","order":2},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Setu Insights notifications","path":"notifications","order":3},{"name":"Overview","visible_in_sidebar":true,"page_title":"Setu Insights overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Setu Insights quickstart","path":"quickstart","order":1,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Setu Insights Postman integration","path":"api-integration","order":1},{"name":"Postman integration","visible_in_sidebar":true,"page_title":"Setu Insights Postman integration","path":"postman","order":0}]},{"path":"v1","children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Setu Insights API reference","path":"api-reference","order":4},{"name":"List of insights","visible_in_sidebar":true,"page_title":"All Setu insights","path":"insights","order":2},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Setu Insights notifications","path":"notifications","order":3},{"name":"Overview","visible_in_sidebar":true,"page_title":"Setu Insights overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Setu Insights quickstart","path":"quickstart","order":1,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Setu Insights Postman integration","path":"api-integration","order":1},{"name":"Postman integration","visible_in_sidebar":true,"page_title":"Setu Insights Postman integration","path":"postman","order":0}]}]},{"path":"v2","children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Setu Insights API reference","path":"api-reference","order":4},{"name":"List of insights","visible_in_sidebar":true,"page_title":"All Setu insights","path":"insights","order":2},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Setu Insights notifications","path":"notifications","order":3},{"name":"Overview","visible_in_sidebar":true,"page_title":"Setu Insights overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Setu Insights quickstart","path":"quickstart","order":1}]}]},{"name":"ULI","path":"uli","order":6,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"GSTIN verification API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"GST Verification quickstart","path":"quickstart","order":1}]},{"name":"GST verification","path":"gst","order":6,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"GSTIN verification API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"GST Verification quickstart","path":"quickstart","order":1}]},{"name":"Match APIs","path":"match-apis","order":7,"visible_in_sidebar":false,"children":[{"name":"Name match","visible_in_sidebar":true,"page_title":"Name match APIs","path":"name-match","order":1,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Name Match API reference","path":"api-reference","order":4},{"name":"Examples","visible_in_sidebar":true,"page_title":"Name Match API response examples","path":"examples","order":3},{"name":"Overview","visible_in_sidebar":true,"page_title":"Name Match API overview","path":"overview","order":1},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Name Match API quickstart","path":"quickstart","order":2}]}]},{"name":"eKYC","path":"ekyc","order":8,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"eKYC API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"PAN verification quickstart","path":"quickstart","order":1}]}]},{"name":"Dev tools","path":"dev-tools","order":2,"visible_in_sidebar":true,"children":[{"name":"The Bridge","path":"bridge","order":0,"versions":["v1","v2"],"default_version":"v2","visible_in_sidebar":true,"children":[{"name":"Analytics and reports","visible_in_sidebar":true,"page_title":"Bridge analytics and reports","path":"analytics-and-reports","order":3},{"name":"Configure products","visible_in_sidebar":true,"page_title":"Bridge explore and configure products","path":"explore-and-configure-products","order":2},{"name":"Glossary","visible_in_sidebar":true,"page_title":"Bridge glossary","path":"glossary","order":1},{"name":"Overview","visible_in_sidebar":true,"page_title":"Bridge overview","path":"overview","order":0},{"name":"Settings","visible_in_sidebar":true,"page_title":"Bridge settings","path":"settings","order":4},{"name":"User profile","visible_in_sidebar":true,"page_title":"Bridge user profile","path":"user-profile","order":5},{"path":"v1","children":[{"name":"Bridge configuration","visible_in_sidebar":false,"page_title":"Bridge configuration","path":"configure","order":6},{"name":"Generate Token","visible_in_sidebar":false,"page_title":"Bridge generate token","path":"generate-token","order":4},{"name":"Org settings","visible_in_sidebar":true,"page_title":"Bridge org settings","path":"org-settings","order":3,"children":[{"name":"API keys","visible_in_sidebar":true,"page_title":"API keys","path":"api-keys","order":2,"children":[{"name":"JWT Auth","visible_in_sidebar":false,"page_title":"JWT Auth","path":"jwt-auth","order":3},{"name":"JWT","visible_in_sidebar":true,"page_title":"JWT","path":"jwt","order":1},{"name":"OAuth","visible_in_sidebar":true,"page_title":"OAuth","path":"oauth","order":2}]},{"name":"People","visible_in_sidebar":true,"page_title":"People","path":"people","order":1}]},{"name":"Overview","visible_in_sidebar":true,"page_title":"Bridge overview","path":"overview","order":0},{"name":"Reports","visible_in_sidebar":true,"page_title":"Bridge reports","path":"reports","order":1,"children":[{"name":"Types","visible_in_sidebar":false,"page_title":"Report types","path":"types","order":1}]},{"name":"Reports API","visible_in_sidebar":false,"page_title":"Reports API","path":"reports-api","order":5}]}]}]},{"name":"Sample Category","path":"sample-category","order":3,"visible_in_sidebar":false,"children":[{"name":"Sample Product","path":"sample-product","order":0,"visible_in_sidebar":false,"children":[{"name":"Sample Page","visible_in_sidebar":false,"page_title":"Docs sample page","path":"sample-page","order":0}]}]}]} \ No newline at end of file +{"home":[{"name":"Payments","path":"payments","order":0,"visible_in_sidebar":true,"api_reference":true,"children":[{"name":"BBPS BillCollect","path":"bbps","order":0,"visible_in_sidebar":true,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"BBPS API reference","path":"api-reference","order":9},{"name":"Axis BBPS","visible_in_sidebar":false,"page_title":"Axis BBPS API Approach Document","path":"axis","order":10},{"name":"Bill Structure","visible_in_sidebar":true,"page_title":"BBPS - Bill Structure","path":"bill-structure","order":5,"children":[{"name":"Special cases","visible_in_sidebar":true,"page_title":"BBPS - Bill Structure special cases","path":"special-cases","order":1}]},{"name":"Go live","visible_in_sidebar":true,"page_title":"BBPS - Go live","path":"go-live","order":3},{"name":"Notifications","visible_in_sidebar":true,"page_title":"BBPS - Notifications","path":"notifications","order":4},{"name":"Overview","visible_in_sidebar":true,"page_title":"BBPS - Overview","path":"overview","order":1},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS - Quickstart","path":"quickstart","order":2,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"BBPS - API integration","path":"api-integration","order":2},{"name":"No-code CSV","visible_in_sidebar":true,"page_title":"BBPS - No-code CSV","path":"no-code-integration","order":1},{"name":"Share bills","visible_in_sidebar":false,"page_title":"BBPS - Share bills","path":"share-biils","order":1}]},{"name":"Reports API","visible_in_sidebar":true,"page_title":"BBPS - Reports API","path":"reports","order":6},{"name":"Additional resources","visible_in_sidebar":true,"page_title":"BBPS - Additional Resources","path":"resources","order":8,"children":[{"name":"Errors","visible_in_sidebar":true,"page_title":"BBPS error codes","path":"errors","order":4},{"name":"JWT authentication","visible_in_sidebar":true,"page_title":"UPI Deeplinks JWT authentication","path":"jwt","order":2},{"name":"OAuth 2.0","visible_in_sidebar":true,"page_title":"BBPS OAuth 2.0","path":"oauth","order":1},{"name":"Settlement object","visible_in_sidebar":true,"page_title":"UPI Deeplinks settlement object","path":"settlement-object","order":3}]}]},{"name":"BBPS BillPay","path":"billpay","order":1,"versions":["v1","v2"],"default_version":"v2","visible_in_sidebar":true,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"BBPS Billpay API integration","path":"api-integration","order":1,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"COU Direct Connectivity API reference","path":"api-reference","order":10},{"name":"List of APIs","visible_in_sidebar":true,"page_title":"BBPS COU - List of APIs","path":"apis","order":2},{"name":"FX Retail","visible_in_sidebar":true,"page_title":"BBPS COU - FX Retail (Forex category)","path":"fx-retail","order":8},{"name":"API encryption (optional)","visible_in_sidebar":true,"page_title":"BBPS COU - API payload encryption (Dynamic IV)","path":"api-encryption","order":9},{"name":"Harmonization of TAT","visible_in_sidebar":true,"page_title":"Harmonization Of TAT (Disputes API)","path":"harmonization_of_tat","order":6},{"name":"Objects","visible_in_sidebar":true,"page_title":"BBPS COU - Objects","path":"objects","order":11},{"name":"Paying Bills","visible_in_sidebar":true,"page_title":"Paying Bills","path":"paying-bills","order":4,"children":[{"name":"Paying for options","visible_in_sidebar":true,"page_title":"Paying for alternative options","path":"bill-payment-options","order":4},{"name":"Passing CCF","visible_in_sidebar":true,"page_title":"Customer Convenience Fee (CCF) Integration Guide","path":"customer-convenience-fee","order":3},{"name":"Paying multiple bills","visible_in_sidebar":true,"page_title":"Paying for multiple bills","path":"multi-bill-processing","order":5},{"name":"Paying for plans","visible_in_sidebar":true,"page_title":"Paying for plans","path":"plan-mdm-integration","order":6},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS Bill Payment Integration Guide","path":"quickstart","order":1},{"name":"Remitter Details","visible_in_sidebar":true,"page_title":"Passing Remitter Details","path":"remittance_flows_guide","order":2}]},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS COU - API integration","path":"quickstart","order":1},{"name":"Integrating with UPMS","visible_in_sidebar":true,"page_title":"BBPS COU - Integrating with UPMS","path":"upms","order":7},{"name":"Migration Guide to v2","visible_in_sidebar":true,"page_title":"BBPS COU - Migration Guide to v2","path":"v2-migration","order":5},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"BBPS COU - Webhooks","path":"webhooks","order":3}]},{"name":"API reference","visible_in_sidebar":false,"page_title":"BillPay API reference","path":"api-reference","order":5},{"path":"mcp","children":[{"name":"Integration Guide","visible_in_sidebar":false,"page_title":"MCP Server for Bill Payments - Integration Guide","path":"integration-guide","order":1},{"name":"Tools and Prompts","visible_in_sidebar":false,"page_title":"MCP Server for Bill Payments - Tools and Prompts","path":"tools-and-prompts","order":2}]},{"name":"Prepaid Recharge","visible_in_sidebar":true,"page_title":"BBPS Billpay Prepaid Recharge APIs","path":"mobile-prepaid-recharge","order":3,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Mobile Prepaid Recharge API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Mobile Prepaid Recharge quickstart","path":"quickstart","order":1},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"Mobile Prepaid Recharge Webhooks","path":"webhooks","order":3}]},{"name":"Overview","visible_in_sidebar":true,"page_title":"BBPS Billpay Overview","path":"overview","order":0},{"name":"Pre-built screens","visible_in_sidebar":true,"page_title":"BBPS Billpay pre-built screens","path":"pre-built-screens","order":2,"children":[{"name":"API reference","visible_in_sidebar":false,"page_title":"BBPS Billpay API reference","path":"api-reference-wl","order":4},{"name":"API reference","visible_in_sidebar":true,"page_title":"BBPS Billpay API reference","path":"api-reference","order":5},{"name":"Custom payment","visible_in_sidebar":true,"page_title":"BBPS Billpay custom payment","path":"custom-payment","order":2,"children":[{"name":"Android","visible_in_sidebar":true,"page_title":"BBPS Billpay android integration for custom payment","path":"android","order":3},{"name":"Required APIs","visible_in_sidebar":true,"page_title":"BBPS Billpay APIs for custom payment","path":"apis","order":1},{"name":"Cross platform","visible_in_sidebar":true,"page_title":"BBPS Billpay cross-platform integration for custom payment","path":"cross-platform","order":3},{"name":"iOS","visible_in_sidebar":true,"page_title":"BBPS Billpay iOS integration for custom payment","path":"iOS","order":4},{"name":"Website","visible_in_sidebar":true,"page_title":"BBPS Billpay website integration for custom payment","path":"website","order":2}]},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS Billpay Quickstart","path":"quickstart","order":1,"children":[{"name":"Android","visible_in_sidebar":true,"page_title":"BBPS Billpay Android integration","path":"android","order":2},{"name":"API","visible_in_sidebar":true,"page_title":"BBPS Billpay API","path":"api","order":2},{"name":"Cross platform","visible_in_sidebar":true,"page_title":"BBPS Billpay cross platform integration","path":"cross-platform","order":4},{"name":"iOS","visible_in_sidebar":true,"page_title":"BBPS Billpay iOS integration","path":"iOS","order":3},{"name":"Website","visible_in_sidebar":true,"page_title":"BBPS Billpay website","path":"website","order":1}]},{"name":"Remitter Details","visible_in_sidebar":true,"page_title":"Remitter Details For Bill Payments Integration Guide","path":"remitter-details","order":4},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"BBPS Billpay webhooks","path":"webhooks","order":2}]},{"path":"v1","children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"BBPS Billpay API integration","path":"api-integration","order":1,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"COU Direct Connectivity API reference","path":"api-reference","order":5},{"name":"List of APIs","visible_in_sidebar":true,"page_title":"BBPS COU - List of APIs","path":"apis","order":2},{"name":"Deprecated APIs","visible_in_sidebar":false,"page_title":"BBPS COU - API integration (deprecated)","path":"deprecated","order":4,"children":[{"name":"Mock environment","visible_in_sidebar":false,"page_title":"BBPS Billpay Mock environment","path":"mock-environment","order":2},{"name":"Polling","visible_in_sidebar":false,"page_title":"BBPS Billpay polling","path":"polling","order":2}]},{"name":"Objects","visible_in_sidebar":true,"page_title":"BBPS COU - Objects","path":"objects","order":3},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS COU - API integration","path":"quickstart","order":1},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"BBPS COU - Webhooks","path":"webhooks","order":4}]},{"name":"API reference","visible_in_sidebar":false,"page_title":"BillPay API reference","path":"api-reference","order":5},{"name":"Overview","visible_in_sidebar":true,"page_title":"BBPS Billpay Overview","path":"overview","order":0},{"name":"Pre-built screens","visible_in_sidebar":true,"page_title":"BBPS Billpay pre-built screens","path":"pre-built-screens","order":2,"children":[{"name":"API reference","visible_in_sidebar":false,"page_title":"BBPS Billpay API reference","path":"api-reference-wl","order":4},{"name":"API reference","visible_in_sidebar":true,"page_title":"BBPS Billpay API reference","path":"api-reference","order":4},{"name":"Custom payment","visible_in_sidebar":true,"page_title":"BBPS Billpay custom payment","path":"custom-payment","order":2,"children":[{"name":"Android","visible_in_sidebar":true,"page_title":"BBPS Billpay android integration for custom payment","path":"android","order":3},{"name":"Required APIs","visible_in_sidebar":true,"page_title":"BBPS Billpay APIs for custom payment","path":"apis","order":1},{"name":"Cross platform","visible_in_sidebar":true,"page_title":"BBPS Billpay cross-platform integration for custom payment","path":"cross-platform","order":3},{"name":"iOS","visible_in_sidebar":true,"page_title":"BBPS Billpay iOS integration for custom payment","path":"iOS","order":4},{"name":"Website","visible_in_sidebar":true,"page_title":"BBPS Billpay website integration for custom payment","path":"website","order":2}]},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BBPS Billpay Quickstart","path":"quickstart","order":1,"children":[{"name":"Android","visible_in_sidebar":true,"page_title":"BBPS Billpay Android integration","path":"android","order":2},{"name":"API","visible_in_sidebar":true,"page_title":"BBPS Billpay API","path":"api","order":2},{"name":"Cross platform","visible_in_sidebar":true,"page_title":"BBPS Billpay cross platform integration","path":"cross-platform","order":4},{"name":"iOS","visible_in_sidebar":true,"page_title":"BBPS Billpay iOS integration","path":"iOS","order":3},{"name":"Website","visible_in_sidebar":true,"page_title":"BBPS Billpay website","path":"website","order":1}]},{"name":"Webhooks","visible_in_sidebar":true,"page_title":"BBPS Billpay webhooks","path":"webhooks","order":2}]}]}]},{"name":"WhatsApp Collect","path":"whatsapp-collect","order":3,"visible_in_sidebar":true,"children":[{"name":"API Integration","visible_in_sidebar":true,"page_title":"WhatsApp Collect API Integration","path":"api-integration","order":3},{"name":"API reference","visible_in_sidebar":true,"page_title":"WhatsApp Collect API reference","path":"api-reference","order":5},{"name":"Error codes","visible_in_sidebar":true,"page_title":"WhatsApp Collect error codes","path":"errors","order":4},{"name":"Collection journey","visible_in_sidebar":true,"page_title":"WhatsApp Collect Journey","path":"journey","order":1},{"name":"Overview","visible_in_sidebar":true,"page_title":"WhatsApp Collect Overview","path":"overview","order":0},{"name":"Collection reminders","visible_in_sidebar":true,"page_title":"WhatsApp Collect reminders","path":"reminders","order":2}]},{"name":"UPI DeepLinks","path":"upi-deeplinks","order":4,"visible_in_sidebar":true,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"UPI Deeplinks API reference","path":"api-reference","order":8},{"name":"Notifications","visible_in_sidebar":true,"page_title":"UPI Deeplinks Notifications","path":"notifications","order":6},{"name":"Overview","visible_in_sidebar":true,"page_title":"UPI Deeplinks Overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"UPI Deeplinks quickstart","path":"quickstart","order":1,"children":[{"name":"Go Live","visible_in_sidebar":true,"page_title":"UPI Deeplinks go live","path":"go-live","order":1}]},{"name":"Refunds","visible_in_sidebar":true,"page_title":"UPI Deeplinks Refunds","path":"refunds","order":4},{"name":"Reports API","visible_in_sidebar":true,"page_title":"UPI Deeplinks Reports API","path":"reports","order":5},{"name":"Additional resources","visible_in_sidebar":true,"page_title":"UPI Deeplinks additonal resources","path":"resources","order":6,"children":[{"name":"JWT authentication","visible_in_sidebar":true,"page_title":"UPI Deeplinks JWT authentication","path":"jwt","order":2},{"name":"OAuth 2.0","visible_in_sidebar":true,"page_title":"UPI Deeplinks OAuth 2.0","path":"oauth","order":1},{"name":"Settlement object","visible_in_sidebar":true,"page_title":"UPI Deeplinks settlement object","path":"settlement-object","order":3}]},{"name":"SDKs","visible_in_sidebar":true,"page_title":"UPI Deeplinks SDKs","path":"sdks","order":3},{"name":"Third party verification","visible_in_sidebar":true,"page_title":"UPI Deeplinks third party verification","path":"third-party-verification","order":3}]},{"name":"UPI Setu","path":"umap","order":7,"visible_in_sidebar":true,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"UPI Setu - API integration","path":"api-integration","order":2,"children":[{"name":"Aggregators","visible_in_sidebar":true,"page_title":"UPI Setu - API integration for aggregators","path":"aggregators","order":1},{"name":"Merchants","visible_in_sidebar":true,"page_title":"UPI Setu - API integration for merchants","path":"merchants","order":2}]},{"name":"API reference","visible_in_sidebar":true,"page_title":"UPI Setu - API reference","path":"api-reference","order":8},{"name":"UPI mandates","visible_in_sidebar":true,"page_title":"UPI mandates","path":"mandates","order":4,"children":[{"name":"Mandate operations","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Mandate operations","path":"generic","order":5,"children":[{"name":"Pause","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Pause","path":"pause","order":3},{"name":"Revoke","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Revoke","path":"revoke","order":2},{"name":"Unpause","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Unpause","path":"unpause","order":4},{"name":"Update","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Update","path":"update","order":1}]},{"name":"OneShot","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - OneShot","path":"one-shot","order":1,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Check payment status","path":"check-status","order":4},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Create One Time Mandate","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Execute One Time Mandate","path":"execute","order":3},{"name":"Pre Debit Notify","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Send One Time Mandate Pre Debit Notification","path":"pre-debit-notify","order":2}]},{"name":"Recur","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Recur","path":"recur","order":3,"children":[{"name":"Check payment status","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Check payment status","path":"check-status","order":4},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Create recurring mandate","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Execute mandate","path":"execute","order":3},{"name":"Pre Debit Notify","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Send Recurring Mandate Pre Debit Notification","path":"pre-debit-notify","order":2}]},{"name":"Reserve","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Reserve","path":"reserve","order":2,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Check payment status","path":"check-status","order":4},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Create Reserve Mandate","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Execute Reserve Mandate","path":"execute","order":3}]},{"name":"ReservePlus","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - ReservePlus","path":"reserve-plus","order":4,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Check payment status","path":"check-status","order":3},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Create single block multi-debit","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Mandates - Execute single block multi-debit","path":"execute","order":2}]}]},{"name":"Merchant on-boarding","visible_in_sidebar":true,"page_title":"UPI Setu - Merchant onboarding","path":"merchant-onboarding","order":2,"children":[{"name":"Check VPA availability","visible_in_sidebar":true,"page_title":"UPI Setu - Merchant on-boarding - Check VPA availability","path":"check-vpa-availability-api","order":2},{"name":"Setup a merchant","visible_in_sidebar":true,"page_title":"UPI Setu - Merchant on-boarding - Setup merchant","path":"create-merchant-api","order":1},{"name":"Registering VPA","visible_in_sidebar":true,"page_title":"UPI Setu - Merchant on-boarding - Registering a VPA","path":"create-vpa-api","order":3}]},{"name":"Notifications and alerts","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts","path":"notifications","order":7,"children":[{"name":"VPA verification","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Customer VPA verification","path":"customer-vpa-verification","order":6},{"name":"Mandates","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Mandates","path":"mandates","order":3,"children":[{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Creation of mandate","path":"create","order":1},{"name":"Execute","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Mandate execution","path":"execute","order":7},{"name":"Notify","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Mandate pre-debit notifications","path":"notify","order":6},{"name":"Pause","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Pausing mandate","path":"pause","order":4},{"name":"Revoke","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Revoking mandate","path":"revoke","order":3},{"name":"Unpause","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Unpausing mandate","path":"unpause","order":5},{"name":"Update","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Updating mandate","path":"update","order":2}]},{"name":"Payments","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Payments","path":"payments","order":2},{"name":"Refunds","visible_in_sidebar":true,"page_title":"UPI Setu - Notifications and alerts - Refunds","path":"refunds","order":4},{"name":"Verify signature","visible_in_sidebar":true,"page_title":"UMAP - Events and notifications","path":"verify-signature","order":1}]},{"name":"Overview","visible_in_sidebar":true,"page_title":"UPI Setu - Overview","path":"overview","order":0},{"name":"UPI payments","visible_in_sidebar":true,"page_title":"UPI payments","path":"payments","order":3,"children":[{"name":"Collect","visible_in_sidebar":true,"page_title":"UPI payments - Collect","path":"collect","order":2,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu payments - Collect request - Check payment status","path":"check-status","order":3},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu payments - Create collect request","path":"create-collect-request","order":2},{"name":"Verify customer VPA","visible_in_sidebar":true,"page_title":"UPI Setu payments - Verify customer VPA","path":"verify-customer-vpa-api","order":1}]},{"name":"Flash","visible_in_sidebar":true,"page_title":"UPI payments - Flash","path":"flash","order":1,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu payments - Intent/QR - Check payment status","path":"check-status","order":2},{"name":"Dynamic QR","visible_in_sidebar":true,"page_title":"UPI Setu payments - Create Dynamic QR","path":"create-dqr","order":1},{"name":"Static QR","visible_in_sidebar":true,"page_title":"UPI Setu payments - Create Static QR","path":"create-sqr","order":1}]},{"name":"TPV","visible_in_sidebar":true,"page_title":"UPI payments - TPV","path":"tpv","order":3,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Payments - TPV - Check payment status","path":"check-status","order":2},{"name":"Create","visible_in_sidebar":true,"page_title":"UPI Setu - Payments - Create TPV API","path":"create-tpv","order":1},{"name":"Payments","visible_in_sidebar":true,"page_title":"UMAP - Notifications and alerts - Payments","path":"life-cycle","order":1}]}]},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"UPI Setu - Quickstart","path":"quickstart","order":1,"children":[{"name":"Aggregators","visible_in_sidebar":true,"page_title":"UPI Setu - Quickstart for aggregators","path":"aggregators","order":1},{"name":"Merchants","visible_in_sidebar":true,"page_title":"UPI Setu - Quickstart for merchants","path":"merchants","order":2}]},{"name":"Refunds and disputes","visible_in_sidebar":true,"page_title":"UPI Setu - Refunds and disputes","path":"refunds-disputes","order":6,"children":[{"name":"Check refund status","visible_in_sidebar":true,"page_title":"UPI Setu - Refunds and disputes - Check refund status API","path":"check-refund-status-api","order":2},{"name":"Create refund","visible_in_sidebar":true,"page_title":"UPI Setu - Refunds and disputes - Create refund API","path":"create-refund-api","order":1},{"name":"Fetch dispute","visible_in_sidebar":true,"page_title":"UPI Setu - Refunds and disputes - Fetch dispute API","path":"fetch-dispute-api","order":3}]},{"name":"Transaction Monitoring","visible_in_sidebar":false,"page_title":"UPI Setu - Transaction Monitoring","path":"transaction-monitoring","order":5,"children":[{"name":"Check status","visible_in_sidebar":true,"page_title":"UPI Setu - Transaction monitoring - Check status API","path":"check-status-api","order":1},{"name":"Check status history","visible_in_sidebar":true,"page_title":"UPI Setu - Transaction monitoring - Check status sistory API","path":"check-status-history-api","order":2},{"name":"Fetch payment","visible_in_sidebar":true,"page_title":"UPI Setu - Transaction monitoring - Fetch payment API","path":"fetch-payment-api","order":3}]}]},{"name":"UPI Issuance","path":"upi-issuance","order":8,"visible_in_sidebar":true,"children":[{"name":"Overview","path":"overview","order":0,"visible_in_sidebar":true,"page_title":"UPI Issuance Overview"},{"name":"Quickstart","path":"quickstart","order":1,"visible_in_sidebar":true,"page_title":"UPI Issuance Quickstart"},{"name":"The API envelope","path":"api-envelope","order":2,"visible_in_sidebar":true,"page_title":"UPI Issuance API envelope"},{"name":"User Onboarding","path":"onboarding","order":3,"visible_in_sidebar":true,"page_title":"UPI Issuance User Onboarding","children":[{"name":"Onboarding states","path":"onboarding-states","order":0,"visible_in_sidebar":true,"page_title":"UPI Issuance onboarding states"},{"name":"API integration","path":"api-integration","order":1,"visible_in_sidebar":true,"page_title":"UPI Issuance API integration","children":[{"name":"Device binding","path":"device-binding","order":0,"visible_in_sidebar":true,"page_title":"UPI Issuance device binding"},{"name":"OTP verification","path":"user-otp","order":1,"visible_in_sidebar":true,"page_title":"UPI Issuance OTP verification"},{"name":"VPA management","path":"vpa-management","order":2,"visible_in_sidebar":true,"page_title":"UPI Issuance VPA management"},{"name":"Programs","path":"programs","order":3,"visible_in_sidebar":true,"page_title":"UPI Issuance programs"}]}]},{"name":"Payee blocklist","path":"payee-blocklist","order":4,"visible_in_sidebar":true,"page_title":"UPI Issuance payee blocklist"},{"name":"Testing on QA env","path":"qa-testing","order":5,"visible_in_sidebar":true,"page_title":"UPI Issuance QA env testing"},{"name":"API reference","path":"api-reference","order":6,"visible_in_sidebar":true,"page_title":"UPI Issuance API reference"}]}]},{"name":"Data","path":"data","order":1,"visible_in_sidebar":true,"children":[{"name":"KYC","path":"kyc","order":0,"visible_in_sidebar":true,"children":[{"name":"Secure Data Add-On","visible_in_sidebar":true,"page_title":"Setu Encrypted APIs","path":"encryption","order":2},{"name":"Overview","visible_in_sidebar":true,"page_title":"Setu KYC Overview","path":"overview","order":1}]},{"name":"PAN verification","path":"pan","order":0,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"PAN verification API reference","path":"api-reference","order":1},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"PAN verification quickstart","path":"quickstart","order":0}]},{"name":"Aadhaar eSign","path":"esign","order":2,"visible_in_sidebar":true,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Aadhaar eSign API reference","path":"api-reference","order":9},{"name":"Error codes","visible_in_sidebar":true,"page_title":"Aadhaar eSign error codes","path":"error-codes","order":8},{"name":"eStamp overview","visible_in_sidebar":true,"page_title":"eStamp overview","path":"estamp","order":2},{"name":"Flexible eSign guide","visible_in_sidebar":true,"page_title":"Integration guide with flexible signature coordinates","path":"flexi-esign","order":4},{"name":"eSign Name Match","visible_in_sidebar":true,"page_title":"Aadhaar eSign Name Match","path":"name-match","order":6},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Aadhaar eSign Notifications","path":"notifications","order":7},{"name":"Overview","visible_in_sidebar":true,"page_title":"Aadhaar eSign overview","path":"overview","order":1},{"name":"PDF templates","visible_in_sidebar":true,"page_title":"Integration guide with pdf templating API's","path":"pdf-templating","order":5},{"name":"Integration guide","visible_in_sidebar":true,"page_title":"Aadhaar eSign integration guide","path":"quickstart","order":3}]},{"name":"DigiLocker","path":"digilocker","order":3,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Digilocker API reference","path":"api-reference","order":3},{"name":"Error codes","visible_in_sidebar":true,"page_title":"DigiLocker error codes","path":"error-codes","order":4},{"name":"Overview","visible_in_sidebar":true,"page_title":"Digilocker overview","path":"overview","order":0},{"name":"Integration guide","visible_in_sidebar":true,"page_title":"Digilocker quickstart","path":"quickstart","order":1}]},{"name":"AA Gateway","path":"account-aggregator","order":4,"versions":["v1","v2"],"default_version":"v2","visible_in_sidebar":true,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Account Aggregator API integration","path":"api-integration","order":3,"children":[{"name":"Account Availability","visible_in_sidebar":true,"page_title":"Account Aggregator Account Availability","path":"account-availability-apis","order":5},{"name":"Consent flow","visible_in_sidebar":true,"page_title":"Account Aggregator Consent flow","path":"consent-flow","order":1},{"name":"Data flow","visible_in_sidebar":true,"page_title":"Account Aggregator Data flow","path":"data-apis","order":2},{"name":"Active FIPs","visible_in_sidebar":true,"page_title":"Account Aggregator Active FIPs","path":"fip-apis","order":4},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Account Aggregator Notifications","path":"notifications","order":3}]},{"name":"API reference","visible_in_sidebar":true,"page_title":"Account Aggregator API reference","path":"api-reference","order":10},{"name":"Consent object","visible_in_sidebar":true,"page_title":"Account Aggregator consent object","path":"consent-object","order":4},{"name":"Embed Setu screens","visible_in_sidebar":true,"page_title":"Account Aggregator Embed Setu screens","path":"embed-setu-aa","order":7},{"name":"FI data types","visible_in_sidebar":true,"page_title":"Account Aggregator FI data types","path":"fi-data-types","order":5},{"name":"Licenses and go live","visible_in_sidebar":true,"page_title":"Account Aggregator license and go live process","path":"licenses-and-go-live","order":8,"children":[{"name":"Go live","visible_in_sidebar":true,"page_title":"FIU go live process","path":"go-live","order":2},{"name":"Licenses","visible_in_sidebar":true,"page_title":"Licenses required to participate in AA","path":"licenses","order":1},{"name":"Participants in AA","visible_in_sidebar":true,"page_title":"Participants in AA","path":"participants-in-aa","order":0}]},{"name":"Multi AA gateway","visible_in_sidebar":true,"page_title":"Account Aggregator multi-AA gateway","path":"multi-aa-gateway","order":2},{"name":"Overview","visible_in_sidebar":true,"page_title":"Account Aggregator overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Account Aggregator quickstart","path":"quickstart","order":1},{"path":"v1","children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Account Aggregator API integration","path":"api-integration","order":3,"children":[{"name":"Consent flow","visible_in_sidebar":true,"page_title":"Account Aggregator Consent flow","path":"consent-flow","order":1},{"name":"Data flow","visible_in_sidebar":true,"page_title":"Account Aggregator Data flow","path":"data-apis","order":2},{"name":"Active FIPs","visible_in_sidebar":true,"page_title":"Account Aggregator Active FIPs","path":"fip-apis","order":4},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Account Aggregator Notifications","path":"notifications","order":3}]},{"name":"API reference","visible_in_sidebar":true,"page_title":"Account Aggregator API reference","path":"api-reference","order":10},{"name":"Consent object","visible_in_sidebar":true,"page_title":"Account Aggregator Consent object","path":"consent-object","order":4},{"name":"Embed Setu screens","visible_in_sidebar":true,"page_title":"Account Aggregator Embed Setu screens","path":"embed-setu-aa","order":7},{"name":"End-to-end encryption","visible_in_sidebar":false,"page_title":"Account Aggregator End-to-end encryption","path":"encryption","order":1},{"name":"FI data types","visible_in_sidebar":true,"page_title":"Account Aggregator FI data types","path":"fi-data-types","order":5},{"name":"Get started","visible_in_sidebar":false,"page_title":"Account Aggregator getting started","path":"get-started","order":0},{"name":"Licenses and go live","visible_in_sidebar":true,"page_title":"Account Aggregator license and go live process","path":"licenses-and-go-live","order":8,"children":[{"name":"Go live","visible_in_sidebar":true,"page_title":"FIU go live process","path":"go-live","order":2},{"name":"Licenses","visible_in_sidebar":true,"page_title":"Licenses required to participate in AA","path":"licenses","order":1},{"name":"Participants in AA","visible_in_sidebar":true,"page_title":"Participants in AA","path":"participants-in-aa","order":0}]},{"name":"Migration guide","visible_in_sidebar":true,"page_title":"Account Aggregator Migration Guide","path":"migration-guide","order":6,"children":[{"name":"Consent flow","visible_in_sidebar":true,"page_title":"Account Aggregator Consent flow","path":"consent-flow","order":1},{"name":"Data flow","visible_in_sidebar":true,"page_title":"Account Aggregator Data flow","path":"data-flow","order":2},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Account Aggregator Notifications","path":"notifications","order":3}]},{"name":"Overview","visible_in_sidebar":true,"page_title":"Account Aggregator overview","path":"overview","order":0},{"name":"Postman integration","visible_in_sidebar":true,"page_title":"Account Aggregator Postman integration","path":"postman","order":2},{"name":"Quickstart","visible_in_sidebar":false,"page_title":"Account Aggregator quickstart","path":"quickstart-v1","order":1},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Account Aggregator quickstart","path":"quickstart","order":1},{"name":"Request signing","visible_in_sidebar":false,"page_title":"Account Aggregator Request signing","path":"request-signing","order":1}]}]},{"name":"Bank account verification","path":"bav","order":5,"visible_in_sidebar":false,"children":[{"name":"Bundled BAV","visible_in_sidebar":true,"page_title":"Bundled Bank Account Verification","path":"bundled-bav","order":2,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Bundled BAV API integration","path":"api-integration","order":2},{"name":"API reference","visible_in_sidebar":true,"page_title":"Bundled BAV API reference","path":"api-reference","order":3},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Quickstart for Bundled BAV","path":"quickstart","order":1}]},{"name":"Penny drop","visible_in_sidebar":true,"page_title":"BAV using penny drop","path":"penny-drop","order":1,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"BAV API integration","path":"api-integration","order":1,"children":[{"name":"Async API","visible_in_sidebar":true,"page_title":"BAV Async API integration","path":"async","order":2},{"path":"bav-codes"},{"name":"Sync API","visible_in_sidebar":true,"page_title":"BAV Sync API integration","path":"sync","order":1}]},{"name":"API reference","visible_in_sidebar":true,"page_title":"BAV API reference","path":"api-reference","order":3},{"name":"Notifications","visible_in_sidebar":true,"page_title":"BAV Async Penny drop Notifications","path":"notifications","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"BAV quickstart","path":"quickstart","order":0}]},{"name":"Penny drop + PennyLess","visible_in_sidebar":true,"page_title":"Bank account verification using Penny drop + PennyLess","path":"pennydrop-pennyless","order":2,"children":[{"name":"API Integration","visible_in_sidebar":true,"page_title":"Penny drop + PennyLess API Integration","path":"api-integration","order":1},{"name":"API reference","visible_in_sidebar":true,"page_title":"Pennydrop-pennyless API reference","path":"api-reference","order":3},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Penny drop + PennyLess Notifications","path":"notifications","order":2}]},{"name":"PennyLess Drop","visible_in_sidebar":true,"page_title":"BAV using PennyLess Drop API","path":"pennyless-drop","order":4,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"BAV Pennyless API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Quickstart for PennyLess drop API","path":"quickstart","order":1}]},{"name":"Reverse Penny drop","visible_in_sidebar":true,"page_title":"BAV using reverse penny drop","path":"reverse-penny-drop","order":3,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"RPD API integration","path":"api-integration","order":2},{"name":"API reference","visible_in_sidebar":true,"page_title":"BAV RPD API reference","path":"api-reference","order":4},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Quickstart for reverse penny drop","path":"quickstart","order":1},{"name":"Webhook Auth","visible_in_sidebar":true,"page_title":"Webhook Authentication","path":"webhook-authentication","order":3}]}]},{"name":"Insights","path":"insights","order":5,"versions":["v1","v2","v3"],"default_version":"v3","visible_in_sidebar":true,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Setu Insights API reference","path":"api-reference","order":4},{"name":"Error codes","visible_in_sidebar":true,"page_title":"Setu Insights error codes","path":"error-code","order":5},{"name":"List of insights","visible_in_sidebar":true,"page_title":"All Setu insights","path":"insights","order":2},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Setu Insights notifications","path":"notifications","order":3},{"name":"Overview","visible_in_sidebar":true,"page_title":"Setu Insights overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Setu Insights quickstart","path":"quickstart","order":1,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Setu Insights Postman integration","path":"api-integration","order":1},{"name":"Postman integration","visible_in_sidebar":true,"page_title":"Setu Insights Postman integration","path":"postman","order":0}]},{"path":"v1","children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Setu Insights API reference","path":"api-reference","order":4},{"name":"List of insights","visible_in_sidebar":true,"page_title":"All Setu insights","path":"insights","order":2},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Setu Insights notifications","path":"notifications","order":3},{"name":"Overview","visible_in_sidebar":true,"page_title":"Setu Insights overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Setu Insights quickstart","path":"quickstart","order":1,"children":[{"name":"API integration","visible_in_sidebar":true,"page_title":"Setu Insights Postman integration","path":"api-integration","order":1},{"name":"Postman integration","visible_in_sidebar":true,"page_title":"Setu Insights Postman integration","path":"postman","order":0}]}]},{"path":"v2","children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Setu Insights API reference","path":"api-reference","order":4},{"name":"List of insights","visible_in_sidebar":true,"page_title":"All Setu insights","path":"insights","order":2},{"name":"Notifications","visible_in_sidebar":true,"page_title":"Setu Insights notifications","path":"notifications","order":3},{"name":"Overview","visible_in_sidebar":true,"page_title":"Setu Insights overview","path":"overview","order":0},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Setu Insights quickstart","path":"quickstart","order":1}]}]},{"name":"ULI","path":"uli","order":6,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"GSTIN verification API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"GST Verification quickstart","path":"quickstart","order":1}]},{"name":"GST verification","path":"gst","order":6,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"GSTIN verification API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"GST Verification quickstart","path":"quickstart","order":1}]},{"name":"Match APIs","path":"match-apis","order":7,"visible_in_sidebar":false,"children":[{"name":"Name match","visible_in_sidebar":true,"page_title":"Name match APIs","path":"name-match","order":1,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"Name Match API reference","path":"api-reference","order":4},{"name":"Examples","visible_in_sidebar":true,"page_title":"Name Match API response examples","path":"examples","order":3},{"name":"Overview","visible_in_sidebar":true,"page_title":"Name Match API overview","path":"overview","order":1},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"Name Match API quickstart","path":"quickstart","order":2}]}]},{"name":"eKYC","path":"ekyc","order":8,"visible_in_sidebar":false,"children":[{"name":"API reference","visible_in_sidebar":true,"page_title":"eKYC API reference","path":"api-reference","order":2},{"name":"Quickstart","visible_in_sidebar":true,"page_title":"PAN verification quickstart","path":"quickstart","order":1}]}]},{"name":"Dev tools","path":"dev-tools","order":2,"visible_in_sidebar":true,"children":[{"name":"The Bridge","path":"bridge","order":0,"versions":["v1","v2"],"default_version":"v2","visible_in_sidebar":true,"children":[{"name":"Analytics and reports","visible_in_sidebar":true,"page_title":"Bridge analytics and reports","path":"analytics-and-reports","order":3},{"name":"Configure products","visible_in_sidebar":true,"page_title":"Bridge explore and configure products","path":"explore-and-configure-products","order":2},{"name":"Glossary","visible_in_sidebar":true,"page_title":"Bridge glossary","path":"glossary","order":1},{"name":"Overview","visible_in_sidebar":true,"page_title":"Bridge overview","path":"overview","order":0},{"name":"Settings","visible_in_sidebar":true,"page_title":"Bridge settings","path":"settings","order":4},{"name":"User profile","visible_in_sidebar":true,"page_title":"Bridge user profile","path":"user-profile","order":5},{"path":"v1","children":[{"name":"Bridge configuration","visible_in_sidebar":false,"page_title":"Bridge configuration","path":"configure","order":6},{"name":"Generate Token","visible_in_sidebar":false,"page_title":"Bridge generate token","path":"generate-token","order":4},{"name":"Org settings","visible_in_sidebar":true,"page_title":"Bridge org settings","path":"org-settings","order":3,"children":[{"name":"API keys","visible_in_sidebar":true,"page_title":"API keys","path":"api-keys","order":2,"children":[{"name":"JWT Auth","visible_in_sidebar":false,"page_title":"JWT Auth","path":"jwt-auth","order":3},{"name":"JWT","visible_in_sidebar":true,"page_title":"JWT","path":"jwt","order":1},{"name":"OAuth","visible_in_sidebar":true,"page_title":"OAuth","path":"oauth","order":2}]},{"name":"People","visible_in_sidebar":true,"page_title":"People","path":"people","order":1}]},{"name":"Overview","visible_in_sidebar":true,"page_title":"Bridge overview","path":"overview","order":0},{"name":"Reports","visible_in_sidebar":true,"page_title":"Bridge reports","path":"reports","order":1,"children":[{"name":"Types","visible_in_sidebar":false,"page_title":"Report types","path":"types","order":1}]},{"name":"Reports API","visible_in_sidebar":false,"page_title":"Reports API","path":"reports-api","order":5}]}]}]},{"name":"Sample Category","path":"sample-category","order":3,"visible_in_sidebar":false,"children":[{"name":"Sample Product","path":"sample-product","order":0,"visible_in_sidebar":false,"children":[{"name":"Sample Page","visible_in_sidebar":false,"page_title":"Docs sample page","path":"sample-page","order":0}]}]}]} \ No newline at end of file diff --git a/content/payments/upi-issuance/api-envelope.mdx b/content/payments/upi-issuance/api-envelope.mdx new file mode 100644 index 00000000..cb8ecb6d --- /dev/null +++ b/content/payments/upi-issuance/api-envelope.mdx @@ -0,0 +1,89 @@ +--- +sidebar_title: The API envelope +page_title: UPI Issuance API envelope +order: 2 +visible_in_sidebar: true +--- + +## The API envelope + +Every request and response body is encrypted, keeping PII (`deviceId`, `mobile`, account details) out of plain text on the wire. The scheme is a standard hybrid encryption envelope. + +### What travels where + +- **PII in the body.** `deviceId` and `mobile` are in the encrypted body, never in headers or the URL. +- **`idempotencyKey` in a header.** It stays a plain header, outside the encrypted body. +- **Reads are POSTs.** Even pure reads (`binding-status`, `list-vpas`) are `POST` so their PII body can be encrypted. + +
+ +### Request format + +The TPAP / Issuing App encrypts the request body into an envelope object with three base64 fields: + + + {`{ + "ct": "", + "sk": "", + "iv": "" +}`} + + +For each request, the TPAP / Issuing App generates a random **32-byte AES-256 key** and **16-byte IV**, encrypts the JSON body with **AES-256-CBC** and PKCS#7 padding, and wraps the session key with **RSA-OAEP (SHA-1)** under Setu's public key. The TPAP / Issuing App keeps the session key and IV to decrypt the response. + +### Response format + +The response is encrypted under the same session key and IV the TPAP / Issuing App generated: + + + {`{ + "ct": "", + "oha": "" +}`} + + +The TPAP / Issuing App decrypts `ct` with the session key and IV, then verifies `oha` matches the SHA-256 of the decrypted plaintext. + + + The wire suite is fixed: RSA-OAEP-SHA1 for the key wrap, AES-256-CBC with PKCS#7 + for the body, SHA-256 for the response integrity hash. + + +
+ +### Reference implementation (Python) + + + {`import os, json, base64, hashlib +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.hazmat.primitives import hashes, serialization +def _pad(b, k=16): n = k - len(b) % k; return b + bytes([n]) * n +def _unpad(b): return b[:-b[-1]] +def encrypt(pub_pem: str, body: dict): + pub = serialization.load_pem_public_key(pub_pem.encode()) + key, iv = os.urandom(32), os.urandom(16) + sk = pub.encrypt(key, padding.OAEP(mgf=padding.MGF1(hashes.SHA1()), + algorithm=hashes.SHA1(), label=None)) + enc = Cipher(algorithms.AES(key), modes.CBC(iv)).encryptor() + ct = enc.update(_pad(json.dumps(body).encode())) + enc.finalize() + env = {"ct": base64.b64encode(ct).decode(), + "sk": base64.b64encode(sk).decode(), + "iv": base64.b64encode(iv).decode()} + return env, key, iv +def decrypt_response(key, iv, enc: dict): + ct = base64.b64decode(enc["ct"]) + dec = Cipher(algorithms.AES(key), modes.CBC(iv)).decryptor() + plain = _unpad(dec.update(ct) + dec.finalize()) + assert enc["oha"] == hashlib.sha256(plain).hexdigest(), "integrity mismatch" + return json.loads(plain)`} + + +`encrypt()` returns the request envelope `env` — the `{ct, sk, iv}` object — along with the session `key` and `iv`. The TPAP / Issuing App sends `env` as the request body with `Content-Type: application/json`, and passes the same `key` and `iv` to `decrypt_response()` to read the response. + +### Next + +- **[User Onboarding](/payments/upi-issuance/onboarding)** — bind a device, create a VPA, and verify OTPs. +- **[Testing on QA env](/payments/upi-issuance/qa-testing)** — reproduce every scenario. + + diff --git a/content/payments/upi-issuance/api-reference.mdx b/content/payments/upi-issuance/api-reference.mdx new file mode 100644 index 00000000..a17eb3f2 --- /dev/null +++ b/content/payments/upi-issuance/api-reference.mdx @@ -0,0 +1,24 @@ +--- +sidebar_title: API reference +page_title: UPI Issuance API reference +order: 6 +visible_in_sidebar: true +--- + +## API reference + +The complete, spec-backed API reference (request and response schemas, every field, every error) is being finalised and will render here from the OpenAPI definition. + +In the meantime, each operation is documented with its request, response, and error table under [API integration](/payments/upi-issuance/onboarding/api-integration): + +- [Device binding](/payments/upi-issuance/onboarding/api-integration/device-binding) — generate binding token, `binding-status` +- [OTP verification](/payments/upi-issuance/onboarding/api-integration/user-otp) — `otp/request`, `otp/verify` +- [VPA management](/payments/upi-issuance/onboarding/api-integration/vpa-management) — `vpa/check`, `create-vpa`, `get-vpa`, `list-vpas`, `vpa/deregister` +- [Payee blocklist](/payments/upi-issuance/payee-blocklist) — `block-vpa`, `unblock-vpa`, `list-blocked-vpas` +- [Programs](/payments/upi-issuance/onboarding/api-integration/programs) — `POST /programs`, `PATCH /programs/{id}` + +### Next + +- **[User Onboarding](/payments/upi-issuance/onboarding)** — the onboarding flow and a step-by-step API walkthrough. + + diff --git a/content/payments/upi-issuance/onboarding.mdx b/content/payments/upi-issuance/onboarding.mdx new file mode 100644 index 00000000..13e9ae57 --- /dev/null +++ b/content/payments/upi-issuance/onboarding.mdx @@ -0,0 +1,49 @@ +--- +sidebar_title: User Onboarding +page_title: UPI Issuance User Onboarding +order: 3 +visible_in_sidebar: true +--- + +## User Onboarding + +Onboarding gets a user ready to transact on UPI. It runs in three steps. + +**1. Device binding.** The TPAP / Issuing App requests a binding token from Setu, which generates one and returns it with a Virtual Mobile Number (VMN). The token is sent as a silent SMS from the user's SIM to the VMN. The telecom then notifies Setu of the VMN, the sending mobile, and the SMS body, and Setu checks all three to bind the device to the user. + +**2. VPA creation.** The TPAP / Issuing App creates a VPA — the user's UPI address — over the user's account. + +**3. OTP verification.** The TPAP / Issuing App requests an OTP from Setu, Setu delivers it to the user's mobile by SMS, and the TPAP / Issuing App submits it back to Setu to activate the VPA. Today this is **required on Android** and **not needed on iOS**. + +New user onboarding and VPA creation: device binding, VPA creation, and the OTP that activates the new VPA (Android) + +

New user onboarding / VPA creation for an existing user

+ +Once onboarded, the user has an active VPA and can transact on UPI. + +On a **device change**, only device binding is repeated — a device change does not require VPA creation. As at onboarding, an OTP is required on Android and not on iOS. + +On **iOS**, a successful SIM binding moves the user status straight to `active`. + +On **Android**, a successful SIM binding moves the user status to `device-bound`. Requesting an OTP then moves the user to `otp-pending`. A successful OTP verification moves the user status to `active`. + +Device change: device binding on the new device, with an OTP on Android moving the user from device-bound to active and iOS activating directly, no VPA creation + +

Device change — OTP verification, no VPA creation

+ + + NPCI is not involved in onboarding for PPI Issuing Apps: the account provider is + already set, and PPI accounts do not need a UPI PIN to be set up. + + +### In this section + +- **[Onboarding states](/payments/upi-issuance/onboarding/onboarding-states)** — the user and VPA state machines, and what moves them. +- **[API integration](/payments/upi-issuance/onboarding/api-integration)** — a step-by-step walkthrough of each onboarding operation. + +### Next + +- **[Payee blocklist](/payments/upi-issuance/payee-blocklist)** — block, unblock, and list blocked payee VPAs. +- **[Testing on QA env](/payments/upi-issuance/qa-testing)** — reproduce every scenario. + + diff --git a/content/payments/upi-issuance/onboarding/api-integration.mdx b/content/payments/upi-issuance/onboarding/api-integration.mdx new file mode 100644 index 00000000..ca2b8fd5 --- /dev/null +++ b/content/payments/upi-issuance/onboarding/api-integration.mdx @@ -0,0 +1,46 @@ +--- +sidebar_title: API integration +page_title: UPI Issuance API integration +order: 1 +visible_in_sidebar: true +--- + +## API integration + +A step-by-step walkthrough of each onboarding operation. All routes are under `/api/v1`, all body-carrying routes use [the envelope](/payments/upi-issuance/api-envelope), and `idempotencyKey` is always a header. + +- **[Device binding](/payments/upi-issuance/onboarding/api-integration/device-binding)** — generate binding token, the silent SMS, and the `binding-status` poll. +- **[OTP verification](/payments/upi-issuance/onboarding/api-integration/user-otp)** — `otp/request` and `otp/verify` to activate a VPA on Android. +- **[VPA management](/payments/upi-issuance/onboarding/api-integration/vpa-management)** — check, create, fetch, list, and deregister VPAs. +- **[Programs](/payments/upi-issuance/onboarding/api-integration/programs)** — create and update program configuration. + +
+ + + Testing any of these? Every scenario is reproducible on the QA env — see + Testing on QA env. + + +## Error responses + +Every error, on every endpoint, returns the **same shape** — encrypted in the envelope like any response: + + + {`{ + "traceId": "01J...", + "code": "invalid-user-state", + "message": "A human-readable description of what went wrong." +}`} + + +- The **HTTP status is authoritative** — branch on it first (`4xx`/`5xx` = error). +- `code` is a **stable machine string** to switch on; `message` is descriptive and may change. +- `traceId` is on **every** response, success or error. Log it and quote it to Setu when raising an issue. + +A `500` with `code: internal-error` means something failed on Setu's side; retry with the same `idempotencyKey`. Each operation's page lists the specific `4xx` codes it can return. + +### Next + +- **[Device binding](/payments/upi-issuance/onboarding/api-integration/device-binding)** — generate a binding token and prove the SIM. + + diff --git a/content/payments/upi-issuance/onboarding/api-integration/device-binding.mdx b/content/payments/upi-issuance/onboarding/api-integration/device-binding.mdx new file mode 100644 index 00000000..409256c4 --- /dev/null +++ b/content/payments/upi-issuance/onboarding/api-integration/device-binding.mdx @@ -0,0 +1,156 @@ +--- +sidebar_title: Device binding +page_title: UPI Issuance device binding +order: 0 +visible_in_sidebar: true +--- + +## Device binding + +Device binding proves that the user's SIM, mobile number, and device belong together. It is the entry point on any device — a fresh install, a new phone, or a re-login. + +Device binding sequence: binding token, silent SMS from the SIM to the VMN, and the binding-status poll to active + +### 1. Generate a binding token + +`POST /api/v1/onboarding/binding-token` (enveloped) + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `os` | string | yes | `android` or `ios`. | +| `otpRequired` | boolean | yes | Whether a successful SIM binding fully activates the user. `false` — the user goes straight to `active`. `true` — the user stops at `device-bound` until an [OTP](/payments/upi-issuance/onboarding/api-integration/user-otp) is verified. | + +
+ +`idempotencyKey` is an optional request header. + +**When OTP verification happens is controlled by the TPAP / Issuing App, and Setu respects it.** There are two options: + +- To verify OTP **after SIM binding and before VPA creation**, generate the binding token with `otpRequired: true`. The user stays at `device-bound` until an OTP is verified. This is the **device change** case, where no new VPA is created. +- To verify OTP **after VPA creation**, generate the binding token with `otpRequired: false` and set `otpRequired: true` on [`create-vpa`](/payments/upi-issuance/onboarding/api-integration/vpa-management) instead. The new VPA stays `pending-verification` until an OTP is verified. This is the **new onboarding / new VPA** case. + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "os": "android", + "otpRequired": false +}`} + + +##### Success response — `200` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `vmn` | string | The Virtual Mobile Number to send the SMS to. | +| `smsBody` | string | The ready-to-send silent-SMS body. The token is embedded here and is never returned separately. | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vmn": "919900000001", + "smsBody": "VERIFY SETqxf8aemkxxdrhbifd4n4zldq7guvxb2k" +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | A required field is missing (`deviceId`, `mobile`, `os`, `otpRequired`) or the request body is malformed. | +| 429 | `device-binding-cap-exceeded` | Too many binding attempts for this device today. | +| 429 | `mobile-binding-cap-exceeded` | Too many binding attempts for this mobile today. | +| 500 | `internal-error` | Something went wrong on Setu's side. Retry with the same `idempotencyKey`. | + +### 2. Send the silent SMS + +`vmn` is a **Virtual Mobile Number** — a receive-only number that the binding SMS is sent to. The TPAP / Issuing App sends `smsBody` as a silent SMS from the user's SIM to `vmn`. The telecom provider then calls a webhook to Setu, indicating the VMN that received the SMS, the mobile it was sent from, and the SMS body. Setu checks all three — the SMS body must carry a token for a live binding, the VMN must be the one that binding was issued for, and the sending mobile must match the claimed `mobile`. When all three match, the SIM is proven and the binding advances. The TPAP / Issuing App does not call anything for this step. + +The binding token is short-lived — it expires **45 seconds** after it is generated. The silent SMS (and the telecom's webhook back to Setu) must complete within that window; if it lapses, generate a fresh binding token. + + + On the QA env there is no telecom. Drive the outcome with a + sim.bind-* directive in the idempotencyKey of the + generate binding token call — see + Testing on QA env. + + +### 3. Poll the binding status + +`POST /api/v1/onboarding/binding-status` (enveloped) + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | + +
+ +`idempotencyKey` is an optional request header. + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999" +}`} + + +##### Success response — `200` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `user` | object | The user in its current state (see [The user object](#the-user-object)). | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "user": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "deviceId": "device-abc-123", + "mobile": "919999999999" + } +}`} + + +Poll until the status settles. With `otpRequired: false` a successful SIM binding lands the user on `active`, and the TPAP / Issuing App can [create a VPA](/payments/upi-issuance/onboarding/api-integration/vpa-management). With `otpRequired: true` the user settles at `device-bound` and needs an [OTP](/payments/upi-issuance/onboarding/api-integration/user-otp) to reach `active` — the OTP is valid for **60 seconds** after it is requested. + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | A required field is missing (`deviceId`, `mobile`) or the request body is malformed. | +| 404 | `binding-not-found` | No binding for this device — polled before generating a binding token, or from a device that is not the bound one. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +### The user object + +The [binding status](#3-poll-the-binding-status) and a device-change [OTP verification](/payments/upi-issuance/onboarding/api-integration/user-otp) return the user in this shape: + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `id` | string | The user's id (ULID). | +| `status` | string | `binding-pending`, `device-bound`, `otp-pending`, or `active`. | +| `deviceId` | string | The user's device id. | +| `mobile` | string | The user's mobile number, with country code (e.g. `919999999999`). | + +
+ +### On a device change + +When the user moves to a new phone or re-installs, only device binding is repeated — the three steps above, against the new `deviceId`. A device change does not require VPA creation. The OTP is OS-driven, just as at onboarding. On **iOS** (`otpRequired: false`) a successful SIM binding moves the user to `active`. On **Android** (`otpRequired: true`) a successful SIM binding moves the user to `device-bound`, and an [OTP](/payments/upi-issuance/onboarding/api-integration/user-otp) then moves the user to `active` before the account is usable on the new device. + +### Next + +- **[OTP verification](/payments/upi-issuance/onboarding/api-integration/user-otp)** — request and verify OTPs. +- **[VPA management](/payments/upi-issuance/onboarding/api-integration/vpa-management)** — create and manage VPAs. + + diff --git a/content/payments/upi-issuance/onboarding/api-integration/programs.mdx b/content/payments/upi-issuance/onboarding/api-integration/programs.mdx new file mode 100644 index 00000000..da1c7d14 --- /dev/null +++ b/content/payments/upi-issuance/onboarding/api-integration/programs.mdx @@ -0,0 +1,144 @@ +--- +sidebar_title: Programs +page_title: UPI Issuance programs +order: 3 +visible_in_sidebar: true +--- + +## Programs + +A program is an **engagement channel** through which users are onboarded onto the TPAP / Issuing App and issued a wallet — for example a distinct branded app or offering built on the stack. Each program carries its own configuration: whether wallets on it may pay and receive, and an optional per-transaction limit. A `programId` is optional on the onboarding calls that accept it. It matters most on `create-vpa`, which ties each VPA to the program it was created under so the program's rules apply to that wallet. + +Setu can provision a program, or the TPAP / Issuing App can manage its own through these endpoints. Program routes are enveloped like the rest of the onboarding surface. + +### The program object + +Both endpoints return the program under `program` in this shape: + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `id` | string | The program id (ULID); pass it as `programId` on onboarding calls. | +| `name` | string | The program's display name. | +| `code` | string | The program's short code — its channel identifier. | +| `isCreditAllowed` | boolean | May wallets on this program receive incoming UPI? | +| `isDebitAllowed` | boolean | May wallets on this program pay outgoing UPI? | +| `amountLimit` | integer | Per-transaction cap, in paise; absent when there is no cap. | +| `status` | string | `active` or `inactive`. | + +
+ +### Create a program + +`POST /api/v1/programs` (enveloped) + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `name` | string | yes | The program's display name. | +| `code` | string | yes | The program's short code — its channel identifier. | +| `isCreditAllowed` | boolean | no | May wallets on this program receive incoming UPI? Defaults `true`. | +| `isDebitAllowed` | boolean | no | May wallets on this program pay outgoing UPI? Defaults `true`. | +| `amountLimit` | integer | no | Per-transaction cap, in paise. Omit for no cap. | + +##### Sample request + + + {`{ + "name": "Acme Wallet", + "code": "ACME", + "isCreditAllowed": true, + "isDebitAllowed": true, + "amountLimit": 2000000 +}`} + + +##### Success response — `201` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `program` | object | The created program (see [The program object](#the-program-object)). Use its `id` (passed as `programId`) in onboarding calls. | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "program": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "name": "Acme Wallet", + "code": "ACME", + "isCreditAllowed": true, + "isDebitAllowed": true, + "amountLimit": 2000000, + "status": "active" + } +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | The request body is malformed. | +| 400 | `missing-parameter` | `name` or `code` is missing. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +
+ +### Update a program + +`PATCH /api/v1/programs/{programId}` (enveloped) — only the fields sent change. `programId` is a path parameter. + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `name` | string | no | The program's display name. | +| `code` | string | no | The program's short code. | +| `isCreditAllowed` | boolean | no | May wallets on this program receive incoming UPI? | +| `isDebitAllowed` | boolean | no | May wallets on this program pay outgoing UPI? | +| `amountLimit` | integer | no | Per-transaction cap, in paise. | +| `status` | string | no | `active` or `inactive`. An `inactive` program is rejected at the onboarding gate (`400 invalid-program`). | + +##### Sample request + +For example, deactivate a program: + + + {`{ + "status": "inactive" +}`} + + +##### Success response — `200` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `program` | object | The updated program (see [The program object](#the-program-object)). | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "program": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "name": "Acme Wallet", + "code": "ACME", + "isCreditAllowed": true, + "isDebitAllowed": true, + "amountLimit": 2000000, + "status": "inactive" + } +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | The request body is malformed. | +| 400 | `missing-parameter` | `programId` is missing. | +| 404 | `program-not-found` | No program with that `programId`. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +### Next + +- **[Device binding](/payments/upi-issuance/onboarding/api-integration/device-binding)** — generate a binding token and start onboarding a user. + + diff --git a/content/payments/upi-issuance/onboarding/api-integration/user-otp.mdx b/content/payments/upi-issuance/onboarding/api-integration/user-otp.mdx new file mode 100644 index 00000000..99948861 --- /dev/null +++ b/content/payments/upi-issuance/onboarding/api-integration/user-otp.mdx @@ -0,0 +1,184 @@ +--- +sidebar_title: OTP verification +page_title: UPI Issuance OTP verification +order: 1 +visible_in_sidebar: true +--- + +## OTP verification + +Onboarding involves two kinds of OTP. Both use the same `otp/request` + `otp/verify` pair, but they unlock different things and are triggered by different calls: + +| Use case | What the OTP unlocks | Triggered by | `vpa` in the request | Verify returns | +| :--- | :--- | :--- | :--- | :--- | +| **New onboarding / new VPA** | transacting on the new VPA (`pending-verification → active`) | `otpRequired: true` on `create-vpa` | yes | the now-`active` VPA | +| **Device change** | transacting from the new device (`device-bound → active`) | `otpRequired: true` on generate binding token | no | the now-`active` user | + +
+ +The OTP for a new VPA never changes the user's status. The OTP for a device change never changes a VPA's status. Whether an `otp/request` or `otp/verify` call applies to a VPA or to the user is decided by whether a `vpa` is present in the body. + +
+ +## New onboarding / new VPA + +A newly created VPA can require an OTP before it can transact. This is **OS-dependent**: on **Android** the OTP is required and the VPA is created `pending-verification`, on **iOS** it is not and the VPA is created `active`. The TPAP / Issuing App signals it by setting `otpRequired` on [`create-vpa`](/payments/upi-issuance/onboarding/api-integration/vpa-management) to match the device OS. + +New VPA activation: on Android create-vpa creates the VPA pending-verification and an OTP promotes it to active, on iOS it is created active directly + +## Device change + +When `otpRequired: true` is sent on the [generate binding token](/payments/upi-issuance/onboarding/api-integration/device-binding) call, a successful SIM binding leaves the user at `device-bound` rather than `active`. Requesting the OTP moves the user to `otp-pending`, and a successful verification moves the user to `active`, letting them transact from the new device. This confirms the user is present on the new device. + +This is **OS-dependent** — `otpRequired` is `true` on **Android** (the user stops at `device-bound`) and `false` on **iOS** (a successful SIM binding activates the user directly). + +Device change: on Android otpRequired true leaves the user device-bound and an OTP promotes them to active, on iOS the SIM binding activates the user directly + +
+ +## Request an OTP + +`POST /api/v1/onboarding/otp/request` (enveloped) — asynchronous, returns `202`. Setu sends the OTP to the user's mobile by SMS. The OTP is valid for **60 seconds** after it is requested; once it lapses, `otp/verify` returns `410 otp-expired-or-exhausted` and a fresh `otp/request` is needed. + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `vpa` | string | conditional | Include it for the **new onboarding / new VPA** case (the VPA being activated). Omit it for the **device change** case. | + +
+ +`idempotencyKey` is an optional request header. + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "vpa": "919999999999-alice@setu" +}`} + + +Omit `vpa` for the **device change** case. + +##### Success response — `202` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV" +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId` or `mobile` is missing, or the request body is malformed. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 404 | `user-not-found` | No user for this mobile. | +| 404 | `vpa-not-found` | A `vpa` was sent but the user does not own a VPA with that string. | +| 409 | `invalid-user-state` | Not in a state that owes an OTP. The **new onboarding / new VPA** case needs the user `active` and the VPA `pending-verification`. The **device change** case needs the user at `device-bound` or `otp-pending`. | +| 429 | `otp-cap-exceeded` | Too many OTP requests. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +
+ +## Verify an OTP + +`POST /api/v1/onboarding/otp/verify` (enveloped) + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `otp` | string | yes | The digits the user entered. | +| `vpa` | string | conditional | Include it for the **new onboarding / new VPA** case (the VPA being activated). Omit it for the **device change** case. | + +
+ +`idempotencyKey` is an optional request header. One attempt per OTP — a wrong guess consumes it, so a retry must `otp/request` again. + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "otp": "123456", + "vpa": "919999999999-alice@setu" +}`} + + +##### Success response — `200` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `vpa` | object | Present for the **new onboarding / new VPA** case — the now-`active` VPA (see [The VPA object](/payments/upi-issuance/onboarding/api-integration/vpa-management#the-vpa-object)). | +| `user` | object | Present for the **device change** case — the now-`active` user (see [The user object](/payments/upi-issuance/onboarding/api-integration/device-binding#the-user-object)). | + +Exactly one of `vpa` or `user` is present. + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu", + "status": "active", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "accountType": "PPIWALLET", + "accountName": "Alice Doe", + "mobile": "919999999999" + } +}`} + + +The **device change** case returns the user instead: + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "user": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "status": "active", + "deviceId": "device-abc-123", + "mobile": "919999999999" + } +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId` or `mobile` is missing, or the request body is malformed. | +| 400 | `missing-parameter` | `otp` is missing. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 401 | `invalid-otp` | The OTP is incorrect. The attempt is consumed. | +| 404 | `user-not-found` | No user for this mobile. | +| 409 | `invalid-user-state` | Not in a state that owes an OTP. The **new onboarding / new VPA** case needs the user `active` and the VPA `pending-verification`. The **device change** case needs the user at `device-bound` or `otp-pending`. | +| 410 | `otp-expired-or-exhausted` | No live OTP to verify — never requested, expired, or already consumed. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +
+ + + On the QA env there is no telecom, so no OTP SMS is sent. Set idempotencyKey: sim.otp-ok + on otp/verify to pass with any code — see + Testing on QA env. + + +### Next + +- **[VPA management](/payments/upi-issuance/onboarding/api-integration/vpa-management)** — create and manage VPAs. + + diff --git a/content/payments/upi-issuance/onboarding/api-integration/vpa-management.mdx b/content/payments/upi-issuance/onboarding/api-integration/vpa-management.mdx new file mode 100644 index 00000000..8aee3003 --- /dev/null +++ b/content/payments/upi-issuance/onboarding/api-integration/vpa-management.mdx @@ -0,0 +1,359 @@ +--- +sidebar_title: VPA management +page_title: UPI Issuance VPA management +order: 2 +visible_in_sidebar: true +--- + +## VPA management + +Once a user is `active`, the TPAP / Issuing App creates and manages their VPAs. All routes are enveloped and under `/api/v1`. `idempotencyKey` is an optional request header on every call. + +### The VPA object + +`create-vpa`, `get-vpa`, `list-vpas`, and `vpa/deregister` return the VPA in this shape: + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `id` | string | The VPA id (ULID). | +| `vpa` | string | The full VPA, `prefix@handle`. | +| `status` | string | `active`, `pending-verification`, or `deregistered`. | +| `programId` | string | The program the VPA belongs to (ULID). | +| `accountNo` | string | The wallet / pool account number. | +| `accountProviderId` | string | The account-provider id. | +| `ifsc` | string | The IFSC of the account. | +| `accountType` | string | The account type (e.g. `PPIWALLET`). | +| `accountName` | string | The account-holder name. | +| `mobile` | string | The owner's mobile number, with country code (e.g. `919999999999`). | + +
+ +### Check availability + +`POST /api/v1/onboarding/vpa/check` (enveloped) — is a chosen VPA free? + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `vpa` | string | yes | The VPA to check — the full VPA `prefix@handle` (e.g. `919999999999-alice@setu`). Its VPA prefix must start with the subscriber's mobile. | +| `programId` | string | no | ULID. Validated for existence only. | + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "vpa": "919999999999-alice@setu" +}`} + + +##### Success response — `200` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `vpa` | string | The full VPA that was checked (`prefix@handle`). | +| `available` | boolean | `false` means the VPA is already taken by another user's active VPA. A taken VPA is not an error. | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu", + "available": true +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId` or `mobile` is missing, or the request body is malformed. | +| 400 | `missing-parameter` | `vpa` is missing. | +| 400 | `invalid-program` | Unknown or inactive `programId`. | +| 400 | `invalid-vpa` | The VPA prefix does not start with the subscriber's mobile number. | +| 400 | `invalid-handle` | The VPA carries a handle that is not the one configured for this TPAP. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 404 | `user-not-found` | No user for this mobile. | +| 409 | `invalid-user-state` | The user is not `active`. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +
+ +### Create a VPA + +`POST /api/v1/onboarding/create-vpa` (enveloped) + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `vpa` | string | yes | The VPA to create — the full VPA `prefix@handle` (e.g. `919999999999-alice@setu`). Its VPA prefix must start with the subscriber's mobile. | +| `accountNo` | string | yes | The wallet / pool account number. | +| `accountName` | string | yes | The account-holder name. | +| `otpRequired` | boolean | no | `true` (Android) — the VPA is created `pending-verification` and an [OTP](/payments/upi-issuance/onboarding/api-integration/user-otp) activates it. `false` (iOS, default) — the VPA is created `active`. | +| `ifsc` | string | no | The IFSC of the account. Optional when a TPAP default is configured. | +| `accountProviderId` | string | no | The account-provider id. Optional when a TPAP default is configured. | +| `programId` | string | no | ULID. Validated for existence when supplied. | +| `defaultDebit` | boolean | no | Make this the user's default debit account. | +| `defaultCredit` | boolean | no | Make this the user's default credit account. | + +The account details are taken from the request. There is no bank round-trip at onboarding. + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu", + "accountNo": "99887766554433", + "accountName": "Alice Doe", + "otpRequired": false +}`} + + +##### Success response — `200` + +Returns the created VPA; its `status` is `active` or `pending-verification`. + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `vpa` | object | The created VPA (see [The VPA object](#the-vpa-object)). | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu", + "status": "active", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "accountType": "PPIWALLET", + "accountName": "Alice Doe", + "mobile": "919999999999" + } +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId` or `mobile` is missing, or the request body is malformed. | +| 400 | `missing-parameter` | `vpa`, `accountNo`, or `accountName` is empty, or `ifsc` / `accountProviderId` is required (no TPAP default configured) and was not supplied. | +| 400 | `invalid-program` | Unknown or inactive `programId`. | +| 400 | `invalid-vpa` | The VPA prefix does not start with the subscriber's mobile number. | +| 400 | `invalid-handle` | The VPA carries a handle that is not the one configured for this TPAP. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 404 | `user-not-found` | No user for this mobile. | +| 409 | `invalid-user-state` | The user is not `active`. | +| 409 | `vpa-taken` | That VPA is already in use. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +
+ + + A VPA prefix is scoped to the owner's mobile, so a caller cannot collide + with another user's VPA (that request is rejected as invalid-vpa), + and re-creating the caller's own VPA is idempotent (returns 200). + + +
+ +### Get a VPA + +`POST /api/v1/onboarding/get-vpa` (enveloped) — fetch one of the user's VPAs by its VPA string. + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `vpa` | string | yes | The VPA to fetch — the full VPA `prefix@handle` (e.g. `919999999999-alice@setu`). Its VPA prefix must start with the subscriber's mobile. | + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "vpa": "919999999999-alice@setu" +}`} + + +##### Success response — `200` + +Returns the VPA under `vpa`. + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `vpa` | object | The requested VPA (see [The VPA object](#the-vpa-object)). | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu", + "status": "active", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "accountType": "PPIWALLET", + "accountName": "Alice Doe", + "mobile": "919999999999" + } +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId`, `mobile`, or `vpa` is missing, or the request body is malformed. | +| 400 | `invalid-vpa` | The VPA prefix does not start with the subscriber's mobile number. | +| 400 | `invalid-handle` | The VPA carries a handle that is not the one configured for this TPAP. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 404 | `user-not-found` | No user for this mobile. | +| 404 | `vpa-not-found` | The user does not own a VPA with that string. | +| 409 | `invalid-user-state` | The user is not `active`. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +
+ +### List VPAs + +`POST /api/v1/onboarding/list-vpas` (enveloped) — the user's live VPAs (`active` + `pending-verification`), newest-added first, keyset-paginated. + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `limit` | integer | no | Max entries this page. Omitted or non-positive defaults to `20`, clamped to `100`. | +| `cursor` | string | no | The `nextCursor` from the previous page. Omit for the first page. | + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "limit": 20 +}`} + + +##### Success response — `200` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `vpas` | array | This page of the user's live VPAs (see [The VPA object](#the-vpa-object)); empty when none. | +| `nextCursor` | string | Cursor for the next page; absent on the last page. | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpas": [ + { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu", + "status": "active", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "accountType": "PPIWALLET", + "accountName": "Alice Doe", + "mobile": "919999999999" + } + ], + "nextCursor": "01ARZ3NDEKTSV4RRFFQ69G5FAV" +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId` or `mobile` is missing, the request body is malformed, or `cursor` is malformed. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 404 | `user-not-found` | No user for this mobile. | +| 409 | `invalid-user-state` | The user is not `active`. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +
+ +### Deregister a VPA + +`POST /api/v1/onboarding/vpa/deregister` (enveloped) — soft-delete a VPA. The row is preserved for audit and re-registration, and the prefix becomes reusable. Idempotent for an already-deregistered VPA. + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `vpa` | string | yes | The VPA to deregister — the full VPA `prefix@handle` (e.g. `919999999999-alice@setu`). Its VPA prefix must start with the subscriber's mobile. | + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "vpa": "919999999999-alice@setu" +}`} + + +##### Success response — `200` + +Returns the deregistered VPA; its `status` is `deregistered`. + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `vpa` | object | The deregistered VPA (see [The VPA object](#the-vpa-object)). | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "vpa": "919999999999-alice@setu", + "status": "deregistered", + "programId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "accountNo": "99887766554433", + "accountProviderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "ifsc": "SETU0000001", + "accountType": "PPIWALLET", + "accountName": "Alice Doe", + "mobile": "919999999999" + } +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId` or `mobile` is missing, or the request body is malformed. | +| 400 | `missing-parameter` | `vpa` is missing. | +| 400 | `invalid-vpa` | The VPA prefix does not start with the subscriber's mobile number. | +| 400 | `invalid-handle` | The VPA carries a handle that is not the one configured for this TPAP. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 404 | `user-not-found` | No user for this mobile. | +| 404 | `vpa-not-found` | The user does not own a VPA with that string. | +| 409 | `invalid-user-state` | The user is not `active`. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +### Next + +- **[Programs](/payments/upi-issuance/onboarding/api-integration/programs)** — provision and manage engagement channels that VPAs are created under. + + diff --git a/content/payments/upi-issuance/onboarding/onboarding-states.mdx b/content/payments/upi-issuance/onboarding/onboarding-states.mdx new file mode 100644 index 00000000..35fd998b --- /dev/null +++ b/content/payments/upi-issuance/onboarding/onboarding-states.mdx @@ -0,0 +1,59 @@ +--- +sidebar_title: Onboarding states +page_title: UPI Issuance onboarding states +order: 0 +visible_in_sidebar: true +--- + +## Onboarding states + +Onboarding tracks two things, both driven by the TPAP / Issuing App's API calls: + +- the **user** — is the device active / is OTP verification pending / is the user active? +- the onboarded **VPA** — is it usable? + +### User states + +| Status | Meaning | +| :--- | :--- | +| `binding-pending` | The user exists (created at token generation) but the SIM is not yet proven. | +| `device-bound` | The SIM binding succeeded, but OTP verification is still owed before the user is active. Only reached when `otpRequired: true` was sent during token generation. | +| `otp-pending` | The OTP has been sent and is awaiting verification. | +| `active` | The user is fully onboarded. Required before any VPA can be created or used. | + +### VPA states + +| Status | Meaning | +| :--- | :--- | +| `pending-verification` | The VPA is created but OTP verification is still owed before it can transact. | +| `active` | The VPA is verified and usable. | +| `deregistered` | The VPA was removed. Its prefix becomes reusable. | + +### When OTP verification happens + +OTP verification is **required for Android** and not needed on iOS. **When** it happens is controlled by the TPAP / Issuing App through the `otpRequired` flag, and Setu respects it: + +- To verify OTP **after SIM binding and before VPA creation**, set `otpRequired: true` on the [generate binding token](/payments/upi-issuance/onboarding/api-integration/device-binding) call. The user stays at `device-bound` until an OTP is verified. Use case: a **device change** (no new VPA is created). +- To verify OTP **after VPA creation**, set `otpRequired: true` on [`create-vpa`](/payments/upi-issuance/onboarding/api-integration/vpa-management). The new VPA stays `pending-verification` until an OTP is verified. Use case: a **new onboarding / new VPA**. + +
+ +### The two scenarios in detail + +#### New onboarding + +OTP verification is performed after VPA creation and blocks VPA activation, preventing any transactions on the new VPA until OTP verification is done. + +New onboarding: on Android create-vpa creates the VPA pending-verification and an OTP promotes it to active, on iOS the VPA is created active directly + +#### Device change + +OTP verification is performed at the user level, right after device binding on the new device. A successful SIM binding leaves the user at `device-bound`, and OTP verification moves the user to `active`. No new VPA is created. + +Device change: on Android binding on the new device leaves the user device-bound and an OTP promotes them to active, on iOS the SIM binding activates the user directly + +### Next + +- **[API integration](/payments/upi-issuance/onboarding/api-integration)** — a step-by-step walkthrough of each operation. + + diff --git a/content/payments/upi-issuance/overview.mdx b/content/payments/upi-issuance/overview.mdx new file mode 100644 index 00000000..7255fd18 --- /dev/null +++ b/content/payments/upi-issuance/overview.mdx @@ -0,0 +1,38 @@ +--- +sidebar_title: Overview +page_title: UPI Issuance Overview +order: 0 +visible_in_sidebar: true +--- + +## UPI Issuance + +Setu UPI Issuance is a **PSP stack** that enables TPAPs and Issuing Apps to allow their users to make and receive UPI payments. Setu provides the PSP roles and the UPI-network integration, exposed as a set of APIs. + +The stack spans the full UPI journey, starting with onboarding. These docs cover the onboarding APIs today, and grow with the rest of the stack. + +### How to read these docs + + + + +

START HERE

+ Quickstart — the first call -> +
+
+ + +

TRY EVERY SCENARIO

+ Testing on QA env -> +
+
+
+ +- **[Quickstart](/payments/upi-issuance/quickstart)** — the base URL, the envelope public key, and how requests are authenticated. +- **[The API envelope](/payments/upi-issuance/api-envelope)** — how every request and response is encrypted. +- **[User Onboarding](/payments/upi-issuance/onboarding)** — the onboarding flow, its state machines, and a step-by-step API walkthrough. +- **[Payee blocklist](/payments/upi-issuance/payee-blocklist)** — block, unblock, and list blocked payee VPAs. +- **[Testing on QA env](/payments/upi-issuance/qa-testing)** — reproduce every success and error scenario on the QA env. +- **[API reference](/payments/upi-issuance/api-reference)** — the full endpoint reference. + + diff --git a/content/payments/upi-issuance/payee-blocklist.mdx b/content/payments/upi-issuance/payee-blocklist.mdx new file mode 100644 index 00000000..61ede0d9 --- /dev/null +++ b/content/payments/upi-issuance/payee-blocklist.mdx @@ -0,0 +1,187 @@ +--- +sidebar_title: Payee blocklist +page_title: UPI Issuance payee blocklist +order: 4 +visible_in_sidebar: true +--- + +## Payee blocklist + +Let a user block payee VPAs they never want to transact with. All routes are enveloped, under `/api/v1`, and require an `active` user. `idempotencyKey` is an optional request header on every call. + +### The blocklist entry object + +`block-vpa` and `unblock-vpa` return the entry (under `blockedPayee`) in this shape: + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `id` | string | The blocklist entry id (ULID). | +| `payeeVpa` | string | The payee VPA, `prefix@handle`. | +| `status` | string | `blocked` or `unblocked`. | +| `blockedAt` | string | When the payee was most recently blocked (RFC3339). | +| `unblockedAt` | string | When the payee was unblocked (RFC3339); absent while blocked. | + +
+ +### Block a payee + +`POST /api/v1/onboarding/block-vpa` (enveloped) — idempotent; blocking an already-blocked payee is a no-op. + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `payeeVpa` | string | yes | The external payee VPA to block (`prefix@handle`; any handle). | + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "payeeVpa": "merchant@otherbank" +}`} + + +##### Success response — `200` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `blockedPayee` | object | The blocklist entry, now `blocked` (see [the entry object](#the-blocklist-entry-object)). | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "blockedPayee": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "blockedAt": "2026-07-09T12:00:00Z" + } +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId` or `mobile` is missing, or the request body is malformed. | +| 400 | `missing-parameter` | `payeeVpa` is missing. | +| 400 | `invalid-vpa` | `payeeVpa` is not a valid VPA of the form `prefix@handle`. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 404 | `user-not-found` | No user for this mobile. | +| 409 | `invalid-user-state` | The user is not `active`. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +
+ +### Unblock a payee + +`POST /api/v1/onboarding/unblock-vpa` (enveloped) — a soft flip to `unblocked`; the entry is preserved for audit. Idempotent for an already-unblocked payee. The request shape matches [Block a payee](#block-a-payee). + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "payeeVpa": "merchant@otherbank" +}`} + + +##### Success response — `200` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `blockedPayee` | object | The blocklist entry, now `unblocked` (see [the entry object](#the-blocklist-entry-object)). | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "blockedPayee": { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "unblocked", + "blockedAt": "2026-07-09T12:00:00Z", + "unblockedAt": "2026-07-09T12:30:00Z" + } +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId` or `mobile` is missing, or the request body is malformed. | +| 400 | `missing-parameter` | `payeeVpa` is missing. | +| 400 | `invalid-vpa` | `payeeVpa` is not a valid VPA of the form `prefix@handle`. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 404 | `user-not-found` | No user for this mobile. | +| 404 | `payee-not-blocked` | That payee VPA is not on the user's blocklist. | +| 409 | `invalid-user-state` | The user is not `active`. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +
+ +### List blocked payees + +`POST /api/v1/onboarding/list-blocked-vpas` (enveloped) — the user's currently-blocked payees, newest-first, keyset-paginated. + +| Field | Type | Required | Notes | +| :--- | :--- | :--- | :--- | +| `deviceId` | string | yes | The user's device id. | +| `mobile` | string | yes | The user's mobile number, with country code (e.g. `919999999999`). | +| `limit` | integer | no | Max entries this page. Omitted or non-positive defaults to `20`, clamped to `100`. | +| `cursor` | string | no | The `nextCursor` from the previous page. Omit for the first page. | + +##### Sample request + + + {`{ + "deviceId": "device-abc-123", + "mobile": "919999999999", + "limit": 20 +}`} + + +##### Success response — `200` + +| Field | Type | Notes | +| :--- | :--- | :--- | +| `traceId` | string | Trace handle for this call (ULID). | +| `blockedPayees` | array | This page of currently-blocked payees (see [the entry object](#the-blocklist-entry-object)); empty when none. | +| `nextCursor` | string | Cursor for the next page; absent on the last page. | + + + {`{ + "traceId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "blockedPayees": [ + { + "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "payeeVpa": "merchant@otherbank", + "status": "blocked", + "blockedAt": "2026-07-09T12:00:00Z" + } + ], + "nextCursor": "01ARZ3NDEKTSV4RRFFQ69G5FAV" +}`} + + +##### Errors + +| Status | Code | When | +| :--- | :--- | :--- | +| 400 | `invalid-request` | `deviceId` or `mobile` is missing, the request body is malformed, or `cursor` is malformed. | +| 401 | `device-not-linked` | This device is not bound for this user. | +| 404 | `user-not-found` | No user for this mobile. | +| 409 | `invalid-user-state` | The user is not `active`. | +| 500 | `internal-error` | Something went wrong on Setu's side. | + +### Next + +- **[Testing on QA env](/payments/upi-issuance/qa-testing)** — reproduce every scenario. +- **[API reference](/payments/upi-issuance/api-reference)** — the full endpoint reference. + + diff --git a/content/payments/upi-issuance/qa-testing.mdx b/content/payments/upi-issuance/qa-testing.mdx new file mode 100644 index 00000000..b72d453a --- /dev/null +++ b/content/payments/upi-issuance/qa-testing.mdx @@ -0,0 +1,91 @@ +--- +sidebar_title: Testing on QA env +page_title: UPI Issuance QA env testing +order: 5 +visible_in_sidebar: true +--- + +## Testing on QA env + +The TPAP / Issuing App can reproduce every onboarding scenario — success, and every error and precondition — against the **real QA env endpoints**. + +A few outcomes depend on an external event the TPAP / Issuing App cannot trigger on the QA env (the SIM-proof callback from the telecom, and the OTP SMS). For those, put a **directive in the `idempotencyKey`** of the initiating call. + +
+ + + Simulation directives work on the QA env only. In production a + sim.* value is treated as an ordinary idempotency key and changes + nothing. + + +
+ +### Simulated scenarios + +Only two things need a directive, because the TPAP / Issuing App cannot otherwise produce them on the QA env. + +#### Device binding + +On production, binding completes when the telecom delivers the silent SMS. On the QA env, set the `idempotencyKey` on `POST /onboarding/binding-token` to drive the outcome — no webhook, no real SMS: + +| `idempotencyKey` | Result | +| :--- | :--- | +| `sim.bind-ok` | The SIM proof succeeds and the user advances to `active`. | +| `sim.bind-fail-mobile` | The proven SIM does not match the claimed mobile. Binding does not complete. | +| `sim.bind-fail-vmn` | The callback carries a token that does not match a live binding. Binding does not complete. | + +After the call, poll `binding-status` as usual to observe the result. To test **reclaim** (the same mobile on a new device), just call `sim.bind-ok` again with a different `deviceId` — no special directive needed. + +#### OTP verification + +On the QA env there is no telecom, so no OTP SMS is sent. To pass verification, set the `idempotencyKey` on `POST /onboarding/otp/verify`: + +| `idempotencyKey` | Result | +| :--- | :--- | +| `sim.otp-ok` | The OTP verifies regardless of the code submitted, activating what it was requested for — the user, or a VPA. | + + + Use sim.otp-ok for the success path. To see a failure, + request the OTP and submit a wrong code (no directive) while it is live — that + returns 401 invalid-otp. + + +
+ +### Natural scenarios + +Everything else is reproduced with ordinary requests. A sampling: + +| To see this | Do this | +| :--- | :--- | +| `device-binding-cap-exceeded` (429) | Generate binding tokens past the per-device daily cap. | +| `otp-cap-exceeded` (429) | Call `otp/request` past the cap. | +| `invalid-otp` (401) | `otp/request`, then `otp/verify` with a wrong code (no directive) while the OTP is live. | +| `otp-expired-or-exhausted` (410) | `otp/verify` with no live OTP (never requested, or the window passed). | +| `device-not-linked` (401) | Call a VPA operation from a device not bound to the user. | +| `user-not-found` (404) | Use a mobile that was never onboarded. | +| `invalid-user-state` (409) | Call `create-vpa` before the user is `active`. | +| `invalid-vpa` (400) | Use a prefix not scoped to the caller's mobile (incl. another user's VPA). | +| `binding-not-found` (404) | Poll `binding-status` before generating a binding token. | +| `invalid-request` (400) | Send a malformed or incomplete body. | +| An abandoned binding | Request a token and never complete it — it expires on its own. | + +
+ +### A full QA env run + +| # | Call | Key inputs | Result | +| :--- | :--- | :--- | :--- | +| 1 | `binding-token` | `idempotencyKey: sim.bind-ok`, `otpRequired: false` | User → `active` | +| 2 | `binding-status` | — | `active` | +| 3 | `vpa/check` | — | Available | +| 4 | `create-vpa` | `otpRequired: true` (the Android path) | VPA → `pending-verification` | +| 5 | `otp/request` | With the VPA | `202` accepted | +| 6 | `otp/verify` | `idempotencyKey: sim.otp-ok`, with the VPA | VPA → `active` | + +### Next + +- **[API reference](/payments/upi-issuance/api-reference)** — the full endpoint reference. + + diff --git a/content/payments/upi-issuance/quickstart.mdx b/content/payments/upi-issuance/quickstart.mdx new file mode 100644 index 00000000..a8f87d2b --- /dev/null +++ b/content/payments/upi-issuance/quickstart.mdx @@ -0,0 +1,65 @@ +--- +sidebar_title: Quickstart +page_title: UPI Issuance Quickstart +order: 1 +visible_in_sidebar: true +--- + +## Quickstart + +This guide covers the one-time setup the TPAP / Issuing App needs before it can call the APIs. Once these are in place, head to [User Onboarding](/payments/upi-issuance/onboarding) for the full API journey. + +
+ +### Base URL + +- QA env — `https://upi-issuance-qa.setu.co/api/v1` + +
+ +### The envelope public key + +Every request and response body is encrypted with the **API envelope**. + +The TPAP / Issuing App can reach out to Setu to provide the **envelope public key**. With this key, the TPAP / Issuing App is supposed to encrypt each request and decrypt each response. + +The [API envelope](/payments/upi-issuance/api-envelope) page has the full wire format and a copy-paste reference implementation. + +For example, a generate binding token request and its response look like this on the wire — the encrypted body (`ct`), the request's one-time key encrypted under Setu's public key (`sk`), and the IV (`iv`): + +##### Sample request + + + {`{ + "ct": "HBAHaU47cY2pu9+9AkzlAYKr8s4CEDhz…Bn1uIfe9ufHgu1", + "sk": "hLGbHiL+TbnjYJhCgWtZM8m/yoWb0bHO…DOENEuzVbdFrX4a70A==", + "iv": "OTLfPjWZQhMRCIoAsEBAtg==" +}`} + + +The response comes back encrypted under the same key — the encrypted body (`ct`) and an integrity hash (`oha`): + +##### Sample response + + + {`{ + "ct": "VbtoxGJjpmPaj40Fo4rhGCxCvN246N7Y…7UZvM24sM0+Q=", + "oha": "7c2eae6a112e43f2b99f16ee9b5a2cd910b88c5463dca683b5a5ad053dbe7c30" +}`} + + +
+ +### Authentication + +The TPAP / Issuing App can share its outbound IP address with Setu, and Setu would whitelist that IP. This is how the TPAP / Issuing App is authenticated, so requests must be server-to-server. + +
+ +### Next + +- **[The API envelope](/payments/upi-issuance/api-envelope)** — encrypt requests and decrypt responses. +- **[User Onboarding](/payments/upi-issuance/onboarding)** — bind a device, create a VPA, and verify OTPs. +- **[Testing on QA env](/payments/upi-issuance/qa-testing)** — reproduce every scenario on the QA env. + + diff --git a/content/redirects.json b/content/redirects.json index 4ef6ae2c..53105b76 100644 --- a/content/redirects.json +++ b/content/redirects.json @@ -35,6 +35,7 @@ "/payments/billpay/custom-payment/website": "/payments/billpay/pre-built-screens/custom-payment/website", "/payments/billpay/custom-payment/android": "/payments/billpay/pre-built-screens/custom-payment/android", "/payments/billpay/custom-payment/iOS": "/payments/billpay/pre-built-screens/custom-payment/iOS", + "/payments/upi-issuance": "/payments/upi-issuance/overview", "/payments/upi-deeplinks": "/payments/upi-deeplinks/overview", "/payments/upi-deeplinks/resources/split-settlement": "/payments/upi-deeplinks/resources/settlement-object", "/payments/upi-deeplinks/resources/generate-token": "/payments/upi-deeplinks/resources/oauth",