{
  "info": {
    "name": "EFRIS External API - Complete Collection",
    "description": "## EFRIS Integration Hub — External API\n\nComplete Postman collection for all external-facing EFRIS endpoints.\n\n### 🔑 Before You Start — Set These Variables\nEdit the **collection variables** (click the collection → Variables tab) and fill in:\n\n| Variable | Description | Example |\n|---|---|---|\n| `base_url` | API server base URL | `https://efris.midwayug.com` |\n| `api_key` | Your company X-API-Key | `efris_abc123...` |\n| `tin` | Your company TIN registered with the system | `1000000001` |\n\nThese variables are used automatically across all requests — you only need to set them once.\n\n### 📁 Folder Structure\n1. **Health & Diagnostics** — connection tests, server time\n2. **Invoices** — submit, query, list invoices; Z-report, reconciliation, batch upload, buyer updates\n3. **Credit Notes** — submit, query, approve, cancel and void credit notes\n4. **Products (Goods & Services)** — register and query goods/services\n5. **Stock Management** — increase, decrease, transfer stock; stock records and adjustments\n6. **Purchase Orders** — submit purchase orders\n7. **Reference Data** — excise duty, units, categories, taxpayer info, branches, exchange rates, HS codes, contacts\n8. **Passthrough (Advanced)** — raw EFRIS interface passthrough\n9. **Fuel & EDC** — fuel types, pumps, nozzles, shifts and EDC invoices\n10. **Device, Session & Agent** — client init, certificates, EFD location/transfer, device status\n11. **System & Utilities** — TCS versions, exception logs, USSD accounts\n12. **Error Examples** — expected failure responses\n\n\n### 📖 Base URL\n`https://efris.midwayug.com`",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_postman_id": "efris-external-api-v2-complete"
  },
  "auth": {
    "type": "apikey",
    "apikey": [
      {
        "key": "key",
        "value": "X-API-Key",
        "type": "string"
      },
      {
        "key": "value",
        "value": "{{api_key}}",
        "type": "string"
      },
      {
        "key": "in",
        "value": "header",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://efris.midwayug.com",
      "type": "string",
      "description": "Your middleware base URL, including the /api/external/efris path."
    },
    {
      "key": "api_key",
      "value": "",
      "type": "string",
      "description": "The X-API-Key issued for your taxpayer account."
    },
    {
      "key": "tin",
      "value": "",
      "type": "string",
      "description": "A TIN to look up. Your own works for every query here. Required by the taxpayer endpoints."
    },
    {
      "key": "invoice_number",
      "value": "",
      "type": "string",
      "description": "An invoice number that exists in your account, for the single-invoice lookup."
    }
  ],
  "item": [
    {
      "name": "1. Health & Diagnostics",
      "description": "Endpoints to test connectivity, server time, and company EFRIS configuration.",
      "item": [
        {
          "name": "Server Time (T101)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/server-time",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "server-time"
              ]
            },
            "description": "Get current server time from URA EFRIS (T101).\n\nVerifies EFRIS connectivity and returns URA's server timestamp. Use this as a quick health check to confirm your API key works and EFRIS is reachable."
          },
          "response": []
        },
        {
          "name": "Diagnostic Self-Test",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/diagnostic-test",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "diagnostic-test"
              ]
            },
            "description": "Perform a full diagnostic test of your company's EFRIS connectivity.\n\nReturns:\n- Company configuration (TIN, device number, test mode, cert status)\n- HTTP connectivity test results for the EFRIS server URLs (production + test)\n\nUseful for troubleshooting connection issues."
          },
          "response": []
        },
        {
          "name": "Registration Details (T102)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/registration-details",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "registration-details"
              ]
            },
            "description": "Get taxpayer profile and registration details from EFRIS (T102).\n\nReturns the registration/taxpayer metadata stored or fetched during the EFRIS handshake. Includes branch IDs needed for stock transfers."
          },
          "response": []
        }
      ]
    },
    {
      "name": "2. Invoices",
      "description": "Submit, query, and list fiscal invoices via EFRIS (T109).",
      "item": [
        {
          "name": "Submit Invoice — Standard B2C (T109)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"invoice_number\": \"INV-2026-001\",\n  \"invoice_date\": \"2026-06-09\",\n  \"customer_name\": \"John Doe\",\n  \"customer_tin\": \"\",\n  \"buyer_type\": \"1\",\n  \"payment_method\": \"101\",\n  \"currency\": \"UGX\",\n  \"remarks\": \"Standard retail sale\",\n  \"invoice_industry_code\": \"101\",\n  \"items\": [\n    {\n      \"item\": \"Office Chair Ergonomic\",\n      \"itemCode\": \"CHAIR-001\",\n      \"qty\": \"2\",\n      \"unitOfMeasure\": \"102\",\n      \"unitPrice\": \"300000\",\n      \"total\": \"600000\",\n      \"taxRate\": \"18\",\n      \"tax\": \"91525\",\n      \"goodsCategoryId\": \"44102906\",\n      \"vatApplicableFlag\": \"1\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/submit-invoice",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "submit-invoice"
              ]
            },
            "description": "Submit a standard B2C (Business-to-Consumer) invoice to EFRIS.\n\n**buyer_type codes:**\n- `0` = B2B (requires customer_tin)\n- `1` = B2C Individual (default)\n- `2` = Foreigner\n- `3` = B2G (Government)\n\n**payment_method codes:**\n- `101` = Cash\n- `102` = Credit\n- `103` = Cheque\n- `105` = Mobile Money\n\n**invoice_industry_code:**\n- `101` = General (default)\n- `102` = Export\n- `112` = Export Service\n\nReturns complete fiscal invoice data including FDN, QR code, seller info, and all fiscalized items."
          },
          "response": []
        },
        {
          "name": "Submit Invoice — B2B (with Customer TIN) (T109)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"invoice_number\": \"INV-2026-002\",\n  \"invoice_date\": \"2026-06-09\",\n  \"customer_name\": \"ABC Company Ltd\",\n  \"customer_tin\": \"1000000000\",\n  \"buyer_type\": \"0\",\n  \"payment_method\": \"102\",\n  \"currency\": \"UGX\",\n  \"remarks\": \"B2B credit sale\",\n  \"invoice_industry_code\": \"101\",\n  \"items\": [\n    {\n      \"item\": \"Laptop Computer\",\n      \"itemCode\": \"LAP-001\",\n      \"qty\": \"5\",\n      \"unitOfMeasure\": \"102\",\n      \"unitPrice\": \"2500000\",\n      \"total\": \"12500000\",\n      \"taxRate\": \"18\",\n      \"tax\": \"1906779\",\n      \"goodsCategoryId\": \"43211507\",\n      \"vatApplicableFlag\": \"1\"\n    },\n    {\n      \"item\": \"Mouse Wireless\",\n      \"itemCode\": \"MOUSE-001\",\n      \"qty\": \"5\",\n      \"unitOfMeasure\": \"102\",\n      \"unitPrice\": \"80000\",\n      \"total\": \"400000\",\n      \"taxRate\": \"18\",\n      \"tax\": \"61017\",\n      \"goodsCategoryId\": \"43211706\",\n      \"vatApplicableFlag\": \"1\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/submit-invoice",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "submit-invoice"
              ]
            },
            "description": "Submit a B2B invoice where buyer_type=0. The customer_tin field is required for B2B invoices."
          },
          "response": []
        },
        {
          "name": "Submit Invoice — Export (T102/T112)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"invoice_number\": \"EXP-2026-001\",\n  \"invoice_date\": \"2026-06-09\",\n  \"customer_name\": \"Kenya Imports Ltd\",\n  \"customer_tin\": \"\",\n  \"buyer_type\": \"2\",\n  \"payment_method\": \"101\",\n  \"currency\": \"USD\",\n  \"remarks\": \"Export to Kenya\",\n  \"invoice_industry_code\": \"102\",\n  \"delivery_terms_code\": \"FOB\",\n  \"customs\": {\n    \"sad_number\": \"SAD12345\",\n    \"office\": \"Busia\",\n    \"cif\": \"5000\",\n    \"ware_house_number\": \"WH001\",\n    \"ware_house_name\": \"Busia Warehouse\",\n    \"destination_country\": \"Kenya\",\n    \"origin_country\": \"Uganda\",\n    \"import_export_flag\": \"2\",\n    \"confirm_status\": \"0\",\n    \"valuation_method\": \"CIF\",\n    \"prn\": \"PRN123\"\n  },\n  \"items\": [\n    {\n      \"item\": \"Coffee Beans - Arabica\",\n      \"itemCode\": \"COFFEE-001\",\n      \"qty\": \"500\",\n      \"unitOfMeasure\": \"103\",\n      \"unitPrice\": \"10\",\n      \"total\": \"5000\",\n      \"taxRate\": \"-\",\n      \"tax\": \"0\",\n      \"goodsCategoryId\": \"50201706\",\n      \"vatApplicableFlag\": \"0\",\n      \"total_weight\": 500.0,\n      \"piece_qty\": 500,\n      \"piece_measure_unit\": \"103\",\n      \"hs_code\": \"0901110000\",\n      \"hs_name\": \"Coffee, not roasted\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/submit-invoice",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "submit-invoice"
              ]
            },
            "description": "Submit an export invoice (invoice_industry_code=102). Export invoices require additional customs fields and per-item weight/piece data.\n\n**Required extra fields for exports:**\n- `delivery_terms_code`: Incoterms (FOB, CIF, CFR, EXW, DAP, etc.)\n- `customs`: Object with SAD number, office, destination country, etc.\n- Per item: `total_weight`, `piece_qty`, `piece_measure_unit`\n\nOptional per item: `hs_code`, `hs_name`"
          },
          "response": []
        },
        {
          "name": "Submit Invoice — Zero-Rated / Tax Exempt (T109)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"invoice_number\": \"INV-2026-ZR-001\",\n  \"invoice_date\": \"2026-06-09\",\n  \"customer_name\": \"Farm Fresh Ltd\",\n  \"customer_tin\": \"1000000010\",\n  \"buyer_type\": \"0\",\n  \"payment_method\": \"101\",\n  \"currency\": \"UGX\",\n  \"items\": [\n    {\n      \"item\": \"Maize Grain\",\n      \"itemCode\": \"MAIZE-001\",\n      \"qty\": \"1000\",\n      \"unitOfMeasure\": \"103\",\n      \"unitPrice\": \"1500\",\n      \"total\": \"1500000\",\n      \"taxRate\": \"-\",\n      \"tax\": \"0\",\n      \"goodsCategoryId\": \"50201717\",\n      \"vatApplicableFlag\": \"0\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/submit-invoice",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "submit-invoice"
              ]
            },
            "description": "Submit a zero-rated or tax-exempt invoice. Set `taxRate` to `\"-\"` and `vatApplicableFlag` to `\"0\"` for exempt items."
          },
          "response": []
        },
        {
          "name": "Get Invoice by Number",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/invoice/{{invoice_number}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "invoice",
                "{{invoice_number}}"
              ]
            },
            "description": "Query the status and details of a specific invoice by its invoice number.\n\nLooks up the invoice from the activity logs and returns:\n- FDN (Fiscal Document Number)\n- Approval status\n- Customer name\n- Total amount and tax\n- Fiscalization timestamp\n- Error message (if rejected)"
          },
          "response": []
        },
        {
          "name": "List Invoices",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/invoices?limit=50&offset=0",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "invoices"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Max records to return (max 100)"
                },
                {
                  "key": "offset",
                  "value": "0",
                  "description": "Pagination offset"
                },
                {
                  "key": "status",
                  "value": "",
                  "description": "Filter: 'success' or 'failed'",
                  "disabled": true
                }
              ]
            },
            "description": "List recent invoices from the activity log with pagination.\n\n**Query Parameters:**\n- `limit` (int): Max records per page (max 100, default 50)\n- `offset` (int): Pagination offset (default 0)\n- `status` (str, optional): Filter by status — `success` or `failed`"
          },
          "response": []
        },
        {
          "name": "List Invoices — Failed Only",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/invoices?status=failed&limit=50&offset=0",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "invoices"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "failed"
                },
                {
                  "key": "limit",
                  "value": "50"
                },
                {
                  "key": "offset",
                  "value": "0"
                }
              ]
            },
            "description": "List only failed invoice submissions for review and resubmission."
          },
          "response": []
        },
        {
          "name": "List invoices eligible for a credit note (T107)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/creditable-invoices?pageNo=1&pageSize=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "creditable-invoices"
              ],
              "query": [
                {
                  "key": "pageNo",
                  "value": "1"
                },
                {
                  "key": "pageSize",
                  "value": "10"
                },
                {
                  "key": "invoiceNo",
                  "value": "00000000001",
                  "disabled": true
                },
                {
                  "key": "deviceNo",
                  "value": "00031000092",
                  "disabled": true
                },
                {
                  "key": "buyerTin",
                  "value": "7777777777",
                  "disabled": true
                },
                {
                  "key": "buyerLegalName",
                  "value": "HENRY KAMUGISHA",
                  "disabled": true
                },
                {
                  "key": "invoiceType",
                  "value": "1",
                  "disabled": true
                },
                {
                  "key": "startDate",
                  "value": "2026-07-01",
                  "disabled": true
                },
                {
                  "key": "endDate",
                  "value": "2026-07-31",
                  "disabled": true
                },
                {
                  "key": "branchName",
                  "value": "Mr. HENRY KAMUGISHA",
                  "disabled": true
                }
              ]
            },
            "description": "Lists the taxpayer's issued invoices and debit notes that can still have a Credit Note or Cancel-of-Debit-Note application raised against them. Documents that already hold an application, and voided documents, are filtered out; results come back newest-issued first.\n\nAn ERP calls this to populate the document picker at the start of a credit note flow — the `id` on each record is the `oriInvoiceId` you then pass to T111/T114.\n\n- `invoiceType`: `1` = invoice, `4` = debit note\n- `dataSource` (response): `101` EFD, `102` Windows Client APP, `103` WebService API, `104` MIS, `105` Web portal, `106` Offline Mode Enabler\n\nDates are `yyyy-MM-dd`. `pageSize` cannot exceed 100. All filters are optional — send none and you get the first page of everything creditable."
          },
          "response": []
        },
        {
          "name": "Upload daily Z-report (T116)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/z-report",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "z-report"
              ]
            },
            "description": "Uploads the end-of-day Z-report for the taxpayer's device. An ERP calls it once per trading day, after the last receipt, as part of its close-of-business routine.\n\n**URA has not published a field list for T116.** The spec's Request Message literally reads \"To be determined\" and its field table is empty, so there are no authoritative key names to send. The endpoint is a raw pass-through: whatever JSON you post is signed, encrypted and forwarded to EFRIS verbatim, with no key mapping or validation in the middleware.\n\nThe body is therefore an empty object — the same content the client sends when nothing is supplied, and the only body that cannot contain a wrong field name. Once URA issues a Z-report schema for your device profile, put those exact keys in this body; do not guess them, because unrecognised keys are forwarded as-is and rejected by EFRIS."
          },
          "response": []
        },
        {
          "name": "Check invoices against EFRIS (T117)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"invoices\": [\n    {\n      \"invoiceNo\": \"322000150744\",\n      \"invoiceType\": \"1\"\n    },\n    {\n      \"invoiceNo\": \"322000150745\",\n      \"invoiceType\": \"2\"\n    },\n    {\n      \"invoiceNo\": \"322000150802\",\n      \"invoiceType\": \"4\"\n    },\n    {\n      \"invoiceNo\": \"322000150811\",\n      \"invoiceType\": \"5\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/invoice-checks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "invoice-checks"
              ]
            },
            "description": "Reconciles a batch of locally held invoice numbers against the copy EFRIS holds — the standard way an ERP detects receipts that never landed, or landed under the wrong document type, after an offline window or a failed upload run.\n\n**invoiceType**: `1` = Invoice/Receipt, `2` = Credit Note with original FDN, `5` = Credit Note without original FDN, `4` = Debit Note.\n\nPost the batch as `{\"invoices\": [ ... ]}`; the middleware unwraps it into the bare JSON array URA expects and stringifies both fields. Matching is scoped to the sellerTin and deviceNo of the request envelope.\n\nGotcha: EFRIS returns **only the invoice numbers that disagree or that it cannot find** — an empty collection means the whole batch reconciles. Batch size is capped by a URA system parameter, so page large reconciliations."
          },
          "response": []
        },
        {
          "name": "Batch upload signed invoices (T129)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"invoices\": [\n    {\n      \"invoiceContent\": \"{\\\"sellerDetails\\\":{\\\"tin\\\":\\\"1009830845\\\",\\\"ninBrn\\\":\\\"\\\",\\\"legalName\\\":\\\"KAMPALA HARDWARE SUPPLIES LTD\\\",\\\"businessName\\\":\\\"KAMPALA HARDWARE SUPPLIES\\\",\\\"address\\\":\\\"Plot 12 Nakivubo Road, Kampala\\\",\\\"mobilePhone\\\":\\\"256772451900\\\",\\\"linePhone\\\":\\\"0414230100\\\",\\\"emailAddress\\\":\\\"billing@kampalahardware.co.ug\\\",\\\"placeOfBusiness\\\":\\\"Kampala\\\",\\\"referenceNo\\\":\\\"SO-2026-004417\\\",\\\"branchId\\\":\\\"207300908813650312\\\",\\\"isCheckReferenceNo\\\":\\\"0\\\"},\\\"basicInformation\\\":{\\\"invoiceNo\\\":\\\"\\\",\\\"antifakeCode\\\":\\\"\\\",\\\"deviceNo\\\":\\\"208178192251887451\\\",\\\"issuedDate\\\":\\\"2026-08-18 09:41:07\\\",\\\"operator\\\":\\\"jkabuye\\\",\\\"currency\\\":\\\"UGX\\\",\\\"oriInvoiceId\\\":\\\"\\\",\\\"invoiceType\\\":\\\"1\\\",\\\"invoiceKind\\\":\\\"1\\\",\\\"dataSource\\\":\\\"103\\\",\\\"invoiceIndustryCode\\\":\\\"101\\\",\\\"isBatch\\\":\\\"0\\\"},\\\"buyerDetails\\\":{\\\"buyerTin\\\":\\\"1000023456\\\",\\\"buyerNinBrn\\\":\\\"\\\",\\\"buyerPassportNum\\\":\\\"\\\",\\\"buyerLegalName\\\":\\\"NILE DISTRIBUTORS LTD\\\",\\\"buyerBusinessName\\\":\\\"NILE DISTRIBUTORS\\\",\\\"buyerAddress\\\":\\\"Plot 4 Jinja Road, Kampala\\\",\\\"buyerEmail\\\":\\\"ap@niledistributors.co.ug\\\",\\\"buyerMobilePhone\\\":\\\"256701998877\\\",\\\"buyerLinePhone\\\":\\\"\\\",\\\"buyerPlaceOfBusi\\\":\\\"Kampala\\\",\\\"buyerType\\\":\\\"0\\\",\\\"buyerCitizenship\\\":\\\"\\\",\\\"buyerSector\\\":\\\"\\\",\\\"buyerReferenceNo\\\":\\\"PO-88213\\\",\\\"nonResidentFlag\\\":\\\"0\\\"},\\\"goodsDetails\\\":[{\\\"item\\\":\\\"Portland Cement 50kg\\\",\\\"itemCode\\\":\\\"CEM50\\\",\\\"qty\\\":\\\"40\\\",\\\"unitOfMeasure\\\":\\\"101\\\",\\\"unitPrice\\\":\\\"32000.00\\\",\\\"total\\\":\\\"1280000.00\\\",\\\"taxRate\\\":\\\"0.18\\\",\\\"tax\\\":\\\"195254.24\\\",\\\"orderNumber\\\":\\\"0\\\",\\\"discountFlag\\\":\\\"2\\\",\\\"deemedFlag\\\":\\\"2\\\",\\\"exciseFlag\\\":\\\"2\\\",\\\"categoryId\\\":\\\"\\\",\\\"categoryName\\\":\\\"\\\",\\\"goodsCategoryId\\\":\\\"30111500\\\",\\\"goodsCategoryName\\\":\\\"Cement and lime\\\",\\\"vatApplicableFlag\\\":\\\"1\\\"}],\\\"taxDetails\\\":[{\\\"taxCategoryCode\\\":\\\"01\\\",\\\"netAmount\\\":\\\"1084745.76\\\",\\\"taxRate\\\":\\\"0.18\\\",\\\"taxAmount\\\":\\\"195254.24\\\",\\\"grossAmount\\\":\\\"1280000.00\\\"}],\\\"summary\\\":{\\\"netAmount\\\":\\\"1084745.76\\\",\\\"taxAmount\\\":\\\"195254.24\\\",\\\"grossAmount\\\":\\\"1280000.00\\\",\\\"itemCount\\\":\\\"1\\\",\\\"modeCode\\\":\\\"0\\\",\\\"remarks\\\":\\\"Offline queue flush 2026-08-18\\\",\\\"qrCode\\\":\\\"\\\"},\\\"payWay\\\":[{\\\"paymentMode\\\":\\\"101\\\",\\\"paymentAmount\\\":\\\"1280000.00\\\",\\\"orderNumber\\\":\\\"a\\\"}]}\",\n      \"invoiceSignature\": \"CUDJBIfpJMpbsutG2GobInoOjkE2vVQ8GuTrmQebHTFG0w4wBrpZl2oEuLIVuLqrP38ddL0fcd5mE/QQHOSSInqEl9uik0RpE1U8gWxndcRaFkw3lJPPW0/FKegaGNJvJFzadmWxnorsoLCQaj+McjWwCvnI6ydDw9HJMtRxr1/KeMeo009gzLvGpEqu1gdo9Nuf8KCeIPpitzb2LeB6CbXxM2y/poCQw+iVLOL2vsqU4WgjIAtpx/4Eysws7PODNUL/DmwNCfxafkjGZ/TwJ7ZI4HEgp57LGbnGsTobQfWPrgyzHEUoLAynxT1JkpAfksG7ikn/6+SN3Ewm8NKpSA==\"\n    },\n    {\n      \"invoiceContent\": \"{\\\"sellerDetails\\\":{\\\"tin\\\":\\\"1009830845\\\",\\\"ninBrn\\\":\\\"\\\",\\\"legalName\\\":\\\"KAMPALA HARDWARE SUPPLIES LTD\\\",\\\"businessName\\\":\\\"KAMPALA HARDWARE SUPPLIES\\\",\\\"address\\\":\\\"Plot 12 Nakivubo Road, Kampala\\\",\\\"mobilePhone\\\":\\\"256772451900\\\",\\\"linePhone\\\":\\\"0414230100\\\",\\\"emailAddress\\\":\\\"billing@kampalahardware.co.ug\\\",\\\"placeOfBusiness\\\":\\\"Kampala\\\",\\\"referenceNo\\\":\\\"SO-2026-004418\\\",\\\"branchId\\\":\\\"207300908813650312\\\",\\\"isCheckReferenceNo\\\":\\\"0\\\"},\\\"basicInformation\\\":{\\\"invoiceNo\\\":\\\"\\\",\\\"antifakeCode\\\":\\\"\\\",\\\"deviceNo\\\":\\\"208178192251887451\\\",\\\"issuedDate\\\":\\\"2026-08-18 10:16:52\\\",\\\"operator\\\":\\\"amutebi\\\",\\\"currency\\\":\\\"UGX\\\",\\\"oriInvoiceId\\\":\\\"\\\",\\\"invoiceType\\\":\\\"1\\\",\\\"invoiceKind\\\":\\\"1\\\",\\\"dataSource\\\":\\\"103\\\",\\\"invoiceIndustryCode\\\":\\\"101\\\",\\\"isBatch\\\":\\\"0\\\"},\\\"buyerDetails\\\":{\\\"buyerTin\\\":\\\"\\\",\\\"buyerNinBrn\\\":\\\"CM91027384756X\\\",\\\"buyerPassportNum\\\":\\\"\\\",\\\"buyerLegalName\\\":\\\"Sarah Nabbanja\\\",\\\"buyerBusinessName\\\":\\\"\\\",\\\"buyerAddress\\\":\\\"Ntinda, Kampala\\\",\\\"buyerEmail\\\":\\\"\\\",\\\"buyerMobilePhone\\\":\\\"256782334455\\\",\\\"buyerLinePhone\\\":\\\"\\\",\\\"buyerPlaceOfBusi\\\":\\\"Kampala\\\",\\\"buyerType\\\":\\\"1\\\",\\\"buyerCitizenship\\\":\\\"\\\",\\\"buyerSector\\\":\\\"\\\",\\\"buyerReferenceNo\\\":\\\"\\\",\\\"nonResidentFlag\\\":\\\"0\\\"},\\\"goodsDetails\\\":[{\\\"item\\\":\\\"Galvanised Iron Sheet 28G\\\",\\\"itemCode\\\":\\\"GIS28\\\",\\\"qty\\\":\\\"12\\\",\\\"unitOfMeasure\\\":\\\"101\\\",\\\"unitPrice\\\":\\\"48500.00\\\",\\\"total\\\":\\\"582000.00\\\",\\\"taxRate\\\":\\\"0.18\\\",\\\"tax\\\":\\\"88779.66\\\",\\\"orderNumber\\\":\\\"0\\\",\\\"discountFlag\\\":\\\"2\\\",\\\"deemedFlag\\\":\\\"2\\\",\\\"exciseFlag\\\":\\\"2\\\",\\\"categoryId\\\":\\\"\\\",\\\"categoryName\\\":\\\"\\\",\\\"goodsCategoryId\\\":\\\"30102900\\\",\\\"goodsCategoryName\\\":\\\"Structural metal products\\\",\\\"vatApplicableFlag\\\":\\\"1\\\"}],\\\"taxDetails\\\":[{\\\"taxCategoryCode\\\":\\\"01\\\",\\\"netAmount\\\":\\\"493220.34\\\",\\\"taxRate\\\":\\\"0.18\\\",\\\"taxAmount\\\":\\\"88779.66\\\",\\\"grossAmount\\\":\\\"582000.00\\\"}],\\\"summary\\\":{\\\"netAmount\\\":\\\"493220.34\\\",\\\"taxAmount\\\":\\\"88779.66\\\",\\\"grossAmount\\\":\\\"582000.00\\\",\\\"itemCount\\\":\\\"1\\\",\\\"modeCode\\\":\\\"0\\\",\\\"remarks\\\":\\\"Offline queue flush 2026-08-18\\\",\\\"qrCode\\\":\\\"\\\"},\\\"payWay\\\":[{\\\"paymentMode\\\":\\\"102\\\",\\\"paymentAmount\\\":\\\"582000.00\\\",\\\"orderNumber\\\":\\\"a\\\"}]}\",\n      \"invoiceSignature\": \"XtOzLqXPfZ6zG+PfPB7R5jN6j66EskmH9RBfh1+EomIJyTcRG/BtAfrqGuvkrSDyJ7BKb8GMjN2KZqwWcITxYRzli8Vhw/qyMxugcZR8IlzWS2cpHl8T5Xp+LI/lsGrGvI1ZULYpxK+FNIvUs7hrt1ZvHKv4oNY8DdW/f2QM9Il1bPJIflPc6oAqSGr86Cs4Iyu0tTKs72x8d3hIPqoED6BmZScmVUKBDviqo2IwPYzfoUNyNrWxIi5gVS3MrSufZTAqMAKyw/Z05wQpUbuxx0exPoY0ST6b2PYtyMrpekp9iEBVviRQN/L1f7w061D1Axgtmh2fExiz7ELz1iWUsQ==\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/batch-invoice-upload",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "batch-invoice-upload"
              ]
            },
            "description": "Flushes a queue of already-signed **T109** invoice payloads to EFRIS in one round trip — what an ERP calls after trading offline.\n\nEach entry carries `invoiceContent` (the T109 request JSON as a *plaintext string*) and `invoiceSignature` (the signature computed over that exact byte-for-byte string — re-serialising or re-indenting the JSON invalidates it). `invoices` is the documented key; the middleware also accepts `data` as an alias for the same array.\n\nEFRIS answers **per invoice**, as an array of `{invoiceContent, invoiceReturnCode, invoiceReturnMessage}`: `00` = accepted, `99` = failed with the reason in `invoiceReturnMessage`. A 200 on this call does **not** mean every invoice landed — always loop the array.\n\nCodes inside each `invoiceContent` — `invoiceType` 1=Invoice/Receipt, 4=Debit Note, 5=Credit Memo/rebate; `invoiceKind` 1=invoice, 2=receipt; `dataSource` 101=EFD, 102=Windows Client APP, 103=WebService API, 104=Mis, 105=Webportal, 106=Offline Mode Enabler, 107=USSD, 108=ASK URA; `invoiceIndustryCode` 101=General Industry, 102=Export, 104=Imported Service, 105=Telecom, 107=Hotel Service, 109=Airline Business, 110=EDC; `buyerType` 0=B2B, 1=B2C, 2=Foreigner, 3=B2G; `discountFlag` 0=discount-amount line, 1=discounted item, 2=non-discount; `deemedFlag`/`exciseFlag` 1=yes, 2=no; `summary.modeCode` 1=Online, 0=Offline; `payWay.paymentMode` 101=Credit, 102=Cash, 103=Cheque, 104=Demand draft, 105=Mobile money, 106=Visa/Master card, 107=EFT, 108=POS, 109=RTGS, 110=Swift transfer.\n\nThree gotchas the spec buries in its field tables: `isBatch` means *batch summary invoice*, not \"sent via T129\" — leave it `0` here. `categoryId` is the **exciseDutyCode**, not the commodity category, so it must be empty whenever `exciseFlag` is `2` (`goodsCategoryId` carries the VAT commodity classification). And `payWay.orderNumber` is a single **lowercase letter** (a, b, c…), while `goodsDetails.orderNumber` counts up from zero."
          },
          "response": []
        },
        {
          "name": "Update buyer details on an issued invoice (T166)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"invoiceNo\": \"321000229045\",\n  \"buyerType\": \"0\",\n  \"buyerTin\": \"1009837013\",\n  \"buyerNinBrn\": \"09656200018719\",\n  \"buyerPassportNum\": \"B1053672\",\n  \"buyerLegalName\": \"Mr. PETER KADDU\",\n  \"buyerBusinessName\": \"ZAYN KIDS ORNAMENT\",\n  \"buyerAddress\": \"KAZAHI KANUNGU KINKIZI WEST KAYONZA\",\n  \"buyerEmailAddress\": \"peter.kaddu@zaynkids.co.ug\",\n  \"buyerMobilePhone\": \"256772500431\",\n  \"buyerLinePhone\": \"00256414233815\",\n  \"buyerPlaceOfBusi\": \"Plot 12 Kampala Road, Kampala\",\n  \"buyerCitizenship\": \"1\",\n  \"buyerSector\": \"1\",\n  \"buyerReferenceNo\": \"SO-2026-004417\",\n  \"mvrn\": \"UBJ 456F\",\n  \"createDateStr\": \"2026-08-18 07:45:12\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/update-buyer-details",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "update-buyer-details"
              ]
            },
            "description": "Amends the buyer recorded against an already-issued invoice or EDC receipt. The classic case is a walk-in fuel customer who produces their TIN after the receipt has already printed.\n\n**Required:** `invoiceNo` (max 20) and `buyerType`. `buyerType` is `0` = B2B, `1` = B2C, `2` = Foreigner — note there is no `3` (B2G) here, unlike T181. `buyerTin` is mandatory whenever `buyerType` is `0`; EFRIS rejects the call otherwise.\n\nEvery other key is optional, and the middleware forwards only the keys you actually send — a key you leave out is not transmitted to URA at all, so send just the fields you are changing.\n\n`createDateStr` is `yyyy-MM-dd HH:mm:ss`. The spec defines no enum for `buyerCitizenship` (max 128) or `buyerSector` (max 200) — URA's own sample sends `\"1\"` for both, which is also what this middleware's T109 invoice build sends. `mvrn` is the motor-vehicle registration number carried on fuel invoices. `buyerReferenceNo` is an external-interface-only field: EFDs and CS clients do not transmit it.\n\nEFRIS returns an empty payload on success."
          },
          "response": []
        },
        {
          "name": "Query invoice remain details (T186)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/invoice-remain-details?invoiceNo=159078217852531032",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "invoice-remain-details"
              ],
              "query": [
                {
                  "key": "invoiceNo",
                  "value": "159078217852531032"
                }
              ]
            },
            "description": "Returns the complete invoice payload for one FDN, with each goods line additionally carrying `remainQty` and `remainAmount` — the quantity and value not yet credited by earlier credit notes.\n\nAn ERP calls this immediately before raising a credit note (T110 / T111) to cap the credited quantity; crediting beyond `remainQty` is rejected by URA, and partially credited invoices are the usual cause.\n\n- `invoiceNo` is **required** — the FDN of the original invoice.\n- Response mirrors the T108 invoice detail: `sellerDetails`, `basicInformation`, `buyerDetails`, `buyerExtend`, `goodsDetails[]`, `taxDetails[]`, `summary`, `payWay[]`, `extend`.\n- `goodsDetails[]` per line: `item`, `itemCode`, `qty`, **`remainQty`**, `unitOfMeasure`, `unitPrice`, `total`, **`remainAmount`**, `taxRate`, `tax`, `discountTotal`, `orderNumber`, `discountFlag`, `deemedFlag`.\n- Date gotcha: `issuedDate` / `oriIssuedDate` in `basicInformation` come back as **dd/MM/yyyy HH:mm:ss**, not the yyyy-MM-dd form used on requests."
          },
          "response": []
        },
        {
          "name": "Query export invoice status (T187)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/export-invoice-status?invoiceNo=1234567891234",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "export-invoice-status"
              ],
              "query": [
                {
                  "key": "invoiceNo",
                  "value": "1234567891234"
                }
              ]
            },
            "description": "Returns the customs clearance status of an export FDN.\n\nERP integrators poll this after issuing a zero-rated export invoice, to confirm the consignment actually left the country before closing the export order or releasing the sale for VAT reporting.\n\n- `invoiceNo` is **required** — the FDN of the export invoice.\n- Response: `{invoiceNo, documentStatusCode}`.\n- `documentStatusCode`: **101** = FDN under processing (still with customs), **102** = Exited (consignment has left). Only 102 confirms the export.\n- Poll on a schedule rather than in the invoice-issuing path — the status can sit at 101 for days while customs processes the consignment."
          },
          "response": []
        }
      ]
    },
    {
      "name": "3. Credit Notes",
      "description": "Submit credit note applications and query existing credit notes via EFRIS (T110, T112).",
      "item": [
        {
          "name": "Submit Credit Note — Simple Format",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"credit_note_number\": \"CN-2026-001\",\n  \"credit_note_date\": \"2026-06-09\",\n  \"original_invoice_number\": \"1234567890123456\",\n  \"original_fdn\": \"1234567890123456\",\n  \"customer_name\": \"John Doe\",\n  \"reason\": \"Product returned — defective item\",\n  \"reason_code\": \"101\",\n  \"items\": [\n    {\n      \"item_name\": \"Office Chair Ergonomic\",\n      \"item_code\": \"CHAIR-001\",\n      \"goods_category_id\": \"44102906\",\n      \"quantity\": 1,\n      \"unit_price\": 300000,\n      \"tax_rate\": 0.18,\n      \"unit_of_measure\": \"102\"\n    }\n  ],\n  \"total_amount\": 300000,\n  \"total_tax\": 45763,\n  \"currency\": \"UGX\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/submit-credit-note",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "submit-credit-note"
              ]
            },
            "description": "Submit a credit note to EFRIS (T110) using the simplified format.\n\n**reason_code values:**\n- `101` = Sales Return\n- `102` = Cancelled Invoice\n- `103` = Discount Given\n- `104` = Price Adjustment\n\nThe `original_fdn` is the Fiscal Document Number from the original approved invoice."
          },
          "response": []
        },
        {
          "name": "Submit Credit Note — Pre-formatted EFRIS T110",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"oriInvoiceId\": \"<URA internal invoiceId of the original, not its FDN>\",\n  \"oriInvoiceNo\": \"1234567890123456\",\n  \"reasonCode\": \"101\",\n  \"reason\": \"Product returned — defective item\",\n  \"sellersReferenceNo\": \"CN-2026-001\",\n  \"applicationTime\": \"2026-06-09 10:00:00\",\n  \"goodsDetails\": [\n    {\n      \"item\": \"Office Chair Ergonomic\",\n      \"itemCode\": \"CHAIR-001\",\n      \"qty\": \"1\",\n      \"unitOfMeasure\": \"102\",\n      \"unitPrice\": \"300000\",\n      \"total\": \"300000\",\n      \"taxRate\": \"0.18\",\n      \"tax\": \"45763\",\n      \"goodsCategoryId\": \"44102906\",\n      \"vatApplicableFlag\": \"1\"\n    }\n  ],\n  \"taxDetails\": [\n    {\n      \"taxCategoryCode\": \"01\",\n      \"netAmount\": \"254237\",\n      \"taxRate\": \"0.18\",\n      \"taxAmount\": \"45763\",\n      \"grossAmount\": \"300000\"\n    }\n  ],\n  \"summary\": {\n    \"netAmount\": \"254237\",\n    \"taxAmount\": \"45763\",\n    \"grossAmount\": \"300000\",\n    \"currency\": \"101\"\n  },\n  \"payWay\": [\n    {\n      \"paymentMode\": \"101\",\n      \"paymentAmount\": \"300000\"\n    }\n  ],\n  \"buyerDetails\": {\n    \"buyerType\": \"1\",\n    \"buyerLegalName\": \"John Doe\",\n    \"buyerTin\": \"\",\n    \"buyerPhoneNo\": \"\",\n    \"buyerEmail\": \"\"\n  },\n  \"basicInformation\": {\n    \"currency\": \"101\",\n    \"invoiceType\": \"1\",\n    \"invoiceIndustryCode\": \"101\"\n  }\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/submit-credit-note",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "submit-credit-note"
              ]
            },
            "description": "Submit a pre-formatted T110 credit note payload. Use this format if your ERP already builds the EFRIS T110 structure (e.g., YourBookSuit or other advanced integrators).\n\nThe endpoint auto-detects which format you're using based on the presence of top-level EFRIS fields (`reasonCode`, `goodsDetails`, `taxDetails`, `summary`)."
          },
          "response": []
        },
        {
          "name": "Query Credit Notes",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/credit-notes?pageNo=1&pageSize=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "credit-notes"
              ],
              "query": [
                {
                  "key": "pageNo",
                  "value": "1",
                  "description": "Page number (1-indexed)"
                },
                {
                  "key": "pageSize",
                  "value": "10",
                  "description": "Records per page"
                },
                {
                  "key": "queryType",
                  "value": "1",
                  "description": "1=By date range (default)",
                  "disabled": true
                },
                {
                  "key": "referenceNo",
                  "value": "",
                  "description": "Filter by reference/credit note number",
                  "disabled": true
                },
                {
                  "key": "oriInvoiceNo",
                  "value": "",
                  "description": "Filter by original invoice number",
                  "disabled": true
                },
                {
                  "key": "invoiceNo",
                  "value": "",
                  "description": "Filter by credit note invoice number",
                  "disabled": true
                },
                {
                  "key": "approveStatus",
                  "value": "",
                  "description": "Filter by approval status",
                  "disabled": true
                },
                {
                  "key": "startDate",
                  "value": "",
                  "description": "Date range start (YYYY-MM-DD)",
                  "disabled": true
                },
                {
                  "key": "endDate",
                  "value": "",
                  "description": "Date range end (YYYY-MM-DD)",
                  "disabled": true
                }
              ]
            },
            "description": "Query credit notes from EFRIS (T112) with optional filters.\n\n**Query Parameters (all optional):**\n- `pageNo` / `pageSize`: Pagination\n- `queryType`: `1` = by date range (default)\n- `referenceNo`: Filter by your reference number\n- `oriInvoiceNo`: Filter by original invoice number\n- `invoiceNo`: Filter by credit note FDN\n- `approveStatus`: Filter by approval status\n- `startDate` / `endDate`: Date range filter (YYYY-MM-DD format)"
          },
          "response": []
        },
        {
          "name": "Query Credit Notes — By Original Invoice",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/credit-notes?oriInvoiceNo={{invoice_number}}&pageNo=1&pageSize=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "credit-notes"
              ],
              "query": [
                {
                  "key": "oriInvoiceNo",
                  "value": "INV-2026-001"
                },
                {
                  "key": "pageNo",
                  "value": "1"
                },
                {
                  "key": "pageSize",
                  "value": "10"
                }
              ]
            },
            "description": "Query credit notes filtered by the original invoice number."
          },
          "response": []
        },
        {
          "name": "Approve credit note application (T113)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"referenceNo\": \"425502528294126235\",\n  \"approveStatus\": \"101\",\n  \"taskId\": \"1382\",\n  \"remark\": \"Goods returned to store on GRN 4471; credit note approved.\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/credit-note-approval",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "credit-note-approval"
              ]
            },
            "description": "Approves or rejects a credit-note / cancel-of-debit-note application waiting in the EFRIS approval workflow, so back-office staff can clear the queue from the ERP instead of the URA web portal.\n\n`referenceNo` and `taskId` both come from the application listing (T111 `records[].referenceNo` and `records[].taskId`).\n\n**approveStatus** (dictionary `creditNoteApproveStatus`): `101` = Approved, `103` = Rejected.\n\nGotcha: all four fields are mandatory — `remark` included, even when approving (max 1024 chars). The response message is null, so re-query T111 to confirm the application left the pending queue."
          },
          "response": []
        },
        {
          "name": "Cancel credit note application (T114)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"oriInvoiceId\": \"31000000000000000001\",\n  \"invoiceNo\": \"786059685752403327\",\n  \"reasonCode\": \"103\",\n  \"invoiceApplyCategoryCode\": \"104\",\n  \"reason\": \"Credit note raised against the wrong original invoice; correct note reissued to the buyer.\",\n  \"attachmentList\": [\n    {\n      \"fileName\": \"cancellation-approval.pdf\",\n      \"fileType\": \"pdf\",\n      \"fileContent\": \"MIIDFjCCAf6gAwIBAgIRAKPGAol9CEdpkIoFa8huM6zfj1WEBRxteoo6PH46un4FGj4N6ioIGzVr9G40uhQGdm16ZU+q44XjW2oUnI9w=\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/cancel-credit-note",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "cancel-credit-note"
              ]
            },
            "description": "Cancels an issued credit note, or raises a cancel-of-debit-note application for approval, when a note was issued in error.\n\n- `oriInvoiceId` — the `invoiceId` of the **original invoice**, not of the note (max 20)\n- `invoiceNo` — the FDN of the credit note being cancelled\n- **reasonCode** (dictionary `refundReason`): `101` buyer refused to accept the invoice due to an incorrect invoice/receipt, `102` not delivered due to an incorrect invoice/receipt, `103` other reasons\n- **invoiceApplyCategoryCode**: `103` cancel of debit note (initiates a URA approval workflow), `104` cancel of credit note (no workflow — invoice status is changed immediately), `105` cancel of credit memo\n\nGotcha: `reason` is mandatory when `reasonCode` is `103`, as in this example. `attachmentList` is optional; each entry carries `fileName`, `fileType` (png, doc, pdf, jpg, txt, docx, xlsx, cer, crt, der) and base64 `fileContent`, and is forwarded to URA untouched."
          },
          "response": []
        },
        {
          "name": "Get credit note application detail (T118)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/credit-note-application-details?id=229700709531101368",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "credit-note-application-details"
              ],
              "query": [
                {
                  "key": "id",
                  "value": "229700709531101368"
                }
              ]
            },
            "description": "Returns the full detail of one Credit Note or Cancel-of-Debit-Note application: `goodsDetails` lines, `taxDetails`, `summary` (with the original invoice's `previousNetAmount`/`previousTaxAmount`/`previousGrossAmount`), `payWay`, and `basicInformation`.\n\nERPs call it after submitting an application to show the approver what was requested, or to reconcile an approved application back into the ledger.\n\n- `id` is the **application id returned by T111**, not an invoice FDN — passing an FDN here returns nothing.\n- `basicInformation.invoiceType`: `2` = Credit Note, `4` = Debit Note; `invoiceKind`: `1` = invoice, `2` = receipt\n- Line flags: `discountFlag` `1` discount / `2` non-discount, `deemedFlag` `1` deemed / `2` not, `exciseFlag` `1` excise / `2` not, `exciseRule` `1` by tax rate / `2` by quantity\n- `payWay.paymentMode`: `101` Credit, `102` Cash, `103` Cheque, `104` Demand draft, `105` Mobile money, `106` Visa/Master card, `107` EFT, `108` POS, `109` RTGS, `110` Swift transfer"
          },
          "response": []
        },
        {
          "name": "Void credit/debit note application (T120)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"businessKey\": \"229700709531101368\",\n  \"referenceNo\": \"425502528294126235\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/void-credit-debit-note-application",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "void-credit-debit-note-application"
              ]
            },
            "description": "Voids a credit-note or cancel-of-debit-note application that was submitted but is **not yet approved** — the ERP's undo for an application raised in error. Once URA has approved it, cancel the resulting note with T114 instead.\n\nBoth values come from the original application record, and both are capped at 20 characters:\n\n- `businessKey` — the application `id` (T111 `records[].id`)\n- `referenceNo` — the application `referenceNo` (T111 `records[].referenceNo`)\n\nGotcha: the response message is null, so treat a success `returnCode` as confirmation and re-query T111 to see the application drop out of the pending list."
          },
          "response": []
        },
        {
          "name": "Get cancelled credit note detail (T122)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/cancel-credit-note-details?invoiceNo=22970000531455",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "cancel-credit-note-details"
              ],
              "query": [
                {
                  "key": "invoiceNo",
                  "value": "22970000531455"
                }
              ]
            },
            "description": "Returns the cancellation record for a credit note that was cancelled through T114 — `currency`, `issueDate`, `grossAmount`, and the reason it was cancelled.\n\nERPs call this when reconciling: a credit note that vanished from the ledger can be confirmed as cancelled, with the reason attached to the journal.\n\n- `invoiceNo` is the **FDN of the credit note** itself, not the original invoice, and is required.\n- `reasonCode` (dictionary `cancelRefundReason`): `101` = buyer refused to accept the invoice due to an incorrect invoice/receipt, `102` = not delivered due to an incorrect invoice/receipt, `103` = other reasons.\n- The free-text `reason` field is only populated when `reasonCode` is `103`; it comes back empty for `101` and `102`.\n- `issueDate` is returned as `dd/MM/yyyy HH:mm:ss`, not `yyyy-MM-dd`."
          },
          "response": []
        }
      ]
    },
    {
      "name": "4. Products (Goods & Services)",
      "description": "Register products/services and query the goods catalogue from EFRIS (T130, T127).",
      "item": [
        {
          "name": "Register Product — Standard Goods",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"item_code\": \"CHAIR-001\",\n  \"item_name\": \"Office Chair — Ergonomic\",\n  \"unit_price\": 300000,\n  \"commodity_code\": \"44102906\",\n  \"unit_of_measure\": \"102\",\n  \"have_excise_tax\": \"102\",\n  \"goods_type_code\": \"101\",\n  \"stock_quantity\": 50,\n  \"description\": \"Ergonomic office chair with lumbar support\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/register-product",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "register-product"
              ]
            },
            "description": "Register a new product or service with EFRIS (T130).\n\n**Required fields:**\n- `item_code` (or `itemCode`): Your internal product code\n- `item_name` (or `itemName`): Product display name\n- `unit_price` (or `unitPrice`): Price in UGX\n- `commodity_code` (or `commodityCode`/`commodityCategoryId`): EFRIS commodity category code (see commodity-categories endpoint)\n\n**Optional fields:**\n- `unit_of_measure`: T115 unit code (101=Stick, 102=Piece/Litre, 103=Kg, 8B=Crate, 4C=Box, 43=Bag, BO=Bottle, etc.)\n- `have_excise_tax`: `101`=Yes, `102`=No (default)\n- `excise_duty_code`: Required ONLY when `have_excise_tax=101`\n- `goods_type_code`: `101`=Goods (default), `102`=Fuel\n- `is_service`: boolean, default false\n- `stock_quantity`: Initial stock prewarning quantity\n- `description`: Product description\n- `operationType`: `101`=New (default), `102`=Update"
          },
          "response": []
        },
        {
          "name": "Register Product — With Excise Duty",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"item_code\": \"BEER-001\",\n  \"item_name\": \"Premium Lager Beer 500ml\",\n  \"unit_price\": 3500,\n  \"commodity_code\": \"50202302\",\n  \"unit_of_measure\": \"BO\",\n  \"have_excise_tax\": \"101\",\n  \"excise_duty_code\": \"LED190100\",\n  \"goods_type_code\": \"101\",\n  \"stock_quantity\": 1000,\n  \"description\": \"Premium quality lager beer 500ml glass bottle\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/register-product",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "register-product"
              ]
            },
            "description": "Register an excisable product (e.g., beer, spirits, tobacco). When `have_excise_tax=101`, you must provide the `excise_duty_code`.\n\nGet available excise codes from the `/api/external/efris/excise-duty` endpoint."
          },
          "response": []
        },
        {
          "name": "Register Service",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"item_code\": \"SVC-CONSULT\",\n  \"item_name\": \"IT Consulting Services\",\n  \"unit_price\": 500000,\n  \"commodity_code\": \"81111500\",\n  \"unit_of_measure\": \"102\",\n  \"have_excise_tax\": \"102\",\n  \"is_service\": true,\n  \"description\": \"Professional IT consulting and advisory services\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/register-product",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "register-product"
              ]
            },
            "description": "Register a service (intangible). Set `is_service: true` to mark as a service instead of a physical good."
          },
          "response": []
        },
        {
          "name": "Register Product — With Multi-Unit (Packaging)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"item_code\": \"SODA-CRATE\",\n  \"item_name\": \"Soda Soft Drink — Crate of 24\",\n  \"unit_price\": 60000,\n  \"commodity_code\": \"50202300\",\n  \"unit_of_measure\": \"8B\",\n  \"have_excise_tax\": \"102\",\n  \"goods_type_code\": \"101\",\n  \"stock_quantity\": 200,\n  \"have_piece_unit\": \"101\",\n  \"piece_measure_unit\": \"BO\",\n  \"piece_unit_price\": 2500,\n  \"package_scaled_value\": \"1\",\n  \"piece_scaled_value\": \"24\",\n  \"description\": \"Soda in crates. 1 crate = 24 bottles.\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/register-product",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "register-product"
              ]
            },
            "description": "Register a product with multi-unit (bulk/retail packaging) support. For example, 1 Crate = 24 Bottles.\n\n**Multi-unit fields:**\n- `have_piece_unit`: `101`=Yes\n- `piece_measure_unit`: Unit code for the smaller unit (e.g., `BO`=Bottle)\n- `piece_unit_price`: Price of the smaller unit\n- `package_scaled_value`: Amount of larger units in the package (usually `1`)\n- `piece_scaled_value`: Number of smaller units per package (e.g., `24`)"
          },
          "response": []
        },
        {
          "name": "Update Existing Product",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"item_code\": \"CHAIR-001\",\n  \"item_name\": \"Office Chair — Ergonomic (Updated)\",\n  \"unit_price\": 350000,\n  \"commodity_code\": \"44102906\",\n  \"unit_of_measure\": \"102\",\n  \"have_excise_tax\": \"102\",\n  \"operationType\": \"102\",\n  \"description\": \"Updated ergonomic office chair with improved lumbar support\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/register-product",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "register-product"
              ]
            },
            "description": "Update an existing product by setting `operationType` to `102` (Update). Use the same `item_code` as the original registration."
          },
          "response": []
        },
        {
          "name": "Query Registered Goods — All",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/goods",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "goods"
              ]
            },
            "description": "Retrieve ALL registered goods and services from EFRIS (T127). Automatically fetches all pages and returns a single unified list.\n\nReturns for each item: item_code, item_name, is_service, commodity_category, unit_of_measure, unit_price, tax_rate, excise info, stock level, and status."
          },
          "response": []
        },
        {
          "name": "Query Registered Goods — Search by Keyword",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/goods?search=chair",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "goods"
              ],
              "query": [
                {
                  "key": "search",
                  "value": "chair",
                  "description": "Keyword search across item_code and item_name"
                }
              ]
            },
            "description": "Search registered goods by a keyword. Matches against both `goodsCode` and `goodsName` (case-insensitive partial match)."
          },
          "response": []
        },
        {
          "name": "Query Registered Goods — By Item Code",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/goods?goods_code=CHAIR-001",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "goods"
              ],
              "query": [
                {
                  "key": "goods_code",
                  "value": "CHAIR-001",
                  "description": "Exact item/goods code filter"
                }
              ]
            },
            "description": "Filter registered goods by an exact item code."
          },
          "response": []
        },
        {
          "name": "Query Registered Goods — Services Only",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/goods?service_only=true",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "goods"
              ],
              "query": [
                {
                  "key": "service_only",
                  "value": "true",
                  "description": "true=services only, false=products only, omit=all"
                }
              ]
            },
            "description": "Retrieve only services (intangibles) from the registered goods catalogue."
          },
          "response": []
        },
        {
          "name": "Query goods by goods code (T144)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/goods-by-code?goodsCode=0001,0002",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "goods-by-code"
              ],
              "query": [
                {
                  "key": "goodsCode",
                  "value": "0001,0002"
                },
                {
                  "key": "tin",
                  "value": "1009837013",
                  "disabled": true
                }
              ]
            },
            "description": "Batch lookup of registered products by their EFRIS goods code, instead of paging the whole catalogue.\n\nPass a single code or a comma-separated list — `\"0001,0002\"` — in `goodsCode`. Only goods whose status is *enabled* are returned, so a code missing from the response means the product is not live on EFRIS and must not be referenced on an invoice.\n\n`tin` is optional and only used when invoicing on behalf of a principal agent (send that agent's TIN).\n\nUnit flags in the response: `measureUnit`, `pieceMeasureUnit` and `otherUnit` are T115 `rateUnit` dictionary codes; `havePieceUnit` and `haveOtherUnit` are `101` = Yes, `102` = No.\n\nGotcha: when `havePieceUnit` is `101` the record carries a `pieceMeasureUnit`; when it is `102` that field is empty. `goodsOtherUnits` is only populated when `haveOtherUnit` is `101`."
          },
          "response": []
        }
      ]
    },
    {
      "name": "5. Stock Management",
      "description": "Manage stock levels in EFRIS via increase, decrease, and branch transfers (T131, T139).",
      "item": [
        {
          "name": "Stock Increase (T131)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"goodsStockIn\": {\n    \"operationType\": \"101\",\n    \"supplierTin\": \"1000000001\",\n    \"supplierName\": \"Uganda Supplies Ltd\",\n    \"stockInType\": \"102\",\n    \"stockInDate\": \"2026-06-09\",\n    \"remarks\": \"Monthly stock replenishment from local supplier\"\n  },\n  \"goodsStockInItem\": [\n    {\n      \"goodsCode\": \"CHAIR-001\",\n      \"quantity\": \"50\",\n      \"unitPrice\": \"250000\",\n      \"measureUnit\": \"102\",\n      \"remarks\": \"\"\n    },\n    {\n      \"goodsCode\": \"LAP-001\",\n      \"quantity\": \"10\",\n      \"unitPrice\": \"2000000\",\n      \"measureUnit\": \"102\",\n      \"remarks\": \"\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-increase",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-increase"
              ]
            },
            "description": "Record a stock increase (goods received) in EFRIS (T131, operationType=101).\n\n**stockInType codes:**\n- `101` = Import\n- `102` = Local Purchase (default)\n- `103` = Manufacture\n- `104` = Opening Stock\n\nBoth `snake_case` and `camelCase` field names are accepted."
          },
          "response": []
        },
        {
          "name": "Stock Decrease (T131)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"goodsStockIn\": {\n    \"operationType\": \"102\",\n    \"adjustType\": \"102\",\n    \"remarks\": \"Damaged goods written off — water damage\"\n  },\n  \"goodsStockInItem\": [\n    {\n      \"goodsCode\": \"CHAIR-001\",\n      \"quantity\": \"5\",\n      \"unitPrice\": \"300000\",\n      \"measureUnit\": \"102\",\n      \"remarks\": \"Irreparably damaged in transit\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-decrease",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-decrease"
              ]
            },
            "description": "Record a stock decrease (write-off / wastage) in EFRIS (T131, operationType=102).\n\n**adjustType codes:**\n- `101` = Damaged\n- `102` = Expired\n- `103` = Stolen\n- `104` = Sampling\n- `105` = Others\n\nBoth `snake_case` and `camelCase` field names are accepted."
          },
          "response": []
        },
        {
          "name": "Stock Transfer Between Branches (T139)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"goodsStockTransfer\": {\n    \"source_branch_id\": \"206637525568955296\",\n    \"destination_branch_id\": \"206637528324276772\",\n    \"transfer_type_code\": \"101\",\n    \"remarks\": \"\",\n    \"roll_back_if_error\": \"0\",\n    \"goods_type_code\": \"101\"\n  },\n  \"goodsStockTransferItem\": [\n    {\n      \"goods_code\": \"CHAIR-001\",\n      \"measure_unit\": \"102\",\n      \"quantity\": \"10\",\n      \"remarks\": \"\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-transfer",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-transfer"
              ]
            },
            "description": "Transfer stock between branches/locations in EFRIS (T139).\n\n**Important:**\n- Get valid `branchId` values from the `GET /api/external/efris/registration-details` endpoint\n- Source and destination branch IDs **cannot** be the same\n- When `transfer_type_code=103` (Others), `remarks` is **mandatory**\n- Either `goods_code` or `commodity_goods_id` must be provided per item\n\n**transfer_type_code values:**\n- `101` = Out of Stock Adjust\n- `102` = Error Adjust\n- `103` = Others (requires remarks)\n\nBoth `snake_case` and `camelCase` accepted."
          },
          "response": []
        },
        {
          "name": "Check stock quantity for one product (T128)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/goods-stock-quantity?id=290707933831281139",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "goods-stock-quantity"
              ],
              "query": [
                {
                  "key": "id",
                  "value": "290707933831281139"
                },
                {
                  "key": "branchId",
                  "value": "298324457142214047",
                  "disabled": true
                }
              ]
            },
            "description": "Returns what EFRIS believes is on hand for a single registered product: `stock` (current quantity) and `stockPrewarning` (the low-stock threshold set when the goods were registered).\n\nERPs call this before invoicing a stock-managed item, and again after a stock increase or decrease, to confirm URA's quantity matches the ERP's — an invoice for more than URA holds is rejected.\n\n- `id` is required and is the **EFRIS goods id** (an 18-digit id returned by T127 or T144), not your ERP SKU or `goodsCode`.\n- `branchId` is optional; omit it to query the branch the device is registered to.\n\nThe response carries only these two numbers — use T145/T149 if you need the movements behind them."
          },
          "response": []
        },
        {
          "name": "Query stock-in records (T145)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-records?referenceNo=425502528294126235&pageNo=1&pageSize=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-records"
              ],
              "query": [
                {
                  "key": "productionBatchNo",
                  "value": "00000000001",
                  "disabled": true
                },
                {
                  "key": "invoiceNo",
                  "value": "320001127399",
                  "disabled": true
                },
                {
                  "key": "referenceNo",
                  "value": "425502528294126235"
                },
                {
                  "key": "pageNo",
                  "value": "1"
                },
                {
                  "key": "pageSize",
                  "value": "10"
                }
              ]
            },
            "description": "Retrieves stock-in (goods increase) records already posted to EFRIS, so an ERP can reconcile a goods receipt against what URA actually holds, or recover the `referenceNo` of an earlier stock increase.\n\n**At least one of `productionBatchNo`, `invoiceNo` or `referenceNo` must be sent** — URA rejects the call when all three are empty. This example sends `referenceNo`; enable the other two as needed.\n\n`pageNo` and `pageSize` are mandatory to URA (the middleware defaults them to 1 and 10); `pageSize` cannot exceed 100.\n\n`stockInType` on each record: `101` = Import, `102` = Local Purchase, `103` = Manufacture/Assembling, `104` = Opening Stock. `productionBatchNo` and `productionDate` are only populated when `stockInType` is `103`.\n\n`adjustType`, where present: `101` = Expired Goods, `102` = Damaged Goods, `103` = Personal Uses, `104` = Others (see `remarks`), `105` = Raw Material(s)."
          },
          "response": []
        },
        {
          "name": "Query branch stock-in records (T147)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/branch-stock-records?pageNo=1&pageSize=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "branch-stock-records"
              ],
              "query": [
                {
                  "key": "combineKeywords",
                  "value": "425502528294126235",
                  "disabled": true
                },
                {
                  "key": "stockInType",
                  "value": "101",
                  "disabled": true
                },
                {
                  "key": "startDate",
                  "value": "2021-09-10",
                  "disabled": true
                },
                {
                  "key": "endDate",
                  "value": "2021-09-11",
                  "disabled": true
                },
                {
                  "key": "supplierTin",
                  "value": "1009839122",
                  "disabled": true
                },
                {
                  "key": "supplierName",
                  "value": "Mr. EMUR SAM",
                  "disabled": true
                },
                {
                  "key": "pageNo",
                  "value": "1"
                },
                {
                  "key": "pageSize",
                  "value": "10"
                }
              ]
            },
            "description": "Browses the **current branch's** stock-in records by date range, stock-in type or supplier — the filter set T145 does not offer, and without T145's requirement to already know a batch, invoice or reference number.\n\n`combineKeywords` is a partial match against `referenceNo` **or** `supplierName`. Every filter is optional, so the request as shipped simply returns the branch's most recent records.\n\n`stockInType`: `101` = Import, `102` = Local Purchase, `103` = Manufacture/Assembling, `104` = Opening Stock. `startDate`/`endDate` are `yyyy-MM-dd`; `pageSize` cannot exceed 100.\n\nEach record carries an `id` — pass it to `GET /api/external/efris/stock-record-detail` (T148) to get the goods lines."
          },
          "response": []
        },
        {
          "name": "Query stock-in record detail (T148)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-record-detail?id=425502528294126235",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-record-detail"
              ],
              "query": [
                {
                  "key": "id",
                  "value": "425502528294126235"
                }
              ]
            },
            "description": "Expands one stock-in record into its header (`goodsStockIn`: stock-in type, supplier, branch, batch, dates) plus every goods line in `goodsStockInGoods` with quantity, unit price and amount.\n\n`id` is required and comes from a `records[].id` returned by T147 (`GET /api/external/efris/branch-stock-records`).\n\nHeader `stockInType`: `101` = Import, `102` = Local Purchase, `103` = Manufacture/Assembling, `104` = Opening Stock. `productionBatchNo` and `productionDate` are only set when `stockInType` is `103`.\n\nGoods lines carry `commodityGoodsId`, `goodsCode`, `measureUnit` (T115 `rateUnit`) and `currency` (T115 `currencyType`). An ERP uses this to reconcile a goods receipt line by line against what was actually declared to URA."
          },
          "response": []
        },
        {
          "name": "Query stock adjustment records (T149)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-adjust-records?pageNo=1&pageSize=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-adjust-records"
              ],
              "query": [
                {
                  "key": "referenceNo",
                  "value": "425502528294126235",
                  "disabled": true
                },
                {
                  "key": "startDate",
                  "value": "2021-09-10",
                  "disabled": true
                },
                {
                  "key": "endDate",
                  "value": "2021-09-11",
                  "disabled": true
                },
                {
                  "key": "pageNo",
                  "value": "1"
                },
                {
                  "key": "pageSize",
                  "value": "10"
                }
              ]
            },
            "description": "Lists stock adjustments (write-offs) already accepted by EFRIS, filtered by reference number or date range. Use it to audit write-offs for a period, or to confirm that a stock decrease your ERP submitted actually landed.\n\nAll filters are optional; `startDate`/`endDate` are `yyyy-MM-dd`. `pageNo` and `pageSize` are mandatory to URA (defaulted here to 1 and 10) and `pageSize` cannot exceed 100.\n\n`adjustType` on each record: `101` = Expired Goods, `102` = Damaged Goods, `103` = Personal Uses, `104` = Others (reason in `remarks`), `105` = Raw Material(s).\n\nEvery record returns an `id` — feed it to `GET /api/external/efris/stock-adjust-detail` (T160) for the goods lines."
          },
          "response": []
        },
        {
          "name": "Query stock adjustment detail (T160)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-adjust-detail?id=208178192251887451",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-adjust-detail"
              ],
              "query": [
                {
                  "key": "id",
                  "value": "208178192251887451"
                }
              ]
            },
            "description": "Expands one stock adjustment into its header (`goodsStockAdjust`: branch, adjust date, adjust type, amount) plus every goods line showing `stock` (quantity before), `adjustQuantity` and `currentQuantity` (quantity remaining).\n\n`id` is required and comes from a `records[].id` returned by T149 (`GET /api/external/efris/stock-adjust-records`).\n\n`adjustType`: `101` = Expired Goods, `102` = Damaged Goods, `103` = Personal Uses, `104` = Others (reason in `remarks`), `105` = Raw Material(s).\n\nUse it to justify a write-off line by line during a URA audit, or when reconciling ERP inventory against EFRIS.\n\nGotcha: URA spells the goods array `goodsStocAdjustGoods` (missing the \"k\") — map that key exactly as returned."
          },
          "response": []
        },
        {
          "name": "Check negative stock configuration (T177)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/negative-stock-configuration",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "negative-stock-configuration"
              ]
            },
            "description": "Reports whether URA currently permits stock to go negative for this taxpayer, over which period, and for which commodity categories.\n\nAn ERP calls this before allowing a sale to drive EFRIS stock below zero — when negative stock is not permitted, the invoice fails at URA with a stock error rather than in your own inventory module.\n\n- **No request parameters.** Response is `goodsStockLimit` plus `goodsStockLimitCategoryList`.\n- `goodsStockLimit`: `id`, `periodFrom` / `periodTo` (yyyy-MM-dd), `allNegativeCode`, `statusCode`.\n- `allNegativeCode`: **101** = Y — negative stock allowed for every category, and the category list is empty; **102** = N — allowed only for the categories listed.\n- `statusCode`: **101** = Enable, **102** = Disable. Treat 102 as \"no negative stock at all\", whatever the period says.\n- Each `goodsStockLimitCategoryList` entry carries `commodityCategoryCode` and `isSelectAll` (**101** = Y, **102** = N)."
          },
          "response": []
        },
        {
          "name": "Query goods stock transfer records (T183)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-transfers?pageNo=1&pageSize=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-transfers"
              ],
              "query": [
                {
                  "key": "referenceNo",
                  "value": "425502528294126235",
                  "disabled": true
                },
                {
                  "key": "sourceBranchId",
                  "value": "206637525568955296",
                  "disabled": true
                },
                {
                  "key": "destinationBranchId",
                  "value": "206637528324276772",
                  "disabled": true
                },
                {
                  "key": "startDate",
                  "value": "2021-09-10",
                  "disabled": true
                },
                {
                  "key": "endDate",
                  "value": "2021-09-11",
                  "disabled": true
                },
                {
                  "key": "pageNo",
                  "value": "1"
                },
                {
                  "key": "pageSize",
                  "value": "10"
                }
              ]
            },
            "description": "Paginated list of branch-to-branch stock transfers already posted to EFRIS (via `POST /api/external/efris/stock-transfer`).\n\nAn ERP uses it to reconcile inter-branch movements for a period, or to recover the record `id` needed for the transfer detail lookup (T184).\n\n- `pageNo` and `pageSize` are always sent; **`pageSize` cannot exceed 100**. All other parameters are optional filters.\n- `startDate` / `endDate` are **yyyy-MM-dd**. `sourceBranchId` / `destinationBranchId` take 18-digit branch ids, not branch names.\n- Response: `page` (`pageNo`, `pageSize`, `totalSize`, `pageCount`) and `records[]` with `id`, `referenceNo`, `sourceBranchName`, `destinationBranchName`, `transferAmount`, `transferDate`.\n- Amounts allow up to 12 integer digits and 8 decimal places; `transferDate` comes back as dd/MM/yyyy.\n- Spec quirk: URA's field table names the branch filters `sourceBranchName` / `destinationBranchName` while its own request sample uses the `...Id` form. The middleware sends the `...Id` form, so pass branch **ids**."
          },
          "response": []
        },
        {
          "name": "Query goods stock transfer detail (T184)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-transfer-detail?id=425502528294126235",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-transfer-detail"
              ],
              "query": [
                {
                  "key": "id",
                  "value": "425502528294126235"
                }
              ]
            },
            "description": "Expands one branch-to-branch stock transfer into its header plus every transferred line item.\n\nCall it after Query stock transfer records (T183) to reconcile an inter-branch movement line by line against ERP inventory, or to justify the movement during an audit.\n\n- `id` is **required** — the 18-digit record id from `records[].id` in the T183 response.\n- `goodsStockTransfer` header: `sourceBranchId`, `destinationBranchId`, `transferDate`, `transferTypeCode`, `remarks`.\n- `transferTypeCode`: **101** = Out of Stock Adjust, **102** = Error Adjust, **103** = Others (please specify). URA may return several comma-separated, e.g. `\"101,102\"`.\n- `goodsStockTransferItem[]` per line: `commodityGoodsId`, `goodsCode`, `goodsName`, `measureUnit` (T115 `rateUnit` dictionary), `currency` (T115 `currencyType`), `unitPrice`, `bookQuantity`, `transferQuantity`, `transferAmount`, `currentQuantity`, `remarks`.\n- `currentQuantity` is the stock left at the source branch after the transfer — use it, not `bookQuantity`, when reconciling."
          },
          "response": []
        }
      ]
    },
    {
      "name": "6. Purchase Orders",
      "description": "Submit purchase orders to EFRIS (T130 - Send Purchase Order).",
      "item": [
        {
          "name": "Submit Purchase Order",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"po_number\": \"PO-2026-001\",\n  \"po_date\": \"2026-06-09\",\n  \"vendor_name\": \"Supplier XYZ Ltd\",\n  \"vendor_tin\": \"1000000001\",\n  \"total_amount\": 12500000,\n  \"currency\": \"UGX\",\n  \"delivery_date\": \"2026-06-20\",\n  \"items\": [\n    {\n      \"item_code\": \"LAP-001\",\n      \"item_name\": \"Laptop Computer\",\n      \"quantity\": 5,\n      \"unit_price\": 2000000,\n      \"total\": 10000000,\n      \"unit_of_measure\": \"102\"\n    },\n    {\n      \"item_code\": \"MOUSE-001\",\n      \"item_name\": \"Wireless Mouse\",\n      \"quantity\": 10,\n      \"unit_price\": 80000,\n      \"total\": 800000,\n      \"unit_of_measure\": \"102\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/submit-purchase-order",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "submit-purchase-order"
              ]
            },
            "description": "Submit a purchase order to EFRIS.\n\n**Required fields:**\n- `po_number` (or `poNumber`)\n- `po_date` (or `poDate`)\n- `vendor_name` (or `vendorName` / `supplierName`)\n- `items` (or `goodsDetails`) — at least one item\n- `total_amount` (or `totalAmount`)\n- `currency`\n\n**Optional:**\n- `vendor_tin` (or `vendorTin` / `supplierTin`)\n- `delivery_date` (or `deliveryDate`)"
          },
          "response": []
        }
      ]
    },
    {
      "name": "7. Reference Data",
      "description": "Lookup endpoints for EFRIS codes, categories, taxpayer info, and units of measure.",
      "item": [
        {
          "name": "Get Excise Duty Codes (T125)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/excise-duty",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "excise-duty"
              ],
              "query": [
                {
                  "key": "excise_code",
                  "value": "",
                  "description": "Filter by specific excise duty code (e.g., LED190100)",
                  "disabled": true
                },
                {
                  "key": "excise_name",
                  "value": "",
                  "description": "Filter by excise duty name (e.g., beer)",
                  "disabled": true
                }
              ]
            },
            "description": "Retrieve EFRIS excise duty codes and rates (T125).\n\nReturns all leaf-node excise codes with their rate, unit, currency, and excise rule.\n\n**Query Parameters (optional):**\n- `excise_code`: Filter by exact code (e.g., `LED190100`)\n- `excise_name`: Filter by name keyword (e.g., `beer`)\n\n**excise_rule in response:**\n- `1` = Ad Valorem (percentage-based)\n- `2` = Specific / Per Unit (fixed amount per litre/kg/etc.)"
          },
          "response": []
        },
        {
          "name": "Get Excise Duty Codes — Filter by Name",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/excise-duty?excise_name=beer",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "excise-duty"
              ],
              "query": [
                {
                  "key": "excise_name",
                  "value": "beer"
                }
              ]
            },
            "description": "Filter excise duty codes by name keyword (case-insensitive partial match)."
          },
          "response": []
        },
        {
          "name": "Get Units of Measure (T115)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/units-of-measure",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "units-of-measure"
              ]
            },
            "description": "Retrieve EFRIS unit of measure codes (T115 system dictionary).\n\nUse these codes when registering products and submitting invoices.\n\nCommon codes:\n- `101` = Stick\n- `102` = Piece / Litre\n- `103` = Kilogram\n- `8B` = Crate\n- `4C` = Box\n- `43` = Bag\n- `BO` = Bottle\n- `TN` = Tin\n- `PA` = Packet\n- `3A` = Jerrican\n\nFalls back to a cached static list if EFRIS is temporarily unavailable."
          },
          "response": []
        },
        {
          "name": "Get Commodity Categories (T124)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/commodity-categories?pageNo=1&pageSize=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "commodity-categories"
              ],
              "query": [
                {
                  "key": "pageNo",
                  "value": "1"
                },
                {
                  "key": "pageSize",
                  "value": "10"
                }
              ]
            },
            "description": "Retrieve EFRIS commodity category codes (T124) with pagination.\n\nUse these codes to map your products to the correct EFRIS category when registering via T130.\n\n**Query Parameters:**\n- `pageNo` (alias: `pageNo`): Page number (default 1)\n- `pageSize` (alias: `pageSize`): Records per page (default 10)"
          },
          "response": []
        },
        {
          "name": "Query Taxpayer by TIN (T119)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/taxpayer/{{tin}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "taxpayer",
                "{{tin}}"
              ]
            },
            "description": "Query a taxpayer's business details from URA EFRIS by their TIN (T119).\n\nUseful for B2B invoice validation — verify a customer's registered business name before invoicing.\n\nThis uses the `{{tin}}` collection variable. You can also replace `{{tin}}` in the URL with any other TIN you want to look up (e.g., a customer's TIN for verification)."
          },
          "response": []
        },
        {
          "name": "Get All Branches (T138)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/branches",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "branches"
              ]
            },
            "description": "Get all branches registered to your taxpayer (T138).\n\nReturns a list of all branches with their IDs and names. Use the `branchId` values when performing stock transfers between branches (T139).\n\n**Response Format:**\n```json\n[\n  {\n    \"branchId\": \"206637525568955296\",\n    \"branchName\": \"Mr. STEPHEN BUNJO\"\n  },\n  {\n    \"branchId\": \"206637528324276772\",\n    \"branchName\": \"ARINAIT AND SONS CO. LIMITED\"\n  }\n]\n```\n\n**Use Cases:**\n- Get valid branch IDs for stock transfer operations (T139)\n- Display available branches to end users\n- Validate branch selection before performing branch-specific operations"
          },
          "response": []
        },
        {
          "name": "Get exchange rate for one currency (T121)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/exchange-rate?currency=USD",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "exchange-rate"
              ],
              "query": [
                {
                  "key": "currency",
                  "value": "USD"
                },
                {
                  "key": "issueDate",
                  "value": "2026-08-18",
                  "disabled": true
                }
              ]
            },
            "description": "Returns URA's official rate for a single currency against UGX, together with the `importDutyLevy`, `inComeTax` and `exportLevy` rates applied to that currency.\n\n`rate` is UGX per one unit of the currency — `\"rate\": \"3700\"` means 1 USD = 3,700 UGX. An ERP calls this before invoicing a foreign-currency order so the UGX amounts on the invoice match what URA will compute.\n\n- `currency` is the 3-letter ISO code (`USD`, `EUR`, `KES`) and is required.\n- `issueDate` is optional, format `yyyy-MM-dd`; omit it for today's rate, or supply the invoice date when back-dating.\n\nIf you need rates for several currencies, call T126 once instead of looping this endpoint."
          },
          "response": []
        },
        {
          "name": "List all commodity categories (T123)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/commodity-category-list",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "commodity-category-list"
              ]
            },
            "description": "Returns the complete, unpaginated commodity category tree in one response — every code with its parent, level, VAT rate, and its zero-rate/exempt windows.\n\nAn ERP pulls this once at setup to build a local category picker, then maps each ERP product onto a category code before registering goods with T130. Keep it cached and refresh incrementally with T134 rather than re-pulling.\n\n**Takes no parameters** — URA's request message for T123 is Null.\n\n- `rate` is a decimal: `0.18` = 18%\n- `isLeafNode`, `serviceMark`, `isZeroRate`, `isExempt`: `101` = Y, `102` = N\n- `enableStatusCode`: `1` = enabled, `0` = disabled\n- `exclusion`: `0` = Zero, `1` = Exempt, `2` = No exclusion\n\nOnly leaf nodes (`isLeafNode` = `101`) may be attached to a product."
          },
          "response": []
        },
        {
          "name": "Get all exchange rates (T126)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/exchange-rates",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "exchange-rates"
              ],
              "query": [
                {
                  "key": "issueDate",
                  "value": "2026-08-18",
                  "disabled": true
                }
              ]
            },
            "description": "Returns URA's full exchange rate table as a **JSON array** — one entry per currency with `rate`, `importDutyLevy`, `inComeTax` and `exportLevy` against UGX.\n\nCache this once a day at startup instead of calling T121 per currency; a multi-currency ERP typically needs several rates per invoicing run and this is a single round trip.\n\n`rate` is UGX per one unit of the currency (1 USD = 3,700 UGX). `issueDate` is optional, format `yyyy-MM-dd` — omit it for the current day's table, or pass an invoice date to price a back-dated document at the rate that applied then."
          },
          "response": []
        },
        {
          "name": "Sync commodity category changes (T134)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/commodity-category-updates?commodityCategoryVersion=1.0",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "commodity-category-updates"
              ],
              "query": [
                {
                  "key": "commodityCategoryVersion",
                  "value": "1.0"
                }
              ]
            },
            "description": "Returns only the commodity categories that changed between a local version and URA's current version, as a **JSON array** — far cheaper than re-pulling the whole T123 list.\n\nThe intended flow: read `commodityCategoryVersion` from the T103 login response, compare it against your stored version, and when URA's is higher call this with **your local version**. Then, for each returned category, replace the matching local code or insert it if new, and finally bump the stored version.\n\nEntries carry the same fields as T123 (`rate` as a decimal, `isLeafNode`/`serviceMark`/`isZeroRate`/`isExempt` as `101` = Y / `102` = N, `enableStatusCode` `1` enabled / `0` disabled) plus two extras:\n\n- `excisable`: `101` = Y, `102` = N\n- `vatOutScopeCode`: `101` = Yes, `102` = No\n- `exclusion`: `0` Zero, `1` Exempt, `2` No exclusion, `3` Both 0% & '-'\n\nOn a first-time sync with no local version, pull the full list from T123 instead."
          },
          "response": []
        },
        {
          "name": "Check exempt or deemed taxpayer status (T137)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/taxpayer-exempt-status?tin=1009830845",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "taxpayer-exempt-status"
              ],
              "query": [
                {
                  "key": "tin",
                  "value": "1009830845"
                },
                {
                  "key": "commodityCategoryCode",
                  "value": "10000000,10000001",
                  "disabled": true
                }
              ]
            },
            "description": "Checks whether a buyer TIN is a normal, exempt, deemed, or both-status taxpayer, and returns the deemed/exempt projects that TIN is entitled to.\n\nCall it before invoicing a buyer who may be deemed or exempt: when you set `deemedFlag` = `1` on a T109 line, the `projectId` and `projectName` on that line **must** come from this response's `deemedAndExemptProjectList`, or the invoice is rejected.\n\n- `tin` is required (the spec's field table mislabels it `fileName`; it is the buyer's TIN).\n- `commodityCategoryCode` is optional — pass a comma-separated list to get per-category status in `commodityCategory`.\n- `taxpayerType` / `commodityCategoryTaxpayerType`: `101` normal, `102` exempt, `103` deemed, `104` both.\n- `exemptType`: `101` VAT, `102` Excise Duty, `103` both.\n- `deemedExemptCode`: `101` Strategic Investor, `102` Petroleum Licensee, `103` Aid-funded project Contractor, `104` Government MDA, `105` VAT & Excise Duty Exempt, `106` Excise Duty Exempt, `107` Mining Licensee, `108` EACOP Licensee, `109` EACOP Level 1 Contractor."
          },
          "response": []
        },
        {
          "name": "Query commodity category or excise duty by date (T146)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/category-excise-by-date?categoryCode=100000000&issueDate=2021-06-23 17:13:12&type=1",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "category-excise-by-date"
              ],
              "query": [
                {
                  "key": "categoryCode",
                  "value": "100000000"
                },
                {
                  "key": "issueDate",
                  "value": "2021-06-23 17:13:12"
                },
                {
                  "key": "type",
                  "value": "1"
                }
              ]
            },
            "description": "Resolves a commodity category, or an excise duty code, **as it stood on a given date** — the rate that applies to a back-dated or historic invoice, not today's rate.\n\n`type` selects what is being looked up: `1` = Commodity Category (`categoryCode` is a commodity category code, e.g. `100000000`), `2` = Excise Duty (`categoryCode` is an excise duty code, e.g. `LED010300`).\n\n`categoryCode` and `issueDate` are both required; `issueDate` must include the time — `yyyy-MM-dd HH:mm:ss`.\n\nIn `commodityCategory`, the flags `isLeafNode`, `serviceMark`, `isZeroRate`, `isExempt` and `excisable` are `101` = Y / `102` = N; `enableStatusCode` is `1` enabled / `0` disabled; `exclusion` is `0` = Zero, `1` = Exempt, `2` = No exclusion, `3` = Both 0% and '-'; `vatOutScopeCode` is `101` = Yes / `102` = No. `rate` is a decimal fraction (`0.18` = 18%).\n\nIn `exciseDuty`, each `exciseDutyDetailsList` entry has `type` `101` = percentage rate, `102` = rate per unit of measurement — `unit` (a `rateUnit` code) is set only when `type` is `102`."
          },
          "response": []
        },
        {
          "name": "Query agent relation information (T179)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/agent-relations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "agent-relations"
              ],
              "query": [
                {
                  "key": "tin",
                  "value": "1009837013",
                  "disabled": true
                }
              ]
            },
            "description": "Lists the principal taxpayers, and their branches, that this taxpayer is authorised to invoice on behalf of as an agent.\n\nCall it at the start of an agent-invoicing flow to populate the \"invoice on behalf of\" picker, and to obtain the `branchId` that T180 requires.\n\n- `tin` is **optional** — supply a principal agent TIN to filter to one relationship, omit it to return every relationship.\n- Each `agentTaxpayerList` entry: `taxpayerId`, `tin`, `ninBrn`, `legalName`, `businessName`, `contactNumber`, `contactEmail`, `address`, `taxpayerType`, `taxpayerStatus`, `branchId`, `branchCode`, `branchName`, `branchStatus`.\n- `taxpayerType`: **201** = Individual, **202** = Non-Individual.\n- `taxpayerStatus` and `branchStatus` both use the same dictionary: **101** = Registered, **102** = Deactivated, **103** = Suspended, **104** = Deregistered. Only a relationship where *both* read 101 can be invoiced against."
          },
          "response": []
        },
        {
          "name": "Query principal agent TIN information (T180)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/principal-agent?tin=1009837013&branchId=210059212594887180",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "principal-agent"
              ],
              "query": [
                {
                  "key": "tin",
                  "value": "1009837013"
                },
                {
                  "key": "branchId",
                  "value": "210059212594887180"
                }
              ]
            },
            "description": "Returns the tax types registered against one principal agent's branch, together with the invoicing rules URA applies when you issue on that principal's behalf.\n\nCall it once per principal branch before agent invoicing, and cache the flags — they decide whether back-dating or out-of-scope VAT lines will be accepted.\n\n- **Both `tin` and `branchId` are required.** Take the pair from Query agent relations (T179); a `branchId` belonging to a different principal is rejected.\n- `taxType[]`: `taxTypeName`, `taxTypeCode` (taxType dictionary — e.g. **301** = Value Added Tax), `registrationDate`, `cancellationDate`.\n- Flags returned as `\"0\"` = No / `\"1\"` = Yes: `issueTaxTypeRestrictions`, `isAllowBackDate`, `isDutyFreeTaxpayer`, `isAllowIssueInvoice`, `isAllowOutOfScopeVAT`.\n- `periodDate` is the number of days back-dating is permitted (URA system parameter, default **7**) and only matters when `isAllowBackDate` is `1`.\n- `sellersLogo` is **not** a flag — it is base64 image content for the seller logo, of unlimited length."
          },
          "response": []
        },
        {
          "name": "Upload frequent contact (T181)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"operationType\": \"102\",\n  \"buyerType\": \"0\",\n  \"id\": \"613714332817808478\",\n  \"buyerTin\": \"1009837013\",\n  \"buyerNinBrn\": \"09656200018719\",\n  \"buyerLegalName\": \"Mr. PETER KADDU\",\n  \"buyerBusinessName\": \"ZAYN KIDS ORNAMENT\",\n  \"buyerEmail\": \"peter.kaddu@zaynkids.co.ug\",\n  \"buyerLinePhone\": \"00256779523165\",\n  \"buyerAddress\": \"KAZAHI KANUNGU KINKIZI WEST KAYONZA\",\n  \"buyerCitizenship\": \"UG-Uganda\",\n  \"buyerPassportNum\": \"B1053672\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/upload-frequent-contact",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "upload-frequent-contact"
              ]
            },
            "description": "Maintains the saved buyer book an ERP reuses when raising invoices — add, edit or remove one frequent contact per call. Read the book back with `GET /api/external/efris/frequent-contacts` (T182).\n\n`operationType`: `101` = Add, `102` = Modify, `103` = Delete. `buyerType`: `0` = B2B, `1` = B2C, `2` = Foreigner, `3` = B2G (T181 accepts `3`; T166 does not). Both are required — the middleware returns **HTTP 400** if either is missing or blank.\n\n`id` is the 18-digit contact id EFRIS assigned, retrieved from T182. The spec's field table marks it optional because it does not apply to every operation: **omit it for `101` (Add)**, and supply it for `102` and `103`, which cannot identify a row without it. The example below is a modify, which is why `id` is present.\n\nAll remaining buyer fields are optional and stored as supplied. `buyerCitizenship` uses the country-code form `\"UG-Uganda\"` here, not the bare `\"1\"` that T166 uses. EFRIS returns an empty payload on success."
          },
          "response": []
        },
        {
          "name": "Get frequent contacts (T182)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/frequent-contacts",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "frequent-contacts"
              ],
              "query": [
                {
                  "key": "buyerTin",
                  "value": "1009837013",
                  "disabled": true
                },
                {
                  "key": "buyerLegalName",
                  "value": "Mr. PETER KADDU",
                  "disabled": true
                }
              ]
            },
            "description": "Returns the saved buyer book previously uploaded through Upload frequent contacts (T181).\n\nUse it to prefill buyer details on an invoice from a stored contact, and to recover the `id` that T181 needs for a modify or delete.\n\n- **Both filters are optional** — omit `buyerTin` and `buyerLegalName` to return the entire book; supply either to narrow it.\n- Each entry: `id`, `buyerType`, `buyerTin`, `buyerNinBrn`, `buyerLegalName`, `buyerBusinessName`, `buyerEmail`, `buyerLinePhone`, `buyerAddress`, `buyerCitizenship`, `buyerPassportNum`.\n- `buyerType`: **0** = B2B, **1** = B2C, **2** = Foreigner, **3** = B2G.\n- Gotcha: the contact's email key here is `buyerEmail`, whereas the invoice interfaces (T109, T166) call the same field `buyerEmailAddress` — remap it when copying a contact onto an invoice."
          },
          "response": []
        },
        {
          "name": "Query HS code list (T185)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/hs-codes",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "hs-codes"
              ]
            },
            "description": "Returns the full URA HS (Harmonised System) code tree used on export and customs invoice lines.\n\nERP integrators pull it once to build an HS code picker and to validate the `hsCode` sent on export invoice lines before submission.\n\n- **No request parameters.** The response is a JSON array of `{hsCode, description, isLeaf, parentClass}`.\n- `isLeaf` is **inverted** from the obvious reading: **0** = yes, this is a leaf; **1** = no, it has children. (Note this differs from T162's `isLeafNode`, which uses 101 = Y / 102 = N.)\n- Only leaf codes may be quoted as the `hsCode` on an invoice line; `parentClass` links a node to its parent so you can rebuild the tree locally.\n- The list is large and changes rarely — cache it rather than calling per invoice."
          },
          "response": []
        }
      ]
    },
    {
      "name": "8. Passthrough (Advanced)",
      "description": "Generic passthrough to call any EFRIS interface code directly. For advanced integrators only.",
      "item": [
        {
          "name": "Passthrough — T101 Server Time",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/passthrough/T101?encrypt_code=1",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "passthrough",
                "T101"
              ],
              "query": [
                {
                  "key": "encrypt_code",
                  "value": "1",
                  "description": "1=Encrypted (default), 2=Plain, 3=Signed only"
                }
              ]
            },
            "description": "Generic EFRIS passthrough for T101 (Server Time). Replace `T101` in the URL with any EFRIS interface code (T101–T187).\n\nThe middleware automatically:\n- Manages the AES session key\n- Signs the payload digitally\n- Encrypts/decrypts as required\n\n**encrypt_code query parameter:**\n- `1` = Encrypted (default)\n- `2` = Plain text\n- `3` = Signed only, no encryption"
          },
          "response": []
        },
        {
          "name": "Passthrough — T119 Taxpayer Query",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"tin\": \"{{tin}}\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/passthrough/T119?encrypt_code=2",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "passthrough",
                "T119"
              ],
              "query": [
                {
                  "key": "encrypt_code",
                  "value": "2"
                }
              ]
            },
            "description": "Passthrough example for T119 (Taxpayer Query). Send the raw content payload in the request body."
          },
          "response": []
        },
        {
          "name": "Passthrough — T127 Goods Query",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"pageNo\": 1,\n  \"pageSize\": 10\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/passthrough/T127?encrypt_code=2",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "passthrough",
                "T127"
              ],
              "query": [
                {
                  "key": "encrypt_code",
                  "value": "2"
                }
              ]
            },
            "description": "Passthrough example for T127 (Goods and Services Query). Send pagination parameters in the request body."
          },
          "response": []
        },
        {
          "name": "Passthrough — T106 Invoice/Receipt Query",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"startDate\": \"2026-08-01\",\n  \"endDate\": \"2026-08-26\",\n  \"invoiceKind\": \"1\",\n  \"pageNo\": \"1\",\n  \"pageSize\": \"10\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/passthrough/T106?encrypt_code=2",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "passthrough",
                "T106"
              ],
              "query": [
                {
                  "key": "encrypt_code",
                  "value": "2"
                }
              ]
            },
            "description": "Passthrough example for T106 (Invoice/Receipt query). Queries all invoice types — invoice/receipt, credit note, debit note and their cancellations. Every field in the body is an optional filter; send only the ones you want to filter on. There is no dedicated REST route for T106, so the passthrough is the supported way to call it."
          },
          "response": []
        },
        {
          "name": "Passthrough — T108 Invoice Details",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"invoiceNo\": \"{{invoice_no}}\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/passthrough/T108?encrypt_code=2",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "passthrough",
                "T108"
              ],
              "query": [
                {
                  "key": "encrypt_code",
                  "value": "2"
                }
              ]
            },
            "description": "Passthrough example for T108 (Invoice details). Returns the full record for one invoice — seller, buyer, goods lines, tax breakdown and summary. Takes the FDN/invoice number only. There is no dedicated REST route for T108, so the passthrough is the supported way to call it."
          },
          "response": []
        }
      ]
    },
    {
      "name": "9. Fuel & EDC",
      "description": "Electronic Dispensing Controller (EDC) interfaces for fuel stations: fuel types, pump/nozzle/tank configuration, shift uploads, EDC invoice inquiry and disconnection reporting.",
      "item": [
        {
          "name": "Query fuel type (T162)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/fuel-types",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "fuel-types"
              ]
            },
            "description": "Returns the EFRIS fuel type catalogue as a flat tree: `fuelTypeCode`, `parentCode`, `fuelTypeName`, `fuelTypeLevel` and `isLeafNode` (`101` = Y, `102` = N).\n\nTakes no query parameters and no body — URA's request message for T162 is NULL.\n\nAn ERP calls this at setup (and occasionally after) to map its own fuel products onto URA codes before uploading shift information (T163) or issuing fuel invoices.\n\nOnly leaf nodes (`isLeafNode` = `101`) are selectable fuel types; the rest are grouping levels, so walk `parentCode` to build the picker."
          },
          "response": []
        },
        {
          "name": "Query fuel pump versions (T168)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/fuel-pump-versions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "fuel-pump-versions"
              ]
            },
            "description": "Returns `fuelPumpList` (`id`, `branchId`, `pumpNo`, `pumpVersion`) and `fuelDefaultBuyerList` (`id`, `taxpayerId`, `branchId`, `legalName`).\n\nTakes no query parameters and no body — URA's request message for T168 is NULL.\n\nAn ERP polls this and compares each `pumpVersion` against its cached copy; a changed value means the pump, its nozzles or its tanks were reconfigured, and the detail is then pulled with T169 using that pump's `id`.\n\n`fuelDefaultBuyerList` gives the default buyer configured per branch, used to stamp unattributed pump sales."
          },
          "response": []
        },
        {
          "name": "Query fuel pump, nozzle and tank detail (T169)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/fuel-pump-details?id=689769596689001259",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "fuel-pump-details"
              ],
              "query": [
                {
                  "key": "id",
                  "value": "689769596689001259"
                }
              ]
            },
            "description": "Given a fuel pump `id` (required — take it from T168's `fuelPumpList[].id`), returns the `fuelPump` record plus its `fuelNozzleList`, `fuelTankList` and `fuelEdcDeviceList`.\n\nThis is where an ERP resolves the `pumpNo`, `nozzleNo` and `tankNo` values that a shift upload (T163) requires, and reads each tank's `presentPrice` and `commodityGoodsId` for pricing fuel invoice lines.\n\n`enableStatusCode` on pump, nozzle, tank and EDC device: `101` = enabled, `102` = disabled. Nozzle `lockedStatusCode`: `101` = yes (locked), `102` = no.\n\n`fuelEdcDeviceList[].edcDeviceTypeCode`: `101` = Controller, `102` = Acquisition Equipment, `103` = Level Gauge."
          },
          "response": []
        },
        {
          "name": "Query EDC UoM exchange rates (T171)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/edc-uom-exchange-rates",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "edc-uom-exchange-rates"
              ]
            },
            "description": "Returns the unit-of-measure exchange rates URA applies to EDC (fuel) devices, as pairs of `unitOfMeasure` and `exchangeRate`.\n\nAn ERP calls this when the pump meters volume in one unit but the fuel invoice line is priced and declared in another, so the metered figure has to be converted before it reaches a T109 invoice.\n\n- **No request parameters.** The response is a JSON array, e.g. `[{\"unitOfMeasure\": \"102\", \"exchangeRate\": \"1\"}]`.\n- `unitOfMeasure` is the 3-digit EFRIS unit code from the `rateUnit` dictionary (retrieved with T115).\n- `exchangeRate` is a decimal string relative to the base unit for that code.\n- The table is small and near-static: fetch once at startup and cache rather than calling per shift upload."
          },
          "response": []
        },
        {
          "name": "Query EDC device versions (T173)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/edc-device-versions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "edc-device-versions"
              ]
            },
            "description": "Lists the EDC (fuel station) device versions URA recognises, with the manufacturer and device type of each.\n\nUse it to validate fuel-station hardware before nozzle status uploads (T172) or shift uploads (T163) — a device whose version is not on this list will be rejected downstream.\n\n- **No request parameters.** The response is a JSON array of `{id, manufacturerCode, manufacturerName, deviceTypeCode, versionNo}`.\n- `deviceTypeCode`: **101** = Controller, **102** = Acquisition Equipment, **103** = Level Gauge.\n- `id` is an 18-digit EFRIS record id (e.g. `208178192251887451`); `versionNo` is a free-form version string up to 20 characters."
          },
          "response": []
        },
        {
          "name": "Upload fuel shift information (T163)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"shiftNo\": \"20260818-01\",\n  \"startVolume\": \"851.91\",\n  \"endVolume\": \"1974.36\",\n  \"fuelType\": \"Kerosene\",\n  \"goodsId\": \"893997229738400343\",\n  \"goodsCode\": \"Kerosene_01\",\n  \"invoiceAmount\": \"5162314.00\",\n  \"invoiceNumber\": \"16\",\n  \"nozzleNo\": \"nozzle_01_0001\",\n  \"pumpNo\": \"pump_01_0001\",\n  \"tankNo\": \"tank_01_0001\",\n  \"userName\": \"Joseph Kabuye\",\n  \"userCode\": \"jkabuye0001\",\n  \"startTime\": \"2026-08-18 06:00:00\",\n  \"endTime\": \"2026-08-18 14:00:00\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/fuel-shifts",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "fuel-shifts"
              ]
            },
            "description": "Posts one completed fuel-pump attendant shift to EFRIS — the EDC forecourt equivalent of a shift close-out. A station system calls it each time an attendant hands over.\n\n**Every field is mandatory.** `startVolume` and `endVolume` are the nozzle totaliser readings at shift open and close (decimal strings), so `endVolume` should exceed `startVolume`. `invoiceAmount` is the money billed across the shift; `invoiceNumber` is the **invoice count**, not an FDN — this is the field integrators most often mis-populate.\n\n`fuelType` is the goods name (max 200) and should match a `fuelTypeName` from T162. `goodsId` (18) and `goodsCode` (50) identify the registered product. `nozzleNo`, `pumpNo` and `tankNo` come from T169 (pump/nozzle/tank detail), which you reach with a pump id from T168. `userCode` is the attendant's login account, `userName` their display name.\n\n`startTime` and `endTime` are `yyyy-MM-dd HH:mm:ss`; `shiftNo` is capped at 20 characters. Success returns a `NULL` payload."
          },
          "response": []
        },
        {
          "name": "Upload fuel nozzle status (T172)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"nozzleId\": \"208178192251887451\",\n  \"nozzleNo\": \"N1225-0011\",\n  \"status\": \"1\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/fuel-nozzle-status",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "fuel-nozzle-status"
              ]
            },
            "description": "Reports the live state of one fuel nozzle to URA as it changes. EDC / fuel-station controllers post this on every state transition so URA can follow pump activity in near real time.\n\nAll three keys are mandatory. `nozzleId` is the 18-digit EFRIS nozzle id: call `GET /api/external/efris/fuel-pump-details` (T169) with a pump id from T168, then take the `id` of the entry you want out of the returned `fuelNozzleList`. `nozzleNo` (max 50) is the nozzle label configured on the pump — it appears alongside that `id` in the same T169 record.\n\n`status`: `1` = Available, `2` = Card Plug-in, `3` = Nozzle Lift, `4` = Fueling, `5` = Nozzle Hang, `6` = Settling, `7` = Nozzle Locked, `10` = Offline. There is no `8` or `9` — the sequence jumps straight to `10`.\n\nEFRIS returns an empty payload on success."
          },
          "response": []
        },
        {
          "name": "Query EDC invoices and receipts (T167)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/edc-invoices?pageNo=1&pageSize=10&queryType=3",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "edc-invoices"
              ],
              "query": [
                {
                  "key": "pageNo",
                  "value": "1"
                },
                {
                  "key": "pageSize",
                  "value": "10"
                },
                {
                  "key": "queryType",
                  "value": "3"
                },
                {
                  "key": "fuelType",
                  "value": "Naphtha",
                  "disabled": true
                },
                {
                  "key": "invoiceNo",
                  "value": "321000229045",
                  "disabled": true
                },
                {
                  "key": "buyerLegalName",
                  "value": "PARAMOUR COSMETICS LIMITED",
                  "disabled": true
                },
                {
                  "key": "startDate",
                  "value": "2021-12-28",
                  "disabled": true
                },
                {
                  "key": "endDate",
                  "value": "2021-12-28",
                  "disabled": true
                },
                {
                  "key": "branchId",
                  "value": "2020090132456",
                  "disabled": true
                }
              ]
            },
            "description": "Paginated search over EDC (fuel station) invoices and receipts, used to reconcile pump sales against the documents URA holds.\n\n`queryType` is mandatory to URA and selects the population: `1` = gas-station invoices that have not been modified, `2` = invoices successfully issued by the modified contact, `3` = all (the default sent here).\n\n`fuelType`, `invoiceNo`, `buyerLegalName`, `startDate`, `endDate` and `branchId` are optional filters; `pageSize` cannot exceed 100.\n\nRecord enums: `invoiceType` `1` = Invoice/Receipt, `2` = Credit Note with original FDN, `3` = Credit Note without original FDN, `4` = Debit Note; `invoiceKind` `1` = Invoice, `2` = Receipt; `isInvalid` `1` = voided, `0` = not voided; `isRefund` `0` = no note issued, `1` = credit note issued, `2` = debit note issued.\n\n`dataSource`: `101` = EFD, `102` = Windows Client APP, `103` = WebService API, `104` = MIS, `105` = Web portal, `106` = Offline Mode Enabler. EDC documents carry `invoiceIndustryCode` `110`."
          },
          "response": []
        },
        {
          "name": "Upload EDC disconnection data (T164)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "[\n  {\n    \"deviceNumber\": \"208178192251887451\",\n    \"disconnectedType\": \"101\",\n    \"disconnectedTime\": \"2026-08-18 10:00:00\",\n    \"remarks\": \"Controller link lost during power outage at Ntinda station\"\n  },\n  {\n    \"deviceNumber\": \"208178192251887451\",\n    \"disconnectedType\": \"102\",\n    \"disconnectedTime\": \"2026-08-18 11:42:35\",\n    \"remarks\": \"Abnormal transaction - nozzle 3333 metered volume did not match the issued receipt\"\n  }\n]"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/edc-disconnections",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "edc-disconnections"
              ]
            },
            "description": "Reports EDC device downtime to URA so the offline window can be reconciled against the receipts issued during it. A forecourt system calls it once the device is back online.\n\nThe body is a bare **JSON array** of records — not an object wrapper — and the middleware forwards it to EFRIS verbatim, so use URA's own field names exactly.\n\n`disconnectedType`: `101` = TCS disconnected with Controller, `102` = Abnormal Transaction. `deviceNumber` (max 50) is the EDC device number, and `disconnectedTime` is `yyyy-MM-dd HH:mm:ss`.\n\n`remarks` is free text and the only optional field; everything else is required on every record. Send one record per disconnection event. Success returns a `NULL` payload."
          },
          "response": []
        }
      ]
    },
    {
      "name": "10. Device, Session & Agent",
      "description": "Device provisioning and session interfaces: client initialisation, key/certificate upload, EFD location and transfer, and device issuing status.",
      "item": [
        {
          "name": "Fetch client initialization keys (T102)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/client-initialization",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "client-initialization"
              ],
              "query": [
                {
                  "key": "otp",
                  "value": "100983",
                  "disabled": true
                }
              ]
            },
            "description": "Seeds the local key store for this taxpayer's device: returns `serverPubKey` (used to verify signatures on every EFRIS response), the encrypted `clientPriKey`, and the white-box `keyTable` used to decrypt that private key.\n\nAn ERP calls this once when a device is provisioned, and again only if the stored keys are lost or corrupted — it is not part of the per-invoice flow.\n\n`otp` is the 6-digit one-time password URA issues for a device; leave it off unless URA gave you one. Note that `clientPriKey` is only returned when the taxpayer's `appId` is `AP01` — other app ids get `serverPubKey` and `keyTable` only."
          },
          "response": []
        },
        {
          "name": "Reset forgotten password (T105)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"userName\": \"admin\",\n  \"changedPassword\": \"Kla#Efris2026\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/forgot-password",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "forgot-password"
              ]
            },
            "description": "Resets the EFRIS **enterprise portal** password for one user name. On success URA emails the account information to the enterprise e-mail on file; the interface returns a null payload, so treat the `returnCode` as the confirmation.\n\nAn ERP rarely calls this — it is an onboarding / account-lockout tool for the taxpayer's own URA portal login.\n\n- `userName` — enterprise user name, mandatory, max 200 chars\n- `changedPassword` — the new password, mandatory, max 200 chars; it must satisfy URA's own password policy or EFRIS rejects the request\n\nThe request is encrypted end to end (encryptCode 2), so the password never travels in clear text."
          },
          "response": []
        },
        {
          "name": "Upload certificate public key (T136)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"fileName\": \"Certum Trusted NetWork CA 2.cer\",\n  \"verifyString\": \"MDQwNDAxMDcxNVowMzELMAkGA1UEBhMCRU4x\",\n  \"fileContent\": \"MIIDFjCCAf6gAwIBAgIRAKPGAol99EKUPlA/VZYC+u8wDQYJKoZIhvcNAQELBQAwMzELMAkGA1UEBhMCRU4xJDAiBgNVBAMMG0NlcnR1bSBUcnVzdGVkIE5ldFdvcmsgQ0EgMjAgFw0wMDA0MTkwMTA3MTVaGA8yMDYwMDQwNDAxMDcxNVowMzELMAkGA1UEBhMCRU4xJDAiBgNVBAMMG0NlcnR1bSBUcnVzdGVkIE5ldFdvcmsgQ0EgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANEC+sWUcfJFToC57ghh7WvGLDrfx5lIp0yrZDEiHXtx32GqAFokXmwzJ82iDVwIrbDSIf62NBQ5zt5NENdk5oi36rwYlDNWMTEs8rtwGMWJuiZRMaleVPVjL1Ecf2T4cCWiGw83qvNyWDAd4OaYV0DCvBe3YPR7bOKrznwEv/Eycp+NiBOkpidYnyrdb/A4gsMBuEKYjIQ3z5lrrEuAUrpJADf2jlxTTJ7ede1Dmyga1yzoOeAuc0ZLEJKaqNG2cwK+tOZ9W7OL/KmHgY/+FhMOd9xzuJoEJnFycjn5x7Ha1+GyScMPUacT3Z3X9+ukYXyQriyAavLOwwTYdZ4hn+ECAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAHIGw8c873dM1gMglwffWS9hx8U+36S3z2zmJPELJo/Vf9qsl+75UCRL0ORagyX1yy5rxN+Wf5TXlHluEosjC+aR0P4NXUqKF9bSz8H4Q/yPgjR0tjiWKDHpxCMdzSGhpVFcdBCHUu2o25k2IeKdw8gm5lkZQW1CxgQpb/C8xwzwD8faqwPKMEf+m96axUoVzi9fgnnP+awERdUVJEhFo6JJVKIX8mTbQv83VC3gI5eq/xSprXEwQyQvELJ9S1TvJtkqbSdgRrnCEdpkIoFa8huM6zfj1WEBRxteoo6PH46un4FGj4N6ioIGzVr9G40uhQGdm16ZU+q44XjW2oUnI9w=\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/certificate-public-key",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "certificate-public-key"
              ]
            },
            "description": "Registers the taxpayer's signing-certificate public key with EFRIS. This is a one-off provisioning step, done after the device is initialised (T102) and before any signed document is uploaded.\n\n`fileName` (max 256) **must** end in `.crt` or `.cer` — EFRIS rejects any other extension outright. `verifyString` is that same file name encrypted with an AES key built from the **first 10 characters of the TIN concatenated with `yymmdd`**; get this wrong and the upload fails even when the certificate itself is perfectly valid. `fileContent` is the certificate DER as one base64 string — no PEM `-----BEGIN CERTIFICATE-----` header/footer and no line breaks.\n\nAll three fields are mandatory. Unlike most EFRIS interfaces this one is **not encrypted** in either direction (the middleware signs but does not AES-encrypt it), and a success response carries a `NULL` payload."
          },
          "response": []
        },
        {
          "name": "Query EFD location history (T170)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/efd-location?deviceNumber=00031000092",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "efd-location"
              ],
              "query": [
                {
                  "key": "deviceNumber",
                  "value": "00031000092"
                },
                {
                  "key": "startDate",
                  "value": "2019-06-14",
                  "disabled": true
                },
                {
                  "key": "endDate",
                  "value": "2019-06-15",
                  "disabled": true
                }
              ]
            },
            "description": "Traces where a fiscal device has been operating, returning `deviceNumber`, `longitude`, `latitude` and `recordDate` per position record.\n\n`deviceNumber` is required. `startDate` and `endDate` are optional `yyyy-MM-dd` bounds — omit them to get the device's most recent positions.\n\nURA caps the result at the latest X records, where X is the system parameter `LocationCountLimit` (default 10), so widening the date range does not return every position inside it.\n\nERPs use this for device-location audits and to confirm an EFD is being operated at its registered branch."
          },
          "response": []
        },
        {
          "name": "Upload device issuing status (T176)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"deviceNo\": \"00022080670\",\n  \"deviceIssuingStatus\": \"101\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/device-issuing-status",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "device-issuing-status"
              ]
            },
            "description": "Keeps URA informed of where a fiscal device sits in its issuing cycle. A TCS/EDC client posts this as the device moves between states, so URA can distinguish an idle device from a stalled one.\n\nBoth keys are mandatory. `deviceNo` (max 20) is the fiscal device number as registered with URA.\n\n`deviceIssuingStatus`: `101` = Ready, `102` = Issuing, `103` = Printing.\n\nUnlike most interfaces in this collection, T176 is sent to URA **unencrypted** in both directions (Request Encrypted = N, Response Encrypted = N; encryptCode 1 in the client). The middleware handles that, and nothing changes for the caller. EFRIS returns an empty payload on success."
          },
          "response": []
        },
        {
          "name": "Transfer EFD to another branch (T178)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"destinationBranchId\": \"214342953041962148\",\n  \"remarks\": \"Relocating EFD to Ntinda branch after store move\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/efd-transfer",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "efd-transfer"
              ]
            },
            "description": "Moves the registered EFD to a different branch of the same taxpayer. Used when a till or fuel controller is physically relocated, so that subsequent invoices carry the correct branch.\n\n`destinationBranchId` is required (18 digits) — look it up with `GET /api/external/efris/branches`. The middleware validates it before calling URA and returns **HTTP 400** if it is missing or blank, rather than a 500.\n\n`remarks` is optional, max 1024 characters, and is stored on the transfer record as an audit note. Omit it entirely and the middleware simply does not send the key.\n\nThere is no source-branch field in the body: the device being transferred is the one identified by the `deviceNo` the middleware puts in the request header, i.e. the device bound to the credentials this request is made with. EFRIS returns an empty payload on success."
          },
          "response": []
        }
      ]
    },
    {
      "name": "11. System & Utilities",
      "description": "TCS version/upgrade interfaces, exception log upload, and USSD taxpayer account creation.",
      "item": [
        {
          "name": "Download TCS upgrade files (T133)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/tcs-upgrade-files?tcsVersion=1&osType=1",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "tcs-upgrade-files"
              ],
              "query": [
                {
                  "key": "tcsVersion",
                  "value": "1"
                },
                {
                  "key": "osType",
                  "value": "1"
                }
              ]
            },
            "description": "Returns everything needed to upgrade a TCS installation: `precommand`/`command` file streams (base64) with their target urls and filenames, a `fileList` of update attachments, and a `sqlList` of scripts to run.\n\nThis is a device-maintenance call, not part of the invoicing flow — poll T135 for the latest published version, compare it with what is installed, and call this only when an upgrade is due.\n\n- `tcsVersion` is required: the version **currently installed locally**, a number starting from 1.\n- `osType`: `0` = linux, `1` = windows. It defaults to `1` here, so a Windows host can omit it.\n\nApply `fileList` and `sqlList` entries in `ordernumber` sequence — the order is significant."
          },
          "response": []
        },
        {
          "name": "Get latest TCS version (T135)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/tcs-latest-version",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "tcs-latest-version"
              ]
            },
            "description": "Returns the newest TCS version URA has published, as `{\"latesttcsversion\": \"5\"}`.\n\n**Takes no parameters** — URA's request message for T135 is NULL.\n\nUse it as the cheap precondition check on the upgrade path: compare `latesttcsversion` against the version installed locally and only call T133 to pull the upgrade files when this one is higher. Relevant to TCS/device deployments; a pure ERP integration never needs it."
          },
          "response": []
        },
        {
          "name": "Upload exception log (T132)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"logs\": [\n    {\n      \"interruptionTypeCode\": \"102\",\n      \"description\": \"Login failed\",\n      \"errorDetail\": \"T104 login rejected for device 208178192251887451: returnCode 2001, invalid user name or password\",\n      \"interruptionTime\": \"2026-08-18 07:02:41\"\n    },\n    {\n      \"interruptionTypeCode\": \"103\",\n      \"description\": \"Receipt upload failure\",\n      \"errorDetail\": \"T109 upload timed out after 30000 ms; invoice SO-2026-004417 held in the offline queue and re-sent via T129\",\n      \"interruptionTime\": \"2026-08-18 09:41:07\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/exception-logs",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "exception-logs"
              ]
            },
            "description": "Reports the abnormal events the client recorded since its last login — disconnections, failed logins, failed receipt uploads. An ERP or offline-mode enabler posts the accumulated log on reconnect, typically right before flushing queued invoices with T129.\n\n`interruptionTypeCode`: `101` = Number of Disconnected, `102` = Login Failure, `103` = Receipt Upload Failure, `104` = System related errors, `105` = Paper roll replacement.\n\n`description` (max 3000) and `interruptionTime` (`yyyy-MM-dd HH:mm:ss`) are mandatory on every entry; `errorDetail` (max 4000) is optional but it is the field URA support actually reads, so fill it with the real upstream error.\n\n`logs` is the documented key; the middleware also accepts `data` as an alias for the same array. A successful response carries a `Null` payload — the return code is the whole answer."
          },
          "response": []
        },
        {
          "name": "Create USSD taxpayer account (T175)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"tin\": \"1009837013\",\n  \"mobileNumber\": \"256772500431\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/ussd-taxpayer-account",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "ussd-taxpayer-account"
              ]
            },
            "description": "Registers a taxpayer on URA's USSD channel so they can issue and query invoices from a feature phone, with no online client installed.\n\nBoth keys are mandatory and neither has an enum. `tin` is 10-20 characters. `mobileNumber` (max 30) becomes the identity bound to the USSD account, so it must be the line the taxpayer will actually dial from.\n\nAn ERP typically calls this once during onboarding, for small merchants who have no EFRIS-capable POS. EFRIS returns an empty payload on success."
          },
          "response": []
        }
      ]
    },
    {
      "name": "12. Error Examples",
      "description": "Example requests that demonstrate common error responses for testing error handling in your ERP.",
      "item": [
        {
          "name": "Error — Missing Required Field",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"invoice_number\": \"INV-ERR-001\",\n  \"invoice_date\": \"2026-06-09\",\n  \"items\": [\n    {\n      \"item\": \"Test Product\",\n      \"qty\": \"1\",\n      \"unitPrice\": \"10000\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/submit-invoice",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "submit-invoice"
              ]
            },
            "description": "Missing `customer_name` field — should return HTTP 422 Unprocessable Entity with validation error details."
          },
          "response": []
        },
        {
          "name": "Error — Invalid API Key (401)",
          "request": {
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-API-Key",
                  "type": "string"
                },
                {
                  "key": "value",
                  "value": "invalid_key_test_12345",
                  "type": "string"
                },
                {
                  "key": "in",
                  "value": "header",
                  "type": "string"
                }
              ]
            },
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/server-time",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "server-time"
              ]
            },
            "description": "Demonstrates the 401 Unauthorized response when an invalid API key is provided."
          },
          "response": []
        },
        {
          "name": "Error — Unconfigured TIN (400)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/external/efris/taxpayer/9999999999",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "taxpayer",
                "9999999999"
              ]
            },
            "description": "Demonstrates the 400 response when a TIN is not yet configured in the system. The middleware validates TINs in path parameters, query params, headers, and request body."
          },
          "response": []
        },
        {
          "name": "Error — Stock Transfer Same Branch (400)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "options": {
                "raw": {
                  "language": "json"
                }
              },
              "raw": "{\n  \"goodsStockTransfer\": {\n    \"source_branch_id\": \"206637525568955296\",\n    \"destination_branch_id\": \"206637525568955296\",\n    \"transfer_type_code\": \"101\"\n  },\n  \"goodsStockTransferItem\": [\n    {\n      \"goods_code\": \"CHAIR-001\",\n      \"measure_unit\": \"102\",\n      \"quantity\": \"10\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/efris/stock-transfer",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "external",
                "efris",
                "stock-transfer"
              ]
            },
            "description": "Demonstrates 400 error when source and destination branch IDs are the same."
          },
          "response": []
        }
      ]
    }
  ]
}