Purpose
Overview
WiseWage supports a controlled B2B commercial-invoice lifecycle: taxpayer setup, invoice drafting, NRS validation, internal approval, fiscalization, final PDF generation, and creation of one linked, unposted accounting-register row.
Draft creation and internal approval are WiseWage controls. Reference-resource checks, NRS validation, signing and confirmation call the configured NRS environment. General-ledger posting remains a separate Management Accounts approval step. Accounting checks can return the register row to Pending, for example if the invoice date is outside the selected period or a required currency is missing; this does not undo NRS fiscalization.
Connection
Authentication
WiseWage authenticates to NRS from its server using environment-specific API credentials owned by the invoice seller (the taxpayer). Requests use x-api-key and x-api-secret headers. The API key and client secret are never embedded in browser code or displayed to company users.
Each managed business separately records its NRS-issued BusinessID and Taxpayer Service ID. These identifiers and the API credentials must belong to the same taxpayer in the selected environment. Copy Business ID from the taxpayer portal, not Entity ID. The eight-character Taxpayer Service ID forms the middle component of the IRN. WiseWage's SI account credentials are not a substitute for the taxpayer's keys.
Deployment
Sandbox and production environments
| Environment | Purpose | Controls |
|---|---|---|
| Sandbox | Integration testing, schema validation, and onboarding evidence. | Separate NRS URL and credentials; records are visibly identified as sandbox activity. |
| Production | Live fiscalization after NRS approval and customer enablement. | Environment-specific credentials bound to the configured taxpayer business and service ID, HTTPS, restricted server access, and explicit activation. Another business cannot borrow those credentials. |
Invoice validation, signing and confirmation have completed successfully in the configured sandbox, with a linked final PDF and Invoice Register entry. This verifies the tested commercial-invoice workflow, not every adjustment, recovery or delivery scenario. Sandbox readiness does not imply production activation. Production use depends on NRS approval, valid production credentials, and enablement of the applicable taxpayer.
Lifecycle
Supported operations
- 1Associate an enabled taxpayer BusinessID and Taxpayer Service ID.
- 2Load supported NRS states, LGAs, product/service classifications, and tax treatments.
- 3Create an internal B2B commercial-invoice draft and permanent WiseWage invoice number.
- 4Generate an IRN and validate the invoice structure with NRS.
- 5Correct and resubmit validation failures while retaining prior attempts.
- 6Approve a validated invoice through WiseWage's internal control.
- 7Fiscalize once and retain the NRS response and verification details.
- 8Cancel eligible drafts without deleting their invoice number or audit history.
- 9Create linked credit/debit note drafts with their own validation, approval and fiscalization controls.
- 10Download the final PDF from e-Invoicing or the linked transaction Supporting documents.
- 11Identify generated register rows by their e-Invoicing source and validate accounting fields before posting.
- 12Run Check and save results to compare saved fiscal evidence, register amounts and current ledger/output VAT.
Credit/debit note controls are implemented; their end-to-end sandbox acceptance is not claimed by the successful commercial-invoice test. Fiscalized cancellation is not enabled. Reconciliation is user-triggered and does not amend records, reconcile filed VAT returns or transmit invoices to buyers.
API reference
Create Invoice request and NRS payload
This reference documents the current WiseWage B2B commercial-invoice implementation against NRS v1.1. Draft creation is internal; the external operation documented by NRS is invoice validation. The examples contain fictional identities and cannot be submitted as enabled taxpayers.
Create Invoice: authenticated WiseWage draft request
POST /api/admin/management-accounting/e-invoicing with action: createDraft. Requires a signed-in, authorised Management Accounts user and company/entity access; this is not an API-key-based public customer endpoint. Select an open period and configured accounts. The seller comes from the saved NRS business profile; the server assigns the permanent invoice number and IRN and calculates amounts.
The scope identifiers, customer, issue date, buyer fiscal details, account mappings and at least one line are required. Company Code and Cost Center follow the managed business classification rules; Output VAT is required for taxable lines. Due date, buyer reference, narration, business description and seller item reference are optional. This example includes all fields accepted by the draft form.
Complete Create Invoice request example
{
"action": "createDraft",
"companyId": "<authorised-company-id>",
"entityId": "<managed-business-id>",
"periodId": "<open-period-id>",
"draft": {
"customerId": "<active-customer-id>",
"issueDate": "2026-09-06",
"dueDate": "2026-10-06",
"currency": "NGN",
"paymentMeansCode": "30",
"buyerReference": "PO-DEMO-2026-0001",
"narration": "Fictional sample",
"companyCode": "<configured-company-code>",
"costCenterCode": "<eligible-cost-center>",
"revenueAccountCode": "<revenue-account>",
"receivableAccountCode": "<receivable-account>",
"outputVatAccountCode": "<output-vat-account>",
"buyer": {
"taxId": "10000002-0001",
"email": "accounts@meridian-trade.example",
"telephone": "+2348020000002",
"businessDescription": "Fictional wholesale and distribution business",
"streetName": "25 Demonstration Commerce Road",
"cityName": "Lagos",
"postalZone": "101233",
"lgaCode": "NG-LA-LMA",
"stateCode": "NG-LA",
"countryCode": "NG"
},
"lines": [
{
"entryMode": "QUANTITY",
"description": "Software integration service",
"quantity": 2,
"unitPrice": 150000,
"unitCode": "EA",
"itemType": "SERVICE",
"classificationCode": "6201",
"classificationName": "Computer programming activities",
"sellerItemReference": "SVC-DEMO-001",
"taxCategoryCode": "STANDARD_VAT"
}
]
}
}NRS invoice validation request
POST {NRS_API_BASE_URL}/api/v1/invoice/validate. Use the API origin and credentials issued for the selected environment, not the documentation website. Authentication is server-side using the two headers below. Never expose credentials in browser code or submission documents.
curl --request POST "$NRS_API_BASE_URL/api/v1/invoice/validate" \ --header "Content-Type: application/json" \ --header "Accept: application/json" \ --header "x-api-key: <NRS_API_KEY>" \ --header "x-api-secret: <NRS_API_SECRET>" \ --data-binary @invoice.json
Save the complete example below as invoice.json. Replace fictional identities with authorised sandbox fixtures before a sandbox submission.
{
"business_id": "9f36d708-4c91-4e2a-92c8-7a75f418b603",
"irn": "INV00000001-A1B2C3D4-20260906",
"issue_date": "2026-09-06",
"due_date": "2026-10-06",
"invoice_type_code": "381",
"invoice_kind": "B2B",
"payment_status": "PENDING",
"note": "Fictional sample prepared solely for NRS system-integration review.",
"tax_point_date": "2026-09-06",
"document_currency_code": "NGN",
"tax_currency_code": "NGN",
"buyer_reference": "PO-DEMO-2026-0001",
"order_reference": "PO-DEMO-2026-0001",
"accounting_supplier_party": {
"party_name": "Acacia Systems Nigeria Limited",
"tin": "10000001-0001",
"email": "billing@acacia-systems.example",
"telephone": "+2348010000001",
"business_description": "Business software implementation and support services",
"postal_address": {
"street_name": "10 Sample Technology Avenue",
"city_name": "Ikeja",
"postal_zone": "100001",
"lga": "NG-LA-IKE",
"state": "NG-LA",
"country": "NG"
}
},
"accounting_customer_party": {
"party_name": "Meridian Trade Services Limited",
"tin": "10000002-0001",
"email": "accounts@meridian-trade.example",
"telephone": "+2348020000002",
"business_description": "Fictional wholesale and distribution business",
"postal_address": {
"street_name": "25 Demonstration Commerce Road",
"city_name": "Lagos",
"postal_zone": "101233",
"lga": "NG-LA-LMA",
"state": "NG-LA",
"country": "NG"
}
},
"payment_means": [
{
"payment_means_code": "30",
"payment_due_date": "2026-10-06"
}
],
"tax_total": [
{
"tax_amount": 22500,
"tax_subtotal": [
{
"taxable_amount": 300000,
"tax_amount": 22500,
"tax_category": {
"id": "STANDARD_VAT",
"percent": 7.5
}
}
]
}
],
"legal_monetary_total": {
"line_extension_amount": 300000,
"tax_exclusive_amount": 300000,
"tax_inclusive_amount": 322500,
"payable_amount": 322500
},
"invoice_line": [
{
"isic_code": "6201",
"service_category": "Computer programming activities",
"invoiced_quantity": 2,
"line_extension_amount": 300000,
"item": {
"name": "Configuration and integration of a fictional business software environment",
"description": "Configuration and integration of a fictional business software environment",
"sellers_item_identification": "SVC-DEMO-001"
},
"price": {
"price_amount": 150000,
"base_quantity": 1,
"price_unit": "EA"
}
}
]
}Supported request fields, including nested structures
Requiredness below describes WiseWage's B2B payload, which requires buyer details. Optional parent objects may be omitted; their required children apply when supplied. Goods use HSN/product category; services use ISIC/service category. Monetary values are JSON numbers, rounded to two decimal places. Line totals, VAT subtotals and payable totals must reconcile.
business_idType: string
Requirement: Required
uuid
irnType: string
Requirement: Required
Up to 80 characters
issue_dateType: string
Requirement: Required
date
due_dateType: string
Requirement: Optional
date
invoice_type_codeType: string
Requirement: Required
381 / 380 / 384
invoice_kindType: string
Requirement: Required
Value: B2B
payment_statusType: string
Requirement: Optional
Value: PENDING
noteType: string
Requirement: Optional
See sample and schema
tax_point_dateType: string
Requirement: Optional
date
document_currency_codeType: string
Requirement: Required
Up to 3 characters
tax_currency_codeType: string
Requirement: Required
Up to 3 characters
buyer_referenceType: string
Requirement: Optional
Up to 225 characters
order_referenceType: string
Requirement: Optional
Up to 255 characters
accounting_supplier_partyType: object
Requirement: Required
See sample and schema
accounting_supplier_party.party_nameType: string
Requirement: Required when parent is supplied
Up to 255 characters
accounting_supplier_party.tinType: string
Requirement: Required when parent is supplied
See sample and schema
accounting_supplier_party.emailType: string
Requirement: Required when parent is supplied
email; Up to 100 characters
accounting_supplier_party.telephoneType: string
Requirement: Optional
Up to 100 characters
accounting_supplier_party.business_descriptionType: string
Requirement: Optional
Up to 255 characters
accounting_supplier_party.postal_addressType: object
Requirement: Required when parent is supplied
See sample and schema
accounting_supplier_party.postal_address.street_nameType: string
Requirement: Required when parent is supplied
Up to 255 characters
accounting_supplier_party.postal_address.city_nameType: string
Requirement: Required when parent is supplied
Up to 100 characters
accounting_supplier_party.postal_address.postal_zoneType: string
Requirement: Required when parent is supplied
Up to 20 characters
accounting_supplier_party.postal_address.lgaType: string
Requirement: Required when parent is supplied
Up to 100 characters
accounting_supplier_party.postal_address.stateType: string
Requirement: Required when parent is supplied
Up to 100 characters
accounting_supplier_party.postal_address.countryType: string
Requirement: Required when parent is supplied
Up to 2 characters
accounting_customer_partyType: object
Requirement: Required
See sample and schema
accounting_customer_party.party_nameType: string
Requirement: Required when parent is supplied
Up to 255 characters
accounting_customer_party.tinType: string
Requirement: Required when parent is supplied
See sample and schema
accounting_customer_party.emailType: string
Requirement: Required when parent is supplied
email; Up to 100 characters
accounting_customer_party.telephoneType: string
Requirement: Optional
Up to 100 characters
accounting_customer_party.business_descriptionType: string
Requirement: Optional
Up to 255 characters
accounting_customer_party.postal_addressType: object
Requirement: Required when parent is supplied
See sample and schema
accounting_customer_party.postal_address.street_nameType: string
Requirement: Required when parent is supplied
Up to 255 characters
accounting_customer_party.postal_address.city_nameType: string
Requirement: Required when parent is supplied
Up to 100 characters
accounting_customer_party.postal_address.postal_zoneType: string
Requirement: Required when parent is supplied
Up to 20 characters
accounting_customer_party.postal_address.lgaType: string
Requirement: Required when parent is supplied
Up to 100 characters
accounting_customer_party.postal_address.stateType: string
Requirement: Required when parent is supplied
Up to 100 characters
accounting_customer_party.postal_address.countryType: string
Requirement: Required when parent is supplied
Up to 2 characters
payment_meansType: array
Requirement: Optional
See sample and schema
payment_means[].payment_means_codeType: string
Requirement: Required when parent is supplied
Up to 3 characters
payment_means[].payment_due_dateType: string
Requirement: Optional
date
tax_totalType: array
Requirement: Required
See sample and schema
tax_total[].tax_amountType: number
Requirement: Required when parent is supplied
See sample and schema
tax_total[].tax_subtotalType: array
Requirement: Required when parent is supplied
See sample and schema
tax_total[].tax_subtotal[].taxable_amountType: number
Requirement: Required when parent is supplied
See sample and schema
tax_total[].tax_subtotal[].tax_amountType: number
Requirement: Required when parent is supplied
See sample and schema
tax_total[].tax_subtotal[].tax_categoryType: object
Requirement: Required when parent is supplied
See sample and schema
tax_total[].tax_subtotal[].tax_category.idType: string
Requirement: Required when parent is supplied
STANDARD_VAT / ZERO_VAT / EXEMPTED
tax_total[].tax_subtotal[].tax_category.percentType: number
Requirement: Required when parent is supplied
See sample and schema
legal_monetary_totalType: object
Requirement: Required
See sample and schema
legal_monetary_total.line_extension_amountType: number
Requirement: Required when parent is supplied
See sample and schema
legal_monetary_total.tax_exclusive_amountType: number
Requirement: Required when parent is supplied
See sample and schema
legal_monetary_total.tax_inclusive_amountType: number
Requirement: Required when parent is supplied
See sample and schema
legal_monetary_total.payable_amountType: number
Requirement: Required when parent is supplied
See sample and schema
invoice_lineType: array
Requirement: Required
See sample and schema
invoice_line[].hsn_codeType: string
Requirement: For goods
Up to 7 characters
invoice_line[].product_categoryType: string
Requirement: For goods
Up to 255 characters
invoice_line[].isic_codeType: string
Requirement: For services
Up to 4 characters
invoice_line[].service_categoryType: string
Requirement: For services
Up to 255 characters
invoice_line[].invoiced_quantityType: number
Requirement: Required when parent is supplied
See sample and schema
invoice_line[].line_extension_amountType: number
Requirement: Required when parent is supplied
See sample and schema
invoice_line[].itemType: object
Requirement: Required when parent is supplied
See sample and schema
invoice_line[].item.nameType: string
Requirement: Required when parent is supplied
See sample and schema
invoice_line[].item.descriptionType: string
Requirement: Required when parent is supplied
See sample and schema
invoice_line[].item.sellers_item_identificationType: string
Requirement: Optional
See sample and schema
invoice_line[].priceType: object
Requirement: Required when parent is supplied
See sample and schema
invoice_line[].price.price_amountType: number
Requirement: Required when parent is supplied
See sample and schema
invoice_line[].price.base_quantityType: number
Requirement: Required when parent is supplied
See sample and schema
invoice_line[].price.price_unitType: string
Requirement: Required when parent is supplied
Up to 3 characters
billing_referenceType: array
Requirement: Optional
See sample and schema
billing_reference[].irnType: string
Requirement: Required when parent is supplied
See sample and schema
billing_reference[].issue_dateType: string
Requirement: Required when parent is supplied
date
Download the supported request JSON Schema. This documents WiseWage's supported subset, not every optional NRS feature. B2C, cross-border invoices, discounts, fees, third-party parties and extra document references are outside this release.
Responses and correction workflow
NRS documents a success body such as the example below. It is illustrative documentation, not evidence of an actual sandbox submission. WiseWage retains the received HTTP status and sanitised response for each attempt.
{
"status": true,
"message": "success"
}Illustrative WiseWage validation error (HTTP 400; not an NRS response):
{
"error": "Business description must not exceed 255 characters.",
"code": "INVALID_REQUEST"
}HTTP 400: correct the identified invoice fields. HTTP 401/403: check credentials, permissions and taxpayer association. Timeouts: retain the attempt and retry through the same invoice workflow. Do not renumber an invoice to retry. Validation is separate from approval and reporting.
IRN and encrypted verification QR
The IRN joins an alphanumeric invoice number, the taxpayer's eight-character Service ID and YYYYMMDD issue date with hyphens. For the QR payload, append a period and UNIX timestamp to that IRN, include the issued certificate, encrypt the JSON with the downloaded RSA public key using the documented OpenSSL-compatible padding, then encode the ciphertext as Base64. The QR contains that Base64 ciphertext, never a plain IRN or invented verification URL.
Administrators configure the matching NRS public key and certificate server-side before fiscalization. Missing or invalid keys block the reporting request. Historical invoices without encrypted QR evidence remain downloadable with a warning; they must not be resubmitted merely to replace a QR code.
Linked credit notes (380) and debit notes (384) use billing_reference to identify the original fiscalized invoice. Create them from the original invoice with a reason and selected line amounts; inherited VAT and account mappings are retained. They require validation, approval and confirmation. Fiscalized cancellation is unavailable pending confirmation of the supported NRS process. Reconciliation compares saved NRS evidence, register values and current ledger receivable, revenue and output VAT amounts; it does not verify filed VAT returns.
Download fictional QR format evidence (encrypted payload, test public key and test certificate; no private key).
The downloadable sample demonstrates the encrypted format using locally generated test keys. It is explicitly not NRS-verified, not a sandbox acceptance record and not valid for tax use. Real verification requires the NRS-issued cryptographic materials and an MBS360/NRS verification check.
Official v1.1 references: Invoice Schema, Generate IRN, QR Code.
Payload
Request mappings
| WiseWage source | NRS invoice area | Control |
|---|---|---|
| NRS business profile | business_id and supplier party | UUID, taxpayer identity, and structured Nigerian address validation |
| Customer fiscal profile | accounting_customer_party | Country, state, and LGA codes must form a valid relationship |
| Invoice header | IRN, issue date, type 381, currency, and payment means | Permanent numbering and date/currency validation |
| Invoice lines | quantity, price, item, ISIC/HSN classification, and tax category | Official classification selection and line-level VAT treatment |
| Calculated totals | tax totals and legal monetary totals | Server-side recalculation before submission |
Reliability
Responses and error handling
WiseWage records the outcome of each NRS validation or fiscalization attempt, including the operation, time, HTTP outcome, and a sanitized business-facing explanation. Validation failures remain available for correction and retry; failed attempts do not create posted accounting entries. Fiscalization requires successful NRS signing and matching invoice confirmation; a VAT reporting response alone is insufficient. When a submission outcome is uncertain, Check NRS status confirms the existing IRN without resending it. Each attempt and its evidence are retained.
Customer-facing messages identify an invalid field when NRS provides that detail. Secrets, raw database failures, stack traces, and private infrastructure information are not returned to the browser.
Authentication or access-denied responses stop the NRS operation and direct an administrator to verify the configured environment and credentials. Upstream unavailability is distinguished from invoice-data validation where the NRS response permits it.
Duplicate protection
Idempotency
Validation attempts are keyed to the invoice revision. Fiscalization uses a server-generated idempotency value derived from the invoice identity, revision, and payload fingerprint; the IRN is also sent as the NRS idempotency key.
Retries for an unchanged request reuse the controlled operation rather than intentionally creating another invoice or accounting-register row. A material draft correction creates a new revision and preserves earlier attempt history.
Controls
Security and data handling
See the WiseWage Security page, Privacy Policy, and NRS e-Invoicing SLA for related controls.
Reviewer resources
Technical evidence and samples
System integration use cases
Updated NRS-template use cases: taxpayer setup, fiscalization, draft cancellation, linked notes, recovery and reconciliation.
Download PDFFictional UBL JSON sample
A non-production commercial-invoice example containing no real taxpayer or customer data.
Download JSONRendered fictional invoice
Fictional invoice with IRN and a test-key encrypted QR. Not NRS-verified or valid for tax use.
Download PDFAll published samples are fictional and must not be used as production taxpayer records. Their invented Business ID and Service ID are illustrative, and the test-key QR is not NRS verification evidence. The successful sandbox transaction is separate evidence and contains no public client data here.
Change record
Version history
Clarified taxpayer-owned authentication and Business ID versus Entity ID; recorded verified sandbox commercial-invoice fiscalization; documented final PDF links, e-Invoicing source labels, separate accounting validation, linked adjustments and user-triggered reconciliation. Updated the use-case submission to the NRS template.
Expanded Create Invoice and NRS request reference, supported JSON Schema, IRN and encrypted QR requirements, and clearly labelled test-key sample evidence.
For documentation or integration questions, contact hello@wisewagehr.com. For security reports, contact security@wisewagehr.com.
Official platform requirements remain controlled by NRS. Review the NRS onboarding guidance for current requirements.
