1. Endpoints Overview
| # | Endpoint | Method | Purpose |
| 1 | /api/airtel/validate | POST | Validate account before debiting subscriber |
| 2 | /api/airtel/process | POST | Process payment after subscriber is debited |
| 3 | /api/airtel/enquiry | POST | Query status of a previously processed transaction |
| 4 | /api/airtel/billfetch | POST | Retrieve outstanding bill for a given reference |
2. Authentication
All endpoints accept a JWT token via the Authorization header:
Authorization: Bearer <JWT_TOKEN>
- Algorithm: HS512
- Shared Secret: Provided separately (AIRTEL_JWT_SECRET)
Note: If no JWT secret is configured on the partner side, JWT validation is skipped (UAT flexibility mode).
3. Validate Transaction
POST https://www.dhamanilink.com/api/airtel/validate
Called by Airtel before debiting the subscriber. Validates whether the account reference exists and can accept payments.
Request
<COMMAND>
<TYPE>C2B</TYPE>
<CUSTOMERMSISDN>254784893664</CUSTOMERMSISDN>
<MERCHANTMSISDN>000005467</MERCHANTMSISDN>
<AMOUNT>100</AMOUNT>
<REFERENCE>QT-5C84C515</REFERENCE>
<REFERENCE1>ATQ_TEST_001</REFERENCE1>
</COMMAND>
| Field | Description |
TYPE | Always C2B |
CUSTOMERMSISDN | Subscriber's phone number (254...) |
MERCHANTMSISDN | Merchant short code |
AMOUNT | Transaction amount (KES) |
REFERENCE | Account reference (Booking/Quote ID, e.g. QT-5C84C515) |
REFERENCE1 | Airtel's transaction ID |
Response — Success (Account Valid)
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>C2B</TYPE>
<TXNID>ATQ_TEST_001</TXNID>
<TXNSTATUS>200</TXNSTATUS>
<MESSAGE>Account Validated</MESSAGE>
</COMMAND>
Response — Failure (Account Not Found)
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>C2B</TYPE>
<TXNID>ATQ_TEST_001</TXNID>
<TXNSTATUS>400</TXNSTATUS>
<MESSAGE>Account Not Found</MESSAGE>
</COMMAND>
Amount Validation Rules
| Rule | Response Message |
| Amount ≤ 0 | Amount must be greater than zero |
| Amount < KES 1 | Requested amount less than allowed limit |
| Amount > KES 250,000 | Amount exceeds maximum (KES 250,000) |
4. Process Transaction
POST https://www.dhamanilink.com/api/airtel/process
Called by Airtel after debiting the subscriber. DhamaniLink processes the payment and responds synchronously. Includes idempotency — duplicate REFERENCE1 values return the original result.
Request
<COMMAND>
<TYPE>C2B</TYPE>
<CUSTOMERMSISDN>254784893664</CUSTOMERMSISDN>
<MERCHANTMSISDN>000005467</MERCHANTMSISDN>
<AMOUNT>100</AMOUNT>
<REFERENCE>QT-5C84C515</REFERENCE>
<REFERENCE1>ATQ_TEST_002</REFERENCE1>
</COMMAND>
| Field | Description |
TYPE | Always C2B |
CUSTOMERMSISDN | Subscriber's phone number (254...) |
MERCHANTMSISDN | Merchant short code |
AMOUNT | Transaction amount (KES) |
REFERENCE | Account reference (Booking/Quote ID) |
REFERENCE1 | Airtel's transaction ID |
Response — Success
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>C2B</TYPE>
<TXNID>DL-M5K3QR7X2F</TXNID>
<TXNSTATUS>200</TXNSTATUS>
<MESSAGE>Transaction Processed Successfully</MESSAGE>
<REFERENCE1>ATQ_TEST_002</REFERENCE1>
</COMMAND>
| Response Field | Description |
TXNID | DhamaniLink's partner transaction ID (unique per transaction) |
TXNSTATUS | 200 = Success |
MESSAGE | Human-readable status |
REFERENCE1 | Airtel's original transaction ID (echoed back for correlation) |
Response — Duplicate (Idempotent)
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>C2B</TYPE>
<TXNID>DL-M5K3QR7X2F</TXNID>
<TXNSTATUS>200</TXNSTATUS>
<MESSAGE>Transaction Already Processed</MESSAGE>
<REFERENCE1>ATQ_TEST_002</REFERENCE1>
</COMMAND>
Response — Failure (Invalid Reference)
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>C2B</TYPE>
<TXNID>DL-M5K3QRABCD</TXNID>
<TXNSTATUS>400</TXNSTATUS>
<MESSAGE>Invalid Account Reference</MESSAGE>
<REFERENCE1>ATQ_TEST_003</REFERENCE1>
</COMMAND>
Response — Failure (Amount Validation)
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>C2B</TYPE>
<TXNID>DL-M5K3QRWXYZ</TXNID>
<TXNSTATUS>400</TXNSTATUS>
<MESSAGE>Amount must be greater than zero</MESSAGE>
<REFERENCE1>ATQ_TEST_004</REFERENCE1>
</COMMAND>
5. Transaction Enquiry
POST https://www.dhamanilink.com/api/airtel/enquiry
Called by Airtel to check the status of a previous transaction (e.g. after a timeout during Process).
Request
<COMMAND>
<TYPE>LOOKUP</TYPE>
<REFERENCE1>ATQ_TEST_002</REFERENCE1>
</COMMAND>
| Field | Description |
TYPE | Always LOOKUP |
REFERENCE1 | Airtel's transaction ID to look up |
Response — Found
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>LOOKUP</TYPE>
<TXNID>ATQ_TEST_002</TXNID>
<TXNSTATUS>200</TXNSTATUS>
<MESSAGE>Success</MESSAGE>
<AMOUNT>100</AMOUNT>
</COMMAND>
Response — Not Found
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>LOOKUP</TYPE>
<TXNID>ATQ_TEST_999</TXNID>
<TXNSTATUS>404</TXNSTATUS>
<MESSAGE>Transaction Not Found</MESSAGE>
</COMMAND>
6. Bill Fetch
POST https://www.dhamanilink.com/api/airtel/billfetch
Called by Airtel to retrieve outstanding bill details for a given account reference.
Request
<COMMAND>
<TYPE>BILLFETCH</TYPE>
<REFERENCE>QT-5C84C515</REFERENCE>
</COMMAND>
Response — Bill Found
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>BILLFETCH</TYPE>
<TXNSTATUS>200</TXNSTATUS>
<MESSAGE>Bill Found</MESSAGE>
<FIRSTNAME>John</FIRSTNAME>
<LASTNAME>Doe</LASTNAME>
<AMOUNT>5000</AMOUNT>
<DUEDATE>2026-04-15</DUEDATE>
<CURRENCY>KES</CURRENCY>
<STATUS>0</STATUS>
</COMMAND>
| Field | Description |
STATUS | 0 = Unpaid, 1 = Paid |
AMOUNT | Outstanding amount in KES |
DUEDATE | Payment due date (YYYY-MM-DD) |
Response — Not Found
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
<TYPE>BILLFETCH</TYPE>
<TXNSTATUS>404</TXNSTATUS>
<MESSAGE>Bill Not Found</MESSAGE>
</COMMAND>
7. Status Codes Summary
| TXNSTATUS | Meaning |
200 | Success |
400 | Bad Request / Validation Failed |
401 | Authentication Failed (Invalid JWT) |
404 | Not Found |
500 | Internal Server Error |
8. Supported Account Reference Formats
| Format | Example | Description |
QT-XXXXXXXX | QT-5C84C515 | Quote reference |
BK-XXXXXXXX | BK-A1B2C3D4 | Booking reference |
DL-XXXXXX | DL-F9E8D7 | Booking shortcode |
| UUID | a1b2c3d4-... | Direct booking/quote UUID |
9. Environment Configuration
| Parameter | UAT | Production |
| Base URL | https://www.dhamanilink.com | https://www.dhamanilink.com |
| JWT Secret | Shared separately | Shared separately |
| Credentials | UAT credentials | Production credentials |
| Environment Isolation | ✅ Fully separated via configuration | ✅ Strict validation enforced |
Note: While the endpoint URLs are the same for both environments, the backend is fully logically separated. UAT and Production use different Airtel credentials, JWT secrets, and processing logic to ensure zero crossover between test and live transactions.