KRA eTIMS API: A Survival Guide for Kenyan SaaS

S
Samuel Kimani
May 11, 2026 3 min read

Why every SaaS will end up here

If your software issues invoices in Kenya, POS, billing platform, ticketing, parcel COD, anything, eTIMS compliance is on your roadmap whether you scheduled it or not. KRA's Electronic Tax Invoice Management System replaced the old ETR receipt-printer regime in 2024, and the API is what every modern business is expected to integrate against.

OSCU vs VSCU, pick the right one

OSCU (Online Sales Control Unit) is the always-online variant. Your server calls KRA every time you issue an invoice; KRA signs it, returns a control unit invoice number (CU Invoice Number) and a QR code, and you store both with the invoice. VSCU (Virtual SCU) is the offline-tolerant variant, your software signs invoices locally with a KRA-issued key and reconciles in batches.Choose OSCU if you have reliable internet and want a single source of truth. Choose VSCU if you serve clients who run on intermittent connectivity (kiosks, rural retail, field agents). VePay defaults to OSCU because most VePay merchants are cloud-native, but it falls back to VSCU mode automatically when KRA is unreachable.

The payload KRA actually accepts

The eTIMS API docs are accurate but skeletal. The fields that trip up integrations: tin (the merchant KRA PIN, no dashes), bhfId (branch ID, every PIN has one, ask the merchant to pull it from iTax), itemCd and itemClsCd (item code and classification code, KRA maintains a master list, do not invent these), and totTaxblAmt versus totAmt (taxable amount vs total amount, the difference is exempt items, and KRA will reject mismatches down to the cent).Build the payload from a typed object, not a hand-rolled array. Every field is required even when "empty", KRA expects 0, "", and N/A in specific positions and will reject a missing key with a generic error. We use a Spatie Data class with strict typing and a serializer that emits null for everything KRA wants null and "" for everything KRA wants empty string.

Error codes that don't mean what they say

KRA returns numeric result codes. The ones you'll meet most: 001 (success, store it), 880 (invalid TIN, usually wrong bhfId, not wrong PIN), 894 (item not in KRA master, your itemClsCd is wrong), 902 (signature mismatch, usually a clock-skew problem on a VSCU node), and the unhelpful 999 which means "anything else went wrong, retry once and then alert a human".Log every request and response in full. The KRA support team needs the exact payload to help debug, and you'll need the response history to defend against audit claims that you under-reported.

When KRA is down (and it will be)

eTIMS is hosted infrastructure with its own incidents. Don't let it block your business. The pattern: every invoice gets a local UUID and is persisted before the KRA call. The KRA call is async, a queued job retries with exponential backoff for up to 24 hours. The invoice is "issued" the moment it has a UUID; "compliant" the moment KRA returns the CU number. Tax compliance reports filter on compliant invoices; operations runs off issued.This pattern survives both KRA outages and clock-skew issues with VSCU signing. The cost is one extra column on the invoices table (cu_invoice_number nullable) and a Horizon worker that retries the eTIMS push. Worth every hour of work the first time KRA goes down on a Friday afternoon.

Need software built?

Tell us what you need. We respond within 24 hours with a realistic quote.