# Weaf EFRIS API > A REST wrapper over Uganda Revenue Authority's EFRIS (Electronic Fiscal > Receipting and Invoicing Solution). It handles the URA handshake, signing and > payload shaping so you can register products, fiscalise invoices and receipts, > raise credit notes and pull reports over ordinary JSON over HTTPS. Provider: Weaf Company Uganda Limited (services@weafcompany.com, +256 756 508 361) Docs: https://efrisapi.weafcompany.com Machine-readable spec: https://weafcompany.com/api/docs?api-docs.json ## How requests are shaped Base URL: `https://weafcompany.com` Two families of endpoint. Note the asymmetry — `v1` is not a global prefix: - `POST /api/v1/auth/*` — token lifecycle. Takes `username` and `password`, returns a bearer token. Does **not** take the `X-Environment` header; a token works against either environment. - `/api/{tin}/*` — the EFRIS operations, with **no `v1` segment**. `{tin}` is the taxpayer's own URA TIN, passed directly after `/api/`. All 18 of these accept the `X-Environment` header. Required headers on EFRIS calls: ``` Authorization: Bearer {token} Content-Type: application/json X-Environment: Sandbox ``` `X-Environment` selects which URA backend the call is routed to. Allowed values are exactly `Production` and `Sandbox`; the spec marks it optional with a default of `Sandbox`. There is no separate hostname or URL path per environment. An `environment` query parameter with the same two values is accepted as an alternative to the header. `Production` fiscalises real documents against the taxpayer's URA account, so default to `Sandbox` in any generated code unless the user has explicitly asked for production. ## Getting a token ``` POST /api/v1/auth/generate-token { "username": "you@example.com", "password": "...", "expiry_days": 30, "token_name": "Integration name" } ``` Returns `data.token`. Tokens expire; refresh via `POST /api/v1/auth/refresh-token` with the current valid token in the `Authorization` header. ## Endpoints There are exactly 21, listed here with their methods. There is no bare `/api/v1` endpoint and no `v1` segment on the EFRIS operations. Auth — these three, and only these, live under `/api/v1`: - `POST /api/v1/auth/generate-token` — exchange username/password for a bearer token - `POST /api/v1/auth/validate-token` — check a token and return user/company info - `POST /api/v1/auth/refresh-token` — issue a replacement token, invalidating the old one Products and catalogue: - `POST /api/{tin}/sync-products` — pull the product catalogue registered in EFRIS - `POST /api/{tin}/register-product` — register products (batch) - `GET|POST /api/{tin}/goods-and-services` — query goods and services Stock: - `POST /api/{tin}/increase-stock` — stock in - `POST /api/{tin}/decrease-stock` — stock out / adjustment down - `POST /api/{tin}/transfer-stock` — move stock between branches Invoicing: - `POST /api/{tin}/generate-fiscal-invoice` — fiscalise an invoice - `POST /api/{tin}/generate-fiscal-receipt` — fiscalise a receipt - `POST /api/{tin}/apply-for-creditnote` — raise a credit note against a fiscalised document Lookups and reporting: - `GET /api/{tin}/registration-details` — taxpayer registration lookup - `POST /api/{tin}/search-taxpayer` — taxpayer search - `POST /api/{tin}/invoice-receipt-query` — query issued invoices and receipts - `GET /api/{tin}/invoice-details/{invoiceNo}` — fetch one fiscalised document - `POST /api/{tin}/query-purchase-invoices` — purchase-side invoice query - `POST /api/{tin}/query-taxpayer-deemed-project` — deemed-project lookup - `GET /api/{tin}/branches` — branches registered for the taxpayer - `GET /api/{tin}/excise-duty` — excise duty codes and rates - `GET /api/{tin}/master-data` — EFRIS master data (codes, units, tax rates) The JSON spec is authoritative for payload schemas: https://weafcompany.com/api/docs?api-docs.json ## Documentation sections - [Onboard](https://efrisapi.weafcompany.com/onboard): what URA requires before you can integrate, including the device number and appointment letter - [Introduction](https://efrisapi.weafcompany.com/): overview and prerequisites - [Authentication](https://efrisapi.weafcompany.com/authentication): tokens, required headers, and environment selection - [Inventory Config](https://efrisapi.weafcompany.com/inventory): product registration and catalogue sync - [Stock Management](https://efrisapi.weafcompany.com/stock): stock in, adjustments and balances - [Invoicing](https://efrisapi.weafcompany.com/invoicing): fiscal invoices and receipts - [Credit Notes](https://efrisapi.weafcompany.com/credit-notes): cancelling and amending fiscalised documents - [Registration Details](https://efrisapi.weafcompany.com/registration-details): taxpayer lookup by TIN - [Deemed Projects](https://efrisapi.weafcompany.com/deemed-projects): deemed-supply handling - [Reports](https://efrisapi.weafcompany.com/reports): fiscal reporting endpoints ## Notes for code generation - Every documented endpoint has a worked example in Shell/cURL, JavaScript, PHP (Laravel `Http`), Java, Python, Rust, Delphi and C#. Prefer copying the shape of those examples over inventing a client. - Responses carry a `status` object with `returnCode` and `returnMessage`; `returnCode` `"00"` means success. Check it — HTTP 200 alone does not mean the URA operation succeeded. - A device number must already exist and be approved in EFRIS before calls succeed. Its format is `{TIN}_01`, `{TIN}_02`, and so on. - Amounts are in UGX. Dates in payloads use `dd/MM/yyyy HH:mm:ss`.