OneTap API Reference
Integrate UPI collections and bank payouts into your app or website with simple JSON APIs and real-time callbacks.
Introduction
The OneTap API lets you accept UPI payments and send bank payouts from your own system. All endpoints accept POST requests with a JSON body and always return JSON.
| Item | Details |
|---|---|
| {BASE_URL} | Your API base URL. It is shared with you after your merchant account is activated. |
| YOUR_API_TOKEN | Your secret API token, available after activation. Never expose it in an app or browser. |
| Content-Type | application/json |
| Accept | application/json. Send this so that errors are also returned as JSON. |
| Callback URL | Register your callback URL with our team. Final payment and payout statuses are posted to it. |
Authentication
Send your API token with every request, either as the api_token field in the request body or as a header:
Authorization: Bearer YOUR_API_TOKEN
IP whitelisting
Payout requests are accepted only from server IPs registered on your account. Share your server IPs with our team before going live. Requests from any other IP get HTTP 403.
HTTP 401. Keep your token on your server only.Create Order UPI Collection
Creates a UPI payment order and returns a UPI intent link. Open the link on the customer's phone to launch their UPI app, or show it as a QR code.
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_token | string | Required | Your API token |
| order_id | string | Required | Your unique order ID (one per order) |
| amount | number | Required | Amount in INR, minimum 1 |
| mobile | string | Required | Customer mobile number |
| name | string | Required | Customer name |
| string | Required | Customer email address |
Sample request
{
"api_token": "YOUR_API_TOKEN",
"order_id": "5665837",
"amount": 11,
"mobile": "9876543210",
"name": "Test Customer",
"email": "customer@example.com"
}Responses
{
"status": "success",
"data": {
"order_id": "5665837",
"amount": 11,
"payment_url": "upi://pay?pa=merchant@upi&pn=MERCHANT&am=11&cu=INR&tr=536482521327337766"
}
}If you send the same order_id again while that order is still pending, the existing order is returned with "note": "Returned existing pending order for this order_id".
{
"status": "failed",
"error": "The amount field is required."
}{
"status": "failed",
"error": "This order_id has already
been processed. Please use a
new order_id."
}{
"status": "failed",
"message": "Payment initiation failed"
}Check Status UPI Collection
Returns the current status of a UPI order by your order_id. Use it if a callback has not arrived.
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_token | string | Required | Your API token |
| order_id | string | Required | The order ID you sent in Create Order |
{
"api_token": "YOUR_API_TOKEN",
"order_id": "749458889909739"
}{
"type": "payin",
"status": "Credit",
"order_id": "749458889909739",
"amount": 11,
"utr": "779979218280",
"date": "2026-02-05",
"time": "18:18:19"
}{
"type": "payin",
"status": "Initiated",
"order_id": "749458889909739",
"amount": 11,
"utr": null,
"date": "2026-02-11",
"time": "13:04:53"
}Possible status values: Order Created, Initiated, Credit, Failure. If the order is unknown, the response is {"message": "Order not found"}.
Callback UPI Collection
When a payment completes, we send a POST request with a JSON body (not form data) to your registered callback URL.
Content-Type: application/json Accept: application/json api_token: YOUR_API_TOKEN
{
"type": "payin",
"status": "credit",
"order_id": "5665837",
"amount": 11.00,
"utr": "773762060229",
"message": "PAYMENT SUCCESS"
}| Field | Description |
|---|---|
| type | Always payin |
| status | credit or failed |
| order_id | Your original order ID |
| amount | Transaction amount |
| utr | Bank UTR (null when failed) |
| message | Status message |
Reading the callback (PHP)
$data = json_decode(file_get_contents('php://input'), true);
// Confirm the request came from OneTap
if (($_SERVER['HTTP_API_TOKEN'] ?? '') !== 'YOUR_API_TOKEN') {
http_response_code(401); exit;
}
if ($data['status'] === 'credit') {
// mark $data['order_id'] as paid
}
http_response_code(200);
echo json_encode(['status' => true, 'message' => 'Callback received successfully']);HTTP 200. Always confirm the amount and order_id against your own records before marking an order as paid.Create Payout Payout
Sends money to a bank account. The payout amount plus its charge is debited from your wallet when the payout is accepted. If the payout fails, the full debit is refunded.
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_token | string | Required | Your API token |
| externalTxnId | string | Required | Your unique transaction ID, maximum 50 characters (letters, numbers, - and _). Each ID can be used only once. |
| amount | number | Required | Payout amount, at most 2 decimal places, within the limits set on your account |
| transfer_mode | string | Required | IMPS, NEFT or RTGS |
| payee_name | string | Required | Beneficiary full name (max 100 characters) |
| payee_account | string | Required | Beneficiary account number (6–25 letters or digits) |
| payee_ifsc | string | Required | Beneficiary IFSC (11 characters, e.g. SBIN0001234) |
| payee_ac_type | string | Required | savings or current |
| payee_bank_name | string | Required | Beneficiary bank name |
{
"api_token": "YOUR_API_TOKEN",
"externalTxnId": "ext_txn_123456",
"amount": 1500,
"transfer_mode": "IMPS",
"payee_name": "Demo User",
"payee_account": "123456789012",
"payee_ifsc": "SBIN0001234",
"payee_ac_type": "savings",
"payee_bank_name": "State Bank of India"
}An accepted payout always returns HTTP 200. Read status (or data.txnStatus) for the outcome.
{
"status": "success",
"message": "Payout successful",
"data": {
"externalTxnId": "ext_txn_123456",
"txnStatus": "SUCCESS",
"amount": 1500,
"charge": 5,
"totalDebit": 1505,
"utr": "605110461990",
"transfer_mode": "IMPS",
"payee_name": "Demo User",
"payee_account": "123456789012",
"payee_ifsc": "SBIN0001234",
"timestamp": "2026-10-12 13:59:00"
}
}{
"status": "pending",
"message": "Payout is being processed.
The final status will be sent
to your callback URL.",
"data": {
"externalTxnId": "ext_txn_123456",
"txnStatus": "PENDING",
"utr": null,
...
}
}{
"status": "failure",
"message": "Payout failed. The amount
has been refunded to your wallet.",
"data": {
"externalTxnId": "ext_txn_123456",
"txnStatus": "FAILED",
"totalDebit": 0,
"utr": null,
...
}
}externalTxnId.Payout Status Payout
Returns the current status of a payout. Use it when the create call timed out or the callback has not arrived. The response has the same fields as the callback.
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_token | string | Required | Your API token |
| externalTxnId | string | Required | The transaction ID sent in Create Payout |
{
"api_token": "YOUR_API_TOKEN",
"externalTxnId": "ext_txn_123456"
}{
"type": "payout",
"externalTxnId": "ext_txn_123456",
"status": "SUCCESS",
"amount": 1500,
"utr": "605110461990",
"message": "Payout successful"
}{
"type": "payout",
"externalTxnId": "ext_txn_123456",
"status": "PENDING",
"amount": 1500,
"utr": null,
"message": "Payout is being processed"
}{
"status": "failure",
"error_code": "NOT_FOUND",
"message": "No payout found for this externalTxnId."
}Callback Payout
When a payout reaches its final status, a JSON POST is sent once to your registered callback URL. The api_token header carries your API token so you can confirm it came from us. Reply with HTTP 200.
{
"type": "payout",
"externalTxnId": "ext_txn_123456",
"status": "SUCCESS",
"amount": 1500,
"utr": "605110461990",
"message": "Payout successful"
}{
"type": "payout",
"externalTxnId": "ext_txn_123456",
"status": "FAILED",
"amount": 1500,
"utr": null,
"message": "Payout failed. Amount
refunded to wallet."
}| Field | Description |
|---|---|
| type | Always payout |
| externalTxnId | Your transaction ID |
| status | SUCCESS or FAILED |
| amount | Payout amount |
| utr | Bank UTR for a successful payout, otherwise null |
| message | Status message |
Error Codes Payout
A request that is not accepted returns an HTTP 4xx / 5xx code with an error_code. Nothing is debited in these cases.
{
"status": "failure",
"error_code": "VALIDATION_ERROR",
"message": "payee_ifsc is not a valid IFSC code."
}| error_code | HTTP | Meaning |
|---|---|---|
| VALIDATION_ERROR | 422 | A parameter is missing or invalid. message says which one. |
| DUPLICATE_TXN_ID | 409 | This externalTxnId was already used. Check its status instead of sending it again. |
| INSUFFICIENT_BALANCE | 400 | Wallet balance does not cover the amount plus charge. |
| SERVICE_NOT_ALLOWED | 403 | Payout is not enabled on your account. |
| SERVICE_UNAVAILABLE | 503 | Payout is temporarily unavailable. Retry later with the same externalTxnId. |
| INTERNAL_ERROR | 500 | The payout could not be created. Nothing was debited. |
| — | 401 | Wrong or missing API token. |
| — | 403 | Request came from an IP that is not whitelisted. |
Need help integrating?
Our tech team can help you go live. Call +91 63709 64732 or email info.onetapsolutions@gmail.com.