Canonical model · STRICT ingress body
Canonical Invoice Schema
The exact JSON shape an ERP sends, one record at a time, in the
invoice_data_json array of POST /api/ingest.
Map your data to these fields on your side and call us. There is no per-caller transformation on
the canonical leg — you send this schema, unchanged.
You send the invoice content. Pronalytics supplies the seller party and mints the
IRN and QR on accept. Money is a JSON number; dates are YYYY-MM-DD;
field names are snake_case; enum input is case-insensitive.
v1 · Canonical
POST /api/ingest
STRICT leg · full validation
FIRS / NRS UBL mapping
One field, one place
Every field below carries a stable id. Hover a field row and click #
to copy a deep link straight to it. Where a rule is stated once (the VAT model, the tax-category
layers, the payment enum) it is stated only once — cross-references point back to that single
definition rather than restating it.
1What you send vs. what we mint#
The canonical model is the customer-ingress body only. Sending a seller-owned or
minted field is not an error — it is ignored.
| You send | Pronalytics supplies / mints |
Invoice content: transaction_id, dates,
invoice_kind, the buyer (non-B2C), line_items, tax, totals,
references. |
The seller party (accounting_supplier_party) from your
registration; the irn and qr_code; business_id;
service_id. Never send these. |
Hard requirements on the STRICT leg: transaction_id,
issue_date, and line_items (at least one),
plus full per-field validation. invoice_kind is inferred when omitted
(see invoice_kind). Everything else is optional or conditional.
The IRN is derived, not sent: IRN = {SEED}-{SERVICE_ID}-{YYYYMMDD}, where
SEED is the uppercased invoice_number
(else transaction_id) stripped to A–Z 0–9.
Every other character — including / and - — is
removed, so INV/261 becomes INV261. Uniqueness is
per (tenant, IRN); first-seen date wins.
2Root invoice record#
One Invoice object. Grouped as identity, dates, currency/mode,
status, notes, references, parties, lines, and totals.
Identity
transaction_idstring
Mandatory
#
Your unique reference and idempotency key; it seeds the IRN when no
invoice_number is present. It is also the only hard requirement on the
LENIENT leg. A unique transaction_id is what guarantees a unique IRN —
the seed-stripping is many-to-one.
Maps to Pronalytics-only — seeds the IRN, not a FIRS wire field.
invoice_numberstring
Optional
#
Human invoice number. Preferred IRN seed; falls back to transaction_id
when absent (see §1 for the strip rule).
Maps to feeds irn (minted by Pronalytics)
invoice_type_codeenum
Optional
default 381
#
FIRS invoice-type code. Defaults to 381 (Commercial Invoice). Full
list — credit note 380, debit note 384, and the
rest — in Enumerations §10.
Maps to invoice_type_code
invoice_kindenum · B2B|B2C|B2G|G2B
Inferred if omitted
#
NRS transaction kind. If omitted, it is inferred: any buyer tax identity present
(TIN / Tax ID / RC) ⇒ B2B, else B2C.
An explicit business kind (B2B / B2G / G2B) is honored unconditionally —
accepted even with an incomplete or absent buyer (FIRS clearance is the completeness gate).
Explicit B2C must omit the customer party
(consumer-PII guard — a B2C carrying a buyer is a hard reject). See
rule §11. Uppercased on the wire.
Maps to invoice_kind
transaction_typestring
Optional
#
A data-mapping helper describing the business purpose of the invoice
(e.g. loan_fees, interest_fees,
late_penalty). Tenant-defined open string. Not a FIRS
field and not the B2B/B2C kind (that is invoice_kind).
Maps to Pronalytics-only — data-mapping helper.
Dates & lifecycle
| Field | Type | Req | Notes |
| issue_date | date | req | YYYY-MM-DD. FIRS-mandatory; not future-dated. On the STRICT leg a present-but-unparseable value is rejected (422). |
| issue_time | string | o | HH:MM:SS, 24-hour (FIRS-optional). |
| due_date | date | o | Payment deadline; defaults to issue_date. |
| tax_point_date | date | o | Tax point if it differs from the issue date. |
| actual_delivery_date | date | o | Date goods/services were delivered (matters for goods sellers). |
| invoice_delivery_period | object | o | Service/delivery window { start_date, end_date }. |
Currency & mode
| Field | Type | Req | Notes |
| currency | string | o | ISO 4217 document currency. Default NGN. |
| tax_currency_code | string | o | Optional input; defaults to NGN (always populated). |
| vat_mode | enum | o | EXCLUSIVE (default) or INCLUSIVE — declares whether stated amounts include VAT. See §5. |
Status & notes
| Field | Type | Req | Notes |
| payment_status | enum | o | On the invoice record this is the fiscal status PENDING (default) / PAID / PARTIAL. The full six-value lifecycle enum used to update a payment lives in §9. |
| note | string | o | FIRS note 1 — free-form (stored encrypted at rest). |
| payment_terms_note | string | o | FIRS note 2 — payment terms (stored encrypted at rest). |
Conveniences
| Field | Type | Req | Notes |
| branch | string | o | Issuing office branch. Pronalytics convenience — not a FIRS field (FIRS encodes branch in the TIN suffix). |
| accounting_cost | string | o | Cost-centre / accounting category. |
| order_reference | string | o | Purchase-order number. |
| buyer_reference | string | o | Buyer's own reference for the invoice. |
Parties (§3), the document-reference family
(§7), line items (§4) and the totals
(§8) each have their own section below.
3Party — buyer & other parties#
The customer (buyer) and every optional party share one
Party shape. The seller party is never sent — Pronalytics supplies it.
customerParty
Conditional
#
Required for B2B / B2G / G2B;
omit for B2C. For a B2B buyer,
FIRS clearance additionally requires postal_address.postal_zone — lga/state
codes do not substitute. See rule §11.
Maps to accounting_customer_party
Party fields
At least one identity form is required; everything
else is optional. The old JTB tin is the wire id used for clearance and
transmit routing.
| Field | Type | Req | Notes |
| party_name | string | req | Legal name. Friendly input key name also accepted. |
| tin | string | 1 of 3 | Old JTB TIN NNNNNNNN-NNNN. The wire id (clearance + transmit). |
| tax_id | string | 1 of 3 | New NRS Tax ID (12–13 digit). Carried alongside tin. |
| rc_number | string | 1 of 3 | CAC RC number. Third accepted identity form. |
| email | string | o | AP email. Validated as an email address. |
| telephone | string | o | Must start with + (country code) — FIRS rejects otherwise. |
| business_description | string | o | If present, at least 5 characters (FIRS). |
| postal_address | PostalAddress | o | Buyer address (friendly input key address). See below. |
PostalAddress
| Field | Type | Req | Notes |
| street_name | string | o | Street line. Friendly input key street. |
| city_name | string | o | City. Friendly input key city. |
| postal_zone | string | cond | Postcode. Optional for B2C/no-party, but FIRS requires it on a B2B buyer for clearance — lga/state codes do not substitute. Any plausible area postcode clears. |
| lga | string | o | LGA code (e.g. 70 / NG-AB-ASO). |
| state | string | o | State code (e.g. 4 / NG-LA). |
| country | string | o | ISO 3166-1 alpha-2. Default NG. |
Other parties
All optional; each takes the same Party
shape above.
| Field | Purpose |
| payee_party | Payment recipient if different from the supplier. |
| bill_party | Bill-to party if different from the buyer. |
| ship_party | Ship-to party if different from the buyer. |
| tax_representative_party | Tax agent acting for the seller. |
4Line items#
line_items is an array of at least one
LineItem. Each line carries its own classification pair and its own VAT
treatment — VAT is per-line (see §5).
descriptionstring
Mandatory
#
What was sold. Becomes the item name and description (e.g. "Portland cement"). The
unit of measure is a separate coded field — see
unit_code below.
quantitynumber > 0
Mandatory
#
The true count of units invoiced, greater than zero. The unit those are counted in is the
separate coded unit_code field below.
unit_pricenumber ≥ 0
Mandatory
#
Unit price magnitude only (net when vat_mode=EXCLUSIVE).
For a credit/debit note, express the reversal via
invoice_type_code 380/384
plus absolute amounts — never a negative price (rule §11).
unit_codestring · coded
Optional
default C62 ("each")
#
The unit of measure for this line's quantity — a
coded FIRS invoice-quantity-code (UN/ECE Rec 20), never free text.
FIRS requires it and its own sample sends a code (e.g. "XBG" = bag).
Leave it blank and it defaults to C62 ("one / each") —
correct for most service, subscription and fee lines. Send the code directly, or a friendly word
we map for you: EACH→C62,
MONTH→MON,
HOUR→HUR,
DAY→DAY,
YEAR→ANN,
KG→KGM,
LITRE→LTR,
BOX→XBX,
BAG→XBG,
PACK→XPK.
Friendly input keys unit_code, price_unit,
uom, unit_of_measure are all accepted.
A real unit we cannot map is HELD — we never guess a code (that once caused a
FIRS rejection). If you see "not a FIRS invoice-quantity-code", send a valid code or a known word
above, or just leave it blank for C62.
line_extension_amountnumber
Optional
#
Line net. Computed from quantity × unit_price (less any discount) when
absent.
line_item_typeenum · GOODS|SERVICE
Optional
default GOODS
#
Picks the classification pair. GOODS uses
hsn_code + product_category;
SERVICE uses isic_code +
service_category (rule §11).
Classification pair
| Field | Type | Used for | Notes |
| hsn_code | string | GOODS | HS code, pattern NNNN.NN (e.g. 8471.30). |
| product_category | string | GOODS | Goods category (at least 2 chars). Pairs with hsn_code. |
| isic_code | string | SERVICE | ISIC code, pattern NNNN (4-digit, no decimal). |
| service_category | string | SERVICE | Service category (at least 2 chars). Pairs with isic_code. |
Unknown hsn_code/isic_code are
accepted with a warning while the shipped reference lists are seed subsets — the
warning rides the feedback webhook, never a reject on our own incomplete data. When a full official
list is loaded, unknowns become hard rejects with no change to your integration
(rule §11).
Per-line VAT & adjustments
| Field | Type | Req | Notes |
| vat_rate | number | o | Per-line VAT %. Default 7.5. Forced to 0 for zero-rate categories (see §5). |
| vat_type | enum | o | Per-line VAT treatment. Default STANDARD. Full driver set + FIRS codes in §6. Legacy input key tax_category_id also accepted. |
| discount_rate | number | o | Per-line discount %. |
| discount_amount | number | o | Per-line discount value. May not exceed line gross (unit_price × quantity). |
| fee_rate | number | o | Per-line fee % (FIRS-optional). |
| fee_amount | number | o | Per-line fee value (FIRS-optional). |
| sellers_item_identification | string | o | Seller's SKU / item code. |
| customer_sku | string | o | Customer's own SKU. |
5The VAT model (per-line)#
The single VAT rule for the whole schema, stated once here. Everything else references
back to it.
One VAT rule
VAT is computed per line, driven by each line's
vat_type + vat_rate.
EXEMPT and ZERO lines contribute
0 VAT regardless of vat_mode.
vat_mode only declares whether stated amounts are tax-inclusive or
tax-exclusive. There is no unconditional divide-by-1.075, and there is no invoice-level fee-amount
VAT source.
How each mode computes
| vat_mode | Meaning | Per-line math |
| EXCLUSIVE (default) | unit_price is net; VAT is added on top. | net = qty × unit_price; vat = net × rate/100. |
| INCLUSIVE | Stated amount already includes VAT. | net = charged / (1 + rate/100); vat = charged − net. |
How each category rates
| Category | Rate applied | VAT contributed |
STANDARD | vat_rate (default 7.5%) | computed |
REDUCED / LOCAL_SALES | the vat_rate you give | computed |
EXEMPT | forced 0 | 0 |
ZERO | forced 0 | 0 |
WHT | forced 0 (own subtotal) | 0 |
Caller-supplied VAT. A header vat_amount is honored
verbatim when it cannot be computed from the payload (e.g. an out-of-band commission VAT). See
§8.
Withholding tax is informational: it is emitted as its own
WITHHOLDING_TAX subtotal and does not change
payable_amount — it reduces only the cash actually remitted to the seller.
A WHT-category line's amount is the withholding base; WHT = base × 7.5%
(rule §11).
6Tax categories — 27 tags, 6 drivers#
Two layers, not a contradiction. Layer 1 is the pinned FIRS master list of
27 tax categories — all 27 are valid tags. Layer 2 is the 6
VAT-family codes that actually drive Nigerian VAT computation.
Layer 1 — the 27-category FIRS master list
FIRS pins a master list of 27 tax categories (GST variants, excise, duty, stamp
duty, and more). Every one of the 27 is a valid tag. Pronalytics serves the live list, verbatim and
cached, from the public reference resource
GET /api/firs-resources/tax-categories so you can
render a picker. On the wire a subtotal's category is
tax_subtotal[].tax_category = { id, percent }.
Layer 2 — the 6 VAT-family drivers
These six codes are what the serializer computes and emits for
Nigerian VAT. Supply any of them as vat_type — the friendly name
or the FIRS code.
| vat_type (friendly) | FIRS wire code | Meaning | Rate |
| STANDARD | STANDARD_VAT | Nigeria standard VAT | 7.5% |
| ZERO | ZERO_VAT | Zero-rated (e.g. exports) | 0 |
| REDUCED | REDUCED_VAT | Reduced rate | rate given |
| EXEMPT | EXEMPTED | VAT-exempt supply | 0 |
| WHT | WITHHOLDING_TAX | Withholding tax (informational) | 0 |
| LOCAL_SALES | LOCAL_SALES_TAX | Local sales tax | rate given |
Accepted input spellings
Each driver is accepted as its friendly name (STANDARD), its FIRS code
(STANDARD_VAT), either in any case (standard), and via the legacy key
tax_category_id. All resolve to the six drivers above. A subtotal on the wire carries
tax_category:{ id, percent }; the six drivers are the only categories the canonical
serializer computes today — a value outside the six is not silently mapped. If you need a category
from the wider 27, raise it with Pronalytics so it can be added to the mapping.
TaxSubtotal shape
{ taxable_amount, tax_amount, tax_category: { id, percent } }.
percent is the rate (7.5 for STANDARD). Zero-rate drivers carry
percent = 0. WHT is a subtotal with the
WITHHOLDING_TAX category.
7Document-reference family#
Every reference here is a DocumentReference object
{ irn, issue_date } (or a list of them where noted). All optional; each links
the invoice to a related prior document for the audit trail.
Correction pointers (credit / debit notes)
| Field | Type | Notes |
| reference_invoice_number | string | Original IRN / number a 380/384 corrects. Feeds billing_reference. |
| reference_invoice_date | date | Issue date of the referenced original. |
| billing_reference | array<DocRef> | Explicit prior-doc links. Built from the two fields above when not given explicitly. |
Related-document pointers
| Field | Type | Links to |
| dispatch_document_reference | DocRef | Despatch advice. |
| receipt_document_reference | DocRef | Receipt advice. |
| originator_document_reference | DocRef | Originating document. |
| contract_document_reference | DocRef | Governing contract. |
| additional_document_reference | array<DocRef> | Any other related documents. |
DocumentReference shape:
{ "irn": string, "issue_date": "YYYY-MM-DD" }. A credit/debit note
(380/384) normally carries one of these back to the
original; a standalone note with no reference is allowed for aggregate adjustments
(rule §11).
8Tax totals & monetary totals#
All optional overrides — omit them and we compute from the lines. Supply them to pin
an exact breakdown (e.g. an out-of-band VAT figure not computable from the payload).
Convenience header amounts
| Field | Type | Notes |
| vat_amount | number | Computed per-line if omitted. Supplying it overrides the computed VAT (used for out-of-band figures). |
| wht_amount | number | Serialized as a WITHHOLDING_TAX subtotal. Informational — does not reduce payable_amount. |
| total_amount | number | Approximately payable_amount. Computed if omitted. |
tax_total · array of TaxTotal
tax_totalarray · TaxTotal
Optional
#
Explicit tax breakdown; computed from the lines when absent. A supplied
tax_total is honored as-is, but any WHT still rides through as its own
subtotal.
TaxTotal =
{ tax_amount, tax_subtotal: [ TaxSubtotal ] }, where each
TaxSubtotal is
{ taxable_amount, tax_amount, tax_category:{id,percent} }
(see §6).
legal_monetary_total · object
legal_monetary_totalobject
Optional
#
Explicit totals; computed when absent.
{ line_extension_amount, tax_exclusive_amount,
tax_inclusive_amount, payable_amount }. WHT is excluded from
payable_amount.
9Payment status, means & charges#
Two distinct things share the name "payment status" — keep them apart.
One payment enum — six values
The canonical payment-status enum used to update an invoice
(POST /api/payment/update) has exactly six values, validated identically on
every payment surface. Case-insensitive on the wire, echoed UPPER. An unrecognized value is a
validation failure.
PENDINGPARTIALPAID
OVERDUECANCELLEDREFUNDED
The payment_status field on the invoice record itself is the
narrower fiscal status set at creation —
PENDING (default) / PAID /
PARTIAL. It records where the invoice sits at issue. The six-value enum above
is the vocabulary for later lifecycle updates to that payment. They are not the same list;
do not conflate them.
payment_meansarray · PaymentMeans
Optional
#
Each entry { payment_means_code, payment_due_date? }. Codes in
Enumerations §10.
Maps to payment_means
allowance_chargearray · AllowanceCharge
Optional
#
Each entry { charge_indicator (bool), amount, reason? }.
charge_indicator true = charge, false = allowance. A document-level charge
raises, an allowance lowers, the standard-rated base. Freight is a charge here, never a
line.
Maps to allowance_charge
10Enumerations#
FIRS / NRS resource-backed value sets. Tax categories are in §6;
the payment-update enum is in §9.
invoice_kind — NRS transaction kind
B2BB2CB2GG2B
invoice_type_code — FIRS invoice-types
| Code | Type | Code | Type |
| 380 | Credit Note | 394 | Self-Billed Invoice |
| 381 | Commercial Invoice (default) | 395 | Credit Note Request |
| 384 | Debit Note | 396 | Invoice Request |
| 385 | Self-Billed Invoice | 397 | Final Settlement |
| 386 | Factored Invoice | 399 | Bill of Lading |
| 388 | Statement of Account | 400 | Waybill |
| 389 | Purchase Order | 402 | Shipping Instructions |
| 390 | Proforma Invoice | 404 | Certificate of Origin |
| 392 | Consignment Invoice | 406 | Customs Declaration |
| 393 | Self-Billed Credit Note | 408 | Packing List |
payment_status — invoice fiscal status
PENDING · defaultPAIDPARTIAL
This is the status on the record. The six-value lifecycle enum for
updating a payment is in §9.
vat_mode
EXCLUSIVE · defaultINCLUSIVE
line_item_type
GOODS · defaultSERVICE
vat_type — the 6 drivers
STANDARD · defaultREDUCEDLOCAL_SALES
ZEROEXEMPTWHT
Green drivers rate to 0. Full mapping and the 27-tag master list in
§6.
payment_means_code — FIRS payment-means
| Code | Means | Code | Means |
| 10 | Cash | 31 | Debit Transfer |
| 20 | Cheque | 42 | ACH Credit |
| 30 | Credit Transfer | 43 | ACH Debit |
payment_means_code is a free string on the model; the codes
above are the common FIRS values. The full list is served by
GET /api/firs-resources.
Reference resources
Public, no-auth, cached 24h:
GET /api/firs-resources/{name} for
states, lgas, countries,
tax-categories (the 27-tag master list),
hs-codes, service-codes.
11Validation rules#
Baked into the canonical model. These explain most accept/reject outcomes — read them
before you map.
invoice_kind ∈ {B2B, B2G, G2B} ⇒
customer expected (identity + email + address, with
postal_zone for clearance). An explicit business kind with no/partial buyer
is accepted at ingress and flagged on the feedback webhook — it will not clear at FIRS until
the buyer is complete. B2C ⇒ customer must be
omitted (no consumer PII); an explicit B2C carrying a buyer is a hard reject. Omitting
invoice_kind infers it from buyer identity.
One classification pair per line
#
Goods = hsn_code +
product_category; service = isic_code +
service_category; matching line_item_type. A
discount_amount may not exceed the line gross.
Use invoice_type_code 380 / 384 with
positive (abs) amounts; express the reversal via the type plus
reference_invoice_number / reference_invoice_date.
Never send a negative unit_price. A standalone 380 (no reference) is allowed
for aggregate adjustments.
EXCLUSIVE (default):
unit_price is net, VAT added on top. INCLUSIVE: the
amount already includes VAT, so net is backed out as charged / (1 + rate/100)
(never × 0.925) and tax = charged − net. Full model in §5.
Mirrors FIRS via a WITHHOLDING_TAX subtotal plus the
wht_amount convenience. A WHT-category line's amount is treated as the
withholding base (WHT = base × 7.5%), not as tax on the full line. WHT does
not reduce payable_amount.
The old JTB tin goes on the wire (clearance +
transmit routing); tax_id and rc_number are carried
alongside. A buyer with only a Tax ID or RC clears at FIRS but will not transmit until an old-format
TIN is supplied.
HS / ISIC value-set warnings
#
hsn_code / isic_code are
checked against the loaded reference set as well as the format. While the shipped lists are seed
subsets, an unknown code is accepted with a warning on the feedback webhook — never
hard-rejected on our own incomplete data. When a full official list is loaded, unknowns become
rejects with no change to your integration.
issue_date on the STRICT leg
#
On the canonical (STRICT) leg a present-but-unparseable
issue_date is rejected (422) — it never silently falls back
to today. It must be a real YYYY-MM-DD and not future-dated.
12Worked examples — Grollo & Mollo#
Fictional. Seller Grollo Consulting (supplied by Pronalytics from
registration — never sent); buyer Mollo Industries. Amounts in NGN.
A · Minimal B2C — no buyer, one goods line
EXCLUSIVE · STANDARD 7.5% · buyer omitted
{
"transaction_id": "POS-000817",
"invoice_kind": "B2C",
"issue_date": "2026-07-08",
"line_items": [
{
"description": "Engine oil, 5 L can",
"quantity": 2,
"unit_price": 12000,
"line_item_type": "GOODS",
"hsn_code": "2710.19",
"product_category": "Lubricants",
"vat_type": "STANDARD",
"vat_rate": 7.5
}
]
}
| Line | Net | Rate | VAT | Gross |
| Engine oil ×2 | 24,000.00 | 7.5% | 1,800.00 | 25,800.00 |
| payable_amount | 24,000.00 | — | 1,800.00 | 25,800.00 |
B · Full B2B — complete buyer, service line, mixed VAT
explicit B2B · one STANDARD line + one EXEMPT line
{
"transaction_id": "GRC-SINV-42",
"invoice_number": "GRC-SINV-42",
"invoice_kind": "B2B",
"invoice_type_code": "381",
"issue_date": "2026-07-08",
"due_date": "2026-08-07",
"payment_status": "PENDING",
"customer": {
"party_name": "Mollo Industries",
"tin": "12345678-0001",
"tax_id": "2522500000001",
"email": "[email protected]",
"telephone": "+2348012345678",
"postal_address": {
"street_name": "12 Marina Road",
"city_name": "Lagos",
"postal_zone": "101241",
"state": "NG-LA",
"country": "NG"
}
},
"line_items": [
{
"description": "Advisory retainer, July",
"quantity": 1,
"unit_price": 250000,
"line_item_type": "SERVICE",
"isic_code": "7020",
"service_category": "Management consultancy",
"vat_type": "STANDARD"
},
{
"description": "Statutory filing fee (pass-through)",
"quantity": 1,
"unit_price": 40000,
"line_item_type": "SERVICE",
"isic_code": "8411",
"service_category": "Public administration",
"vat_type": "EXEMPT"
}
],
"payment_terms_note": "Payment due within 30 days."
}
| Line | vat_type | Net | Rate | VAT |
| Advisory retainer | STANDARD | 250,000.00 | 7.5% | 18,750.00 |
| Statutory filing fee | EXEMPT | 40,000.00 | 0 | 0.00 |
| payable_amount | — | 290,000.00 | — | 18,750.00 |
Payable = 290,000 net + 18,750 VAT = 308,750.00. The EXEMPT line
contributes 0 VAT regardless of vat_mode — the single VAT rule from
§5.
C · INCLUSIVE mode — VAT backed out of a gross price
vat_mode INCLUSIVE · net = charged / 1.075
{
"transaction_id": "GRC-INC-09",
"invoice_kind": "B2C",
"issue_date": "2026-07-08",
"vat_mode": "INCLUSIVE",
"line_items": [
{
"description": "Diagnostic session (price shown incl. VAT)",
"quantity": 1,
"unit_price": 10750,
"line_item_type": "SERVICE",
"isic_code": "7020",
"service_category": "Technical services",
"vat_type": "STANDARD"
}
]
}
| Charged (incl.) | Net | VAT |
| 10,750.00 | 10,000.00 | 750.00 |
Net = 10,750 / 1.075 = 10,000; VAT = 10,750 − 10,000 = 750. Never
× 0.925 (rule §11).
D · Credit note (380) — corrects invoice B, abs amounts
type 380 · positive amount · reference points back to GRC-SINV-42
{
"transaction_id": "GRC-CN-07",
"invoice_type_code": "380",
"invoice_kind": "B2B",
"issue_date": "2026-07-08",
"reference_invoice_number": "GRC-SINV-42",
"reference_invoice_date": "2026-07-08",
"customer": {
"party_name": "Mollo Industries",
"tin": "12345678-0001",
"email": "[email protected]",
"postal_address": { "street_name": "12 Marina Road", "city_name": "Lagos", "postal_zone": "101241" }
},
"line_items": [
{
"description": "Advisory retainer adjustment",
"quantity": 1,
"unit_price": 50000,
"line_item_type": "SERVICE",
"isic_code": "7020",
"service_category": "Management consultancy",
"vat_type": "STANDARD"
}
]
}
The reversal is carried by invoice_type_code: "380" plus
the reference — the amount stays positive. A negative unit_price is never sent
(rule §11).