Odit Verify

Bank of Abyssinia

Detail page — public SPA URL, underlying API endpoint, token format, and return shape.

Bank of Abyssinia's cs.bankofabyssinia.com/slip/ is a React SPA that fetches its data from a same-origin JSON endpoint. We bypass the SPA entirely and hit the underlying API directly.

URL format

Public slip URL (what users share)

https://cs.bankofabyssinia.com/slip/?trx=<TOKEN>
PartPatternExample
hostliteralcs.bankofabyssinia.com
<TOKEN>FT[A-Z0-9]{15} (17 chars total)FT00000000000000A

What we actually hit

GET https://cs.bankofabyssinia.com/api/onlineSlip/getDetails/?id=<TOKEN>
Accept: application/json
Referer: https://cs.bankofabyssinia.com/slip/?trx=<TOKEN>

Token anatomy

The 17-char URL token is approximately <12-char reference><5-char suffix>. The reference echoed inside the receipt body (transactionReference) is just the leading 12 chars; the trailing 5 look like a channel/branch suffix. The API wants the full 17, not the inner reference.

Return type

receipt.source === "boa-json". Amounts are numbers.

interface BoaReceipt {
  source: 'boa-json';
 
  // Identity
  transactionReference?: string;     // 12-char inner reference
  paymentReference?: string;
  transactionDate?: string;          // "DD/MM/YY HH:MM"
  transactionType?: string;          // "Account Transfer" | …
 
  // Counterparties
  receiverName?: string;
  receiverAccount?: string;          // masked: "1******00"
 
  // Amounts (numeric)
  transferredAmount?: number;
  serviceCharge?: number;
  vat?: number;
  totalAmount?: number;
  currency?: string;                 // "ETB"
 
  // Free-text
  transferredAmountInWord?: string;
  narrative?: string;                // e.g. "Transfer"
 
  // Upstream envelope status (from header.status)
  upstreamStatus?: string;           // typically "success"
}

Sample (placeholder values)

{
  "source": "boa-json",
  "transactionReference": "FT00000000",
  "paymentReference": "",
  "transactionDate": "01/01/26 00:00",
  "transactionType": "Account Transfer",
  "receiverName": "<receiver name>",
  "receiverAccount": "1******00",
  "transferredAmount": 10,
  "serviceCharge": 0,
  "vat": 0,
  "totalAmount": 10,
  "currency": "ETB",
  "transferredAmountInWord": "TEN BIRR",
  "narrative": "Transfer",
  "upstreamStatus": "success"
}

Quirks

  • The slip page is a 456-byte React shellcurl against the public URL returns the empty SPA; the receipt data only lands after the JS bundle fetches the API. We avoid that round trip entirely by going to the API directly.
  • No payer fields are exposed — unlike telebirr or CBE, BoA's public slip never includes the sender's name or account. Only the receiver side is visible.
  • Envelope has a header wrapper — the raw upstream returns { header: { status, audit, … }, body: [ { ...receipt } ] }. We unwrap to a single object and lift header.status to upstreamStatus.
  • Amount strings include the currency — some upstream fields like amountDebitedWithCurrency arrive as "ETB10.50". Our parser strips the optional 3-letter prefix.

On this page