API Documentation
Integrate VerPay into your application to verify Ethiopian payments.
Introduction
VerPay is an open-source verification engine for Ethiopian fintech. It lets businesses and developers programmatically verify customer payments by sending a receipt reference number (or an image of the receipt) to the API. The engine checks the transaction directly with the bank and returns a JSON response confirming whether the payment is real or fake.
Getting Started
1. Database Setup (Supabase)
- Create a new project at Supabase.
- Navigate to the SQL Editor in your Supabase dashboard.
- Copy the contents of
supabase/migrations/001_init.sqland run it. This creates theapi_keysandusage_logstables, plus theincrement_api_key_usageRPC function. - Go to Project Settings > API to find your URL and Service Role Key.
2. Local Setup
git clone https://github.com/robiabebe/verpay.git
cd verpay
npm install
cp .env.example .envEdit the .env file with your actual keys:
SUPABASE_URL=https://your-project-id.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
ADMIN_KEY=your-secure-admin-password
MISTRAL_API_KEY=your-mistral-ai-key
# TELEBIRR_PROXY_URL=http://your-ethiopian-proxy.com:8080
PORT=30013. Generate an API Key
All verification endpoints require an API key passed in the x-api-key header. Generate one using your admin key:
curl -X POST http://localhost:3001/admin/api-keys \
-H "x-admin-key: your-secure-admin-password" \
-H "Content-Type: application/json" \
-d '{"owner": "My Production App"}'Response:
{
"message": "API Key generated successfully. Save this key, it will not be shown again.",
"apiKey": "verpay_live_a1b2c3d4e5f6...",
"owner": "My Production App"
}Authentication
All verification endpoints (/verify-cbe, /verify-telebirr, /verify-image) require an API key passed via the x-api-key HTTP header. Admin endpoints require the x-admin-key header.
curl -X POST http://localhost:3001/verify-cbe \
-H "x-api-key: verpay_live_YOUR_GENERATED_KEY" \
-H "Content-Type: application/json" \
-d '{"reference": "v2-hfHCxz6TmMYrTUfWldzb"}'CBE Verification
Verify a Commercial Bank of Ethiopia receipt by its reference number. Uses the modern CBE JSON API (Mbreceipt) for fast, direct lookups.
/verify-cbev2- followed by an alphanumeric string (e.g., v2-hfHCxz6TmMYrTUfWldzb).{
"reference": "v2-hfHCxz6TmMYrTUfWldzb"
}Success Response 200
{
"success": true,
"provider": "cbe",
"data": {
"payerName": "John Doe",
"payerAccount": "1000123456789",
"receiverName": "Jane Smith",
"receiverAccount": "9876543210",
"amount": "ETB 1500",
"date": "6/4/2026, 11:46:00 AM",
"reference": "v2-hfHCxz6TmMYrTUfWldzb",
"description": "CBE Mobile Transfer"
}
}Error Response 400
{
"success": false,
"provider": "cbe",
"error": "Transaction not found or invalid reference"
}Telebirr Verification
Verify an Ethio Telecom Telebirr receipt. This endpoint scrapes the official Telebirr receipt page and extracts all transaction details. Requires an Ethiopian IP or proxy for deployments outside Ethiopia.
/verify-telebirrAG3HF92K10).{
"reference": "AG3HF92K10"
}Success Response 200
{
"success": true,
"provider": "telebirr",
"data": {
"payerName": "John Doe",
"payerNumber": "+251911234567",
"receiverName": "Jane Smith",
"receiverAccount": "1234567890",
"bankName": "CBE",
"status": "SUCCESS",
"receiptNumber": "AG3HF92K10",
"date": "2026-06-04",
"amount": "1500",
"serviceFee": "15",
"vat": "2.25",
"total": "1517.25"
}
}Error Response 400
{
"success": false,
"provider": "telebirr",
"error": "Receipt not found or invalid format"
}AI Image Verification
Upload a screenshot of a receipt instead of typing a reference number. The system first attempts to extract a QR code for 100% accuracy (CBE receipts), then falls back to Mistral AI OCR. Extracted data is automatically cross-verified with the bank API.
/verify-image{
"image": "base64_encoded_string_here..."
}data:image/jpeg;base64, prefix). The API handles both formats.Success Response 200
{
"success": true,
"provider": "cbe",
"data": {
"provider": "cbe",
"reference": "v2-hfHCxz6TmMYrTUfWldzb",
"amount": "1500",
"date": "2026-06-04",
"payerName": "John Doe",
"receiverName": "Jane Smith",
"payerAccount": "1000123456789",
"receiverAccount": "9876543210",
"description": "CBE Mobile Transfer",
"isAutoVerified": true
}
}The isAutoVerified: true field confirms the OCR-extracted data was cross-checked with the real bank API and matched. If verification fails, the response includes ocrData with what was extracted from the image so you can debug.
Error Response 400
{
"success": false,
"provider": "cbe",
"error": "Official verification failed: Transaction not found",
"ocrData": {
"provider": "cbe",
"reference": "v2-hfHCxz6TmMYrTUfWldzb",
"amount": "1500",
"payerName": "John Doe",
"receiverName": "Jane Smith"
}
}Admin Endpoints
Use the admin endpoints to generate and manage API keys. Pass your ADMIN_KEY via the x-admin-key header.
Generate a new API key. The raw key is returned only once.
curl -X POST http://localhost:3001/admin/api-keys \
-H "x-admin-key: your-secure-admin-password" \
-H "Content-Type: application/json" \
-d '{"owner": "My Production App"}'List all API keys with usage stats.
curl -X GET http://localhost:3001/admin/api-keys \
-H "x-admin-key: your-secure-admin-password"Vercel Deployment
This project is configured for serverless deployment on Vercel out of the box.
- Install the Vercel CLI:
npm i -g vercel - Run
verceland link your project. - Add your environment variables using
vercel env add. - Deploy to production:
vercel --prod
Troubleshooting
1 Telebirr Proxy Errors
Telebirr blocks non-Ethiopian IPs. If developing locally, comment out
TELEBIRR_PROXY_URLin.env. If deploying outside Ethiopia, you will need a working residential Ethiopian proxy.2 Mistral API Errors
Ensure your Mistral account is active and the
MISTRAL_API_KEYis set. Pass a clean Base64 string (without thedata:image/jpeg;base64,prefix) if calling the API directly.