Airtel CMS · Airtel CMS Services
Inbound Webhook Callback Listener
Webhook callback specifications for balance verification, debit, and transaction posting
POST request
URL: https://uat-api.vizodigital.com/api/v1/cms/airtel/callback
Body
{
"action": "transaction_post",
"merchantId": "3123456789",
"amount": "100",
"transactionId": "DEMOTRAN123",
"billerId": "011023",
"billerName": "TEST",
"utr": "DEMO0101012",
"mobile": "9829098290",
"tranDateTime": "07-10-2024 04:47:01",
"commission": "0.1",
"otherFields": "",
"description": "DEMODEMODEMO 12132123",
"tranStatus": "Success"
}
Include a valid Bearer token with every request
Code sample
curl --location 'https://api.vizodigital.com/api/v1/cms/airtel/callback' \
--header 'Authorization: Bearer <YOUR_API_TOKEN>' \
--header 'X-Timestamp: 2026-10-30T11:25:06' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"action": "transaction_post",
"merchantId": "3123456789",
"amount": "100",
"transactionId": "DEMOTRAN123",
"billerId": "011023",
"billerName": "TEST",
"utr": "DEMO0101012",
"mobile": "9829098290",
"tranDateTime": "07-10-2024 04:47:01",
"commission": "0.1",
"otherFields": "",
"description": "DEMODEMODEMO 12132123",
"tranStatus": "Success"
}'
<?php
$client = new \GuzzleHttp\Client();
$response = $client->post('https://api.vizodigital.com/api/v1/cms/airtel/callback', [
'headers' => [
'Authorization' => 'Bearer <YOUR_API_TOKEN>',
'X-Timestamp' => '2026-10-30T11:25:06',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => array (
'action' => 'transaction_post',
'merchantId' => '3123456789',
'amount' => '100',
'transactionId' => 'DEMOTRAN123',
'billerId' => '011023',
'billerName' => 'TEST',
'utr' => 'DEMO0101012',
'mobile' => '9829098290',
'tranDateTime' => '07-10-2024 04:47:01',
'commission' => '0.1',
'otherFields' => '',
'description' => 'DEMODEMODEMO 12132123',
'tranStatus' => 'Success',
),
]);
echo $response->getBody();
import requests
url = 'https://api.vizodigital.com/api/v1/cms/airtel/callback'
headers = {
'Authorization': 'Bearer <YOUR_API_TOKEN>',
'X-Timestamp': '2026-10-30T11:25:06',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
payload = {
"action": "transaction_post",
"merchantId": "3123456789",
"amount": "100",
"transactionId": "DEMOTRAN123",
"billerId": "011023",
"billerName": "TEST",
"utr": "DEMO0101012",
"mobile": "9829098290",
"tranDateTime": "07-10-2024 04:47:01",
"commission": "0.1",
"otherFields": "",
"description": "DEMODEMODEMO 12132123",
"tranStatus": "Success"
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
const axios = require('axios');
axios.post('https://api.vizodigital.com/api/v1/cms/airtel/callback', {"action":"transaction_post","merchantId":"3123456789","amount":"100","transactionId":"DEMOTRAN123","billerId":"011023","billerName":"TEST","utr":"DEMO0101012","mobile":"9829098290","tranDateTime":"07-10-2024 04:47:01","commission":"0.1","otherFields":"","description":"DEMODEMODEMO 12132123","tranStatus":"Success"}, {
headers: {
'Authorization': 'Bearer <YOUR_API_TOKEN>',
'X-Timestamp': '2026-10-30T11:25:06',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(res => console.log(res.data))
.catch(err => console.error(err));
Success Example
{
"status": "1",
"message": "Transaction Posting Successful"
}
Failure response
{
"status": "error",
"message": "Request failed. Check credentials, wallet balance, or validation errors."
}
Overview
Airtel CMS – Client Callback Responses
During the Airtel CMS transaction process, the system sends three types of callback requests to the client’s callback URL:
POST https://api.vizodigital.com/api/v1/cms/airtel/callback
⚠️ Important Callback Implementation Notes
- HTTPS Endpoint: A valid HTTPS Callback URL is required to receive and handle the final transaction response.
- POST Method: The callback should be capable of accepting POST responses containing transaction status and details.
- Valid JSON Response: The client must respond in valid JSON format.
- Status Field: The
statusfield accepts only"0"(Fail) or"1"(Success). - String Format Rule: In the JSON request and response, all fields must be strings.
- 15-Minute Posting Timing: For
transaction_post(Final Callback), client callback data will be received within 15 minutes after the transaction. - Acknowledgment Responsibility: The client is fully responsible for any successful (
status = "1") acknowledgment sent.
1. Balance Check (action: "balance_check")
Purpose: To verify whether the client/merchant has sufficient balance before initiating a transaction.
| Field | Type | Description | Example |
|---|---|---|---|
action |
string |
Always "balance_check" |
"balance_check" |
merchantId |
string |
10-digit numeric Merchant ID | "123456789" |
amount |
string |
Transaction amount as string | "100" |
transactionId |
string |
Unique transaction ID | "DEMOTRAN123" |
Client Response:
{
"status": "1",
"message": "Success"
}
2. Balance Check Debit (action: "balance_check_debit")
Purpose: Debit the merchant’s account with the specified transaction amount.
| Field | Type | Description | Example |
|---|---|---|---|
action |
string |
Always "balance_check_debit" |
"balance_check_debit" |
merchantId |
string |
10-digit numeric Merchant ID | "123456789" |
amount |
string |
Transaction amount to debit | "100" |
transactionId |
string |
Unique transaction ID | "DEMOTRAN123" |
billerId |
string |
Biller ID selected by customer | "011023" |
billerName |
string |
Biller name | "TEST" |
mobile |
string |
Customer mobile number | "9829098290" |
Client Response:
{
"status": "1",
"message": "Amount Debit Successful"
}
3. Transaction Post (Final Callback) (action: "transaction_post")
Purpose: Indicates that the final transaction posting process has been completed.
| Field | Type | Description | Example |
|---|---|---|---|
action |
string |
Always "transaction_post" |
"transaction_post" |
merchantId |
string |
10-digit numeric Merchant ID | "3123456789" |
amount |
string |
Collected amount | "100" |
transactionId |
string |
Unique transaction identifier | "DEMOTRAN123" |
billerId |
string |
Biller ID | "011023" |
billerName |
string |
Biller organization name | "TEST" |
utr |
string |
Bank UTR reference number | "DEMO0101012" |
mobile |
string |
Customer mobile number | "9829098290" |
tranDateTime |
string |
Bank transaction date & time | "07-10-2024 04:47:01" |
commission |
string |
Retailer commission | "0.1" |
otherFields |
string |
Additional metadata | "" |
description |
string |
Description or status remarks | "DEMODEMODEMO 12132123" |
tranStatus |
string |
Final status: Success or Failed |
"Success" |
Client Response:
{
"status": "1",
"message": "Transaction Posting Successful"
}
Headers
-
Authorization · string required
An authentication token required for the request (Sanctum Bearer Token or Noble API token).
Example: Bearer <YOUR_API_TOKEN>
-
X-Timestamp · string required
Generated at the time of request, with skew time of 15 seconds (must be in format yyyy-MM-ddTHH:mm:ss).
Example: 2024-10-20T21:27:09
-
Content-Type · string required
Request content-type. Only application/json is allowed.
Example: application/json
-
Accept · string required
Response content-type. Must be application/json.
Example: application/json
Body
JSON payload for Inbound Webhook Callback Listener
Schema
{
"type": "object",
"required": [
"action",
"merchantId",
"amount",
"transactionId"
],
"properties": {
"action": {
"type": "string",
"description": "Callback action: balance_check, balance_check_debit, or transaction_post",
"example": "transaction_post"
},
"merchantId": {
"type": "string",
"description": "10-digit numeric Merchant ID",
"example": "3123456789"
},
"amount": {
"type": "string",
"description": "Transaction cash amount as string",
"example": "100"
},
"transactionId": {
"type": "string",
"description": "Unique transaction identifier",
"example": "DEMOTRAN123"
},
"billerId": {
"type": "string",
"description": "Biller ID (present in debit & post callbacks)",
"example": "011023"
},
"billerName": {
"type": "string",
"description": "Biller organization name",
"example": "TEST"
},
"utr": {
"type": "string",
"description": "Bank UTR reference number",
"example": "DEMO0101012"
},
"mobile": {
"type": "string",
"description": "Depositor customer mobile number",
"example": "9829098290"
},
"tranDateTime": {
"type": "string",
"description": "Transaction date & time string",
"example": "07-10-2024 04:47:01"
},
"commission": {
"type": "string",
"description": "Retailer commission earned",
"example": "0.1"
},
"tranStatus": {
"type": "string",
"description": "Final status: Success or Failed",
"example": "Success"
}
}
}
Example
{
"action": "transaction_post",
"merchantId": "3123456789",
"amount": "100",
"transactionId": "DEMOTRAN123",
"billerId": "011023",
"billerName": "TEST",
"utr": "DEMO0101012",
"mobile": "9829098290",
"tranDateTime": "07-10-2024 04:47:01",
"commission": "0.1",
"otherFields": "",
"description": "DEMODEMODEMO 12132123",
"tranStatus": "Success"
}
Responses
-
200 · application/json default
Webhook callback acknowledgment response.
Example
{ "status": "1", "message": "Transaction Posting Successful" } -
200 · application/json
Callback failure acknowledgment
Example
{ "status": "0", "message": "Transaction Posting Failed" }
Errors
-
IR0001 · HTTP 400
Invalid Request: Malformed or invalid request body. Check syntax and required fields.
Invalid Request: Malformed or invalid request body. Check syntax and required fields.
{ "status": 0, "statusCode": "IR0001", "message": "Invalid Request: Malformed or invalid request body. Check syntax and required fields." } -
PM0002 · HTTP 422
Parameter Missing: Required parameter is missing.
Parameter Missing: Required parameter is missing.
{ "status": 0, "statusCode": "PM0002", "message": "Parameter Missing: Required parameter is missing." } -
VF0003 · HTTP 422
Validation Failed: Input validation failed.
Validation Failed: Input validation failed.
{ "status": 0, "statusCode": "VF0003", "message": "Validation Failed: Input validation failed." } -
IE0004 · HTTP 404
Invalid Api Endpoint: Endpoint not found.
Invalid Api Endpoint: Endpoint not found.
{ "status": 0, "statusCode": "IE0004", "message": "Invalid Api Endpoint: Endpoint not found." } -
IC0007 · HTTP 401
Invalid Credentials: Authentication failed.
Invalid Credentials: Authentication failed.
{ "status": 0, "statusCode": "IC0007", "message": "Invalid Credentials: Authentication failed." } -
SE0006 · HTTP 500
Internal Server Error: Server is down. Please try again later.
Internal Server Error: Server is down. Please try again later.
{ "status": 0, "statusCode": "SE0006", "message": "Internal Server Error: Server is down. Please try again later." } -
AE0021 · HTTP 400
Invalid Header: Header validation failed.
Invalid Header: Header validation failed.
{ "status": 0, "statusCode": "AE0021", "message": "Invalid Header: Header validation failed." } -
AE0022 · HTTP 429
Authentication Error: Rate limit exceeded. Please try again later.
Authentication Error: Rate limit exceeded. Please try again later.
{ "status": 0, "statusCode": "AE0022", "message": "Authentication Error: Rate limit exceeded. Please try again later." } -
AE0024 · HTTP 400
Authentication Error: Invalid timestamp format (must be yyyy-MM-ddTHH:mm:ss).
Authentication Error: Invalid timestamp format (must be yyyy-MM-ddTHH:mm:ss).
{ "status": 0, "statusCode": "AE0024", "message": "Authentication Error: Invalid timestamp format (must be yyyy-MM-ddTHH:mm:ss)." } -
AE0026 · HTTP 401
Authentication Error: Header Token is invalid or inactive.
Authentication Error: Header Token is invalid or inactive.
{ "status": 0, "statusCode": "AE0026", "message": "Authentication Error: Header Token is invalid or inactive." } -
AE0028 · HTTP 403
Authentication Error: IP address not allowed.
Authentication Error: IP address not allowed.
{ "status": 0, "statusCode": "AE0028", "message": "Authentication Error: IP address not allowed." } -
AC0001 · HTTP 200
Success: Transaction processed successfully.
Success: Transaction processed successfully.
{ "status": 1, "statusCode": "AC0001", "message": "Success: Transaction processed successfully." } -
AC0002 · HTTP 422
Failed: Transaction failed downstream with Airtel Bank.
Failed: Transaction failed downstream with Airtel Bank.
{ "status": 0, "statusCode": "AC0002", "message": "Failed: Transaction failed downstream with Airtel Bank." } -
AC0003 · HTTP 500
Error: System error or partner connectivity failure.
Error: System error or partner connectivity failure.
{ "status": 0, "statusCode": "AC0003", "message": "Error: System error or partner connectivity failure." } -
APB_000 · HTTP 200
Success: Ideal success code in all scenarios.
Success: Ideal success code in all scenarios.
{ "status": 1, "statusCode": "APB_000", "message": "Success: Ideal success code in all scenarios." } -
APB_001 · HTTP 422
Form Data not found (Biller is not configured in the system).
Form Data not found (Biller is not configured in the system).
{ "status": 0, "statusCode": "APB_001", "message": "Form Data not found (Biller is not configured in the system)." } -
APB_002 · HTTP 422
Insufficient balance in account, please add funds and try again.
Insufficient balance in account, please add funds and try again.
{ "status": 0, "statusCode": "APB_002", "message": "Insufficient balance in account, please add funds and try again." } -
APB_004 · HTTP 422
Amount cannot be credited as account exceeds maximum balance limit.
Amount cannot be credited as account exceeds maximum balance limit.
{ "status": 0, "statusCode": "APB_004", "message": "Amount cannot be credited as account exceeds maximum balance limit." } -
APB_006 · HTTP 422
Credit freeze on account, ask beneficiary to contact bank.
Credit freeze on account, ask beneficiary to contact bank.
{ "status": 0, "statusCode": "APB_006", "message": "Credit freeze on account, ask beneficiary to contact bank." } -
APB_010 · HTTP 422
Either debit or credit account is closed.
Either debit or credit account is closed.
{ "status": 0, "statusCode": "APB_010", "message": "Either debit or credit account is closed." } -
APB_011 · HTTP 422
Transaction could not be processed as Credit account is blocked.
Transaction could not be processed as Credit account is blocked.
{ "status": 0, "statusCode": "APB_011", "message": "Transaction could not be processed as Credit account is blocked." } -
APB_042 · HTTP 422
Permissible daily transaction amount has exceeded.
Permissible daily transaction amount has exceeded.
{ "status": 0, "statusCode": "APB_042", "message": "Permissible daily transaction amount has exceeded." } -
APB_043 · HTTP 202
Transaction pending. Deposited amount will be credited against ID.
Transaction pending. Deposited amount will be credited against ID.
{ "status": 1, "statusCode": "APB_043", "message": "Transaction pending. Deposited amount will be credited against ID." } -
APB_111 · HTTP 422
Default failure code: Partner Not Found or Partner status is inactive.
Default failure code: Partner Not Found or Partner status is inactive.
{ "status": 0, "statusCode": "APB_111", "message": "Default failure code: Partner Not Found or Partner status is inactive." } -
APB_112 · HTTP 422
Txn failed due to duplicate request, please retry with fresh ID.
Txn failed due to duplicate request, please retry with fresh ID.
{ "status": 0, "statusCode": "APB_112", "message": "Txn failed due to duplicate request, please retry with fresh ID." } -
APB_121 · HTTP 422
No such transaction exists in system, please retry.
No such transaction exists in system, please retry.
{ "status": 0, "statusCode": "APB_121", "message": "No such transaction exists in system, please retry." } -
APB_182 · HTTP 422
Balance not found for corresponding COD account.
Balance not found for corresponding COD account.
{ "status": 0, "statusCode": "APB_182", "message": "Balance not found for corresponding COD account." } -
APB_183 · HTTP 422
Account details not found.
Account details not found.
{ "status": 0, "statusCode": "APB_183", "message": "Account details not found." }
Notes
🔄 Airtel CMS 4-Step Transaction Flow
- Start Transaction: Call
/api/v1/cms/airtel/startwithmerchantIdandtransactionIdto receive the official Airtel Bank Plugin redirection URL. - Enter Details & Generate OTP: Retailer opens the redirection URL and enters biller, depositor mobile, and cash amount.
- OTP Verification & Balance Check: Retailer enters OTP; Airtel triggers
balance_checkandbalance_check_debitwebhook callbacks. - Transaction Posting: Once completed, Airtel sends
transaction_postcallback (delivered within 15 minutes) and retailer commission is credited.
💰 Real-Time Wallet Balance, Commission & Auto-Refund
- Zero Surcharge: No fee or surcharge is charged to the retailer or customer on cash collections.
- Retailer Commission: The retailer earns a commission on each successfully settled transaction, credited automatically to their primary wallet.
- Atomic Debit: Your wallet is atomically debited for the exact collection amount when Airtel issues the
balance_check_debitcallback. - Instant Auto-Refund: If the transaction fails downstream (Status
Failedor provider decline), your wallet is 100% automatically refunded.
🔔 Inbound Callback Contract
- In every callback request and response, all fields must be strings.
- The
statusfield accepts only"1"(Success) or"0"(Fail). - Always maintain a stable HTTPS callback listener and respond promptly with valid JSON.
Rate Limits
60/min