Skip to main content

Reference

Credit Notes

Sales-side corrections with their own GL reversal and NRS 380 transmission. Posted credit notes are terminal — to correct one, issue a debit note.

A credit note reduces what a customer owes (or, against a paid invoice, creates an open credit or disburses a refund). Unlike an invoice void, a credit note is a real document with its own number, date, reason, and VAT treatment — the customer receives it and your books reflect both the original sale and the correction as distinct events.

Once posted, credit notes are terminal: no edits, no voids. If a posted credit note turns out to have been wrong, the correction is a debit note with reason credit_note_correction, which re-raises the amount on the ledger. This keeps NRS e-invoice filings clean (one invoice → at most one credit note; corrections flow the opposite direction).

Lifecycle

  draft → [post] → posted → [apply allocations] → applied
    │                  │
    │                  └── can receive allocations (cross-invoice)
    │
    └── [delete] → gone         (drafts only; no GL impact)

Drafts are freely editable. Posted credit notes create a revenue + VAT reversal journal entry in the same batch as the COA balance update. When the originating invoice has an NRS IRN, the CN is auto-transmitted to NRS as invoice type 380 post-commit (fire-and-forget; NRS failures are surfaced via cn.nrs.status='rejected' without unwinding the ledger).

List credit notes

GET/v1/credit-notes

Returns credit notes for a business, newest first.

Query parameters

FieldTypeRequiredNotes
businessIdstringyes
limitintegernoDefault 50, max 100.
statusstringnodraft, posted, applied.
directionstringnocustomer (AR-side) or supplier (AP-side).
customerIdstringno
supplierIdstringno
startAfterstringnoCursor — pass the previous page's nextCursor.

Get a single credit note

GET/v1/credit-notes/{id}

Returns the credit note plus its allocations.

Response includes the full document (line items, totals, GL state, NRS transmission status) and an allocations array showing every invoice or bill this credit has been applied to.

Create a credit note

POST/v1/credit-notes

Creates a draft (or directly posts with post=true).

Body — customer-side (sales)

FieldTypeRequiredNotes
directionstringyescustomer
customerIdstringyesLink to an existing customer.
customerNamestringyes
customerEmailstringno
referencedInvoiceIdsstring[]noInvoice IDs this CN relates to. Empty = standalone open credit.
reasonstringyesgoods_returned, price_correction, discount, bad_debt, goodwill, other.
reasonNotestringwhen reason='other'Required for other; optional comment elsewhere.
creditNoteDateISO 8601noDefaults to today. Drives the period for VAT reversal.
lineItemsarrayyes1–100 items with description, quantity, unitPrice (naira) or unitPriceKobo, optional taxable (default true).
vatRatenumbernoDefault 7.5.
whtRatenumbernoCustomer-side CNs don't reverse WHT per Nigerian cash-basis rules — rate carries for display only.
discountAmountKobo / discountAmountnumbernoPre-VAT discount.
applyAsRefundbooleannotrue = credit a bank / cash account instead of AR.
refundBankAccountIdstringrequired when applyAsRefund=trueCOA doc id of the refund account.
notesstringno
postbooleannotrue skips the draft stage and posts immediately.

Body — supplier-side (purchases)

Same schema but replace customer* with supplier*. Referenced documents are invoices on the sales side, bills on the purchase side. Supplier-side credit notes are uncommon — most purchase corrections go through debit notes.

Response — 201

{
  "success": true,
  "data": {
    "id": "cn_abc",
    "number": "CN-2026-00001",
    "status": "draft",
    "direction": "customer",
    "totalKobo": 107500,
    "total": 1075,
    "createdAt": "2026-04-23T10:45:34.419Z"
  }
}

Update a draft

PUT/v1/credit-notes/{id}

Edits a draft. Posted credit notes are terminal and reject updates.

Accepts the same body fields as create (partial updates allowed). Returns the full sanitised credit note.

Post a draft

POST/v1/credit-notes/{id}/post

Flips status draft → posted; GL posting runs asynchronously.

Empty body. Response 200 with status: 'posted' and a note string pointing at isPostedToGL + glEntryId as the async-settle signals.

The GL trigger creates one balanced journal entry with the reversal lines. For a customer-side CN on an unpaid invoice:

DR  4010 Service Revenue     = CN subtotal − discount
DR  2021 VAT Provision       = CN VAT
    CR  1021 Trade Debtors        = CN total

VAT splits proportionally between 2021 Provision and 2026 Payable based on how much of the referenced invoice has already been paid. Bad-debt CNs (reason='bad_debt') debit 6090 Bad Debt Expense instead of 4010 Revenue.

Apply to one or more invoices

POST/v1/credit-notes/{id}/apply

Allocates the credit to specific invoices (or bills, supplier-side). Up to 50 per call, atomic.

Body

FieldTypeRequiredNotes
allocationsarrayyesEach { targetType, targetId, amountKobo }.
allocations[].targetTypestringyesinvoice for customer-side CN, bill for supplier-side.
allocations[].targetIdstringyes
allocations[].amountKobointegeryesMust not exceed the target's outstanding balance.

The sum of active allocations is capped at the credit note's totalKobo. When fully consumed, the CN status advances from posted to applied.

Response — 200

{
  "success": true,
  "data": {
    "id": "cn_abc",
    "allocationIds": ["alloc_1", "alloc_2"],
    "remainingKobo": 0,
    "remaining": 0
  }
}

Unapply an allocation

POST/v1/credit-notes/{id}/allocations/{allocId}/unapply

Reverses a specific allocation, freeing the credit back onto the note.

The allocation doc is preserved (not deleted) with isReversed: true so customer statements retain the full narrative.

Delete a draft

DELETE/v1/credit-notes/{id}

Deletes a draft. Posted credit notes cannot be deleted — they are terminal.

Errors

CodeWhen
VALIDATION_ERRORMissing / malformed body fields.
BAD_REQUESTLifecycle violation (e.g. update on posted CN, allocation > remaining balance).
NOT_FOUNDCredit note or allocation id doesn't exist.
FORBIDDENAPI key's user doesn't own businessId.
METHOD_NOT_ALLOWEDWrong verb for the route.

Related endpoints

Reference index

Back to all modules