← All KRA eTIMS Error Codes

KRA eTIMS Integration FAQ

Answers to the most common questions from developers building on the KRA eTIMS OSCU and VSCU APIs.

OSCU · VSCU

What does KRA eTIMS resultCd 901 mean?

resultCd 901 means Not a Valid Device. The device serial number (dvcSrlNo) you submitted is not registered or approved in KRA's system. This is unrecoverable without KRA intervention — you cannot self-register a serial.

In sandbox, try the pre-provisioned serial dvcv1130. In production, email timsupport@kra.go.ke with subject: "Request for OSCU Device Registration — [Company Name] — PIN: [Your PIN]". Budget several business days for a response.

VSCU

Why does my eTIMS integration return error 921?

resultCd 921 means Sales Invoice Sequence Violation. You called saveInvoice before saveSales on the VSCU path. VSCU requires two sequential calls in this exact order:

1. POST /trnsSales/saveSales — transaction metadata
2. POST /trnsSales/saveInvoice — invoice detail + receipt signature

OSCU combines both into a single POST /saveTrnsSalesOsdc call. These paths cannot be mixed. Every developer who builds from OSCU documentation and switches to VSCU hits this.

Gotcha

What does resultCd 994 mean on retry?

resultCd 994 means Duplicate Record. On the OSCU path, treat 994 on retry or offline queue replay as an idempotent success — the invoice was already registered. Do not raise an exception.

On the VSCU JAR path, the same situation returns 899 instead, not 994 (verified against the live VSDC 2.0.6 sandbox, 2026-07-06) — do not wait for a 994 that never comes. Either way, the original submission likely succeeded and KRA consumed the receipt counter; verify via the corresponding selectTrnsSales endpoint before re-signing. Invoice numbers can never be reused even after cancellation.

Gotcha

What are the KRA eTIMS success codes? Is "000" the only one?

"000" is the documented OSCU spec code (§4.18), and live signings against the real VSDC 2.0.6 sandbox JAR also return "000" (verified 2026-07-06). But "0000" has been observed live from GavaConnect, and "00" has been reported for the VSCU JAR (unconfirmed by direct observation).

Never hardcode a single string. Always check membership in {"0", "00", "000", "0000"} so every variant is treated as success.

VSCU

What is the VSCU 24-hour connectivity ceiling?

The VSCU JAR stops issuing receipt numbers exactly 24 hours after the last successful connection to KRA servers, with no warning signal. When this ceiling is reached, the failure surfaces as a TCP connection refusal or HTTP 503 — indistinguishable from a JAR crash (resultCd 894).

Track your last successful connectivity timestamp at the application layer. Ensure the JAR reconnects to KRA at least once every 24 hours.

OSCU · VSCU

What is cmcKey and how should I store it?

cmcKey is the Communication Certificate Key issued by KRA during device initialization. It is issued exactly once with no rotation mechanism. You must persist it immediately after the init response.

Store it AES-256-GCM encrypted at rest — never in plaintext. Redact it before any logging, as any log line containing the full init response permanently leaks this key. If lost, you must contact KRA to regenerate it. There is no self-service reset path.

OSCU · VSCU

What is the difference between OSCU and VSCU?

OSCU (Online Sales Control Unit) communicates directly with KRA servers via a single combined API call per sale (POST /saveTrnsSalesOsdc). VSCU (Virtual Sales Control Unit) is a local JAR process that signs receipts offline and syncs with KRA, requiring two sequential calls per sale (saveSales then saveInvoice).

VSCU-specific constraints: 24-hour connectivity ceiling, local storage limit (resultCd E11), and separate device serials. OSCU and VSCU serials cannot be cross-used — doing so causes resultCd 903 or 905.

OSCU · VSCU

What are the KRA eTIMS tax band codes?

KRA eTIMS uses five tax band codes:

A — Exempt, 0% (no input VAT credit)
B — Standard VAT, 16%
C — Zero-Rated, 0% (input credit allowed)
D — Non-VAT, 0% (outside the VAT Act entirely)
E — Special Rate, 8% (petroleum products, LPG)

Warning: the official §4.1 Tax Type table contains a known error — some spec versions state B=16.00% while live API samples have returned B=18.00%. Always fetch rates from selectCodes at runtime. Never hardcode tax rates.

OSCU · VSCU

Are all 15 tax fields required even if I only use one tax band?

Yes. All 15 fields — taxblAmtA/B/C/D/E, taxRtA/B/C/D/E, taxAmtA/B/C/D/E — are required in every transaction request, even for single-category businesses. Set unused fields to 0 rather than omitting them. Omitting any of these fields causes resultCd 910.

OSCU · VSCU

My initialization keeps returning resultCd 902. Is my device broken?

No. resultCd 902 means Device Already Installed — the device serial has already been initialized and an active cmcKey exists. This is idempotent, not a hard failure.

The 902 response does NOT return the cmcKey — verified live against the KRA sandbox (2026-07-04), the body is {"resultCd":"902","resultMsg":"This device is installed","data":null}. Use the cmcKey you persisted at first initialization. If you redeployed and lost it, contact timsupport@kra.go.ke to de-register the serial so the device can be re-initialized.

OSCU · VSCU

Why does my eTIMS integration return resultCd 001 on the first day?

resultCd 001 means No Search Result. It is not a failure — no records exist matching your query yet. New integrations querying for purchases or stock on day one hit this constantly.

Most public SDKs check if resultCd != "000" and raise an exception here — that is wrong. Treat 001 as an empty list [], not an error. Only raise if your business logic requires at least one result.

OSCU · VSCU

What is the KRA eTIMS date format?

KRA eTIMS uses two formats depending on the field:

YYYYMMDD — date-only fields: salesDt, pchsDt
YYYYMMDDHHmmss — datetime fields: cfmDt, stockRlsDt

Sending a date in the wrong format causes resultCd 910.

OSCU · VSCU

Can I reuse an invoice number after cancelling an invoice?

No. Invoice numbers are sequential integers and can never be reused, even after cancellation. They must be strictly monotonically increasing (1, 2, 3…) — not string identifiers like INV001. Reusing an invoice number causes resultCd 994 (Duplicate Record).

VSCU

What timeout should I use for VSCU saveSales? Why does a 1-second timeout fail every sale?

In ONLINE mode the VSCU JAR relays each saveSales call synchronously to KRA's servers before responding. Live signings against the KRA sandbox take about 2.0–2.2 seconds (measured 2026-07-06). Any client timeout at or below ~2 seconds therefore fails every real signing — and dangerously: KRA still consumes the receipt counter even though your client never sees the response.

Use a client timeout of 15 seconds or more, and treat a timeout as "outcome unknown", not "failed": check whether the receipt exists (select endpoint or receipt-counter arithmetic) before replaying, because a replay of the same invoice number returns 899 on the VSCU path.

Gotcha

Does the VSCU JAR use HTTP status codes for errors?

No. The VSCU JAR returns HTTP 200 for error responses — both 899 (client catch-all) and 902 (device already installed) arrive as HTTP 200 with the error in the JSON body (verified live against VSDC 2.0.6, 2026-07-04). GavaConnect does the same for some malformed requests.

Parse resultCd from the body on every response. Status-code-based error handling silently treats every KRA error as success.

VSCU

Why is VSCURcptPbctDate null in my saveSales response?

The spec's §3.3.6 JSON sample names the receipt publication timestamp VSCURcptPbctDate, but the real VSDC 2.0.6 JAR returns the field as vsdcRcptPbctDate (verified live 2026-07-06: {"data":{…,"vsdcRcptPbctDate":"20260706202219",…}}). A strict mapping against the spec name silently yields null.

Parse the timestamp case-insensitively or register aliases for vsdcRcptPbctDate, VSDCRcptPbctDate, and VSCURcptPbctDate. The real JAR also returns mrcNo in the data object.

OSCU · VSCU

How do I handle eTIMS rate limiting (resultCd 990)?

Cache code list and item classification responses — call selectCodes and selectItems once at initialization and refresh on a schedule, not on every transaction. When you hit a 990, back off and retry with exponential delay. Never poll these endpoints in a tight loop.

Gotcha

What is resultCd E04?

resultCd E04 means Device / Branch Not Found. The bhfId in your request does not exist in KRA's system for your TIN. Verify your bhfId against what was assigned during registration — the default sandbox bhfId is "00".

This is a letter-prefixed code absent from all official spec documents. It is only confirmed through live GavaConnect production observation.