Nigeria Revenue Service e-Invoicing · v1.2

e-Invoicing API Specification

The reference for creating, clearing, and managing electronic invoices on the Taxable platform. It covers the Partner API for third-party integrators, public IRN verification, webhooks, and the audit log.

Document ID
TAX-EINV-APISPEC-2026.07-v1.2
Version
v1.2
Date
20 July 2026
Status
Issued for accreditation review
Document Owner
Taxable Platform Engineering
Source of Truth
Platform OpenAPI document
Contact
www.taxable.ng · hello@taxable.ng

Who this document is for. Partners and system integrators building against Taxable’s e-invoicing Partner API, and technical evaluators assessing the platform as part of NRS System Integrator and Access Point Provider accreditation. It is organised the way a new integrator actually experiences the platform: onboarding first, then authentication, then the full endpoint reference.

1. Overview

The Taxable E-Invoicing API lets a business create invoices, submit them to the Nigeria Revenue Service (NRS) for clearance, and receive back an Invoice Reference Number (IRN) that makes each invoice independently verifiable. Around that core clearance flow, the API provides customer management, invoice lifecycle actions (send, pay, void, credit and debit notes), PDF and signed-document retrieval, purchase (input-side) invoice recording, and a per-period VAT ledger that feeds VAT return prefill.

EnvironmentBase URLNotes
Productionhttps://api.taxable.ngLive NRS clearance; production IRNs
Sandboxhttps://dev-api.taxable.ngFull API surface; sandbox IRNs

The API serves two audiences with two distinct authentication families:

  • Partner API (/partner/v1/*) is for third-party integrators. Authenticated with an API key in the x-api-key header. Each key maps to exactly one business.
  • First-party API is used by Taxable's own invoicing application and developer console. Authenticated with a platform-issued JWT bearer token, scoped to a single business per request.

There is also one deliberately public, unauthenticated endpoint, GET /nrs/verify/{irn}, so that anyone holding an invoice can verify its authenticity without platform credentials.

What happens when an invoice clears

An invoice is created as a draft, then issued: issuing assigns the invoice number and triggers submission to the NRS clearance gateway. On successful clearance the NRS returns an IRN, the invoice becomes a cleared fiscal document, and a webhook event is dispatched to any registered endpoints. Clearance calls to NRS are retried only on transient failures (HTTP 429, 5xx, 408, and network errors); business errors (400, 401, 403, 404, and 409 duplicates) are terminal and never retried. Every cleared invoice also feeds the business's per-period VAT ledger, which becomes the prefill for its VAT return.

2. Getting started: partner onboarding

Partner onboarding is entirely self-service through the Taxable Developer Console, a hosted portal that fronts the platform API. The console is stateless: it owns no database of its own, and every read and write passes through to the platform API using your own credentials.

1. Sign in. Authentication is passwordless. Enter your email address and the console sends a magic link. The same link both registers a new developer account and signs in an existing one, so there is no separate signup form. The link is verified server-side before any session cookie is set.

2. Select your business and check NRS enrolment. The console home page shows a business selector and the NRS enrolment status of the selected business. NRS enrolment is a precondition for issuing invoices that clear. If the business is not yet enrolled, complete enrolment before attempting your first issue call.

3. Create an API key. Create, list, and revoke Partner API keys for the selected business. Existing keys are always displayed masked.

Keys are shown once

The key value is shown exactly once, at creation. Copy it into your secrets manager immediately, because it cannot be retrieved again. If a key is lost, revoke it and create a new one. This is deliberate: the platform never stores or redisplays the plaintext key.

4. Register a webhook. Register your outbound webhook endpoint URL and choose the event types you want to receive. The signing secret is also shown once, at registration. Store it alongside your API key; you will use it to verify webhook signatures. The webhooks page includes a delivery log with one-click replay of failed deliveries.

5. Make your first call. Passing an invoice payload to POST /partner/v1/invoices creates the invoice; by default it is issued immediately (use ?issue=false to create a draft only).

Create and issue an invoice (sandbox)

curl -X POST "https://dev-api.taxable.ng/partner/v1/invoices" \
     -H "x-api-key: $TAXABLE_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{
         "customer": {
             "name": "Eko Allied Manufacturing Ltd",
             "tin": "01234567-0001",
             "email": "accounts@ekoallied.ng",
             "address": "14 Creek Road, Apapa, Lagos"
         },
         "issueDate": "2026-07-13",
         "dueDate": "2026-08-12",
         "currency": "NGN",
         "lineItems": [
             {
                 "description": "Industrial packaging film — 500kg roll",
                 "quantity": 4,
                 "unitPrice": 185000.00,
                 "vatRate": 7.5
             },
             {
                 "description": "Delivery and handling, Apapa to Ikeja",
                 "quantity": 1,
                 "unitPrice": 45000.00,
                 "vatRate": 7.5
             }
         ]
     }'

Response: 201 Created

{
    "success": true,
    "data": {
        "id": "inv_01J9ZQ4T8RVXW2M5KD73PA6QNH",
        "invoiceNumber": "INV-2026-0147",
        "status": "ISSUED",
        "irn": "IRN-1784297456123",
        "customer": { "name": "Eko Allied Manufacturing Ltd", "tin": "01234567-0001" },
        "currency": "NGN",
        "subtotal": 785000.00,
        "vatAmount": 58875.00,
        "total": 843875.00,
        "issueDate": "2026-07-13",
        "dueDate": "2026-08-12"
    }
}

Note the sandbox-shaped IRN (IRN-<epoch-ms>). In production the IRN follows the NRS format; see the IRN format appendix.

6. Watch it in the audit log. The console's activity page shows recent Partner API calls made with the selected business's keys: method, path, status, latency, and request ID. See Audit log for exactly what is, and is never, recorded.

7. Optional: bulk import. For high-volume backfills, upload an invoice CSV, watch rows clear via live polling against the batch-status endpoint, and download a per-row result CSV showing success or failure for every line.

3. Authentication

The platform has two authentication families. Which one you use is determined by which API surface you are calling, and they are not interchangeable.

First-party (internal app)Partner API
MechanismPlatform-issued JWT, Authorization: BearerAPI key via x-api-key header
ScopeOne authenticated user, scoped to a single business per requestOne key maps to exactly one business
Rate limitGoverned by session-level controls10 req/s sustained, burst 20, 50,000 requests/month
Issued viaPlatform sign-in (magic link)Self-service via the developer console
Error shape{ error: { type, code, message } }{ success, data | error }

Partner API: every /partner/v1/* route requires the key. Keys are attached to an API gateway usage plan, so rate limiting and the monthly quota are enforced at the gateway, before a request reaches application code.

curl "https://api.taxable.ng/partner/v1/invoices?status=ISSUED&limit=20" \
    -H "x-api-key: $TAXABLE_API_KEY"

First-party calls carry a platform-issued bearer JWT. The authenticated user must hold the OWNER or ACCOUNTANT role on the target business, otherwise the request is rejected with 403.

Key and webhook management is first-party only

A partner cannot create, rotate, or revoke its own API keys through the Partner API. Key and webhook management lives behind bearer authentication and the developer console. This is intentional: a leaked API key cannot be used to mint further keys.

4. Making requests

  • Base URLs: production https://api.taxable.ng, sandbox https://dev-api.taxable.ng. Integrate and certify against sandbox first.
  • Content type: request and response bodies are JSON; send Content-Type: application/json. The exception is binary document endpoints (invoice PDF).
  • Business scoping: Partner API calls are scoped automatically, because the API key identifies the business.
  • Monetary units: all monetary values in this API — invoice amounts, tax summaries, and VAT ledger figures — are expressed in document-currency major units, that is naira with decimal kobo (e.g. 185000.00). No minor-unit conversion is applied at any layer.

Rate limits (Partner API), enforced at the API gateway via a usage plan, per key:

LimitValue
Sustained rate10 requests/second
Burst20 requests
Monthly quota50,000 requests

Every Partner API endpoint can return 429 Too Many Requests. Treat 429 as retryable with exponential backoff and jitter.

HTTP/1.1 429 Too Many Requests

{
    "success": false,
    "error": {
        "type": "rate_limited",
        "code": "RATE_LIMIT_EXCEEDED",
        "message": "Request rate limit exceeded. Retry with backoff."
    }
}

5. Reading responses

The two API surfaces use deliberately different response envelopes. Match your client's parsing to the surface you call. The Partner API wraps every payload in success / data; the first-party API returns resources directly and uses a bare error object on failure.

Partner API envelope

// Success
{
    "success": true,
    "data": { "id": "inv_01J9ZQ…", "status": "ISSUED" }
}

// Failure
{
    "success": false,
    "error": {
        "type": "validation_error",
        "code": "INVALID_LINE_ITEM",
        "message": "lineItems[0].unitPrice must be a positive number"
    }
}
StatusMeaningTypical cause
400Invalid stateAn action the invoice's current lifecycle state does not allow (e.g. paying a voided invoice)
401UnauthenticatedMissing or invalid API key / JWT
403ForbiddenFirst-party caller lacks the OWNER / ACCOUNTANT role on the business
404Not foundUnknown resource ID, or a resource belonging to another business
422Validation errorRequest body fails schema validation
429Rate limitedPartner rate or monthly quota exceeded

6. Partner API reference

All endpoints below require the x-api-key header, are scoped to the key's business, and can return 429. Responses use the partner envelope ({ success, data | error }).

Customers. Customers are the counterparties on your invoices. Creating them as first-class records lets you reference them by ID and keeps TIN and contact data consistent across invoices.

POST/partner/v1/customers

Create a customer.

GET/partner/v1/customers

List customers for the business (paginated).

GET/partner/v1/customers/search

Search customers by name, TIN, or email, e.g. ?q=zaria.

GET/partner/v1/customers/{id}

Retrieve one customer by ID.

PUT/partner/v1/customers/{id}

Update a customer. Send the fields to change; the response returns the full updated record.

DELETE/partner/v1/customers/{id}

Delete a customer. Invoices already issued against the customer are unaffected; they retain their own snapshot of the customer details.

Invoices: create, issue, lifecycle.

POST/partner/v1/invoices

Create an invoice. By default the invoice is issued immediately (number assigned, NRS clearance triggered). Pass ?issue=false to create a draft only.

GET/partner/v1/invoices

List invoices, filterable by status and date, e.g. ?status=ISSUED&from=2026-07-01&to=2026-07-31.

GET/partner/v1/invoices/{id}

Retrieve one invoice with full line items, tax summary, and clearance status.

PUT/partner/v1/invoices/{id}

Update a draft invoice. Once issued, an invoice is a cleared fiscal document and can no longer be edited; use a credit or debit note to adjust it.

POST/partner/v1/invoices/{id}/issue

Issue a draft: assigns the invoice number and submits the invoice to NRS for clearance. On success the response carries the IRN.

Response: 200

{
    "success": true,
    "data": {
        "id": "inv_01J9ZQ4T8RVXW2M5KD73PA6QNH",
        "invoiceNumber": "INV-2026-0147",
        "status": "ISSUED",
        "irn": "IRN-1784297456123",
        "clearedAt": "2026-07-13T10:02:44Z"
    }
}
POST/partner/v1/invoices/{id}/send

Send the invoice to the customer (email delivery with the PDF attached).

POST/partner/v1/invoices/{id}/pay

Record payment against the invoice.

POST/partner/v1/invoices/{id}/void

Void an invoice. Voiding is terminal; the invoice remains on record and verifiable but is marked void. Lifecycle actions on a voided invoice return 400 with an invalid-state error.

POST/partner/v1/invoices/{id}/credit-note

Issue a credit note against a cleared invoice: the correct instrument for reducing or reversing an already-cleared amount.

POST/partner/v1/invoices/{id}/debit-note

Issue a debit note against a cleared invoice, for charging an additional amount related to the original supply.

Documents and clearance status.

GET/partner/v1/invoices/{id}/pdf

Download the invoice as a PDF. The response body is the binary document (Content-Type: application/pdf), not a JSON envelope.

GET/partner/v1/invoices/irn/{irn}/signed

Retrieve the signed (cleared) invoice document by IRN: the fiscal artefact as cleared by NRS, addressed by its reference number rather than the platform ID.

GET/partner/v1/transmission/{irn}

Check the NRS transmission status for an IRN; use this to track clearance progress and outcomes without polling the invoice itself.

Purchases (input-side invoices).

POST/partner/v1/purchases

Record a purchase invoice received from a supplier, so that input VAT is captured in the business's VAT ledger alongside output VAT from sales.

VAT ledger. Every cleared invoice and recorded purchase feeds a per-business, per-period VAT ledger, which is the source for VAT return prefill. Periods use YYYY-MM. All ledger amounts are in naira, consistent with the invoice endpoints.

GET/partner/v1/vat-ledger/{period}

The full ledger for a period: every entry contributing to output and input VAT.

GET/partner/v1/vat-ledger/{period}/summary

Period totals, grouped into output, input, and adjustment positions.

Response: 200

{
    "success": true,
    "data": {
        "period": "2026-06",
        "output": {
            "standardRated": 550500000.00,
            "zeroRated": 0.00,
            "exempt": 0.00,
            "totalVat": 41287500.00,
            "entryCount": 214
        },
        "input": {
            "vatableValue": 124000000.00,
            "inputVatPaid": 9300000.00,
            "entryCount": 37
        },
        "adjustments": {
            "netAdjustment": 0.00,
            "entryCount": 0
        }
    }
}
GET/partner/v1/vat-ledger/{period}/prefill

The period's figures shaped as a VAT return prefill: the same data the Taxable filing product uses to pre-populate a VAT return.

Resources.

GET/partner/v1/resources/{resource}

Reference data lookups (enumerations and code lists used in invoice payloads), addressed by resource name.

7. Public IRN verification

GET/nrs/verify/{irn}

PUBLIC — no authentication of any kind.

Verify the authenticity of an invoice by its IRN. Anyone holding an invoice — a consumer checking a receipt, an auditor sampling a ledger, a counterparty's accounts team — can confirm that the IRN is genuine and corresponds to a cleared invoice, without needing platform credentials.

curl "https://api.taxable.ng/nrs/verify/INV0147-A1B2C3D4-20260713"

This is a trust-and-transparency feature of the platform: the value of an IRN comes precisely from the fact that its validity can be checked by anyone, independently of the parties to the transaction.

8. First-party API

The first-party API is the surface behind Taxable's own invoicing application and developer console. It shares the same OpenAPI document as the Partner API and uses bearer authentication. Each request is scoped to a single business, and the caller must hold the OWNER or ACCOUNTANT role on that business, otherwise the request is rejected with 403.

It covers the following capability families:

Capability familyCovers
E-InvoicesFull invoice lifecycle: create, update, issue, send, pay, void, credit and debit notes, email, PDF download, get/list/search
Invoice ReportingDashboard KPIs, revenue (CIT prefill), submissions ledger, bulk CSV batches and batch status
CustomersCustomer records and search
VAT LedgerPeriod ledger, period summary, and VAT return prefill
SettingsE-invoice settings
BusinessBusiness profile, NRS enrolment management, partner key lifecycle, webhook registration, and the activity log

Management capabilities are excluded from the Partner API

NRS enrolment management, partner key lifecycle (create, list masked, revoke), webhook registration and signing-secret management, and the partner-call activity log are reachable only with bearer authentication, through the console or the first-party application. They are deliberately absent from the key-authenticated Partner API surface.

9. Webhooks

Webhooks push invoice lifecycle updates to your systems so you do not have to poll the transmission endpoint. You register an endpoint URL and choose event types in the console's webhooks page.

The following event types are available for subscription:

EventFired when
invoice.createdAn invoice record is created
invoice.issuedA draft is issued and submitted for clearance
invoice.clearedNRS clears the invoice and an IRN is assigned
invoice.rejectedNRS rejects the submission
invoice.transmittedThe invoice is transmitted to NRS
invoice.paidPayment is recorded against the invoice
invoice.voidedThe invoice is voided
invoice.credit_notedA credit note is issued against the invoice
invoice.debit_notedA debit note is issued against the invoice
Table 1. Subscribable webhook event types. The event name is also sent in the X-Taxable-Event header on every delivery.

Signature verification. Each webhook endpoint has a signing secret, shown once at registration. Every delivery is signed with this secret; verify the signature before trusting a payload, and reject deliveries that fail verification.

Delivery, retries, and replay. The console's webhooks page includes a delivery log for your endpoint. Failed deliveries can be replayed with one click, so a transient outage on your side never means silently lost events. Design your handler to be idempotent: between retries and manual replay, the same event can legitimately arrive more than once.

10. Audit log

Every Partner API call made with your keys is recorded and surfaced in the console's activity page. For each call you can see exactly five things:

FieldExample
MethodPOST
Path/partner/v1/invoices
Status201
Latency412 ms
Request ID7f3c9a2e-4b1d-4e8a-9c67-d21f80a5b3e4

Request and response bodies are never logged

The activity pipeline is built from API gateway access logs, which capture request metadata only. This is a deliberate privacy and security commitment, not a limitation: your invoice data, customer PII, and payment details never enter the audit pipeline. What you get is a complete, tamper-evident record that a call happened and how it was answered — never what it contained.

Two practical notes: the log covers key-authenticated Partner API calls, so it is the audit trail for your integration's traffic specifically; and the request ID shown is the same ID you can capture from the API response, making the log directly correlatable with your own application logs when raising a support issue.

11. Appendix A: IRN format reference

EnvironmentShapeExample
SandboxIRN-<epoch-ms>IRN-1784297456123
Production (NRS format){InvoiceNo}-{ServiceID}-{YYYYMMDD}INV0147-A1B2C3D4-20260713

Sandbox IRNs are locally generated and exist so the full clearance flow can be exercised end-to-end without touching the live regulator gateway. Production IRNs follow the NRS reference-number format and are verifiable by anyone via GET /nrs/verify/{irn}. The ServiceID segment shown above is illustrative; each accredited provider is assigned its own.

12. Appendix B: Rate limits quick reference

SurfaceSustainedBurstMonthly quotaEnforced at
Partner API10 req/s2050,000 requestsAPI gateway usage plan, per key
First-partySession-level controlsApplication layer
Public verifyUnauthenticated public endpoint

On 429, back off exponentially with jitter. If your integration's steady-state volume approaches the monthly quota, contact Taxable about your usage plan before you hit it; the quota is a gateway-enforced hard stop.

13. Appendix C: Changelog

VersionDateChanges
v1.220 July 2026Published to the web. Stated monetary units definitively as naira across all endpoints, including the VAT ledger. Corrected the VAT ledger period-summary response shape. Documented the subscribable webhook event types. Replaced individual attribution with role-based document ownership.
v1.113 July 2026Applied Taxable brand identity; added the document control block and branded footer.
v1.013 July 2026Initial publication.

Taxable E-Invoicing API Specification · TAX-EINV-APISPEC-2026.07-v1.2 · 20 July 2026 · www.taxable.ng · hello@taxable.ng