← Back to KRA Invoice Verifier

API Documentation

Programmatic access to verified KRA eTIMS invoice data — including the Control Unit (CU) number. Free, no authentication, no rate limits.

Overview

The KRA Invoice Verifier API lets third‑party software retrieve the verified Control Unit (CU) invoice number and other invoice details for a KRA eTIMS invoice, given the invoice’s public URL.

You send a URL; the API fetches the KRA invoice page, extracts the invoice fields, and returns them — including the CU number — as JSON. Results are cached server‑side so repeat lookups are fast.

ItemValue
Base URLhttps://www.aisheild.tech
EndpointPOST /api/fetch-url/
Full URLhttps://www.aisheild.tech/api/fetch-url/
Bypass cachehttps://www.aisheild.tech/api/fetch-url/?refresh=1
MethodPOST only (others → HTTP 405)
AuthenticationNone required
CSRFNot required
Rate limitingNone enforced (cache on your side)

Request

Headers

Only one header is required:

Content-Type: application/json
X-CSRFToken is accepted but not needed.

Body

{
  "url": "https://itax.kra.go.ke/KRA-Portal/invoiceChk.htm?actionCode=loadPage&invoiceNo=123456789"
}
FieldTypeRequiredNotes
url string yes Public URL of the KRA invoice. https:// is added automatically if missing. Must contain a dot in the hostname.

Requests with a missing or malformed URL are rejected with HTTP 400.

⚠️ Windows CMD users: If the URL contains & (as most KRA invoice URLs do), you must escape it as ^&. See Windows Notes.

Response — Success

HTTP 200

Real, verified working example:

{
  "success": true,
  "url": "https://itax.kra.go.ke/KRA-Portal/invoiceChk.htm?actionCode=loadPage&invoiceNo=123456789",
  "cached": true,
  "cu_number": "123456789",
  "data": [
    { "label": "Control Unit Invoice Number", "value": "123456789" },
    { "label": "Trader System Invoice No",    "value": "5128" },
    { "label": "Invoice Date",                "value": "02/10/2026" },
    { "label": "Total Taxable Amount",        "value": "7413.79" },
    { "label": "Supplier Name",               "value": "123456789 ENTERPRISES" }
  ]
}
FieldTypeDescription
successbooltrue when invoice data was retrieved
urlstringThe normalized URL that was queried
cachedbooltrue = served from cache; false = freshly fetched from KRA
cu_numberstringVerified Control Unit Invoice Number ("" if not present)
dataarrayAll extracted invoice fields as {label, value} objects

About the data array

The API attempts to extract 7 fields, but a KRA invoice may legitimately contain fewer — some invoice types omit certain fields. Observed in production:

The cu_number shortcut is always present (empty string if the invoice genuinely has no CU number). Integrators who only need the CU number should read cu_number directly rather than searching data.

Response — Errors

Every error has the same shape:

{ "success": false, "url": "...", "error": "..." }
StatusMeaningWhat to do
400Invalid/missing JSON body; missing URL; URL fails validationFix the request — URL must be non-empty and contain a dot in hostname
404Page loaded but no KRA invoice fields found (body also has raw_text)URL isn't a valid KRA invoice link — do not retry
405Method other than POSTUse POST
502Could not reach KRA (timeout or connection error)Retry later with ?refresh=1; underlying failure is cached and next call will re-attempt

Code Examples

Python (requests)

import requests

resp = requests.post(
    "https://www.aisheild.tech/api/fetch-url/",
    json={"url": "https://itax.kra.go.ke/KRA-Portal/invoiceChk.htm?actionCode=loadPage&invoiceNo=123456789"},
    timeout=30,
)
data = resp.json()

if data.get("success"):
    print("CU Number:", data["cu_number"])
    for item in data["data"]:
        print(f'{item["label"]}: {item["value"]}')
else:
    print("Error:", data.get("error"))

JavaScript / Node (fetch)

const res = await fetch("https://www.aisheild.tech/api/fetch-url/", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    url: "https://itax.kra.go.ke/KRA-Portal/invoiceChk.htm?actionCode=loadPage&invoiceNo=123456789"
  }),
});

const data = await res.json();

if (data.success) {
  console.log("CU Number:", data.cu_number);
} else {
  console.error("Error:", data.error);
}

PHP (cURL)

$ch = curl_init("https://www.aisheild.tech/api/fetch-url/");
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode([
        "url" => "https://itax.kra.go.ke/KRA-Portal/invoiceChk.htm?actionCode=loadPage&invoiceNo=123456789"
    ]),
    CURLOPT_HTTPHEADER     => ["Content-Type: application/json"],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
]);
$data = json_decode(curl_exec($ch), true);

if (!empty($data["success"])) {
    echo "CU Number: " . $data["cu_number"];
}

cURL — Linux / macOS (bash)

curl -X POST "https://www.aisheild.tech/api/fetch-url/" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://itax.kra.go.ke/KRA-Portal/invoiceChk.htm?actionCode=loadPage&invoiceNo=123456789"}'

cURL — Windows CMD (note the ^& escape)

curl -X POST "https://www.aisheild.tech/api/fetch-url/" -H "Content-Type: application/json" -d "{\"url\":\"https://itax.kra.go.ke/KRA-Portal/invoiceChk.htm?actionCode=loadPage^&invoiceNo=123456789\"}"

cURL — Windows, via a JSON file (most reliable)

Create body.json:

{"url":"https://itax.kra.go.ke/KRA-Portal/invoiceChk.htm?actionCode=loadPage&invoiceNo=123456789"}

Then run in CMD:

curl -X POST "https://www.aisheild.tech/api/fetch-url/" -H "Content-Type: application/json" --data-binary "@body.json"

PowerShell (Invoke-RestMethod, cleanest on Windows)

Invoke-RestMethod -Uri "https://www.aisheild.tech/api/fetch-url/" `
  -Method POST `
  -ContentType "application/json" `
  -Body '{"url":"https://itax.kra.go.ke/KRA-Portal/invoiceChk.htm?actionCode=loadPage&invoiceNo=123456789"}'

Integration Best Practices

1. Use cu_number as your primary result

It’s the verified CU number sourced directly from KRA. The data array is useful for displaying full invoice details, but most integrations only need cu_number.

2. Handle the three outcomes explicitly

if not data.get("success"):
    # error — inspect data.get("error")
elif data.get("cu_number"):
    # verified CU number found
else:
    # valid KRA invoice with no CU number (rare)

3. Don’t assume all 7 fields are present

Some KRA invoices omit Total Tax Amount or Total Invoice Amount. Iterate over data defensively — look fields up by label rather than by array position.

4. Respect the cache

Every successful response is cached server‑side. Repeat lookups for the same URL return instantly and don’t hit KRA again. Only pass ?refresh=1 when you have a specific reason to want a live re‑read.

5. Use a client timeout of at least 30 seconds

A cold fetch (cache miss) waits up to ~20s on KRA’s server. A 5‑second timeout will fail intermittently.

6. Back off between retries on 502

The failure is recorded server‑side; hammering won’t help. Use exponential backoff (e.g. 5s → 15s → 60s).

7. Don’t retry 404

A 404 means “this page isn’t a KRA invoice” — it won’t become one on retry. Show the user a clear message instead.

8. Log the cached flag

It’s a useful diagnostic: a sudden run of cached: false usually means new invoice URLs are being queried; a steady stream of cached: true means your workload is repeating existing URLs.

Windows Quoting Notes

When testing from Windows CMD:

You want to sendYou must write
" inside a "..." argument\"
& anywhere in the argument^&
|, <, >, ^prefix with ^ too

Otherwise CMD splits your URL at & and you’ll see errors like:

{"success": false, "error": "Invalid JSON body."}
'invoiceNo' is not recognized as an internal or external command

The easiest escapes from Windows quoting altogether are:

Quick Reference

ItemValue
EndpointPOST https://www.aisheild.tech/api/fetch-url/
Bypass cachePOST https://www.aisheild.tech/api/fetch-url/?refresh=1
Required headerContent-Type: application/json
Required body{"url": "<invoice URL>"}
Success status200
Primary result fieldcu_number
Full result fielddata (array of {label, value})
Recommended client timeout≥ 30 s
Verified working exampleCU 123456789, supplier ENTERPRISES
— End of documentation —