API Documentation

https://api.invota.ng/api/v1

INVOTA Platform

API Documentation

Complete REST API reference for the INVOTA e-invoicing platform. All endpoints conform to the FIRS NRS specification for e-invoice generation, signing, and transmission in Nigeria.

Base URLhttps://api.invota.ng/api/v1
Version1.0
AuthBearer Token / API Key
FormatJSON
01

Overview

The INVOTA API gives you programmatic access to every part of the e-invoicing lifecycle, from creating a draft to confirming NRS acknowledgement. All requests go to the base URL above over HTTPS.

Authentication

The dashboard API uses bearer token authentication. After logging in, include the token in every subsequent request:

Authorization: Bearer {your-token}

The B2B enterprise API uses API key authentication. See Section 8 for details.

Rate Limits

API GroupLimitWindow
Dashboard API (all authenticated routes)60 requestsPer minute
B2B Enterprise API100 requestsPer minute

When a rate limit is exceeded the API returns HTTP 429 with a Retry-After header.

Response Format

All responses are JSON. Successful responses include a data key. Error responses include a message key and, where applicable, an errors key with field-level details.

// Success
{ "data": { ... } }

// Validation error
{
  "message": "Validation failed.",
  "errors": {
    "invoice_number": ["The invoice number field is required."]
  }
}

Multi-Tenancy

Every authenticated request is automatically scoped to the organisation of the authenticated user. It is not possible to access data belonging to another organisation through this API.

Invoice Status Flow

Invoices progress through the following statuses as they move through the NRS pipeline:

draftvalidatedsignedtransmittingtransmittedacknowledgedreported

Any stage can transition to failed on NRS rejection. Failed invoices can be retried. They return to draft.

02

Authentication

All authentication endpoints are public. No token required.

POST/auth/register

Registers a new organisation and creates the first user account (the owner). The user receives the finance role with is_owner = true.

Request Body

FieldTypeRequiredDescription
org_namestringRequiredName of the business
tinstringRequiredFIRS Tax Identification Number
emailstringRequiredBusiness email address
passwordstringRequiredMinimum 8 characters
namestringRequiredFull name of the registering user
phonestringOptionalBusiness phone number
addressstringOptionalBusiness address

Response: 201 Created

{
  "data": {
    "token": "1|abcdefghijklmnopqrstuvwxyz",
    "user": {
      "id": "uuid", "name": "Adaeze Okonkwo",
      "email": "adaeze@acme.ng", "role": "finance"
    },
    "organization": { "id": "uuid", "name": "Acme Nigeria Ltd" }
  }
}
POST/auth/login

Authenticates a user and returns a bearer token.

Request Body

FieldTypeRequired
emailstringRequired
passwordstringRequired

Response: 200 OK

{
  "data": {
    "token": "2|abcdefghijklmnopqrstuvwxyz",
    "user": {
      "id": "uuid", "name": "Adaeze Okonkwo",
      "email": "adaeze@acme.ng",
      "role": "finance", "is_owner": true
    }
  }
}
POST/auth/logout

Revokes the current bearer token. The token becomes invalid immediately.

Response: 200 OK

{ "data": { "message": "Logged out successfully." } }
03

Invoice Management

All routes require authentication. Write operations require an active subscription. Supplier party details are automatically derived from the authenticated organisation's taxpayer profile.

GET/invoices

Returns a paginated list of invoices for the authenticated organisation.

Query Parameters

ParameterTypeDescription
statusstringFilter by: draft, validated, signed, transmitting, transmitted, acknowledged, reported, failed
searchstringSearch by invoice number or buyer name
pageintegerPage number (default: 1)

Response: 200 OK

{
  "data": [
    {
      "id": "uuid",
      "irn": "INV001-2741A890-20260701",
      "invoice_number": "INV001",
      "issue_date": "2026-07-01",
      "status": "signed",
      "currency_code": "NGN",
      "total_amount": 150000.00,
      "vat_amount": 19565.22
    }
  ],
  "meta": { "total": 42, "per_page": 15, "current_page": 1, "last_page": 3 }
}
POST/invoices

Creates a new invoice in draft status. Supplier party details are taken from the organisation's taxpayer profile. The IRN is built and validated server-side. Per-line amounts and totals are calculated server-side.

Request Body

FieldTypeRequiredDescription
invoice_numberstringRequiredAlphanumeric only. No special characters or spaces.
invoice_type_codestringRequiredNRS invoice type code (e.g. 380)
issue_datedateRequiredYYYY-MM-DD. Used to build the IRN.
currency_codestringRequiredISO 4217 currency code (e.g. NGN)
buyer.namestringRequiredBuyer company or individual name
buyer.emailstringRequiredBuyer email address
buyer.tinstringOptionalRequired for B2B invoices
buyer.incorporation_numberstringOptionalUsed when buyer TIN is not available
buyer.addressstringOptional
linesarrayRequiredAt least one line item
lines[].descriptionstringRequired
lines[].quantitydecimalRequired
lines[].unit_pricedecimalRequired
lines[].tax_category_codestringRequiredNRS tax category (e.g. S, Z, E)
lines[].product_categorystringRequiredgoods or services
lines[].hsn_codestringRequired for goodsFormat: 0000.00
lines[].isic_codestringRequired for services4-digit ISIC code
notestringOptionalStored encrypted
payment_terms_notestringOptionalStored encrypted

Response: 201 Created

{
  "data": {
    "id": "uuid",
    "irn": "INV001-2741A890-20260701",
    "status": "draft",
    "total_amount": 150000.00,
    "vat_amount": 19565.22
  }
}
GET/invoices/{id}

Returns the full details of a single invoice including all line items and party details.

PUT/invoices/{id}

Updates a draft invoice. Only allowed when status is draft. Only the account owner (is_owner = true) may edit an invoice. If the invoice number or issue date changes, the IRN is rebuilt and re-validated server-side.

DELETE/invoices/{id}

Soft-deletes a draft invoice. Only allowed when status is draft. Only the account owner may delete. Deleted invoices are not permanently removed from the database.

POST/invoices/bulk

Creates up to 100 invoices in a single request.

Request Body

{ "invoices": [ { ... }, { ... } ] }

Response: 207 Multi-Status

Returns a result for each submitted invoice: success or the specific validation error for that item.

04

Invoice Lifecycle

These endpoints move an invoice through the NRS submission pipeline. All background communication with NRS runs as queued jobs. The API returns 202 Accepted immediately and processing continues in the background.

POST/invoices/{id}/submit

Submits a draft invoice to NRS for validation and signing. Dispatches a background job that first validates the invoice against NRS, then signs it and generates the QR code. The invoice status moves from draft through validated to signed if both steps succeed.

Response: 202 Accepted

{ "data": { "message": "Invoice submitted. Processing in background." } }
GET/invoice/confirm/{irn}

Polls NRS to confirm the current status of an invoice by its IRN. Use this to check whether a submitted invoice has been signed or to surface any NRS-side issue.

Response: 200 OK

{ "data": { "irn": "...", "status": "signed", "nrs_message": "..." } }
POST/invoices/{id}/transmit

Transmits a signed invoice to the NRS exchange network so the buyer's system can receive it. Only available once the invoice status is signed. Runs as a background job.

Response: 202 Accepted

{ "data": { "message": "Invoice queued for transmission." } }
PATCH/invoices/{id}/payment

Updates the payment status of an invoice. When status is set to PAID or PARTIAL, the system automatically queues a VAT post-payment report to NRS and sends a receipt email to the buyer.

Request Body

FieldTypeRequiredDescription
payment_statusstringRequiredPENDING, PARTIAL, PAID, or REJECTED
payment_datedateOptionalDate payment was received
amount_paiddecimalOptionalRequired when status is PARTIAL
GET/invoices/{id}/pdf

Streams the invoice as a downloadable PDF. Includes the invoice header, supplier and buyer details, line items, tax totals, the IRN, and the QR code image.

Response

Content-Type: application/pdf. File is streamed as a download.

GET/invoices/{id}/qr

Returns a time-limited pre-signed URL to the QR code image in file storage. Only available once the invoice is signed.

Response: 200 OK

{ "data": { "url": "https://storage.invota.ng/qr-codes/org-id/irn.png?token=..." } }
POST/invoices/{id}/email

Queues an email to the buyer containing invoice details and a PDF attachment.

Response: 202 Accepted

{ "data": { "message": "Email queued for delivery." } }
05

Customers

Customers are buyer contacts saved to the organisation's address book. They can be selected when creating an invoice to pre-fill buyer details.

GET/customers

Returns a paginated list of customers for the authenticated organisation.

Query Parameters

ParameterTypeDescription
searchstringFilter by name or email
pageintegerPage number (default: 1)
POST/customers

Creates a new customer record.

Request Body

FieldTypeRequired
namestringRequired
emailstringRequired
tinstringOptional
phonestringOptional
addressstringOptional
GET/customers/{id}

Returns the full details of a single customer.

PUT/customers/{id}

Updates a customer record. All fields are optional.

DELETE/customers/{id}

Deletes a customer record.

06

Items

Items are saved products or services that can be selected when adding lines to an invoice. Each item stores NRS classification codes so they do not need to be entered each time.

GET/items

Returns a paginated list of items for the authenticated organisation.

Query Parameters

ParameterTypeDescription
searchstringFilter by name or description
typestringFilter by goods or services
pageintegerPage number (default: 1)
POST/items

Creates a new item.

Request Body

FieldTypeRequiredDescription
namestringRequired
descriptionstringOptional
unit_pricedecimalRequired
product_categorystringRequiredgoods or services
hsn_codestringRequired for goodsFormat: 0000.00
isic_codestringRequired for services4-digit ISIC code
tax_category_codestringRequiredNRS tax category
GET/items/{id}

Returns the full details of a single item.

PUT/items/{id}

Updates an item record.

DELETE/items/{id}

Deletes an item record.

07

Reports

Reporting endpoints provide summary and export data for the authenticated organisation. Requires the auditor or finance role.

GET/reports/summary

Returns aggregate invoice statistics over a given date range.

Query Parameters

ParameterTypeDescription
fromdate (YYYY-MM-DD)Start of date range
todate (YYYY-MM-DD)End of date range

Response: 200 OK

{
  "data": {
    "total_invoices": 127,
    "total_value": 4500000.00,
    "total_vat": 586956.52,
    "by_status": {
      "draft": 5, "signed": 12,
      "acknowledged": 98, "reported": 12, "failed": 0
    }
  }
}
GET/reports/vat

Returns VAT post-payment report records for the authenticated organisation.

Query Parameters

ParameterTypeDescription
fromdateStart of period
todateEnd of period
statusstringpending, submitted, failed
GET/reports/export

Exports a list of invoices as a CSV file for the given date range and optional status filter.

Query Parameters

ParameterTypeDescription
fromdateStart of period
todateEnd of period
statusstringOptional filter by invoice status
formatstringcsv (default)

Response

Content-Type: text/csv. File is streamed as a download.

08

B2B Enterprise API

The B2B API is for enterprise clients that connect their ERP or POS systems directly to INVOTA. It uses API key authentication instead of bearer tokens. Clients access this API only. They do not use the web dashboard.

Authentication

Include both headers on every B2B API request:

X-Api-Key: {your-api-key}
X-Api-Secret: {your-api-secret}

API credentials are provisioned by a Best Teck Nigeria Limited admin. Clients can rotate their own credentials at any time using the credentials endpoint below.

POST/b2b/invoices

Submits a single invoice through the B2B API. Uses the same request body structure as POST /invoices. Immediately dispatches the validate and sign job. Returns 202 with the IRN as a reference for polling.

Response: 202 Accepted

{ "data": { "irn": "INV001-2741A890-20260701", "status": "draft" } }
GET/b2b/invoices/{irn}

Returns the current status of an invoice by its IRN. Poll this after submitting to track progress.

Response: 200 OK

{
  "data": {
    "irn": "INV001-2741A890-20260701",
    "status": "signed",
    "qr_url": "https://storage.invota.ng/qr-codes/..."
  }
}
POST/b2b/invoices/bulk

Submits up to 50 invoices in a single request. Returns a 207 Multi-Status response with a result for each invoice.

Request Body

{ "invoices": [ { ... }, { ... } ] }
GET/b2b/credentials

Returns the current active credential for the authenticated B2B client (key ID and creation date). The actual key and secret values are not returned after initial provisioning.

POST/b2b/credentials/rotate

Rotates the B2B API credentials. The old key is deactivated immediately. The new key and secret are returned once only.

Response: 200 OK

{
  "data": {
    "api_key": "new-key-shown-once",
    "api_secret": "new-secret-shown-once"
  }
}
Important: The api_secret is only returned in this response. It is stored encrypted and cannot be retrieved again. Rotate only when you are ready to update your system immediately.

Enterprise Dashboard (Account Management)

Everything above is called by your ERP/POS system using theX-Api-Key / X-Api-Secret pair. The endpoints below are different: they use ordinary Bearer token auth (the same login as the regular dashboard) and power the /dashboard/api developer portal a human enterprise user actually logs into to manage their account — viewing usage, rotating keys, switching billing mode, buying credits, and setting a webhook URL. Your integration code should not call these; they are for the person administering the integration, not the integration itself.

GET/enterprise/summary

Overview stats for the enterprise dashboard home page: submission counts by outcome, the 10 most recent invoices, and the organisation's current billing state.

Response: 200 OK

{
  "stats": {
    "total_submitted": 812, "validated_count": 790,
    "failed_count": 6, "pending_count": 16
  },
  "billing": {
    "mode": "prepaid",
    "outstanding_balance": 0,
    "credit_limit_ngn": 500000,
    "credits_balance": 340,
    "plan_slug": "enterprise",
    "per_invoice_rate_ngn": 50.00,
    "currency": "NGN",
    "available_packs": [
      { "id": "100", "credits": 100, "price_ngn": 5000 },
      { "id": "500", "credits": 500, "price_ngn": 22500 }
    ]
  },
  "recent_invoices": [ { "id": "uuid", "irn": "...", "status": "signed", "..." : "..." } ],
  "webhook_callback_url": "https://erp.example.com/hooks/invota"
}
GET/enterprise/credentials

Returns metadata for the active API credential (environment, created/rotated/revoked timestamps). The key and secret values are never returned here — only at the moment they are created or rotated. Credentials are issued automatically once KYC is approved; if none exist yet, credential is null.

POST/enterprise/credentials/rotate

Rotates the active credential within its current environment. The old key stops working immediately. Same one-time-reveal rule as /b2b/credentials/rotate above.

PATCH/enterprise/credentials/environment

Switches between sandbox and production. The environment is encoded in the key prefix itself, so switching issues a brand new key pair rather than relabeling the old one — every credential in the other environment is revoked at the same time, so nothing from the previous environment keeps working afterwards.

Request Body

FieldTypeRequired
environmentstringRequired
PATCH/enterprise/billing/mode

Switches how invoice submissions are billed: payg (Pay As You Go — a running balance invoiced per submission) or prepaid (a credits balance that decreases per submission, topped up manually). Switching to Prepaid is blocked while an outstanding PAYG balance is unpaid.

Request Body

FieldTypeRequired
modestringRequired
POST/enterprise/billing/pay/initialize

Starts a Paystack payment — either clearing an outstanding PAYG balance (purpose: "balance") or buying a prepaid credit pack (purpose: "credits", with a pack_id from the packs listed in GET /enterprise/summary). Returns a Paystack checkout URL to redirect the user to.

Request Body

FieldTypeRequiredDescription
purposestringRequiredbalance or credits
pack_idstringRequired if purpose is creditsMust match an available pack

Response: 200 OK

{ "authorization_url": "https://checkout.paystack.com/...", "reference": "ent_...", "amount_ngn": 5000 }
POST/enterprise/billing/pay/verify

Verifies a Paystack transaction reference after the user returns from checkout and applies it — clearing the balance or crediting the purchased pack onto credits_balance. Safe to call more than once for the same reference; an already-applied payment is reported back without being applied twice.

Request Body

FieldTypeRequired
referencestringRequired
PATCH/enterprise/webhook-callback-url

Sets the URL that receives NRS transmission events for this organisation's invoices (see Section 9). Must be https:// in production.

POST/enterprise/webhook/verify

Sends a single synthetic test event to the saved webhook URL right away, so the user can confirm it's reachable before relying on it. This is a one-off reachability check, not a real event — it is not retried and has no connection to the fire-and-forget delivery used for actual invoice events.

Response: 200 OK / 422

{ "verified": true, "reason": "ok", "status_code": 200 }
09

Webhooks

INVOTA receives event notifications from NRS and forwards them to your registered webhook callback URL. Set the callback URL on your organisation record.

NRS Event Receiver

POST/webhooks/nrs

This endpoint receives event notifications from NRS. It is registered with NRS as the callback URL for all transmission events. Always returns HTTP 200 to acknowledge receipt. Duplicate events are detected using SHA-256 hash checks and ignored automatically.

Events Forwarded to Your Callback URL

EventDescription
TRANSMITTINGNRS has received the invoice on the exchange network
TRANSMITTEDNRS confirms the invoice reached the buyer's access point
ACKNOWLEDGEDThe buyer's system has acknowledged the invoice
FAILEDNRS has reported a failure for this invoice

Webhook Payload

{
  "event": "TRANSMITTED",
  "irn": "INV001-2741A890-20260701",
  "timestamp": "2026-07-01T14:30:00Z"
}
Delivery: Webhook delivery to your callback URL is best-effort. INVOTA does not retry failed deliveries. Use GET /b2b/invoices/{irn} as a fallback if your endpoint is temporarily unavailable.
10

Reference Data

The platform caches reference data from NRS and refreshes it daily at 02:00 WAT. These lists power the dropdown menus in the invoice form and validate classification codes at submission time.

GET/reference/{type}

Returns the cached list for the given type.

Available Types

TypeDescription
invoice_typesNRS invoice type codes (e.g. 380 for commercial invoice)
payment_meansPayment method codes
tax_categoriesVAT and tax category codes (S = Standard, Z = Zero, E = Exempt)
currenciesISO 4217 currency codes
quantity_codesUnit of measure codes for invoice lines
hs_codesHarmonised System codes for goods classification
services_codesISIC codes for services classification
countriesCountry codes and names
statesNigerian state codes
lgasNigerian Local Government Areas

Response: 200 OK

{
  "data": [
    { "code": "380", "name": "Commercial Invoice",  "resource_type": "invoice_types" },
    { "code": "381", "name": "Credit Note",         "resource_type": "invoice_types" }
  ]
}
11

IRN Format

The Invoice Reference Number (IRN) is constructed by INVOTA as the System Integrator. NRS does not assign it. The platform builds and validates the IRN before saving each invoice.

Structure

{InvoiceNumber}-{ServiceID}-{YYYYMMDD}
PartRulesExample
InvoiceNumberAlphanumeric characters only. No spaces, dashes, or special characters.INV001
ServiceID8-character alphanumeric NRS-assigned code for the taxpayer. Stored on the organisation record.2741A890
YYYYMMDDInvoice issue date. Must be a valid calendar date.20260701

Full Example

INV001-2741A890-20260701

IRN with Timestamp (used for NRS signing payload only)

The Unix timestamp is appended only in the cryptographic signing payload sent to NRS. It does not form part of the IRN printed on the invoice or stored in the database.

INV001-2741A890-20260701.1751328000

Uniqueness

No two invoices within the same organisation may share the same IRN. The platform checks for duplicates before saving. Once an IRN has been submitted to NRS and signed it cannot be reused or re-signed under a different invoice.

12

Error Codes

All errors follow a consistent structure. The HTTP status code indicates the general error type. The message field gives a human-readable explanation.

HTTP StatusMeaningCommon Cause
400Bad RequestMissing required fields, invalid date format, invalid IRN characters
401UnauthorizedToken expired, token revoked, missing Authorization header
403ForbiddenWrong role, editing an invoice not in draft status, non-owner trying to delete
404Not FoundInvalid invoice ID, cross-tenant access attempt
409ConflictDuplicate IRN, duplicate invoice number
422Unprocessable EntityHSN code format wrong, ISIC code not in reference data, invalid invoice type
429Too Many RequestsMore than 60 rpm (dashboard) or 100 rpm (B2B)
500Internal Server ErrorNRS API unavailable, background job failure
503Service UnavailableNRS scheduled maintenance or outage

Validation Error Response

{
  "message": "The given data was invalid.",
  "errors": {
    "invoice_number": ["The invoice number may only contain letters and numbers."],
    "lines.0.hsn_code": ["The HSN code must be in the format 0000.00."]
  }
}

NRS Rejection Response

{
  "message": "NRS rejected the invoice.",
  "nrs_code": "INV-004",
  "nrs_message": "Supplier TIN not found in NRS database."
}
13

KYC & Verification

Business identity verification. NRS invoice submission can be blocked for an organisation until KYC is approved, depending on the platform's current enforcement settings.

GET/kyc

Returns the authenticated organisation's overall KYC status plus the state of each individual required document.

Response: 200 OK

{
  "kyc_status": "pending",
  "documents": [
    {
      "type": "cac_certificate",
      "label": "CAC Certificate of Incorporation",
      "required": true,
      "status": "approved",
      "rejection_reason": null,
      "submitted_at": "2026-07-01T09:00:00Z",
      "reviewed_at": "2026-07-02T11:00:00Z"
    },
    {
      "type": "directors_id",
      "label": "Director's Government ID",
      "required": true,
      "status": "pending",
      "rejection_reason": null,
      "submitted_at": "2026-07-01T09:05:00Z",
      "reviewed_at": null
    }
  ]
}

Overall Status Values

StatusMeaning
not_submittedNo required document has been uploaded yet
pendingAt least one required document is awaiting review
approvedEvery required document has been approved
rejectedAt least one required document was rejected — re-upload it

Document Types

TypeLabelRequired
cac_certificateCAC Certificate of IncorporationRequired
directors_idDirector's Government IDRequired
proof_of_addressProof of Business AddressRequired
tin_certificateFIRS TIN CertificateOptional
POST/kyc/submit

Uploads one document for one type. Re-submitting a type that is still pending or was rejected replaces it — an already approved document cannot be overwritten by re-uploading. Send as multipart/form-data, not JSON.

Request Body (multipart/form-data)

FieldTypeRequiredDescription
document_typestringRequiredOne of the document types above
documentfileRequiredPDF, JPG or PNG, max 10 MB

Response: 201 Created

{
  "message": "Document submitted for review.",
  "document_type": "cac_certificate",
  "status": "pending",
  "submitted_at": "2026-07-01T09:00:00Z"
}
14

Billing & Subscriptions

Subscription plan billing for ordinary business and practice accounts via Paystack. Not to be confused with Section 8's Enterprise Dashboard billing, which uses a separate Pay As You Go / Prepaid Credits model for API integrators.

GET/billing

Returns the authenticated organisation's current subscription and payment method state.

Response: 200 OK

{
  "subscription": {
    "plan_slug": "growth",
    "plan_name": "Growth",
    "status": "active",
    "billing_type": "monthly",
    "monthly_fee_ngn": 15000,
    "invoice_limit": 200,
    "invoices_used": 47,
    "cycle_start_at": "2026-07-01T00:00:00Z",
    "cycle_end_at": "2026-08-01T00:00:00Z",
    "next_renewal_at": "2026-08-01T00:00:00Z",
    "outstanding_balance": 0,
    "gateway": "paystack",
    "has_payment_method": true,
    "card_last4": "4081",
    "card_type": "visa",
    "card_expiry": "09/28",
    "features": ["Up to 200 invoices/month", "Email support"],
    "trial_days": 0,
    "is_popular": true
  }
}
GET/billing/history

Returns a paginated list of payment events (charges, renewals, failures) for the authenticated organisation, newest first.

Query Parameters

ParameterTypeDescription
per_pageinteger5–50, default 10
GET/billing/history/export

Downloads the full payment history as a CSV file.

Response

Content-Type: text/csv. File is streamed as a download.

POST/billing/initialize

Starts a Paystack payment to activate or renew a subscription plan. Returns a checkout URL to redirect the user to. Consent note: activating a plan this way saves the card used and authorises automatic renewal charges each billing cycle until the plan is changed or cancelled — this is disclosed to the user in the activation dialog before they are redirected.

Request Body

FieldTypeRequiredDescription
plan_slugstringRequired
billing_typestringRequiredmonthly or yearly

Response: 200 OK

{
  "authorization_url": "https://checkout.paystack.com/...",
  "access_code": "...",
  "reference": "inv_...",
  "amount_ngn": 15000,
  "plan_name": "Growth",
  "billing_type": "monthly"
}
POST/billing/verify

Verifies a Paystack reference after the user returns from checkout and activates the subscription. Safe to call more than once for the same reference.

Request Body

FieldTypeRequired
referencestringRequired
15

Compliance & Audit Trail

Aggregate compliance reporting and the organisation's own activity trail. Distinct from Section 4's per-invoice VAT post-payment reporting — this is summary and historical view, not a write operation.

GET/compliance/summary

Returns a compliance score plus NRS submission and VAT reporting statistics for the authenticated organisation. The score is a weighted average: NRS acceptance rate × 0.6 + VAT submission rate × 0.4.

Response: 200 OK

{
  "compliance_score": 87,
  "nrs_acceptance_rate": 92.5,
  "vat_submission_rate": 75.0,
  "invoice_stats": { "total": 120, "transmitted": 111, "failed": 2, "pending": 7 },
  "vat_stats": { "total": 8, "submitted": 6, "failed": 0, "pending": 2 },
  "vat_trend": [
    { "month": "Apr", "submitted": 1, "pending": 0 },
    { "month": "May", "submitted": 2, "pending": 1 }
  ],
  "nrs_submissions": [
    { "irn": "INV045-2741A890-20260701", "status": "acknowledged", "date": "2026-07-01", "amount": 85000.00 }
  ],
  "breakdown": [
    { "label": "Invoices transmitted", "value": 111, "total": 120 },
    { "label": "VAT reports submitted", "value": 6, "total": 8 }
  ]
}
GET/compliance/export

Downloads the full NRS submission history (IRN, status, taxable/VAT/total amounts) as a CSV file.

GET/audit-trail

Returns the authenticated organisation's own activity trail — every tracked create/update/delete action taken within it, sourced from the platform's immutable audit log. Scoped strictly to the caller's own organisation; there is no way to see another organisation's activity through this endpoint.

Query Parameters

ParameterTypeDescription
per_pageinteger5–50, default 10
searchstringFilter by actor name, action, or IP address
sortstringrecency (default), last_6_months, or alphabetical

Response: 200 OK

{
  "entries": [
    {
      "id": "225",
      "timestamp": "2026-09-09T13:09:31Z",
      "actor_name": "Adaeze Okonkwo",
      "action": "invoice.updated",
      "action_label": "Invoice Updated",
      "action_tone": "neutral",
      "target": "Invoice",
      "ip_address": "102.89.23.4",
      "status": "successful"
    }
  ],
  "meta": { "current_page": 1, "last_page": 6, "per_page": 10, "total": 59 }
}
INVOTA API Documentation — Version 1.0 — Updated September 2026Best Teck Nigeria Limited — Confidential