API Documentation
Free REST API. No auth. No rate limit. No scam.
Overview
The cheki API verifies Ethiopian bank and mobile money receipts by fetching public bank endpoints. No authentication is required. No API key. No rate limit. Just POST to /api/verify with a bank code and reference number.
Base URL
https://chekiapp.vercel.appQuick Start
Verify a CBE receipt with one cURL call:
curl -X POST https://chekiapp.vercel.app/api/verify \
-H "Content-Type: application/json" \
-d '{"bank":"cbe","reference":"FT26140P01YB","accountNumber":"1000560536171"}'Response
{
"success": true,
"verified": true,
"bank": "Commercial Bank of Ethiopia",
"reference": "FT26140P01YB",
"amount": 20000,
"currency": "ETB",
"senderName": "Mr Mohammed Abdulwasi Reshid",
"receiverName": "SAMI ADIL ZEKARIA",
"date": "5/20/2026 7:29:00 PM",
"sourceUrl": "https://apps.cbe.com.et:100/?id=FT26140P01YB60536171"
}POST /api/verify
/api/verifyVerify a single receipt. Send bank code, reference, and (for CBE/BOA) account number. For BOA inter-bank transfers, send the QR payload in qrData instead.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| bank | string | Yes (unless URL) | Bank code: cbe, telebirr, boa, mpesa, dashen, zemen, cbebirr, siinqee |
| reference | string | Yes | Transaction reference number (e.g. FT26140P01YB) or receipt URL |
| accountNumber | string | CBE, BOA | Last 8 digits for CBE, last 5 for BOA |
| qrData | string | BOA QR | Raw QR payload for BOA inter-bank transfers |
| phone | string | CBE Birr | Payer phone number, format: 2519XXXXXXXXX |
Request body (CBE)
{
"bank": "cbe",
"reference": "FT26140P01YB",
"accountNumber": "1000560536171"
}Request body (BOA QR code)
{
"bank": "boa",
"qrData": "3cHRaxVjn/pySp..."
}Response (200)
{
"success": true,
"verified": true,
"bank": "Commercial Bank of Ethiopia",
"reference": "FT26140P01YB",
"senderName": "Mr Mohammed Abdulwasi Reshid",
"senderAccount": "1****1685",
"receiverName": "SAMI ADIL ZEKARIA",
"receiverAccount": "1****6171",
"amount": 20000,
"currency": "ETB",
"date": "5/20/2026 7:29:00 PM",
"branch": "MEKANISA MICHAEL BRANC",
"durationMs": 7782,
"sourceUrl": "https://apps.cbe.com.et:100/?id=FT26140P01YB60536171"
}Response fields
| Parameter | Type | Required | Description |
|---|---|---|---|
| success | boolean | Whether the request succeeded (not whether the receipt is real) | |
| verified | boolean | Whether the receipt was found and matches the bank's records | |
| bank | string | Full bank name | |
| reference | string | Transaction reference number | |
| senderName | string | Name of the account that sent the payment | |
| senderAccount | string | Masked sender account number | |
| receiverName | string | Name of the account that received the payment | |
| receiverAccount | string | Masked receiver account number | |
| amount | number | Transfer amount in ETB | |
| currency | string | Currency code (always ETB for domestic) | |
| date | string | Transaction date and time | |
| sourceUrl | string | The bank endpoint URL cheki fetched the data from | |
| durationMs | number | Time spent fetching from the bank endpoint, in milliseconds |
POST /api/verify/batch
/api/verify/batchVerify up to 50 receipts in parallel. Send an array of receipt objects with the same fields as the single verify endpoint.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| receipts | array | Yes | Array of receipt objects (same fields as verify). Max 50. |
{
"receipts": [
{
"bank": "cbe",
"reference": "FT26140P01YB",
"accountNumber": "1000560536171"
},
{
"bank": "telebirr",
"reference": "DET8FJGUJ4"
}
]
}GET /api/banks
/api/banksList all supported banks with metadata: code, name, type, status, endpoint, and verification requirements.
Response (200)
[
{
"code": "cbe",
"name": "Commercial Bank of Ethiopia",
"type": "bank",
"status": "live",
"requiresAccount": true,
"accountDigits": 8
},
{
"code": "telebirr",
"name": "Telebirr",
"type": "wallet",
"status": "live",
"requiresAccount": false
}
]GET /api/health
/api/healthCheck if each bank endpoint is reachable. Reports status and latency per bank. Useful for monitoring and debugging.
Response (200)
{
"status": "ok",
"banks": {
"cbe": {
"status": "up",
"latencyMs": 340
},
"telebirr": {
"status": "geo-blocked",
"latencyMs": null
},
"boa": {
"status": "up",
"latencyMs": 180
}
}
}GET /api/receipt
/api/receipt?bank=cbe&reference=FT...&account=...Download the original receipt file (PDF or HTML) from the bank endpoint. Returns the raw file with the appropriate Content-Type header.
SDKs
SDKs are available in 5 languages. All wrap the same REST API with typed errors, retry with exponential backoff, and timeout support.
npm install cheki-verify
import { Cheki } from "cheki-verify";
const cheki = new Cheki();
const result = await cheki.verify("cbe", "FT26140P01YB", {
accountNumber: "1000560536171"
});
console.log(result.verified); // true
console.log(result.senderName);
console.log(result.amount);
const batch = await cheki.verifyBatch([
{ bank: "cbe", reference: "FT26140P01YB", accountNumber: "1000560536171" },
{ bank: "telebirr", reference: "DET8FJGUJ4" }
]);
const { banks } = await cheki.getBanks();
const health = await cheki.getHealth();Error Codes
{
"success": false,
"error": "Receipt not found. Check the reference number.",
"bank": "Commercial Bank of Ethiopia",
"reference": "INVALID123"
}| Status | Name | Description |
|---|---|---|
| 400 | Bad Request | Missing required fields or malformed reference number |
| 404 | Not Found | Bank code not recognized or receipt not found at the bank endpoint |
| 422 | Unprocessable | Bank endpoint returned data but it could not be parsed |
| 502 | Bad Gateway | Bank endpoint is unreachable, geo-blocked, or timed out |
| 500 | Server Error | Internal server error. Check /api/health for endpoint status. |
Self-hosting with Docker
git clone https://github.com/1RB/cheki.git
cd cheki
docker-compose up -d
# API at http://localhost:3000/api/verify
# Self-hosting on an Ethiopian IP bypasses geo-blocks