EFRIS API Integration Hub
Connect your ERP, POS or billing system to the Uganda Revenue Authority's (URA) EFRIS. Send ordinary JSON; get back the fiscal document number, verification code and QR code.
You send the sale as your system holds it; we take care of URA's EFRIS for you, so you reach compliance in hours instead of months.
Key Features
- Plain JSON: send tax-inclusive prices and each item's tax type; get back everything needed to print a compliant document.
- Invoices and receipts: tax invoices for VAT-registered businesses, receipts for the rest.
- Errors your accountants can act on: URA's own code and message, with what to do.
- Your field names: snake_case or camelCase, whichever your system produces.
📚 Resources & Downloads
Get started quickly with our comprehensive documentation and API collection.
What to send for each daily operation — products, stock, invoices and receipts, credit notes — and what comes back.
⬇ Download MarkdownThe requests from the guide, ready to import. Set your API key and start testing.
⬇ Download JSON🎥 Integration Video Tutorials
Learn through step-by-step video guides from our development team.
Loading videos...
🔌 Authentication
Every request carries your business's API key, which your EFRIS provider gives you. Keep it secret, and keep it and the base URL in your system's settings rather than its code.
Header Requirement:
X-API-Key: your_company_api_key_here
🧪 Sandbox & Testing
Your EFRIS provider sets your account to URA's test system while you build, and gives you its API key. Everything in the guide works the same there. Moving to live is a setting on your account: no change in your code.
📝 Submit Invoice (Simple Format)
The recommended approach for ERPs is the Simple Format. Under this mode (triggered by sending "format": "simple" in the payload), you only send the gross, tax-inclusive price, and the gateway automatically calculates EFRIS tax, net amounts, and required separate discount lines.
Choose your programming language below to view the request sample:
import requests
import json
url = "https://efris.midwayug.com/api/external/efris/submit-invoice"
headers = {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"format": "simple",
"invoiceNumber": "INV-2026-001",
"invoiceDate": "2026-05-29",
"customerName": "Excise Buyer Ltd",
"customerTin": "1000123456",
"buyerType": "0",
"paymentMethod": "102",
"items": [
{
"item_name": "Premium Beer",
"item_code": "BEER-01",
"quantity": 10,
"unit_price": 5000, # Gross price (inclusive of VAT & Excise)
"tax_rate": 18,
"excise_flag": "1",
"excise_rule": "1",
"excise_rate": "30%",
"excise_tax": 9000
}
]
}
response = requests.post(url, headers=headers, json=payload)
print(json.dumps(response.json(), indent=2))
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'X-API-Key' => 'YOUR_API_KEY',
'Content-Type' => 'application/json'
])->post('https://efris.midwayug.com/api/external/efris/submit-invoice', [
'format' => 'simple',
'invoiceNumber' => 'INV-2026-001',
'invoiceDate' => '2026-05-29',
'customerName' => 'Excise Buyer Ltd',
'customerTin' => '1000123456',
'buyerType' => '0',
'paymentMethod' => '102',
'items' => [
[
'item_name' => 'Premium Beer',
'item_code' => 'BEER-01',
'quantity' => 10,
'unit_price' => 5000,
'tax_rate' => 18,
'excise_flag' => '1',
'excise_rule' => '1',
'excise_rate' => '30%',
'excise_tax' => 9000
]
]
]);
print_r($response->json());
const axios = require('axios');
const url = 'https://efris.midwayug.com/api/external/efris/submit-invoice';
const headers = {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
};
const payload = {
format: 'simple',
invoiceNumber: 'INV-2026-001',
invoiceDate: '2026-05-29',
customerName: 'Excise Buyer Ltd',
customerTin: '1000123456',
buyerType: '0',
paymentMethod: '102',
items: [
{
item_name: 'Premium Beer',
item_code: 'BEER-01',
quantity: 10,
unit_price: 5000,
tax_rate: 18,
excise_flag: '1',
excise_rule: '1',
excise_rate: '30%',
excise_tax: 9000
}
]
};
axios.post(url, payload, { headers })
.then(response => console.log(response.data))
.catch(error => console.error(error));
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var json = @"{
""format"": ""simple"",
""invoiceNumber"": ""INV-2026-001"",
""invoiceDate"": ""2026-05-29"",
""customerName"": ""Excise Buyer Ltd"",
""customerTin"": ""1000123456"",
""buyerType"": ""0"",
""paymentMethod"": ""102"",
""items"": [
{
""item_name"": ""Premium Beer"",
""item_code"": ""BEER-01"",
""quantity"": 10,
""unit_price"": 5000,
""tax_rate"": 18,
""excise_flag"": ""1"",
""excise_rule"": ""1"",
""excise_rate"": ""30%"",
""excise_tax"": 9000
}
]
}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://efris.midwayug.com/api/external/efris/submit-invoice", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
url := "https://efris.midwayug.com/api/external/efris/submit-invoice"
jsonStr := []byte(`{
"format": "simple",
"invoiceNumber": "INV-2026-001",
"invoiceDate": "2026-05-29",
"customerName": "Excise Buyer Ltd",
"customerTin": "1000123456",
"buyerType": "0",
"paymentMethod": "102",
"items": [
{
"item_name": "Premium Beer",
"item_code": "BEER-01",
"quantity": 10,
"unit_price": 5000,
"tax_rate": 18,
"excise_flag": "1",
"excise_rule": "1",
"excise_rate": "30%",
"excise_tax": 9000
}
]
}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
req.Header.Set("X-API-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
import okhttp3.*;
import java.io.IOException;
public class EfrisClient {
public static void main(String[] args) throws IOException {
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"format\": \"simple\",\n \"invoiceNumber\": \"INV-2026-001\",\n \"invoiceDate\": \"2026-05-29\",\n \"customerName\": \"Excise Buyer Ltd\",\n \"customerTin\": \"1000123456\",\n \"buyerType\": \"0\",\n \"paymentMethod\": \"102\",\n \"items\": [\n {\n \"item_name\": \"Premium Beer\",\n \"item_code\": \"BEER-01\",\n \"quantity\": 10,\n \"unit_price\": 5000,\n \"tax_rate\": 18,\n \"excise_flag\": \"1\",\n \"excise_rule\": \"1\",\n \"excise_rate\": \"30%\",\n \"excise_tax\": 9000\n }\n ]\n}");
Request request = new Request.Builder()
.url("https://efris.midwayug.com/api/external/efris/submit-invoice")
.post(body)
.addHeader("X-API-Key", "YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
}
}
require 'net/http'
require 'uri'
require 'json'
uri = URI.parse("https://efris.midwayug.com/api/external/efris/submit-invoice")
request = Net::HTTP::Post.new(uri)
request["X-API-Key"] = "YOUR_API_KEY"
request["Content-Type"] = "application/json"
request.body = JSON.dump({
"format" => "simple",
"invoiceNumber" => "INV-2026-001",
"invoiceDate" => "2026-05-29",
"customerName" => "Excise Buyer Ltd",
"customerTin" => "1000123456",
"buyerType" => "0",
"paymentMethod" => "102",
"items" => [
{
"item_name" => "Premium Beer",
"item_code" => "BEER-01",
"quantity" => 10,
"unit_price" => 5000,
"tax_rate" => 18,
"excise_flag" => "1",
"excise_rule" => "1",
"excise_rate" => "30%",
"excise_tax" => 9000
}
]
})
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts response.body
import 'package:dio/dio.dart';
void main() async {
var dio = Dio();
dio.options.headers["X-API-Key"] = "YOUR_API_KEY";
dio.options.headers["Content-Type"] = "application/json";
var payload = {
"format": "simple",
"invoiceNumber": "INV-2026-001",
"invoiceDate": "2026-05-29",
"customerName": "Excise Buyer Ltd",
"customerTin": "1000123456",
"buyerType": "0",
"paymentMethod": "102",
"items": [
{
"item_name": "Premium Beer",
"item_code": "BEER-01",
"quantity": 10,
"unit_price": 5000,
"tax_rate": 18,
"excise_flag": "1",
"excise_rule": "1",
"excise_rate": "30%",
"excise_tax": 9000
}
]
};
try {
var response = await dio.post(
"https://efris.midwayug.com/api/external/efris/submit-invoice",
data: payload,
);
print(response.data);
} catch (e) {
print(e);
}
}
Expected Successful Response Schema
The endpoint returns both the nested fullEfrisResponse (as per our integration guide) and flat convenience fields at the top level for backward compatibility:
{
"success": true,
"message": "Invoice successfully submitted to EFRIS",
"fdn": "FDN-123456",
"verificationCode": "VER-1234",
"qrCode": "https://ura.go.ug/qr/123",
"fiscalized_at": "2026-05-29T21:00:00Z",
"invoiceNumber": "INV-2026-001",
"fullEfrisResponse": {
"fdn": "FDN-123456",
"verification_code": "VER-1234",
"qr_code": "https://ura.go.ug/qr/123",
...
}
}
📦 Products & Inventory
Before an item can be fiscalized, it must be registered with EFRIS. We provide endpoints to register products, adjust stock quantities (stock increases/decreases), and query commodity categories.
Multi-Unit Packaging
If you sell bulk packages (e.g. Boxes, Crates) but manage inventory in sub-units (e.g. Sticks, Bottles), you can specify packaging scales during registration and invoice submissions. Use package_scaled, piece_scaled, and piece_qty fields in the item lists, as the integration guide shows.
🗂️ Daily Operations
What your system calls, in the order it needs them. The integration guide gives the fields and replies for each.
| Method | Path | Purpose |
|---|---|---|
| GET | /diagnostic-test | Check your connection |
| POST | /register-product | Register or update a product |
| POST | /stock-increase | Record stock received |
| POST | /stock-decrease | Record stock written down |
| POST | /stock-transfer | Move stock between branches |
| POST | /submit-invoice | Tax invoice (VAT-registered businesses) |
| POST | /submit-receipt | Receipt (businesses not registered for VAT) |
| POST | /submit-credit-note | Credit note against an invoice or receipt |
| POST | /cancel-credit-note | Cancel an issued credit note |
Paths are relative to https://efris.midwayug.com/api/external/efris.
🚀 Ready to integrate?
Download the integration guide and Postman collection, and ask your EFRIS provider for your API key.
Get the guide