Fiscal Invoices
Fiscalisation is the heart of EFRIS: every sale is reported to URA in real time, and URA responds with a Fiscal Document Number (FDN), a verification code, and a QR code that must appear on the printed invoice. One endpoint handles all invoice types:
The body wraps the full EFRIS invoice structure in an invoice object:
{
"invoice": {
"sellerDetails": {},
"basicInformation": {},
"buyerDetails": {},
"goodsDetails": [],
"taxDetails": [],
"summary": {},
"payWay": []
}
}
A. Standard invoice
A complete, internally consistent example: 2 bottles at a gross (tax-inclusive) price of 100,000 UGX each. VAT at
18% is extracted from the gross: 200,000 × 18 ÷ 118 = 30,508.47.
{
"invoice": {
"sellerDetails": {
"tin": "1014409555",
"legalName": "YOUR BUSINESS NAME",
"businessName": "Your Brand",
"emailAddress": "info@yourbusiness.com",
"referenceNo": "INV-2026-001", // Your ERP's own invoice number
"isCheckReferenceNo": "0" // 0: No (default), 1: reject duplicates of referenceNo
},
"basicInformation": {
"invoiceNo": "", // Leave empty - URA returns the FDN here
"antifakeCode": "", // Leave empty - URA fills the verification code
"deviceNo": "1014409555_02",
"issuedDate": "2026-05-30 10:30:00", // yyyy-MM-dd HH:mm:ss
"operator": "Jane Kasule", // The person serving the customer
"currency": "UGX", // From the currencyType dictionary
"invoiceType": "1", // 1: Invoice/Receipt, 4: Debit Note, 5: Credit Memo/Rebate
"invoiceKind": "1", // 1: Invoice, 2: Receipt
"dataSource": "103" // 103: WebService API - use this for ERP integrations
},
"buyerDetails": {
"buyerType": "1", // 0: B2B, 1: B2C, 2: Foreigner, 3: B2G
"buyerLegalName": "John Doe"
},
"goodsDetails": [
{
"item": "Premium Water 500ml",
"itemCode": "SKU-BOTTLE-01", // Must match a registered good's goodsCode
"qty": "2",
"unitOfMeasure": "101", // From the rateUnit dictionary
"unitPrice": "100000", // Gross (tax-inclusive)
"total": "200000", // qty x unitPrice
"taxRate": "0.18", // 0.18 = 18%, 0 = zero-rated, "-" = exempt
"tax": "30508.47", // VAT portion of total: 200000 x 18/118
"orderNumber": "0", // Starts at 0, +1 per line
"discountFlag": "2", // 2: non-discount item
"deemedFlag": "2", // 2: not deemed
"exciseFlag": "2", // 2: no excise
"goodsCategoryId": "22011000" // VAT commodity classification from registration
}
],
"taxDetails": [
{
"taxCategoryCode": "01", // 01: Standard (18%)
"netAmount": "169491.53",
"taxRate": "0.18",
"taxAmount": "30508.47",
"grossAmount": "200000.00" // netAmount + taxAmount must equal grossAmount
}
],
"summary": {
"netAmount": "169491.53",
"taxAmount": "30508.47",
"grossAmount": "200000.00",
"itemCount": "1", // Number of goodsDetails lines MINUS discount lines
"modeCode": "1", // 1: Online, 0: Offline (qrCode required if 0)
"remarks": "Thank you for your business" // Optional, max 500 chars
},
"payWay": [
{
"paymentMode": "102", // See payment codes below
"paymentAmount": "200000.00",
"orderNumber": "a" // Lowercase letters: a, b, c...
}
]
}
}
Key field reference
buyerType:
| Code | Meaning |
|---|---|
0 |
B2B (Business to Business) - buyerTin required |
1 |
B2C (Individual) |
2 |
Foreigner |
3 |
B2G (Government) - buyerTin required |
paymentMode:
| Code | Meaning |
|---|---|
101 |
Credit |
102 |
Cash |
103 |
Cheque |
104 |
Demand Draft |
105 |
Mobile Money |
106 |
Visa/Mastercard |
107 |
EFT |
108 |
POS |
109 |
RTGS |
110 |
Swift Transfer |
taxRate per line:
| Value | Meaning |
|---|---|
0.18 |
Standard VAT (18%) |
0 |
Zero Rated |
"-" |
Exempt |
invoiceIndustryCode:
| Code | Meaning |
|---|---|
101 |
General Industry (default - omit this field for normal invoices) |
102 |
Export (see scenario D) |
104 |
Imported Service (see scenario F) |
105 |
Telecom |
106 |
Stamp Duty |
107 |
Hotel Service |
108 |
Other Taxes |
109 |
Airline Business (see scenario G) |
110 |
EDC (see scenario G) |
111 |
Auction |
112 |
Export Service |
summary.itemCount must equal the number of goodsDetails lines minus
the number of discount lines (discountFlag = 0), or EFRIS returns error 1304.
B. Discounts
A discounted item is expressed as two lines: the parent item (discountFlag: "1")
followed immediately by a discount line (discountFlag: "0").
Rules:
- Parent line:
discountFlag: "1",discountTotal= negative discount amount (equal to the absolute value of the discount line'stotal),discountTaxRateas decimal (e.g."0.18"). - Discount line:
discountFlag: "0", negativetotalandtax;qty,unitOfMeasure,unitPricemust be empty; item name = parent name +" (discount)". qty,unitPriceare required (and positive) whendiscountFlagis1or2.- The first goods line cannot be
discountFlag: "0"and the last line cannot be"1".
{
"goodsDetails": [
{
"item": "Premium Water 500ml",
"itemCode": "SKU-BOTTLE-01",
"qty": "5",
"unitOfMeasure": "101",
"unitPrice": "100000",
"total": "500000",
"taxRate": "0.18",
"tax": "76271.19",
"discountTotal": "-10000", // Negative; = |total| of the discount line
"discountTaxRate": "0.18",
"orderNumber": "0",
"discountFlag": "1", // 1: discounted item
"deemedFlag": "2",
"exciseFlag": "2",
"goodsCategoryId": "22011000"
},
{
"item": "Premium Water 500ml (discount)", // Parent name + " (discount)"
"itemCode": "SKU-BOTTLE-01",
"qty": "", // Must be empty on the discount line
"unitOfMeasure": "",
"unitPrice": "",
"total": "-10000", // Negative
"taxRate": "0.18",
"tax": "-1525.42", // Negative
"orderNumber": "1",
"discountFlag": "0", // 0: discount amount line
"deemedFlag": "2",
"exciseFlag": "2",
"goodsCategoryId": "22011000"
}
],
"taxDetails": [
{
"taxCategoryCode": "01",
"netAmount": "415254.23",
"taxRate": "0.18",
"taxAmount": "74745.77",
"grossAmount": "490000.00"
}
],
"summary": {
"netAmount": "415254.23",
"taxAmount": "74745.77",
"grossAmount": "490000.00",
"itemCount": "1", // 2 lines - 1 discount line
"modeCode": "1"
}
}
C. Excise duty items
For items subject to excise duty, set exciseFlag: "1". The following per-item fields then become
required: categoryId (the excise duty code), categoryName,
exciseRate, exciseRule, exciseTax. When exciseRule = "2"
(unit-based), pack, stick, exciseUnit, and exciseCurrency
are also required.
{
"goodsDetails": [
{
"item": "Mineral Water 1L",
"itemCode": "WATER-LITRE",
"qty": "100",
"unitOfMeasure": "102",
"unitPrice": "2000",
"total": "200000",
"taxRate": "0.18",
"tax": "30508.47", // VAT portion only
"orderNumber": "0",
"discountFlag": "2",
"deemedFlag": "2",
"exciseFlag": "1", // 1: item attracts excise duty
"goodsCategoryId": "50202310",
"categoryId": "LED190400", // Excise Duty code - required when exciseFlag = 1
"categoryName": "Mineral Water", // Required when exciseFlag = 1
"exciseRule": "2", // 1: by rate (percentage), 2: by quantity (unit)
"exciseRate": "150", // Rule 1: decimal e.g. "0.12"; Rule 2: amount per unit
"exciseTax": "15000", // Total excise for this line - required when exciseFlag = 1
"pack": "1", // Required when exciseRule = 2 - use packageScaledValue from registration
"stick": "1", // Required when exciseRule = 2 - use pieceScaledValue from registration
"exciseUnit": "102", // Required when exciseRule = 2 - rateUnit dictionary
"exciseCurrency": "UGX", // Required when exciseRule = 2 - currencyType dictionary
"exciseRateName": "UGX150 per litre" // Rule 1: (rate x 100) + "%"; Rule 2: currency + rate + " " + unit
}
],
"taxDetails": [
{
"taxCategoryCode": "01", // Standard VAT line
"netAmount": "169491.53",
"taxRate": "0.18",
"taxAmount": "30508.47",
"grossAmount": "200000.00"
},
{
"taxCategoryCode": "05", // Separate Excise Duty line
"netAmount": "154491.53",
"taxRate": "150", // Per-unit rate
"taxAmount": "15000.00",
"grossAmount": "169491.53",
"exciseUnit": "102", // Required in taxDetails when excise is per-unit
"exciseCurrency": "UGX", // Required in taxDetails when excise is per-unit
"taxRateName": "UGX150 per litre"
}
]
}
exciseRule:
| Code | Meaning |
|---|---|
"1" |
Percentage-based (exciseRate = decimal e.g. "0.12" for 12%;
"-" if the rate is Nil)
|
"2" |
Quantity/unit-based (exciseRate = fixed amount per unit e.g. "150" =
UGX 150 per litre) |
exciseUnit codes (from the rateUnit dictionary):
| Code | Meaning |
|---|---|
101 |
Per stick |
102 |
Per litre |
103 |
Per kg |
104 |
Per user per day of access |
105 |
Per minute |
106 |
Per 1,000 sticks |
107 |
Per 50 kgs |
109 |
Per 1 g |
D. Export invoices
For goods being exported, set basicInformation.invoiceIndustryCode: "102".
Rules for exports:
buyerDetails.deliveryTermsCodeis mandatory (Incoterms):CFR,CIF,CIP,CPT,DAP,DDP,DPU,EXW,FAS,FCA,FOB.- Per-item
totalWeight(Total Net Weight in KGM) is mandatory. - Per-item
pieceQtyandpieceMeasureUnitapply only to exports (optional). hsCode/hsName(HS tariff code and description) are optional.- Exported goods are zero-rated: use
taxRate: "0"andtaxCategoryCode: "02". buyerDetails.nonResidentFlag: "1"for non-resident buyers.
{
"invoice": {
"sellerDetails": { "...": "as in scenario A" },
"basicInformation": {
"invoiceIndustryCode": "102", // Export
"...": "other fields as in scenario A"
},
"buyerDetails": {
"buyerType": "2", // Foreigner
"buyerLegalName": "Nairobi Traders Ltd",
"nonResidentFlag": "1",
"deliveryTermsCode": "FOB" // Mandatory for export
},
"goodsDetails": [
{
"item": "Ugandan Coffee",
"itemCode": "COFFEE-001",
"qty": "500",
"unitOfMeasure": "103",
"unitPrice": "12000",
"total": "6000000",
"taxRate": "0", // Zero-rated
"tax": "0",
"orderNumber": "0",
"discountFlag": "2",
"deemedFlag": "2",
"exciseFlag": "2",
"goodsCategoryId": "09011100",
"totalWeight": "500", // Mandatory for export (KGM)
"pieceQty": "500", // Export only
"pieceMeasureUnit": "103", // Export only - rateUnit dictionary
"hsCode": "0901110000", // Optional
"hsName": "Coffee, not roasted, not decaffeinated" // Optional
}
],
"taxDetails": [
{
"taxCategoryCode": "02", // Zero rate
"netAmount": "6000000",
"taxRate": "0",
"taxAmount": "0",
"grossAmount": "6000000"
}
],
"summary": {
"netAmount": "6000000",
"taxAmount": "0",
"grossAmount": "6000000",
"itemCount": "1",
"modeCode": "1"
}
}
}
invoiceIndustryCode: "112" with
deliveryTermsCode; the per-item weight fields do not apply.
Bond / High-Sea sales (optional per item): highSeaBondFlag ("1"
bond/high-sea, "2" not), highSeaBondCode ("101" Bond Sale,
"102" High Sea Sale), highSeaBondNo.
E. Deemed VAT items
Deemed VAT applies when the buyer is a registered "deemed" party (e.g. Strategic Investors). Set
deemedFlag: "1" on each deemed item.
Rules:
- Item name must carry the suffix
" (deemed)"per the EFRIS specification (name + space +(deemed)). vatProjectIdandvatProjectNamemust come from the URA project registry - query them via the deemed projects lookup first. Omitting them causes EFRIS to reject the invoice.deemedExemptCode:"101"= Deemed,"102"= Exempt.- Group deemed lines under
taxCategoryCode: "04"(Deemed 18%) intaxDetails.
{
"goodsDetails": [
{
"item": "Consulting Services (deemed)", // Name + " (deemed)"
"itemCode": "SVC-CONSULT-01",
"qty": "1",
"unitOfMeasure": "112",
"unitPrice": "5000000.00",
"total": "5000000.00",
"taxRate": "0.18",
"tax": "762711.86",
"orderNumber": "0",
"discountFlag": "2",
"deemedFlag": "1", // 1: deemed
"exciseFlag": "2",
"goodsCategoryId": "73110000",
"deemedExemptCode": "101", // 101: Deemed, 102: Exempt
"vatProjectId": "893997229738400343", // From the deemed projects lookup - REQUIRED
"vatProjectName": "Strategic Investor Project" // REQUIRED
}
],
"taxDetails": [
{
"taxCategoryCode": "04", // Deemed (18%)
"netAmount": "4237288.14",
"taxRate": "0.18",
"taxAmount": "762711.86",
"grossAmount": "5000000.00"
}
]
}
F. Imported services
For imported services, set invoiceIndustryCode: "104". The importServicesSeller block
then becomes required:
{
"invoice": {
"sellerDetails": {
"branchId": "207300908813650312", // Cannot be empty when invoiceIndustryCode = 104
"...": "as in scenario A"
},
"basicInformation": {
"invoiceIndustryCode": "104",
"...": "as in scenario A"
},
"importServicesSeller": {
"importBusinessName": "Foreign Supplier Ltd", // Required when industry = 104
"importAddress": "Nairobi, Kenya", // Required when industry = 104
"importInvoiceDate": "2026-05-19", // yyyy-MM-dd
"importEmailAddress": "supplier@example.com",
"importContactNumber": "+254701234567",
"importAttachmentName": "invoice.pdf", // png, doc, pdf, jpg, txt, docx, xlsx, cer, crt, der
"importAttachmentContent": "BASE64_FILE_CONTENT"
},
"...": "goodsDetails / taxDetails / summary as in scenario A"
}
}
G. Airline & EDC (fuel) invoices
Airline Business (invoiceIndustryCode: "109"): the
airlineGoodsDetails array becomes required. It mirrors goodsDetails
fields (item, itemCode, qty, unitOfMeasure,
unitPrice, total, taxRate, tax, orderNumber,
discountFlag, excise fields, etc.).
EDC / Fuel (invoiceIndustryCode: "110"): the edcDetails block becomes
required:
{
"edcDetails": {
"tankNo": "1111", // Required
"pumpNo": "2222", // Required
"nozzleNo": "3333", // Required
"controllerNo": "44444",
"acquisitionEquipmentNo": "5555",
"levelGaugeNo": "66666",
"mvrn": ""
}
}
H. Debit notes
A debit note is uploaded through the same invoice endpoint with:
basicInformation.invoiceType: "4"(Debit Note)basicInformation.oriInvoiceId= theinvoiceIdURA returned for the original invoice (leave empty for normal invoices/receipts)- an
extendblock with the reason:
{
"extend": {
"reason": "Extra goods delivered", // Max 1024 chars
"reasonCode": "101"
}
}
extend.reasonCode when invoiceType = 4 (Debit Note):
| Code | Meaning |
|---|---|
101 |
Increase in the amount payable/invoice value due to extra goods delivered or goods charged at an incorrect value |
102 |
Buyer asked for a new debit note |
103 |
Others (Please specify) |
I. Batch invoice upload
Fiscalise multiple invoices in one request. Each element of invoices is a complete invoice object
(same structure as scenario A):
{
"invoices": [
{ "sellerDetails": {}, "basicInformation": {}, "...": "invoice 1" },
{ "sellerDetails": {}, "basicInformation": {}, "...": "invoice 2" }
]
}
What comes next
The response to a successful fiscalisation carries the FDN, verification code, and QR code - see Invoice Response for where to find each one. To reverse an invoice, see Credit Notes.