Tax / Fiscal · Tax

Acumatica Nigeria FIRS Integration — A Complete Guide

Wiring Acumatica AR invoice release into Nigeria's FIRS e-invoicing platform through an accredited Access Point Provider, without letting a government API outage block invoicing.

John Kihiu12 min read

Nigeria's move to real-time e-invoicing changes what "invoice released" means inside Acumatica. It is no longer just a posting event — it is the trigger for a call to a FIRS-connected platform that has to succeed, or at least be queued reliably, before the document is fiscally complete. The FIRS national e-invoicing rollout (built around the Merchant Buyer Solution and the wider FIRS e-invoice programme) asks for invoice data in near real time, and hands back an Invoice Reference Number (IRN) and a QR code that must appear on the document the buyer actually receives. This is the pattern I use to wire that into Acumatica without turning invoice release into a single point of failure.

What FIRS actually expects

The most common misunderstanding I run into is the assumption that you integrate directly with FIRS. You don't. Under the Merchant Buyer Solution (the FIRSMBS / "eInvoice" platform), taxpayers connect through a licensed Access Point Provider that relays the invoice to FIRS, gets it validated, and hands back the pre-validation reference and QR code. FIRS built the rollout this way deliberately — the access point providers absorb the integration complexity so FIRS itself only has to certify a handful of providers rather than every ERP in the country. If a client asks you to "call the FIRS API," the actual work is choosing (or working with whichever) accredited access point provider they've signed up with and integrating against that provider's API, not FIRS's.

The rollout is also phased, not a single cutover date. It started with the largest taxpayers in mid-2025 and has been extending down to medium and smaller taxpayers since. That matters for scoping: a client who isn't in scope today typically will be within the next year or two, so building the integration properly the first time — rather than a rushed stopgap — pays off regardless of what size the client is right now.

Mechanically it resembles what Kenya's eTIMS and Uganda's EFRIS already require: every taxable invoice gets pre-validated before the buyer sees it, and comes back stamped with a reference and QR code. Both the seller's and buyer's Tax Identification Numbers (TIN) are validated as part of the submission, VAT is calculated at Nigeria's standard rate of 7.5%, and the invoice is priced and reported in Naira (NGN) even when Acumatica's base currency is USD or another currency for group reporting.

The detail that catches people out: an invoice without a valid pre-validation reference and QR code is not just a compliance gap, it is a document the buyer's own tax filing may reject for input VAT recovery. That pushes the integration toward synchronous-ish behaviour at invoice release, not a nightly batch job.

Where it hooks into Acumatica

Two places to attach this, and I have used both depending on the client's appetite for customisation: a graph extension on AR Invoice (and SO Invoice, if invoices are generated from shipments) that intercepts the Release action, or a Business Event fired on invoice release that calls out to an integration endpoint. The graph extension gives you a cleaner way to block printing until the IRN is attached; the Business Event is less invasive if the client already has a middleware layer doing outbound integrations.

Either way, the extension packages the same payload: seller TIN, buyer TIN, invoice number, currency and NGN-converted amounts, VAT line detail at 7.5%, and line items. That payload goes out over REST to whichever Access Point Provider the client is accredited through — never to FIRS directly. This is the same shape as an Egypt ETA integration: an intermediary platform sits between the ERP and the tax authority, and the ERP-side work is identical regardless of which country's intermediary you're talking to.

Don't block release on a government API

Real-time government tax APIs go down, rate-limit, or time out — this is not specific to Nigeria, it is true everywhere this pattern exists. Hard-blocking invoice release on a successful FIRS response means AR grinds to a halt the moment the Access Point has a bad afternoon. The pattern that holds up is a custom DAC — something like FIRSSubmission — that tracks each invoice's submission state: Pending, Submitted, Failed. The invoice can release normally; the submission record queues in the background.

A scheduled processing screen (Acumatica's automation schedules are enough here, no external scheduler needed) picks up Pending and Failed rows, retries with backoff, and writes the IRN and QR payload back onto the submission record once it succeeds. Printing or emailing the invoice checks that record first — if no IRN yet, either hold the document or clearly mark it as pending fiscal confirmation, depending on what the client's finance team is comfortable with.

Don't invent a fixed API contract

Nigeria's e-invoicing platform and its integration specifics have been evolving, and the exact endpoint shape depends on which Access Point or System Integrator the client is accredited through. Treat the snippet below as the shape of the integration, not a copy-paste spec — confirm field names and auth against whatever the client's accredited provider actually publishes.

C# · SUBMISSION HANDLER
// Fired from a graph extension on ARInvoiceEntry.Release, or from
// a Business Event handler — either way this queues, never blocks.
public class FIRSInvoiceSubmitter
{
    public FIRSSubmission Submit(ARInvoice invoice, List<ARTran> lines)
    {
        var payload = new
        {
            sellerTin = CompanySettings.Current.TaxRegistrationID,
            buyerTin = invoice.GetExtension<ARInvoiceExt>().UsrBuyerTIN,
            invoiceNumber = invoice.RefNbr,
            currency = "NGN",
            totalAmount = invoice.CuryDocTotal,
            vatAmount = invoice.CuryTaxTotal,   // 7.5% standard rate
            lines = lines.Select(l => new {
                description = l.TranDesc,
                quantity = l.Qty,
                unitPrice = l.CuryUnitPrice,
                lineTotal = l.CuryTranAmt
            })
        };

        var submission = new FIRSSubmission
        {
            InvoiceRefNbr = invoice.RefNbr,
            Status = FIRSSubmissionStatus.Pending,
            PayloadJson = JsonConvert.SerializeObject(payload)
        };
        PXDatabase.Insert<FIRSSubmission>(submission);

        // Actual HTTP call happens on the retry schedule below,
        // not inline — release must never wait on FIRS uptime.
        return submission;
    }

    // Runs on an Acumatica automation schedule, picks up Pending/Failed rows.
    public void ProcessQueue()
    {
        foreach (var sub in GetPendingOrFailedSubmissions())
        {
            try
            {
                var response = accessPointClient.PostInvoice(sub.PayloadJson);
                sub.IRN = response.IRN;
                sub.QRCodePayload = response.QRCode;
                sub.Status = FIRSSubmissionStatus.Submitted;
            }
            catch (Exception ex)
            {
                sub.Status = FIRSSubmissionStatus.Failed;
                sub.LastError = ex.Message;
                sub.RetryCount++;
            }
            PXDatabase.Update<FIRSSubmission>(sub);
        }
    }
}

Stamping the IRN and QR code onto the invoice

Once a submission comes back Submitted, the IRN and QR code need to land on the printed or PDF invoice — usually as a QR image generated from the returned payload plus the IRN printed as text near the invoice total. In Acumatica this means extending the invoice report (RPX/Report Designer) to pull from the FIRSSubmission record rather than the AR Invoice DAC directly, and treating "no IRN yet" as a reason to either suppress the customer-facing PDF or watermark it as provisional, depending on what the business decides.

Comparing to other regional e-invoicing regimes

If you've built Kenya eTIMS or Uganda EFRIS integrations already, the Nigeria FIRS shape will feel familiar — same category of problem, different vendor plumbing.

AuthorityCountryReal-time artifactTypical access route
FIRSNigeriaIRN + QR codeAccredited Access Point / System Integrator
KRA (eTIMS)KenyaControl unit invoice number + QROSCU/VSCU device or virtual signer
URA (EFRIS)UgandaFiscal Document Number + QRDirect EFRIS API or middleware
RRARwandaEBM-signed receipt numberCertified EBM device/software

Wrapping up

The core thing to get right on a FIRS integration is not the payload shape — that's a normal REST-and-retry problem. It's the mental model: you are never talking to FIRS directly, you are integrating against whichever Access Point Provider the client is accredited through, and that provider is the one relaying to FIRSMBS. Build invoice release so it queues the submission instead of blocking on it, track submission state on its own DAC, and don't let a client's current size convince you to skip the proper integration — the phased rollout means most Nigerian taxpayers will be in scope within a couple of years of when they first ask about it.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.