XoomPe Client Payments API
Client endpoints for authentication, wallet balance, payout creation, and transaction tracking.
Base URL
Authorization: Bearer <accessToken>.{{base_url}}, {{access_token}}, {{refresh_token}}, {{txnId}}.Authentication
Generate access tokens using ClientId and ClientSecret, then call payout endpoints with Bearer JWT.
Authorization Header
Authorization: Bearer {{access_token}}
Generate Access Token
Generate tokens using ClientId + ClientSecret (recommended) or Email + Password.
POSTRequest
curl --location '{{base_url}}/token' \
--header 'Content-Type: application/json' \
--data '{
"clientId": "{{client_id}}",
"clientSecret": "{{client_secret}}"
}'
const response = await fetch('{{base_url}}/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
clientId: '{{client_id}}',
clientSecret: '{{client_secret}}'
})
});
const data = await response.json();
import requests
response = requests.post('{{base_url}}/token', json={
'clientId': '{{client_id}}',
'clientSecret': '{{client_secret}}'
})
data = response.json()
$ch = curl_init('{{base_url}}/token');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'clientId' => '{{client_id}}',
'clientSecret' => '{{client_secret}}'
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
Response
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "def50200...",
"expiresIn": 3600,
"tokenType": "Bearer"
}
Refresh Token
Use refresh token to get a new access token.
POSTRequest
curl --location '{{base_url}}/refresh' \
--header 'Content-Type: application/json' \
--data '{
"refreshToken": "{{refresh_token}}"
}'
const response = await fetch('{{base_url}}/refresh', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refreshToken: '{{refresh_token}}' })
});
const data = await response.json();
import requests
response = requests.post('{{base_url}}/refresh', json={'refreshToken': '{{refresh_token}}'})
data = response.json()
$ch = curl_init('{{base_url}}/refresh');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['refreshToken' => '{{refresh_token}}']));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
Response
{
"accessToken": "...new...",
"refreshToken": "...new...",
"expiresIn": 3600,
"tokenType": "Bearer"
}
Get Wallet Balance
Retrieve current available wallet balance.
GETRequest
curl --location '{{base_url}}/Payout/getWalletBalance' \
--header 'Authorization: Bearer {{access_token}}'
const response = await fetch('{{base_url}}/Payout/getWalletBalance', {
headers: { 'Authorization': 'Bearer {{access_token}}' }
});
const data = await response.json();
import requests
response = requests.get('{{base_url}}/Payout/getWalletBalance',
headers={'Authorization': 'Bearer {{access_token}}'}
)
data = response.json()
$ch = curl_init('{{base_url}}/Payout/getWalletBalance');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer {{access_token}}']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
Response
{
"statusCode": 200,
"status": true,
"message": "Balance fetched successfully",
"availableBalance": 12345.67
}
Initiate Payout
Create a payout transaction from client wallet to beneficiary bank account.
POSTRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
| beneficiaryName | string | Yes | Only letters and spaces; 3–200 chars |
| beneficiaryAccountNumber | string | Yes | 8–20 chars |
| ifsc | string | Yes | ^[A-Z]{4}0[A-Z0-9]{6}$ |
| amount | number | Yes | 5000–10000000 |
| clientTransactionRefNo | string | No | Optional idempotency reference |
Request
curl --location '{{base_url}}/Payout/CreateTransaction' \
--header 'Authorization: Bearer {{access_token}}' \
--header 'Content-Type: application/json' \
--data '{
"beneficiaryName": "John Doe",
"beneficiaryAccountNumber": "123456789012",
"ifsc": "ABCD0123456",
"amount": 5000,
"clientTransactionRefNo": "INV-1001"
}'
const response = await fetch('{{base_url}}/Payout/CreateTransaction', {
method: 'POST',
headers: {
'Authorization': 'Bearer {{access_token}}',
'Content-Type': 'application/json'
},
body: JSON.stringify({
beneficiaryName: 'John Doe',
beneficiaryAccountNumber: '123456789012',
ifsc: 'ABCD0123456',
amount: 5000,
clientTransactionRefNo: 'INV-1001'
})
});
const data = await response.json();
import requests
response = requests.post(
'{{base_url}}/Payout/CreateTransaction',
headers={'Authorization': 'Bearer {{access_token}}'},
json={
'beneficiaryName': 'John Doe',
'beneficiaryAccountNumber': '123456789012',
'ifsc': 'ABCD0123456',
'amount': 5000,
'clientTransactionRefNo': 'INV-1001'
}
)
data = response.json()
$ch = curl_init('{{base_url}}/Payout/CreateTransaction');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'beneficiaryName' => 'John Doe',
'beneficiaryAccountNumber' => '123456789012',
'ifsc' => 'ABCD0123456',
'amount' => 5000,
'clientTransactionRefNo' => 'INV-1001'
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer {{access_token}}',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
Response (success)
{
"statusCode": 201,
"responseCode": 1,
"status": true,
"message": "Transaction created successfully",
"transactionNumber": "TX26010300001",
"transaction": {
"transactionNumber": "TX26010300001",
"clientTransactionRefNo": "INV-1001",
"beneficiaryName": "John Doe",
"beneficiaryAccountNumber": "123456789012",
"ifsc": "ABCD0123456",
"amount": 5000,
"status": "Pending",
"utr": null,
"remarks": null,
"createdAt": "2026-01-09T17:21:00",
"updatedAt": null
}
}
Response (idempotent duplicate reference)
{
"statusCode": 200,
"responseCode": 1,
"status": true,
"message": "Transaction already exists (idempotent)",
"transactionNumber": "TX26010300001",
"transaction": {
"transactionNumber": "TX26010300001",
"clientTransactionRefNo": "INV-1001",
"beneficiaryName": "John Doe",
"beneficiaryAccountNumber": "123456789012",
"ifsc": "ABCD0123456",
"amount": 5000,
"status": "Pending"
}
}
Create Bulk Payouts
Submit multiple payout transactions in a single API call (1–500 items).
POSTRequest
curl --location '{{base_url}}/Payout/CreateBulkTransactions' \
--header 'Authorization: Bearer {{access_token}}' \
--header 'Content-Type: application/json' \
--data '{
"transactions": [
{
"beneficiaryName": "A Person",
"beneficiaryAccountNumber": "1234567890",
"ifsc": "ABCD0123456",
"amount": 5000,
"clientTransactionRefNo": "BULK-1"
},
{
"beneficiaryName": "B Person",
"beneficiaryAccountNumber": "9876543210",
"ifsc": "WXYZ0123456",
"amount": 7500,
"clientTransactionRefNo": "BULK-2"
}
]
}'
const response = await fetch('{{base_url}}/Payout/CreateBulkTransactions', {
method: 'POST',
headers: {
'Authorization': 'Bearer {{access_token}}',
'Content-Type': 'application/json'
},
body: JSON.stringify({
transactions: [
{ beneficiaryName:'A Person', beneficiaryAccountNumber:'1234567890', ifsc:'ABCD0123456', amount:5000, clientTransactionRefNo:'BULK-1' },
{ beneficiaryName:'B Person', beneficiaryAccountNumber:'9876543210', ifsc:'WXYZ0123456', amount:7500, clientTransactionRefNo:'BULK-2' }
]
})
});
const data = await response.json();
import requests
response = requests.post(
'{{base_url}}/Payout/CreateBulkTransactions',
headers={'Authorization': 'Bearer {{access_token}}'},
json={
'transactions': [
{'beneficiaryName':'A Person','beneficiaryAccountNumber':'1234567890','ifsc':'ABCD0123456','amount':5000,'clientTransactionRefNo':'BULK-1'},
{'beneficiaryName':'B Person','beneficiaryAccountNumber':'9876543210','ifsc':'WXYZ0123456','amount':7500,'clientTransactionRefNo':'BULK-2'}
]
}
)
data = response.json()
$ch = curl_init('{{base_url}}/Payout/CreateBulkTransactions');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'transactions' => [
['beneficiaryName'=>'A Person','beneficiaryAccountNumber'=>'1234567890','ifsc'=>'ABCD0123456','amount'=>5000,'clientTransactionRefNo'=>'BULK-1'],
['beneficiaryName'=>'B Person','beneficiaryAccountNumber'=>'9876543210','ifsc'=>'WXYZ0123456','amount'=>7500,'clientTransactionRefNo'=>'BULK-2']
]
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer {{access_token}}',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
Response
{
"statusCode": 200,
"status": true,
"message": "Success: 2, Failed: 0",
"successCount": 2,
"failedCount": 0,
"totalProcessed": 2,
"successTransactions": [
{ "transactionNumber": "TX26010300001", "clientTransactionRefNo": "BULK-1", "beneficiaryName": "A Person", "amount": 5000 }
],
"failedTransactions": []
}
Get Transactions (Client Filters)
Retrieve client transactions with pagination and filters.
GETRequest
curl --location '{{base_url}}/Payout/GetClientTransactionsWithFilters?page=1&pageSize=50&status=Success' \
--header 'Authorization: Bearer {{access_token}}'
const url = new URL('{{base_url}}/Payout/GetClientTransactionsWithFilters');
url.searchParams.set('page','1');
url.searchParams.set('pageSize','50');
url.searchParams.set('status','Success');
const response = await fetch(url, {
headers: { 'Authorization': 'Bearer {{access_token}}' }
});
const data = await response.json();
import requests
response = requests.get(
'{{base_url}}/Payout/GetClientTransactionsWithFilters',
headers={'Authorization': 'Bearer {{access_token}}'},
params={'page': 1, 'pageSize': 50, 'status': 'Success'}
)
data = response.json()
$url = '{{base_url}}/Payout/GetClientTransactionsWithFilters?page=1&pageSize=50&status=Success';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer {{access_token}}']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
Response
{
"status": true,
"message": "Transactions fetched successfully",
"data": [],
"pagination": {
"currentPage": 1,
"pageSize": 50,
"totalCount": 0,
"totalPages": 0,
"hasNextPage": false,
"hasPreviousPage": false
}
}
Get Transaction by ID
Retrieve complete details using transaction number (txnId).
GETRequest
curl --location '{{base_url}}/Payout/GetTransactionByTxnId/TX26010300001' \
--header 'Authorization: Bearer {{access_token}}'
const response = await fetch('{{base_url}}/Payout/GetTransactionByTxnId/TX26010300001', {
headers: { 'Authorization': 'Bearer {{access_token}}' }
});
const data = await response.json();
import requests
response = requests.get(
'{{base_url}}/Payout/GetTransactionByTxnId/TX26010300001',
headers={'Authorization': 'Bearer {{access_token}}'}
)
data = response.json()
$ch = curl_init('{{base_url}}/Payout/GetTransactionByTxnId/TX26010300001');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer {{access_token}}']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
Response
{
"status": true,
"message": "Transaction fetched successfully",
"transaction": {
"transactionNumber": "TX26010300001",
"clientTransactionRefNo": "INV-1001",
"beneficiaryName": "John Doe",
"beneficiaryAccountNumber": "123456789012",
"ifsc": "ABCD0123456",
"amount": 5000,
"status": "Success",
"utr": "UTR123456789",
"remarks": null,
"createdAt": "2026-01-09T17:21:00",
"updatedAt": "2026-01-09T17:25:00"
}
}
Webhooks
Receive real-time notifications when transaction status changes.
Webhook Payload
{
"event": "transaction.status.updated",
"timestamp": "2026-01-09T17:25:00Z",
"data": {
"transactionNumber": "TX26010300001",
"clientTransactionRefNo": "INV-1001",
"status": "Success",
"utr": "UTR123456789",
"amount": 5000,
"beneficiaryName": "John Doe"
}
}
Transaction Statuses
| Status | Description |
|---|---|
| Pending | Transaction created and queued for processing |
| Processing | Transaction is being processed by the payment gateway |
| Success | Transaction completed successfully |
| Failed | Transaction failed (insufficient balance, invalid account, etc.) |
| Reversed | Transaction was reversed/refunded |
Error Handling
API uses standard HTTP status codes and returns error details in JSON format.
Error Response Format
{
"statusCode": 400,
"status": false,
"message": "Validation failed",
"errors": {
"beneficiaryName": ["Name must contain only letters and spaces"],
"amount": ["Amount must be between 5000 and 10000000"]
}
}
Common HTTP Status Codes
| Code | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request - Validation error |
| 401 | Unauthorized - Invalid or expired token |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error |
Validation Rules
Beneficiary Name
- Only letters and spaces allowed
- Minimum 3 characters, maximum 28 characters
- No special characters or numbers
Account Number
- 8 to 20 characters
- Alphanumeric
IFSC Code
- Must match pattern: ^[A-Z]{4}0[A-Z0-9]{6}$
- Example: ABCD0123456
Amount
- Minimum: ₹5,000
- Maximum: ₹1,00,00,000
- Must be a positive number
Rate Limiting
API implements rate limiting to ensure fair usage and system stability.
| Endpoint Type | Limit |
|---|---|
| Authentication (/token, /refresh) | 10 requests per minute |
| Single Payout | 100 requests per minute |
| Bulk Payout | 10 requests per minute |
| Transaction Queries | 200 requests per minute |
Security Best Practices
- Store ClientId/ClientSecret and webhook secret securely (environment variables or vault)
- Always use HTTPS for all API requests
- Verify webhook signature and timestamp (reject old timestamps to prevent replay attacks)
- Use idempotency key
clientTransactionRefNoto avoid duplicate transactions - Rotate access tokens regularly using refresh token
- Never expose credentials in client-side code or version control
- Implement proper error handling without exposing sensitive information
- Monitor API usage for unusual patterns