NRS E-Invoicing


Interswitch NRS E-Invoicing Platform — Technical & API Documentation

The Interswitch NRS E-Invoicing Platform facilitates the secure validation, signing, transmission, and reconciliation of sales invoices between taxpayers and the National Revenue Service (NRS). It enables businesses to integrate their ERP or accounting systems with the NRS e-invoicing infrastructure through secure APIs, ensuring invoices comply with NRS standards before transmission.

Interswitch operates in two roles within the e-invoicing ecosystem: System Integrator (SI) and Access Point Provider (APP). This document covers both roles.


Table of Contents

  1. Platform Roles
  2. How It Works
  3. System Architecture
  4. Invoice Standardization — System Integrator Role
  5. Invoice Schema
  6. Rendered Invoice Example
  7. Authentication
  8. API Reference — Access Point Provider Role
  9. Error Reference
  10. HTTP Status Codes
  11. Security & Compliance

Platform Roles

System Integrator (SI)

The System Integrator is responsible for preparing invoices from within the organisation's ERP or POS system and converting them into the standardized format required by NRS.

SI responsibilities include:

  • Extracting invoice data from ERP/POS systems
  • Mapping local tax codes to NRS tax categories
  • Mapping ERP products/services to NRS product/service codes
  • Generating Invoice Reference Numbers (IRN)
  • Validating invoice data against the NRS schema
  • Standardizing the invoice into the required JSON format
  • Generating human-readable invoices
  • Submitting standardized invoices to the Access Point Provider

Access Point Provider (APP)

The Access Point Provider is responsible for transmitting standardized invoices to the NRS platform.

APP responsibilities include:

  • Authenticating API clients
  • Validating invoice payloads
  • Digitally signing invoices
  • Transmitting invoices to NRS
  • Handling invoice status updates
  • Managing webhook notifications
  • Returning QR codes for invoice verification

How It Works

The end-to-end flow from invoice creation to NRS transmission:

  1. Invoice Created — An invoice is created in the ERP or POS system.
  2. Standardization (SI) — The Interswitch SI middleware extracts the invoice data, maps tax codes and product codes to NRS standards, generates an IRN, validates the payload against the NRS schema, and converts it to standardized JSON.
  3. Transmission (APP) — The standardized invoice is submitted to the APP API, which authenticates the request, validates the payload, digitally signs the invoice, and transmits it to NRS.
  4. QR Code Response — NRS returns a signed response. The platform generates a QRCodeData string which must be stored and printed on the physical invoice to make it NRS-compliant and verifiable.
  5. Status Updates — NRS sends status events back to the platform via webhook. The platform updates the invoice record and notifies relevant parties.

System Architecture

The platform consists of four layers:

LayerDescription
Client ApplicationsERP or POS systems where invoices originate
System Integrator LayerInterswitch middleware that extracts, maps, validates, and standardizes invoice data
Access Point Provider APIAuthenticates, signs, and transmits the standardized invoice to NRS
NRS PlatformVerifies the invoice and emits status events

High Level Architecture


Data flow:


Invoice Standardization

This section covers the System Integrator role — how raw ERP data is transformed into a NRS-compliant invoice before transmission.

Standardization Steps

  1. Invoice is created in the ERP/POS system.
  2. Invoice data is extracted by the Interswitch middleware.
  3. ERP tax codes are mapped to NRS tax categories.
  4. ERP products/services are mapped to NRS product/service codes.
  5. A unique Invoice Reference Number (IRN) is generated.
  6. Invoice data is validated against the NRS schema.
  7. The invoice is converted to standardized JSON format.
  8. A human-readable invoice is generated.
  9. The standardized invoice is submitted to the Access Point Provider API.

IRN Generation

The Invoice Reference Number is generated using the following format:

IRN = InvoiceNo + "-" + ServiceId + "-" + InvoiceDate(YYYYMMDD)

Example: INV1023-SRV01-20250901

This ensures every IRN is unique per invoice transaction.


ERP Field Mapping

The tables below show how data from ERP system tables is mapped to the standardized NRS invoice JSON fields.

Invoice Header Mapping

ERP FieldSource TableStandard Invoice FieldNotes
BusinessIdTaxPayerTablebusiness_idUnique business identifier
InvoiceNoSalesInvoiceTableirn (part)Combined with ServiceId and date to form IRN
ServiceIdTaxPayerTableirn (part)Combined with InvoiceNo and date to form IRN
InvoiceDateSalesInvoiceTableissue_dateInvoice issue date
InvoiceDateSalesInvoiceTabledue_datePayment due date
DocumentTypeDerivedinvoice_type_code381 = Invoice, 380 = Credit Note, 384 = Debit Note
CurrencyCodeSalesInvoiceTabledocument_currency_codeInvoice currency
CurrencyCodeSalesInvoiceTabletax_currency_codeTax currency
PaymentStatusSalesInvoiceTablepayment_statusInvoice payment state

Supplier Mapping

Supplier data is sourced from the Legal Entity table.

ERP FieldStandard Invoice Field
BusinessNameaccounting_supplier_party.party_name
TINaccounting_supplier_party.tin
Emailaccounting_supplier_party.email
PhoneNoaccounting_supplier_party.telephone
Sectoraccounting_supplier_party.business_description
Streetaccounting_supplier_party.postal_address.street_name
CityNameaccounting_supplier_party.postal_address.city_name
PostalZoneaccounting_supplier_party.postal_address.postal_zone
Countryaccounting_supplier_party.postal_address.country

Customer Mapping

Customer data is sourced from the Sales Invoice table. Customer information is only included in the payload if a Customer TIN is present.

ERP FieldStandard Invoice Field
CustomerNameaccounting_customer_party.party_name
CustomerTINaccounting_customer_party.tin
CustomerEmailaccounting_customer_party.email
CustomerPhoneNoaccounting_customer_party.telephone
CustomerStreetNameaccounting_customer_party.postal_address.street_name
CustomerCityNameaccounting_customer_party.postal_address.city_name
CustomerPostalZoneaccounting_customer_party.postal_address.postal_zone
CustomerCountryaccounting_customer_party.postal_address.country

Invoice Line Mapping

Invoice line data is sourced from the Sales Invoice Line table.

ERP FieldStandard Invoice Field
HsnCodeinvoice_line[].hsn_code
ItemNameinvoice_line[].item.name
ItemNameinvoice_line[].product_category
HsnCodeinvoice_line[].item.sellers_item_identification
Quantityinvoice_line[].invoiced_quantity
UnitPriceExclinvoice_line[].price.price_amount
UnitOfMeasureinvoice_line[].price.price_unit
LineAmountinvoice_line[].line_extension_amount
DiscountRateinvoice_line[].discount_rate
DiscountAmountinvoice_line[].discount_amount

Tax Mapping

Tax data is derived from VAT information on ERP invoice lines.

ERP FieldStandard Invoice Field
VATAmounttax_total.tax_amount
LineAmounttax_subtotal.taxable_amount
VATAmounttax_subtotal.tax_amount
TaxTypeCodetax_category.id
TaxRatetax_category.percent

Monetary Total Mapping

Invoice totals are calculated dynamically during standardization.

CalculationStandard Invoice Field
SUM(LineAmount)legal_monetary_total.line_extension_amount
SUM(LineAmount)legal_monetary_total.tax_exclusive_amount
SUM(LineAmount + VATAmount)legal_monetary_total.tax_inclusive_amount
SUM(LineAmount + VATAmount − DiscountAmount)legal_monetary_total.payable_amount

Invoice Transmission Flow


Invoice Schema

All invoices must conform to the standardized schema defined by the NRS E-Invoicing platform.

Invoice Header

FieldDescriptionTypeRequiredMax Length
business_idBusiness UUIDStringYes36
irnInvoice Reference NumberStringYes50
invoice_kindInvoice nature: B2B, B2C, or B2GStringYes3
issue_dateInvoice issue dateDate (YYYY-MM-DD)Yes10
due_dateInvoice due dateDate (YYYY-MM-DD)Yes10
issue_timeInvoice issue timeTime (HH:mm:ss)Yes8
invoice_type_codeInvoice type codeStringYes10
tax_point_dateTax point dateDate (YYYY-MM-DD)Yes10
document_currency_codeDocument currencyStringYes3
tax_currency_codeTax currencyStringYes3
billing_reference[].irnOriginal invoice IRN — credit notes onlyStringYes50
billing_reference[].issue_dateOriginal invoice issue date — credit notes onlyDate (YYYY-MM-DD)Yes10

Supplier Information (accounting_supplier_party)

FieldDescriptionTypeRequiredMax Length
party_nameSupplier nameStringYes100
tinSupplier TINStringYes20
emailSupplier emailStringYes100
telephoneSupplier phoneStringYes20
business_descriptionBusiness descriptionStringNo255
postal_address.street_nameStreet nameStringYes150
postal_address.city_nameCityStringYes100
postal_address.postal_zonePostal codeStringNo20
postal_address.countryCountry code (ISO 3166-1 alpha-2)StringYes2

Customer Information (accounting_customer_party)

Customer information is only included in the payload if a Customer TIN is present.

FieldDescriptionTypeRequiredMax Length
party_nameCustomer nameStringYes100
tinCustomer TIN (min 5 chars)StringYes20
emailCustomer emailStringYes100
telephoneCustomer phoneStringYes20
business_descriptionBusiness descriptionStringNo255
postal_address.street_nameStreet nameStringNo150
postal_address.city_nameCityStringYes100
postal_address.postal_zonePostal codeStringNo20
postal_address.countryCountry code (ISO 3166-1 alpha-2)StringYes2

Invoice Line Items (invoice_line[])

FieldDescriptionTypeRequired
hsn_codeProduct classification codeStringYes
product_categoryProduct categoryStringYes
invoiced_quantityQuantityDecimalYes
line_extension_amountLine total amountDecimalYes
discount_rateDiscount rateDecimalNo
discount_amountDiscount amountDecimalNo
fee_rateFee rateDecimalNo
fee_amountFee amountDecimalNo
item.nameItem nameStringYes
item.descriptionItem descriptionStringNo
item.sellers_item_identificationItem IDStringYes
price.price_amountUnit priceDecimalYes
price.base_quantityBase quantityDecimalYes
price.price_unitPrice unitStringYes

Tax Structure (tax_total[])

FieldDescriptionTypeRequired
tax_amountTotal tax amountDecimalYes
tax_subtotal[].taxable_amountTaxable amountDecimalYes
tax_subtotal[].tax_amountTax amountDecimalYes
tax_subtotal[].tax_category.idTax category (e.g. STANDARD_VAT, ZERO_VAT)StringYes
tax_subtotal[].tax_category.percentTax rate (%)DecimalYes

Monetary Totals (legal_monetary_total)

FieldDescriptionTypeRequired
line_extension_amountSum of all line amountsDecimalYes
tax_exclusive_amountTotal before taxDecimalYes
tax_inclusive_amountTotal after taxDecimalYes
payable_amountFinal payable amountDecimalYes

Rendered Invoice Example

The image below shows a sample human-readable tax invoice generated by the platform after a successful submission. The Tax Information section at the bottom contains the IRN and the QR code returned by the API — both must appear on every printed invoice for NRS compliance and verifiability.

Sample FIRS-compliant Tax Invoice

Key elements on the rendered invoice:

  • Supplier name, TIN, and address
  • Customer name and Customer TIN
  • Invoice number and date
  • Line items with HSN Code, Description, Quantity, Unit Price, Discount, and Amount
  • VAT Analysis table showing tax code, goods value, rate, and VAT amount
  • Summary totals: Sub Total, Discount, VAT, and Total
  • Tax Information footer containing the transmission Date, Time, IRN, and QR Code

Authentication

All API requests require a Bearer token obtained from the Token endpoint. Tokens expire after 3600 seconds (1 hour) and must be refreshed by calling the endpoint again.

Get Access Token

POST /Api/SwitchTax/Token

Request

{
  "ClientId": "TEST001",
  "ClientSecret": "RTR56457%4k"
}

Response

{
  "Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "expires_in": 3600
}

Use the returned token in the Authorization header on all subsequent requests:

Authorization: Bearer <Token>

API Reference

This section covers the Access Point Provider role — the endpoints used to transmit, manage, and reconcile invoices with NRS.

Endpoints Summary

EndpointMethodPurpose
/Api/SwitchTax/TokenPOSTGenerate an access token
/Api/SwitchTax/postInvoicePOSTSubmit an invoice to NRS
/UpdateStatusPOSTUpdate an invoice's payment status
/transmit/{IRN}POSTManually trigger transmission of a specific invoice
/PostQueuedInvoicesPOSTTransmit all queued invoices for a TIN within a date range

Post Invoice

Submits a standardized invoice to NRS. The platform authenticates, validates, digitally signs, and transmits the invoice, then returns a QR code on success.

The same endpoint handles both standard invoices and credit notes. Credit notes require an additional billing_reference array linking to the original invoice.

POST /Api/SwitchTax/postInvoice

Sample Request

{
  "business_id": "1c6eaf77-d0bd-455c-9c5c-500a3f1dbfb2",
  "irn": "NISW007611-6AFCD0BD-20250901",
  "invoice_kind": "B2B",
  "issue_date": "2025-09-01",
  "due_date": "2025-09-01",
  "issue_time": "13:34:34",
  "invoice_type_code": "396",
  "tax_point_date": "2025-09-01",
  "document_currency_code": "NGN",
  "tax_currency_code": "NGN",
  "accounting_supplier_party": {
    "party_name": "NG",
    "tin": "15631438-0242",
    "email": "[email protected]",
    "telephone": "+23416283888",
    "business_description": "Financial technology services",
    "postal_address": {
      "street_name": "Oko-Awo Street, Victoria Island",
      "city_name": "Lagos",
      "postal_zone": "80164",
      "country": "NG"
    }
  },
  "accounting_customer_party": {
    "party_name": "Sterling Bank Plc",
    "tin": "15631438-0242",
    "email": "[email protected]",
    "telephone": "+254712034397",
    "business_description": null,
    "postal_address": {
      "street_name": "",
      "city_name": "Victoria Island",
      "postal_zone": "",
      "country": "NG"
    }
  },
  "invoice_line": [
    {
      "hsn_code": "2TG27",
      "product_category": "3D Secure Monthly Acquiring Fee",
      "discount_rate": 0.00,
      "discount_amount": 0.00,
      "fee_rate": 0.0,
      "fee_amount": 0.0,
      "invoiced_quantity": 10.00,
      "line_extension_amount": 35000.00,
      "item": {
        "name": "3D Secure Monthly Acquiring Fee",
        "description": "10.00 Each at 3500.00 each",
        "sellers_item_identification": "2TG27"
      },
      "price": {
        "price_amount": 3500.00,
        "base_quantity": 1,
        "price_unit": "NGN per Each"
      }
    },
    {
      "hsn_code": "1CD02",
      "product_category": "CollegePAY",
      "discount_rate": 0.00,
      "discount_amount": 0.00,
      "fee_rate": 0.0,
      "fee_amount": 0.0,
      "invoiced_quantity": 3.00,
      "line_extension_amount": 12000.00,
      "item": {
        "name": "CollegePAY",
        "description": "3.00 Each at 4000.00 each",
        "sellers_item_identification": "1CD02"
      },
      "price": {
        "price_amount": 4000.00,
        "base_quantity": 1,
        "price_unit": "NGN per Each"
      }
    }
  ],
  "tax_total": [
    {
      "tax_amount": 2625.00,
      "tax_subtotal": [
        {
          "taxable_amount": 35000.00,
          "tax_amount": 2625.00,
          "tax_category": {
            "id": "STANDARD_VAT",
            "percent": 7.50
          }
        },
        {
          "taxable_amount": 12000.00,
          "tax_amount": 0.00,
          "tax_category": {
            "id": "ZERO_VAT",
            "percent": 0.00
          }
        }
      ]
    }
  ],
  "legal_monetary_total": {
    "line_extension_amount": 47000.00,
    "tax_exclusive_amount": 47000.00,
    "tax_inclusive_amount": 49625.00,
    "payable_amount": 49625.00
  }
}

For credit notes, include a billing_reference array in the request body:

{
  "billing_reference": [
    {
      "irn": "ITW001-E9E0C0D3-20250619",
      "issue_date": "2025-05-14"
    }
  ]
}

Response

{
  "code": 201,
  "message": "Transmitted successfully",
  "data": {
    "IRN": "NISW-008634-6AFCD0BD-20251014",
    "PostingDateTime": "2025-10-19 22:28:24",
    "QRCodeData": "Base64EncodedQRCode"
  }
}

The QRCodeData field contains a Base64-encoded QR code. Decode it, store it against the invoice record, and render it on the printed invoice.


Update Invoice Status

Updates the payment status of a previously submitted invoice.

POST /UpdateStatus

Request

{
  "payment_status": "PAID",
  "reference": "payment_reference_or_note",
  "irn": "NISW008608-6AFCD0BD-20250930"
}

Response

{
  "invoiceId": "INV-2025-001",
  "status": "ACCEPTED",
  "timestamp": "2025-07-01T12:00:00Z"
}

Transmit Invoice

Manually triggers transmission of a specific invoice to NRS by IRN.

POST /transmit/{IRN}

Response

{
  "code": 200,
  "data": {
    "ok": true
  }
}

Post Queued Invoices

Transmits all invoices that have been queued but not yet sent to NRS for a given TIN, within a specified date range.

POST /PostQueuedInvoices

Request

{
  "tin": "15631438-0242",
  "startDate": "2025-05-01",
  "endDate": "2025-12-31"
}

Response

{
  "code": "200",
  "message": "Transmitted successfully",
  "InvoicesPosted": [
    {
      "IRN": "ITW005-6AFCD0BD-20250730",
      "PostingDateTime": "2025-11-17 21:04:34",
      "QRCodeData": "Z4QjuUDN8CY..."
    },
    {
      "IRN": "ITW009-6AFCD0BD-20250730",
      "PostingDateTime": "2025-11-17 21:04:34",
      "QRCodeData": "PiiEpggiZF0..."
    }
  ]
}

Error Reference

All errors follow a standard structured response format. The details or error_description field contains the specific reason for the failure.

Authentication Errors

Invalid or expired token — 401 Unauthorized

{
  "error": "invalid_token",
  "error_description": "The access token is invalid or has expired."
}

Validation Errors

Missing required field — 400 Bad Request

{
  "errorCode": "400",
  "errorMessage": "Validation Failed",
  "details": "CustomerTIN is required."
}

Schema validation failed — 422 Unprocessable Entity

{
  "errorCode": "422",
  "errorMessage": "Schema validation failed",
  "details": "InvoiceDate must be in YYYY-MM-DD format."
}

Duplicate IRN — 400 Bad Request

{
  "code": 400,
  "data": null,
  "message": "error has occurred",
  "error": {
    "id": "96b4a6dc-ab2c-403e-adec-8a4c0200d87e",
    "handler": "invoice_actions",
    "details": "unable to complete this operation at this time, kindly try again later",
    "public_message": "validation failed: we are unable to process your request. also confirm this is not a duplicate request"
  }
}

Invalid Business ID — 400 Bad Request

{
  "code": 400,
  "data": null,
  "message": "error has occurred",
  "error": {
    "id": "d64ba7c8-e62e-4b3a-aa55-12f49226fcad",
    "handler": "invoice_actions",
    "details": "invalid UUID length: 35",
    "public_message": "validation failed: we are unable to process your request. also confirm this is not a duplicate request"
  }
}

Invalid tax category — 400 Bad Request

{
  "code": 400,
  "data": null,
  "message": "error has occurred",
  "error": {
    "id": "a4f0d39d-5780-492f-9f0d-e11cc6acfad2",
    "handler": "invoice_actions",
    "details": "invoicerequest.invoice.taxtotal[0].taxsubtotal[0].taxcategory.id must be a valid tax category, refer to the invoice resource apis",
    "public_message": "validation failed: we are unable to process your request. also confirm this is not a duplicate request"
  }
}

Invalid tax point date — 400 Bad Request

{
  "code": 400,
  "data": null,
  "message": "error has occurred",
  "error": {
    "id": "bbeaab9c-6a28-4ca6-b2fe-9bb82406f01a",
    "handler": "invoice_actions",
    "details": "invoicerequest.invoice.taxpointdate must be a valid date value yyyy-mm-dd (e.g: 2024-04-29)",
    "public_message": "validation failed: we are unable to process your request. also confirm this is not a duplicate request"
  }
}

Invalid country code — 400 Bad Request

{
  "code": 400,
  "data": null,
  "message": "error has occurred",
  "error": {
    "id": "2b2775ae-1b7b-4fb7-9124-dcac8e670996",
    "handler": "invoice_actions",
    "details": "invoicerequest.invoice.accountingsupplierparty.postaladdress.country must be a valid country code, refer to the invoice resource apis",
    "public_message": "validation failed: we are unable to process your request. also confirm this is not a duplicate request"
  }
}

Invalid TIN — 400 Bad Request

{
  "code": 400,
  "data": null,
  "message": "error has occurred",
  "error": {
    "id": "8172fe11-e6b7-4c10-af5c-57d3a920a832",
    "handler": "invoice_actions",
    "details": "invoicerequest.invoice.accountingcustomerparty.tin must be at least in length or value 5",
    "public_message": "validation failed: we are unable to process your request. also confirm this is not a duplicate request"
  }
}

Queued Invoice Errors

Invalid TIN

{
  "code": "400",
  "message": "Invalid TIN"
}

No queued invoices found

{
  "code": "400",
  "message": "There are no queued invoices pending to be transmitted"
}

Server Errors

Internal server error — 500

{
  "errorCode": "500",
  "errorMessage": "An unexpected error occurred. Please try again later.",
  "supportId": "b7f4c7d2-82f3-4a3e-b9f5-0a12345xyz"
}

NRS system unavailable — 500

{
  "code": "500",
  "message": "NRS system is currently offline. Please try again later"
}

HTTP Status Codes

Status CodeMeaningTypical Scenario
200 OKRequest successfulInvoice submitted, status updated, token generated
201 CreatedResource createdNew invoice or client record created
400 Bad RequestInvalid inputMissing required field, duplicate IRN, malformed JSON
401 UnauthorizedAuthentication failedInvalid or expired access token
403 ForbiddenAccess deniedClient lacks permission for the resource
404 Not FoundResource not foundInvalid endpoint or record not found
422 Unprocessable EntityValidation failedSchema or business rule validation error
429 Too Many RequestsRate limit exceededClient exceeded request quota
500 Internal Server ErrorUnexpected server errorUnhandled exception, NRS system offline
503 Service UnavailableService temporarily unavailableScheduled downtime or overload

Security & Compliance

FeatureDetail
AuthenticationOAuth 2.0 Client Credentials flow with role-based access
Login Security2FA enabled for all web application logins
Data in TransitTLS 1.3
Data at RestDatabase encryption
Invoice IntegrityDigital signing of all invoices before transmission
AuditFull logging of all API calls and actions
ComplianceNRS e-invoicing regulations and Nigerian data protection laws