NRS API Through Your Domain
Call well-known NRS endpoints through the approved Gateway host and understand which routes are protected, relayed, and billed.
Your approved domain is an authenticated NRS API entry point. For an ordinary NRS operation, replace the NRS origin with your Gateway origin and keep the HTTP method, path, query string, and NRS request body.
NRS path: /api/v1/invoice/resources/tax-categories
Gateway URL: https://acme.invoice.tryduplo.com/api/v1/invoice/resources/tax-categoriesSend the API key generated in Duplo Dashboard as x-api-key on every request, as shown in the examples below.
Use only the Gateway headers documented for each operation. The Gateway applies the approved business, state, and route rules before forwarding an eligible NRS request.
Billing rule
Ordinary NRS calls through the domain are unbilled. The only billable route is the exact POST /api/v1/invoice/sign operation. A sign attempt is debited before NRS is called; a definitive rejection is reversed, while an unconfirmed NRS outcome can retain the charge temporarily for reconciliation. Read Billing and safe retries before automating sign retries.
How routing works
Authenticate
The host and API key resolve one approved business and state in Duplo Dashboard.
Route
Gateway applies the rules for the requested operation in the approved NRS environment.
Relay
For ordinary routes, the method, path, query, status, and response body pass through.
The general proxy rule has deliberate exceptions:
POST /api/v1/invoice/signis intercepted for mode handling, tenant checks, billing, and recovery.POST /api/v1/invoice/validate,GET /api/v1/invoice/transmit/lookup/{irn}, andPOST /api/v1/invoice/transmit/{irn}are represented-business-bound Pass-through routes.- Other unsupported
POST /api/v1/invoice/transmit...shapes are rejected instead of being forwarded. /sub-businesses,/invoices,/health, and platform webhook/administration paths belong to Duplo, not NRS.
All other recognized HTTP methods and unclaimed NRS paths, including their query strings, are streamed to NRS without a Gateway signing charge.
Header requirements by route
| Operation | x-api-key | x-sub-business-id | Idempotency key | Charge |
|---|---|---|---|---|
| Ordinary NRS read or utility call | Required | Not a Gateway requirement | Not a Gateway requirement | No |
| Validate raw invoice | Required | Required | Not required | No |
| Sign invoice | Required | Required | Strongly recommended in Pass-through; required in Stored | Yes |
| Lookup a signed Pass-through IRN | Required | Required | Not required | No |
| Transmit a signed Pass-through IRN | Required | Required | Not required | No |
| Stored invoice read/transmit | Required | Sent where that operation documents it | Required for transmit | No additional sign charge |
Pass-through sign also accepts a positive x-attempt-number, which defaults to 1. Keep it stable with the idempotency key for one logical attempt; read Billing and safe retries before creating a later attempt.
NRS may impose additional fields or semantics on an ordinary proxied route. Follow the official NRS e-Invoicing documentation, version 1.1.6 for the regulator-owned contract.
Well-known NRS endpoints
This table is a practical map, not a replacement for the NRS reference. Resource names and response fields can change independently of the Gateway.
| Method and path | Purpose | Gateway handling |
|---|---|---|
POST /api/v1/utilities/authenticate | Authenticate an NRS portal user and obtain an entity identifier | Direct, unbilled diagnostic |
GET /api/v1/entity/{entityId} | Read the entity and its NRS businesses | Direct and unbilled |
GET /api/v1/invoice/transmit/lookup/tin/{tin} | Check whether a recipient TIN can receive | Direct and unbilled |
GET /api/v1/invoice/transmit/self-health-check | Check the current sender/NRS connection | Direct and unbilled |
GET /api/v1/invoice/resources/tax-categories | Fetch current tax categories and rates | Direct and unbilled |
GET /api/v1/invoice/resources/vat-exemptions | Fetch current VAT exemptions | Direct and unbilled |
GET /api/v1/invoice/resources/hs-codes | Fetch product classification codes | Direct and unbilled |
GET /api/v1/invoice/resources/services-codes | Fetch service classification codes | Direct and unbilled |
GET /api/v1/invoice/resources/invoice-types | Fetch the current invoice type codes | Direct and unbilled |
GET /api/v1/invoice/resources/invoice-quantity-codes | Fetch invoice unit/quantity codes | Direct and unbilled |
GET /api/v1/invoice/resources/payment_means | Fetch payment means codes. Note the underscore | Direct and unbilled |
GET /api/v1/invoice/resources/currencies | Fetch currency codes | Direct and unbilled |
GET /api/v1/invoice/resources/countries | Fetch country codes | Direct and unbilled |
GET /api/v1/invoice/resources/states | Fetch Nigerian state codes | Direct and unbilled |
GET /api/v1/invoice/resources/lgas | Fetch Nigerian local government areas | Direct and unbilled |
POST /api/v1/invoice/validate | Validate a raw NRS invoice | Pass-through-only, child-bound, unbilled |
POST /api/v1/invoice/sign | Sign an invoice or accept it for Stored processing | Gateway-controlled and billable at sign |
GET /api/v1/invoice/transmit/lookup/{irn} | Check parties for an already signed IRN | Pass-through-only, child/IRN-bound, unbilled |
POST /api/v1/invoice/transmit/{irn} | Transmit an already signed IRN | Pass-through-only, child/IRN-bound, unbilled |
GET /api/v1/invoice/download/{irn} | Download inbound encrypted invoice material | Direct and unbilled; follow the NRS crypto contract |
PATCH /api/v1/invoice/transmit/{irn} | Acknowledge an inbound invoice | Direct and unbilled; body is normally {} |
Retrieve represented-business identifiers
Gateway onboarding returns gatewaySubBusinessId, but it does not currently return the NRS business_id or IRN template needed to build a raw Pass-through document. Persist the child ID from onboarding, and obtain the public NRS values from the NRS portal.
If you need a one-time diagnostic through the approved domain, authenticate the represented business's NRS portal user:
curl --request POST \
--url https://acme.invoice.tryduplo.com/api/v1/utilities/authenticate \
--header 'content-type: application/json' \
--header 'x-api-key: pk_test_replace_with_your_key' \
--data '{
"email": "nrs-owner@acme.example",
"password": "replace-with-a-transient-secret"
}'A common response is:
{
"code": 200,
"data": {
"entity_id": "entity-demo"
}
}Then read the entity:
curl \
--url https://acme.invoice.tryduplo.com/api/v1/entity/entity-demo \
--header 'x-api-key: pk_test_replace_with_your_key'{
"code": 200,
"data": {
"id": "entity-demo",
"reference": "entity-reference-demo",
"businesses": [
{
"id": "nrs-business-demo",
"name": "Acme Retail Limited",
"tin": "12345678-0001",
"irn_template": "{{invoice_id}}-2A3A045D-{{YYYYMMDD}}",
"is_active": true
}
]
}
}Select only the active business with an exact normalized TIN match. Store its id as the raw invoice business_id, retain the template, and remove the NRS password from memory and logs as soon as the diagnostic finishes. Do not call this authentication endpoint for every invoice.
The entity or business reference can be absent and is not an onboarding or invoice requirement. Gateway requires the selected business's ID, name, TIN, and IRN template; when you omit tin from onboarding, the entity must instead contain exactly one active business.
Recipient lookup and health
Check a receiver before building a transmission workflow:
curl \
--url https://acme.invoice.tryduplo.com/api/v1/invoice/transmit/lookup/tin/11111111-0001 \
--header 'x-api-key: pk_test_replace_with_your_key'{
"code": 200,
"data": {
"up": true,
"has_webhook_setup": true
}
}Check the NRS connection selected for the current domain and state:
curl \
--url https://acme.invoice.tryduplo.com/api/v1/invoice/transmit/self-health-check \
--header 'x-api-key: pk_test_replace_with_your_key'{
"code": 200,
"data": {
"ok": true
}
}These calls say nothing about your wallet balance in Duplo Dashboard or domain approval workflow. A Gateway host health check is separately available at GET /health and returns { "status": "ok" }.
Fetch NRS resources instead of hard-coding them
curl \
--url https://acme.invoice.tryduplo.com/api/v1/invoice/resources/tax-categories \
--header 'x-api-key: pk_test_replace_with_your_key'A resource response can resemble:
{
"code": 200,
"data": [
{
"code": "STANDARD_VAT",
"value": "Standard VAT",
"percent": "7.5"
}
]
}Treat STANDARD_VAT, 7.5, service code 6201, and quantity code HUR in these guides as snapshots used to explain shape. Fetch the current NRS catalogs, cache them for a bounded period, and refresh them when NRS validation reports an unknown or changed value.
Invoice endpoint responses
Common NRS success bodies seen by the Gateway integration are:
{ "code": 200, "data": { "ok": true } }{ "code": 201, "data": { "ok": true, "irn": "INV000001-2A3A045D-20260818" } }{ "code": 200, "data": { "ok": true } }For signed-IRN lookup, current integration evidence shows party objects such as accounting_supplier_party, accounting_customer_party, bill_party, and ship_party, each with an up flag. The exact lookup schema is not sufficiently stable to use as a generated type; preserve unknown fields and check the current NRS documentation.
Understand response ownership
Your client will encounter three response families:
| Family | Examples | Parsing rule |
|---|---|---|
| NRS relay | Resource, entity, recipient lookup, validation, raw transmit | Preserve the NRS HTTP status and body; tolerate additive fields |
| Gateway management | Represented-business onboarding, Stored invoice intake/read/transmit | Read statusCode, message, and data where supplied; errors commonly use statusCode, message, and error |
| Duplo Dashboard API | Signup, key settings, domain configuration | Read the Duplo Dashboard API response envelope; it can also include timestamp and path |
Do not assume that every successful response uses the same HTTP status or that every error is an NRS envelope. Log the HTTP status, sanitized response body, x-request-id you sent, and any returned traceId without logging credentials or full invoice payloads.
Continue with the Pass-through guide, Stored guide, or the complete official NRS reference.
How is this guide?
Last updated on