Verify any Ethiopian payment with one POST
No API key. No signup. The cheki API is free and open source. Just POST to /api/verify. Requests are rate limited per IP: verify 30 per minute, batch 5 per minute, parse and ocr 20 per minute each, counted per server instance. Over the limit you get a 429 with a Retry-After header.
curl -X POST https://cheki.et/api/verify \
-H "Content-Type: application/json" \
-d '{
"bank": "cbe",
"reference": "https://mbreciept.cbe.com.et/fHCxExampleRcpt01"
}'
# Older CBE receipt with only an FT reference (legacy format):
# -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",
"durationMs": 1240,
"sourceUrl": "https://mbreciept.cbe.com.et/fHCxExampleRcpt01"
}API endpoints
/api/verify
Verify a single receipt. Send the bank code and the receipt link or reference in its current format. BOA, and older CBE FT-only receipts, also need the account number.
/api/verify/batch
Verify up to 20 receipts at once. Send an array of receipt objects.
/api/banks
List all supported banks and their verification status.
/api/health
Check API health and per-bank endpoint latency.
/api/receipt
Download the bank's receipt file. CBE (with account), Zemen and Dashen only.
SDKs and libraries
npm install cheki-verify
import { Cheki, isVerified } from "cheki-verify";
const cheki = new Cheki();
const result = await cheki.verify("cbe", "https://mbreciept.cbe.com.et/fHCxExampleRcpt01");
isVerified(result); // true only when the bank confirmed itSelf-hosting with Docker
git clone https://github.com/1RB/cheki.git
cd cheki
docker-compose up -d
# API available at http://localhost:3000/api/verify
# Self-hosting on an Ethiopian IP bypasses Telebirr/M-Pesa geo-blocksClean architecture
cheki v1.0 uses hexagonal architecture (ports & adapters). The core domain has zero runtime dependencies. Bank parsers are pluggable plugins. Configuration lives in a single JSON manifest.