Welcome to the definitive open-source verification engine for Ethiopian fintech. This project provides a fully automated way to validate receipts and transactions from various payment providers, complete with an AI-powered OCR fallback.
This API allows businesses and developers to programmatically verify the authenticity of customer payments. Instead of manually checking bank portals or USSD messages to see if a customer actually paid, your application can send the receipt's "Reference Number" (or an image of the receipt) to this API. The API will instantly verify the transaction with the respective bank and return a JSON response confirming if the payment is real, preventing fraud and automating checkout flows.
- Extensive Provider Support: Integrates CBE and Telebirr.
- AI Image Verification: Upload screenshots of receipts; powered by Mistral AI, the system extracts data and automatically cross-verifies it with the provider (includes built-in QR code extraction for CBE).
- Usage Analytics: Every API request is logged to Supabase, providing analytics on success rates, endpoints, and durations.
- Serverless Ready: Out-of-the-box support for Vercel deployment.
| Provider | Reference Format | Example | Implementation |
|---|---|---|---|
| CBE | v2- prefix followed by alphanumeric |
v2-hfHCxz6TmMYrTUfWldzb |
Direct JSON API (Mbreceipt) |
| Telebirr | 10 Alphanumeric chars | AG3HF92K10 |
Web Scraping (Proxy support) |
- 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.
Clone the repository and install dependencies:
git clone https://github.com/robiabebe/verpay.git
cd verpay
npm installConfigure your environment variables:
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 (Uncomment if needed)
PORT=3001Start the development server:
npm run devAll verification endpoints require an API Key passed in the x-api-key header.
Use your ADMIN_KEY to generate secure access keys for your applications.
Endpoint: POST /admin/api-keys
Headers: x-admin-key: <your-secure-admin-password>
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 (201):
{
"message": "API Key generated successfully. Save this key, it will not be shown again.",
"apiKey": "verpay_live_a1b2c3d4e5f6...",
"owner": "My Production App"
}Retrieve a list of generated API keys to monitor usage and activity.
Endpoint: GET /admin/api-keys
Headers: x-admin-key: <your-secure-admin-password>
curl -X GET http://localhost:3001/admin/api-keys \
-H "x-admin-key: your-secure-admin-password"Response (200):
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"owner": "My Production App",
"is_active": true,
"created_at": "2026-06-04T08:00:00Z",
"last_used_at": "2026-06-04T12:00:00Z",
"usage_count": 42
}
]Verify a CBE receipt by its reference number.
Endpoint: POST /verify-cbe
Headers: x-api-key: <your-generated-api-key>
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"}'Response (200 on success, 400 on failure):
{
"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"
}
}Verify a Telebirr receipt by its 10-character reference.
Endpoint: POST /verify-telebirr
Headers: x-api-key: <your-generated-api-key>
curl -X POST http://localhost:3001/verify-telebirr \
-H "x-api-key: verpay_live_YOUR_GENERATED_KEY" \
-H "Content-Type: application/json" \
-d '{"reference": "AG3HF92K10"}'Response (200 on success, 400 on failure):
{
"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"
}
}Have a screenshot instead of text? Send the base64 image! The system automatically detects QR codes for precision, uses Mistral AI for OCR, and instantly validates the findings directly with the bank.
Endpoint: POST /verify-image
Headers: x-api-key: <your-generated-api-key>
curl -X POST http://localhost:3001/verify-image \
-H "x-api-key: verpay_live_YOUR_GENERATED_KEY" \
-H "Content-Type: application/json" \
-d '{
"image": "base64_encoded_string_here..."
}'Response (200 on success, 400 on failure):
{
"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. If verification fails, the response includes ocrData with what was extracted from the image so you can debug.
This project is configured out-of-the-box for serverless deployment on Vercel.
- Install the Vercel CLI:
npm i -g vercel - Run
verceland link your project. - Add your environment variables:
vercel env add SUPABASE_URL vercel env add SUPABASE_SERVICE_ROLE_KEY vercel env add ADMIN_KEY vercel env add MISTRAL_API_KEY
- Deploy to production:
vercel --prod
We welcome contributions! If you have integrated a new Ethiopian bank, fixed a bug, or improved the AI OCR logic, please follow these steps:
- Read the Architecture Guide: Check out
ARCHITECTURE.mdto understand how the codebase is structured. - Fork the repository.
- Create a new branch (
git checkout -b feature/amazing-feature). - Commit your changes (
git commit -m 'Add some amazing feature'). - Push to the branch (
git push origin feature/amazing-feature). - Open a Pull Request.
Please ensure your code follows the existing TypeScript conventions and passes the compiler checks (npm run build).
- Telebirr Proxy Errors (
ENOTFOUND): Telebirr often blocks non-Ethiopian IPs. If you are developing locally, you might need to comment outTELEBIRR_PROXY_URLin.env. If you deploy outside Ethiopia, you will need a working residential Ethiopian proxy. - Mistral API Errors: Ensure your account is active and you are passing a clean Base64 string (without the
data:image/jpeg;base64,prefix) if calling the API directly.
This project is licensed under the MIT License - see the LICENSE file for details.