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 through your Gateway host
NRS path:     /api/v1/invoice/resources/tax-categories
Gateway URL:  https://acme.invoice.tryduplo.com/api/v1/invoice/resources/tax-categories

Send 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

  1. Authenticate

    The host and API key resolve one approved business and state in Duplo Dashboard.

  2. Route

    Gateway applies the rules for the requested operation in the approved NRS environment.

  3. 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/sign is intercepted for mode handling, tenant checks, billing, and recovery.
  • POST /api/v1/invoice/validate, GET /api/v1/invoice/transmit/lookup/{irn}, and POST /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

Operationx-api-keyx-sub-business-idIdempotency keyCharge
Ordinary NRS read or utility callRequiredNot a Gateway requirementNot a Gateway requirementNo
Validate raw invoiceRequiredRequiredNot requiredNo
Sign invoiceRequiredRequiredStrongly recommended in Pass-through; required in StoredYes
Lookup a signed Pass-through IRNRequiredRequiredNot requiredNo
Transmit a signed Pass-through IRNRequiredRequiredNot requiredNo
Stored invoice read/transmitRequiredSent where that operation documents itRequired for transmitNo 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 pathPurposeGateway handling
POST /api/v1/utilities/authenticateAuthenticate an NRS portal user and obtain an entity identifierDirect, unbilled diagnostic
GET /api/v1/entity/{entityId}Read the entity and its NRS businessesDirect and unbilled
GET /api/v1/invoice/transmit/lookup/tin/{tin}Check whether a recipient TIN can receiveDirect and unbilled
GET /api/v1/invoice/transmit/self-health-checkCheck the current sender/NRS connectionDirect and unbilled
GET /api/v1/invoice/resources/tax-categoriesFetch current tax categories and ratesDirect and unbilled
GET /api/v1/invoice/resources/vat-exemptionsFetch current VAT exemptionsDirect and unbilled
GET /api/v1/invoice/resources/hs-codesFetch product classification codesDirect and unbilled
GET /api/v1/invoice/resources/services-codesFetch service classification codesDirect and unbilled
GET /api/v1/invoice/resources/invoice-typesFetch the current invoice type codesDirect and unbilled
GET /api/v1/invoice/resources/invoice-quantity-codesFetch invoice unit/quantity codesDirect and unbilled
GET /api/v1/invoice/resources/payment_meansFetch payment means codes. Note the underscoreDirect and unbilled
GET /api/v1/invoice/resources/currenciesFetch currency codesDirect and unbilled
GET /api/v1/invoice/resources/countriesFetch country codesDirect and unbilled
GET /api/v1/invoice/resources/statesFetch Nigerian state codesDirect and unbilled
GET /api/v1/invoice/resources/lgasFetch Nigerian local government areasDirect and unbilled
POST /api/v1/invoice/validateValidate a raw NRS invoicePass-through-only, child-bound, unbilled
POST /api/v1/invoice/signSign an invoice or accept it for Stored processingGateway-controlled and billable at sign
GET /api/v1/invoice/transmit/lookup/{irn}Check parties for an already signed IRNPass-through-only, child/IRN-bound, unbilled
POST /api/v1/invoice/transmit/{irn}Transmit an already signed IRNPass-through-only, child/IRN-bound, unbilled
GET /api/v1/invoice/download/{irn}Download inbound encrypted invoice materialDirect and unbilled; follow the NRS crypto contract
PATCH /api/v1/invoice/transmit/{irn}Acknowledge an inbound invoiceDirect 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:

Authentication response
{
  "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'
Entity response
{
  "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'
Recipient lookup response
{
  "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'
Self-health response
{
  "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:

Tax category response
{
  "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:

Validate
{ "code": 200, "data": { "ok": true } }
Sign
{ "code": 201, "data": { "ok": true, "irn": "INV000001-2A3A045D-20260818" } }
Transmit
{ "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:

FamilyExamplesParsing rule
NRS relayResource, entity, recipient lookup, validation, raw transmitPreserve the NRS HTTP status and body; tolerate additive fields
Gateway managementRepresented-business onboarding, Stored invoice intake/read/transmitRead statusCode, message, and data where supplied; errors commonly use statusCode, message, and error
Duplo Dashboard APISignup, key settings, domain configurationRead 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

On this page