Bank receipt endpoints

The public receipt URL each bank serves, what goes into it and what comes back. Generated from the same manifest the verifier uses, so it changes when the code changes.

Only live banks are verified; in-development banks are documented here but cheki does not check their receipts yet. Daily endpoint health is on the status page (GET /api/health gives a reachability snapshot, cached for 5 minutes).

Calling cheki instead of the banks? See the API docs. Requests are rate limited per IP (verify 30 per minute, batch 5 per minute with up to 20 receipts each); over the limit you get a 429 with a Retry-After header.

CBE

Commercial Bank of EthiopiaWorking

Current format

Receipt ID or mbreciept.cbe.com.et link. Shared from the CBE app as a link or QR code. Tokens look like fHCx... (v1) or v2-... (v2). No account number is needed. The API needs the CBE web app's X-App-ID/X-App-Version headers.

https://mbreciept.cbe.com.et/{RECEIPT_ID}

cheki reads it from https://mb.cbe.com.et/api/v1/transactions/public/transaction-detail/{ref}.

Redacted example: https://mbreciept.cbe.com.et/fHCxXXXXXXXXXXXXXX

Placeholders

{RECEIPT_ID}

The CBE Receipt ID: the last part of the receipt link the CBE app shares.

Where to find it
Share the receipt from the CBE app, or scan its QR code. The link is mbreciept.cbe.com.et/{Receipt ID}. cheki reads it through CBE's JSON API at mb.cbe.com.et.
Length and pattern
Opaque token, letters and digits: fHCx... on v1 receipts, v2-... on newer ones. Length varies (about 18 to 24 characters).
Traps
It is not the FT reference. An FT reference sent to this API answers "Invalid or tampered legacy token".

Gotchas

  • The JSON API needs the CBE web app's X-App-ID and X-App-Version headers (and cheki also sends its Origin and Referer). Without them it answers HTTP 400 "Missing Headers".
  • Account numbers come back masked (1****1234).
  • A Receipt ID can't be derived from an FT reference, so an older receipt with only an FT reference needs the legacy format below.
Response and fieldsJSON · 9 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
reasonPayment reason or narrative
Unknown-reference error shape

HTTP 500 application/problem+json, detail "Security Alert: Invalid or tampered legacy token!".

Last seen: 500 application/problem+json "Security Alert: Invalid or tampered legacy token!"

Older receipts1 format

Most receipts use the current format above.

FT reference + last 8 digits of the receiving accountStill checked · inferred

https://apps.cbe.com.et:100/?id={ref}{account}

Needs: FT reference + Receiving account (last 8 digits). Response: PDF. Replaced by the current format. cheki still checks it. Older receipts and SMS that only show an FT reference. Also reached from dashed mbreciept links (mbreciept.cbe.com.et/FT...-12345678), which carry the FT reference and the 8-digit suffix (link shape inferred from links.et).

Evidence: Status inferred: links.et reports apps.cbe.com.et unreachable since July 2026; cheki's egress could not connect on 2026-10-11 (CONNECT 502), while a repo probe on 2026-10-10 got the 404 'You Are Not Allowed to See This Data' page. Not proven shut down, so cheki still tries it.

Last check: Endpoint answers in the expected shape. ()

{REFERENCE}

The CBE FT transaction reference.

Where to find it
On older receipts as "Reference No. (VAT Invoice No)", and in the CBE SMS.
Length and pattern
12 characters: "FT" plus 10 letters and digits, e.g. FT26140P01YB.
Traps
None known
{LAST_8_DIGITS_OF_ACCOUNT}

The last 8 digits of the receiving (credit) account.

Where to find it
The receiver's account number on the receipt, or your own account if you received the money.
Length and pattern
8 digits, appended directly after the reference with no separator.
Traps
The payer's account does not work. Only the receiving account matches.

Redacted example: https://apps.cbe.com.et:100/?id=FT26140P01YBXXXXXXXX

Unknown reference: HTTP 404 text/html, "You Are Not Allowed to See This Data, Please Check your Link" (seen 2026-10-10; the host is often unreachable).

Changelog4 changes
  1. cheki leads with the Receipt ID; FT reference + account is kept as a legacy format. cheki's egress could not connect to apps.cbe.com.et:100.
  2. Repo probe: apps.cbe.com.et:100 answered an unknown id with HTTP 404 'You Are Not Allowed to See This Data'.
  3. 2026-07links.et reports the apps.cbe.com.et:100 PDF host unreachable since July 2026 and resolves CBE receipts through the JSON host.
  4. cheki added CBE share-link receipts (mbreciept.cbe.com.et, read through the mb.cbe.com.et JSON API).

Telebirr

TelebirrGeo-restricted

Template URL

https://transactioninfo.ethiotelecom.et/receipt/{REFERENCE}

Redacted example: https://transactioninfo.ethiotelecom.et/receipt/DETXXXXXXX

Placeholders

{REFERENCE}

The Telebirr transaction number.

Where to find it
In the Telebirr SMS sent to payer and receiver, and on the in-app receipt. The receipt's Payment QR Code holds it too: scan or upload the QR and cheki reads the number out of it.
Length and pattern
10 characters: a 2 or 3 letter prefix (DET, CHQ, DAB, DJA, DEL, ADQ, ...) plus letters and digits, e.g. DET8FJGUJ4.
Traps
None known

Gotchas

  • Geo-restricted: only Ethiopian IP addresses get an answer. CI runners abroad mark it as not checked.
  • Geo-blocked: requests from outside Ethiopia time out or are refused. cheki shows the official link as a fallback.
  • The receipt's Payment QR Code is base64 of a hex string holding TLV data: tag 81 contains tag 00, the transaction number in ASCII; tag 63 is a CRC-16/CCITT-FALSE over the characters before it, case-sensitive. It holds nothing else cheki uses (no amount, no names), so cheki only takes the transaction number from it and checks that like a typed one. A QR is never proof of payment. Decoder: src/lib/qr/telebirr.ts, write-up: docs/telebirr-qr.md.
Response and fieldsHTML · 22 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
invoiceNumberInvoice number
transactionStatusStatus as the bank reports it
settledAmountBank-specific field
stampDutyBank-specific field
discountAmountBank-specific field
serviceFeeService fee
serviceFeeVatVAT on the service fee
totalPaidTotal paid, fees included
amountInWordsBank-specific field
paymentModePayment mode
paymentChannelChannel (app, USSD, agent)
reasonPayment reason or narrative
bankAccountNumberBank-specific field
bankAccountNameBank-specific field
Unknown-reference error shape

Not checked from CI. The endpoint only answers Ethiopian IP addresses.

Changelog1 change
  1. cheki reads the Payment QR Code on Telebirr receipts (base64 → hex → TLV, tag 81/00 = transaction number, CRC-16/CCITT-FALSE checked) and checks the number like a typed reference. Before this the QR was not recognised. DJA added to the known transaction-number prefixes.

BOA

Bank of AbyssiniaWorking

Template URL

https://cs.bankofabyssinia.com/api/onlineSlip/getDetails/?id={REFERENCE}{LAST_5_DIGITS}

Redacted example: https://cs.bankofabyssinia.com/api/onlineSlip/getDetails/?id=FT252003JZPPXXXXX

Placeholders

{REFERENCE}

The Bank of Abyssinia transaction reference.

Where to find it
On the BOA receipt or slip link (cs.bankofabyssinia.com/slip/?trx=...). Inter-bank transfers use an FT reference.
Length and pattern
Letters and digits, starting with 2 letters, e.g. FT252003JZPP.
Traps
None known
{LAST_5_DIGITS}

The last 5 digits of the receiving account.

Where to find it
The receiver's account number on the receipt.
Length and pattern
5 digits, appended directly after the reference.
Traps
None known

Gotchas

  • A miss still returns HTTP 200, so the parser must read the body.
Response and fieldsJSON · 8 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
Unknown-reference error shape

HTTP 200 application/json with body[0]["Payer's Name"] = "Invalid reference number".

Last seen: 200 application/json "[{"Payer's Name":"Invalid reference number"}]"

ChangelogNone yet

No changes recorded.

M-Pesa

M-Pesa EthiopiaBetaGeo-restricted

Beta. M-Pesa's receipt format is taken from other open-source verifiers. cheki has not yet verified a real M-Pesa receipt, so treat a result as provisional until one confirms the parser.

Template URL

https://m-pesabusiness.safaricom.et/api/receipt/getReceipt?trxNo={REFERENCE}

Redacted example: https://m-pesabusiness.safaricom.et/api/receipt/getReceipt?trxNo=UXXXXXXXXX

Placeholders

{REFERENCE}Unconfirmed

The M-Pesa Ethiopia transaction ID (trxNo), printed on the receipt as TRANSACTION ID.

Where to find it
In the M-Pesa SMS confirmation and on the receipt.
Length and pattern
Letters and digits, usually 10 characters (Safaricom style, e.g. UAB1CD2EF3).
Traps
None known

Gotchas

  • Geo-restricted: only Ethiopian IP addresses get an answer. CI runners abroad mark it as not checked.
  • Geo-blocked: requests from outside Ethiopia time out or are refused.
  • The answer is JSON, but the receipt itself is a PDF in base64Data. cheki checks the base64, caps the decoded PDF at 5 MB, and reads the PDF text (TRANSACTION ID, SENDER or PAYER NAME, RECEIPT NO / PAYMENT DATE / SETTLED AMOUNT, TOTAL, ...).
  • Beta: the envelope and the PDF labels come from other open-source verifiers' source code. cheki's tests use a synthetic receipt; no real receipt has been checked yet.
  • Other verifiers send a Referer of https://m-pesabusiness.safaricom.et/; one notes the endpoint requires it. cheki sends it too.
Response and fieldsJSON envelope with the receipt as a base64 PDF (inferred, beta) · 13 fields
FieldMeaning
referenceThe bank's own reference
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
settledAmountBank-specific field
serviceFeeService fee
serviceFeeVatVAT on the service fee
totalPaidTotal paid, fees included
dateTransaction time as the bank prints it
transactionTypeBank-specific field
paymentChannelChannel (app, USSD, agent)
Unknown-reference error shape

Not checked from CI (geo-blocked). Other verifiers treat any responseCode other than "0", or a missing base64Data, as no receipt; the exact error code and wording are not known.

Changelog3 changes
  1. cheki reads the envelope and its PDF instead of flat JSON fields (which no source shows the endpoint returning). M-Pesa labelled beta until a real receipt verifies.
  2. Parser reads the base64 PDF envelope instead of flat JSON fields. Labelled beta until a real receipt verifies.
  3. Vixen878/verifier-api adds M-Pesa: getReceipt returns {responseCode, base64Data}; the PDF is parsed for PAYER NAME, TRANSACTION ID, TOTAL and more.

Dashen

Dashen BankWorking

Current format

FT Ref. The FT Ref is 16 letters and digits. The app's longer Transaction Ref / Transfer Reference (WDTI..., OBTI...) is rejected.

https://receipts.dashenbanksc.com/receipt/{REFERENCE}

Redacted example: https://receipts.dashenbanksc.com/receipt/B22WDTIXXXXXXXXX

Placeholders

{REFERENCE}

The Dashen FT Ref.

Where to find it
In the Dashen app it is labelled "FT Ref". On the web receipt it is labelled "Transaction Reference".
Length and pattern
16 characters, letters and digits, e.g. B22WDTI2619100WH.
Traps
The app also shows a longer "Transaction Ref" or "Transfer Reference" (WDTI... or OBTI...). The endpoint rejects it. Use the FT Ref.

Gotchas

  • The old host receipt.dashensuperapp.com now returns 502 Bad Gateway. Old PDF links on api.dashensuperapp.com are still detected and routed to the new host.
  • The live endpoint returns an HTML receipt, not a PDF. GET /api/receipt redirects to it rather than serving the bank's HTML from cheki.
Response and fieldsHTML · 9 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
reasonPayment reason or narrative
Unknown-reference error shape

HTTP 400 application/json, {"statusCode":400,"message":"Transaction not found"}.

Last seen: 400 application/json "Transaction not found"

Older receipts1 format

Most receipts use the current format above.

Dashen Super App receipt linkRetired

https://receipt.dashensuperapp.com/receipt/{ref}

Needs: Old receipt link. Response: PDF. Retired 2026-10-10. Replaced by the current format. cheki never fetches it; links are read for their reference only. Never fetched. Old links (receipt.dashensuperapp.com/receipt/{ref}, api.dashensuperapp.com/receipts/Within-Dashen-Transfer-{ref}.pdf) are still recognised: cheki reads the FT Ref from them and checks it on receipts.dashenbanksc.com.

Evidence: receipt.dashensuperapp.com answered 502 Bad Gateway (cheki, 2026-10-10).

Changelog2 changes
  1. /api/receipt redirects to Dashen's own receipt page instead of proxying its HTML.
  2. Moved from receipt.dashensuperapp.com (PDF, now 502) to receipts.dashenbanksc.com (HTML). The FT Ref is the only accepted reference.

Awash

Awash BankWorking

Template URL

https://awashpay.awashbank.com:8225/-{BASE36_TRANSACTION_ID}-{COUNTER_TOKEN}

Redacted example: https://awashpay.awashbank.com:8225/-2KDLXXXXXX-4UXXXX

Placeholders

{BASE36_TRANSACTION_ID}

The Awash Transaction ID written in base 36.

Where to find it
The first segment after the dash in the share link from the Awash SMS.
Length and pattern
About 10 characters, digits and capital letters. The decoded ID is 15 digits (YYMMDDHHMM plus a 5 digit sequence).
Traps
None known
{COUNTER_TOKEN}

A server counter issued when the receipt is shared.

Where to find it
The second segment of the share link.
Length and pattern
About 6 characters, base 36.
Traps
It cannot be derived from the Transaction ID, so a bare Transaction ID is not enough. Paste the full link.

Gotchas

  • Port 8225 with a certificate that does not verify.
  • Sits behind an F5 BIG-IP WAF; aggressive retries can get blocked.
Response and fieldsHTML · 11 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
branchBranch
reasonPayment reason or narrative
transactionTypeBank-specific field
Unknown-reference error shape

HTTP 200 text/html, a short page reading "Receipt not found".

Last seen: 200 text/html "Receipt not found"

ChangelogNone yet

No changes recorded.

Zemen

Zemen BankNot supported yet

In development, help us. A real receipt link is what we need to finish this one. Send one privately.

Template URL

https://share.zemenbank.com/rt/{REFERENCE}/pdf

Redacted example: https://share.zemenbank.com/rt/XXXXXXXXXXXXXXXXXXXXXXXX/pdf

Placeholders

{REFERENCE}Unconfirmed

The token in a Zemen share link, share.zemenbank.com/rt/{token}/pdf.

Where to find it
Use the share button on the Zemen receipt and paste the whole link. cheki reads the token from the path.
Length and pattern
Unconfirmed. links.et docs describe a 24 character token (an 8 character prefix plus the 16 character reference). Another open-source app builds the URL from the bare reference. Neither is proven.
Traps
A bare reference may not work. Paste the full share link until a real receipt settles the format.

Gotchas

  • The parser labels come from the expected PDF layout and are not tested on a real receipt yet.
Response and fieldsPDF (expected) · 10 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
reasonPayment reason or narrative
transactionStatusStatus as the bank reports it
Unknown-reference error shape

HTTP 404 application/json, {"messages":"Transaction not found.","status":"404"}.

Last seen: 404 application/json "Transaction not found."

Changelog1 change
  1. Marked in development until a real receipt confirms the token format and PDF layout.

CBE Birr

CBE BirrNot supported yet

In development, help us. A real receipt link is what we need to finish this one. Send one privately.

Template URL

https://cbepay1.cbe.com.et/aureceipt?TID={REFERENCE}&PH={PAYER_PHONE}

Redacted example: https://cbepay1.cbe.com.et/aureceipt?TID=XXXXXXXXXX&PH=2519XXXXXXXX

Placeholders

{REFERENCE}Unconfirmed

The CBE Birr receipt number (TID).

Where to find it
On the CBE Birr receipt and in the confirmation SMS.
Length and pattern
10 letters and digits according to another open-source verifier's parser. Unconfirmed here.
Traps
None known
{PAYER_PHONE}

The phone number of the wallet that paid.

Where to find it
Ask the payer, or read it from the SMS.
Length and pattern
12 digits starting with 2519, e.g. 2519XXXXXXXX.
Traps
The receiver's phone does not work.

Gotchas

  • A miss still returns HTTP 200 (the Telerik shell). Only the labels tell a real receipt apart.
  • Another open-source verifier reads real receipts as a PDF with labels Debit Account, Credit Account, Receiver Name, Order ID, Transaction Status, Reference, Receipt Number, Paid amount, Service charge, VAT, Total Paid Amount, Payment Reason and Payment Channel. cheki accepts PDF or HTML until a real receipt confirms which.
Response and fieldsPDF or HTML (unconfirmed) · 14 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
orderIdOrder ID
transactionStatusStatus as the bank reports it
referenceThe bank's own reference
dateTransaction time as the bank prints it
amountAmount transferred
serviceFeeService fee
serviceFeeVatVAT on the service fee
totalPaidTotal paid, fees included
reasonPayment reason or narrative
paymentChannelChannel (app, USSD, agent)
Unknown-reference error shape

HTTP 200 text/html: an empty Telerik ReportViewer shell titled "Auto Receipt" with no transaction data.

Last seen: 200 text/html "Auto Receipt"

Changelog4 changes
  1. Request timed out from cheki's egress.
  2. Unknown TID/PH returns HTTP 200 with an empty Telerik ReportViewer shell.
  3. Marked in development until tested on a real receipt.
  4. Parser reads PDF or HTML using the real receipt labels.

Siinqee

Siinqee BankDown

Template URL

https://receipt.ebirr.com/siinqee/{token}

Redacted example: https://receipt.ebirr.com/siinqee/XXXXXXXXXXXX

Placeholders

{token}Unconfirmed

The Siinqee receipt token on the shared eBirr platform.

Where to find it
The receipt link in the SMS. It is the last path segment.
Length and pattern
Alphanumeric, length not yet confirmed.
Traps
None known

Gotchas

  • On 2026-10-10 the siinqee route answered HTTP 404 text/plain "Cannot GET /siinqee/...", unlike other eBirr tenants. The tenant name may have changed. A real Siinqee receipt link would settle it.
Response and fieldsHTML · 8 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
Unknown-reference error shape

Expected like other eBirr tenants: HTTP 200 text/html "Not Found Page".

Last seen: 404 text/plain "Cannot GET /siinqee/chekiprobe000000"

Also reported, not supported yet1

Siinqee Bank receipt linkNewer, not supported yet · inferred

Host: receipts.siinqeebank.com

Needs: Receipt link. Response: PDF. cheki does not read it yet. Not fetched. Needs a real receipt link and a parser that respects the view limit.

Evidence: links.et lists receipts.siinqeebank.com:871 (PDF) for Siinqee Bank and says each receipt allows about five views in total; it showed Siinqee unavailable on 2026-10-11. Not tested by cheki and not supported yet.

Changelog2 changes
  1. links.et lists Siinqee Bank receipts on receipts.siinqeebank.com:871 (PDF). Recorded as inferred, not supported.
  2. receipt.ebirr.com/siinqee/... answered HTTP 404 'Cannot GET'.

eBirr

eBirrWorking

Template URL

https://receipt.ebirr.com/{tenant}/{token}

Redacted example: https://receipt.ebirr.com/nib/XXXXXXXXXXXX

Placeholders

{tenant}

The issuing bank on the shared eBirr platform.

Where to find it
The first path segment of the receipt link.
Length and pattern
One of nib, wegagen, ahadu, kaafimf, siinqee.
Traps
None known
{token}Unconfirmed

The receipt token.

Where to find it
The last path segment of the receipt link.
Length and pattern
Alphanumeric, length not yet confirmed.
Traps
None known

Gotchas

  • An unknown token still returns HTTP 200, so the parser must check the page body.
Response and fieldsHTML · 8 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
Unknown-reference error shape

HTTP 200 text/html, a short page with "Not Found Page".

Last seen: 200 text/html "Not Found Page"

ChangelogNone yet

No changes recorded.

Nib

Nib International BankNot supported yet

In development, help us. A real receipt link is what we need to finish this one. Send one privately.

Template URL

https://receipt.ebirr.com/nib/{token}

Redacted example: https://receipt.ebirr.com/nib/XXXXXXXXXXXX

Placeholders

{token}Unconfirmed

The Nib receipt token on the shared eBirr platform (tenant "nib").

Where to find it
The receipt link in the SMS or the share button in the app. It is the last path segment.
Length and pattern
Alphanumeric, length not yet confirmed.
Traps
None known

Gotchas

  • An unknown token still returns HTTP 200, so the parser must check the page body.
  • The tenant route exists, but the Nib receipt layout is not confirmed with a real receipt yet.
Response and fieldsHTML · 8 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
Unknown-reference error shape

HTTP 200 text/html, a short page with "Not Found Page".

Last seen: 200 text/html "Not Found Page"

ChangelogNone yet

No changes recorded.

Wegagen

Wegagen BankNot supported yet

In development, help us. A real receipt link is what we need to finish this one. Send one privately.

Template URL

https://receipt.ebirr.com/wegagen/{token}

Redacted example: https://receipt.ebirr.com/wegagen/XXXXXXXXXXXX

Placeholders

{token}Unconfirmed

The Wegagen receipt token on the shared eBirr platform (tenant "wegagen").

Where to find it
The receipt link in the SMS or the share button in the app. It is the last path segment.
Length and pattern
Alphanumeric, length not yet confirmed.
Traps
None known

Gotchas

  • An unknown token still returns HTTP 200, so the parser must check the page body.
  • The tenant route exists, but the Wegagen receipt layout is not confirmed with a real receipt yet.
Response and fieldsHTML · 8 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
Unknown-reference error shape

HTTP 200 text/html, a short page with "Not Found Page".

Last seen: 200 text/html "Not Found Page"

ChangelogNone yet

No changes recorded.

Ahadu

Ahadu BankNot supported yet

In development, help us. A real receipt link is what we need to finish this one. Send one privately.

Template URL

https://receipt.ebirr.com/ahadu/{token}

Redacted example: https://receipt.ebirr.com/ahadu/XXXXXXXXXXXX

Placeholders

{token}Unconfirmed

The Ahadu receipt token on the shared eBirr platform (tenant "ahadu").

Where to find it
The receipt link in the SMS or the share button in the app. It is the last path segment.
Length and pattern
Alphanumeric, length not yet confirmed.
Traps
None known

Gotchas

  • An unknown token still returns HTTP 200, so the parser must check the page body.
  • The tenant route exists, but the Ahadu receipt layout is not confirmed with a real receipt yet.
Response and fieldsHTML · 8 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
Unknown-reference error shape

HTTP 200 text/html, a short page with "Not Found Page".

Last seen: 200 text/html "Not Found Page"

Also reported, not supported yet1

Ahadu Bank receipt linkNewer, not supported yet · inferred

Host: receipt.ahadubank.com

Needs: Receipt link. Response: PDF. cheki does not read it yet.

Evidence: links.et lists receipt.ahadubank.com (PDF). Not tested by cheki and not supported yet.

ChangelogNone yet

No changes recorded.

KAAFI

KAAFI MicrofinanceNot supported yet

In development, help us. A real receipt link is what we need to finish this one. Send one privately.

Template URL

https://receipt.ebirr.com/kaafimf/{token}

Redacted example: https://receipt.ebirr.com/kaafimf/XXXXXXXXXXXX

Placeholders

{token}Unconfirmed

The KAAFI receipt token on the shared eBirr platform (tenant "kaafimf").

Where to find it
The receipt link in the SMS or the share button in the app. It is the last path segment.
Length and pattern
Alphanumeric, length not yet confirmed.
Traps
None known

Gotchas

  • An unknown token still returns HTTP 200, so the parser must check the page body.
  • The tenant route exists, but the KAAFI receipt layout is not confirmed with a real receipt yet.
Response and fieldsHTML · 8 fields
FieldMeaning
senderNamePayer's name
senderAccountPayer's account or phone (often masked)
receiverNameReceiver's name
receiverAccountReceiver's account or phone (often masked)
amountAmount transferred
currencyCurrency, ETB
dateTransaction time as the bank prints it
referenceThe bank's own reference
Unknown-reference error shape

HTTP 200 text/html, a short page with "Not Found Page".

Last seen: 200 text/html "Not Found Page"

ChangelogNone yet

No changes recorded.

No public endpoint yet

We have not found a public receipt link for these banks. A shared receipt link or QR code is the fastest way to find one.

How to research a new bank

  1. Make a small payment to yourself and open the bank's share or download option on the receipt. Note the link it gives you, or scan the QR code with any reader to get its text.
  2. Find the variable parts of the link: which segment is the reference, and whether an account suffix, phone number or token is needed. Compare two receipts to see what changes.
  3. Send a fake reference in the same shape and record the status code, content type and body. That is the unknown-reference shape the health check will watch.
  4. Check whether the endpoint answers from outside Ethiopia. If not, mark it geo-blocked in the manifest.
  5. Run npm run probe -- <your link> locally to see what the current detector and parsers make of it, without sending the receipt to anyone.
  6. Open a bank request with the host and a redacted pattern only. Never paste a full receipt link in a public issue. If you are happy to share the real link, use the private box on the bank's page.
  7. To write the parser yourself, follow Adding or fixing a bank: a manifest entry, a parser, a redacted fixture and a test.