API
Credit notes API
Issue credit notes, apply credit to invoices, and pay credit back against a payment, by payout or manually.
On this page
Overview#
A credit note records money you owe a customer: a return, an overcharge or goodwill, optionally against one of their invoices. Once issued, its balance can be used in any mix of ways: applied to another invoice, refunded against one of the customer's payments, paid out to their bank account by Netcash payout, or recorded as paid back outside CentraPoint. Requires a plan that includes Invoicing.
| Endpoint | Purpose |
|---|---|
POST /api/v1/credit-notes | Create (draft or issued) |
GET /api/v1/credit-notes | List, filter by status, customer or invoice |
GET /api/v1/credit-notes/{id} | Get one credit note |
POST /api/v1/credit-notes/{id}/issue | Issue a draft |
POST /api/v1/credit-notes/{id}/void | Void an unused credit note |
POST /api/v1/credit-notes/{id}/apply | Apply credit to an invoice |
POST /api/v1/credit-notes/{id}/refund | Pay credit back |
GET /api/v1/credit-notes/{id}/pdf | Branded credit note PDF |
Wherever a path takes {id}, you can also use the credit note number (e.g. CN-000008).
The credit note object#
The same object is returned by every credit note endpoint and sent as data in credit_note.* webhooks.
{
"object": "credit_note",
"id": "cmg3c7d8e0002crn0001abcd",
"number": "CN-000008",
"status": "issued",
"issueDate": "2026-09-27T09:10:00.000Z",
"periodStart": "2026-09-01",
"periodEnd": "2026-09-30",
"reason": "Hosting downtime 12-14 September",
"currency": "ZAR",
"taxInclusive": false,
"subtotal": 200,
"taxAmount": 30,
"total": 230,
"amountApplied": 100,
"amountRefunded": 0,
"balance": 130,
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001",
"email": "[email protected]"
},
"invoice": {
"id": "cmg2i9n0v0005inv0001abcd",
"number": "INV-000042",
"externalReference": "ORDER-1001"
},
"lineItems": [
{
"description": "Service credit - downtime",
"details": "Outage 12-14 September (3 days)",
"quantity": 1,
"unitPrice": 200,
"amount": 200,
"taxRate": 15,
"periodStart": "2026-09-12",
"periodEnd": "2026-09-14"
}
],
"history": [
{
"at": "2026-09-27T09:20:00.000Z",
"kind": "applied",
"amount": 100,
"ref": "INV-000051"
}
],
"refunds": [],
"payouts": [],
"issuedAt": "2026-09-27T09:10:00.000Z",
"voidedAt": null,
"createdAt": "2026-09-27T09:10:00.000Z",
"updatedAt": "2026-09-27T09:20:00.000Z"
}| Field | Type | Description |
|---|---|---|
objectrequired | string | Always credit_note. |
idrequired | string | CentraPoint credit note ID. |
numberrequired | string | Sequential number, e.g. CN-000008. |
statusrequired | string | See Statuses. |
issueDaterequired | string | ISO 8601 UTC timestamp. |
periodStart, periodEndrequired | string | null | Period being credited (YYYY-MM-DD, inclusive), or null. See Billing periods and line details. |
reasonrequired | string | null | Why the credit was given (printed on the PDF). |
currencyrequired | string | ISO 4217 code (the invoice's currency when created against an invoice). |
taxInclusiverequired | boolean | Whether line prices include tax. |
subtotal, taxAmount, totalrequired | number | Totals excluding VAT, VAT, and including VAT. |
amountAppliedrequired | number | Applied to invoices. |
amountRefundedrequired | number | Paid back to the customer, including scheduled payouts that have not gone out yet (released again if the payout is cancelled or fails). |
balancerequired | number | total − amountApplied − amountRefunded: credit still available. |
customerrequired | object | { id, externalReference, email } |
invoicerequired | object | null | { id, number, externalReference } of the invoice being credited. |
lineItemsrequired | object[] | description, details (string | null), quantity, unitPrice, amount, taxRate (%), periodStart / periodEnd (YYYY-MM-DD | null). |
historyrequired | object[] | How the credit was used: { at, kind, amount, ref, note? } with kind applied (ref = invoice number), refund (ref = payment reference), payout (ref = payout reference) or manual. |
refundsrequired | object[] | Refunds recorded against payments: { id, number, amount, transactionId }. See the refund object. |
payoutsrequired | object[] | Payouts: { id, reference, status, amount, actionDate, paidAt }. See the payout object. |
issuedAt, voidedAtrequired | string | null | |
createdAt, updatedAtrequired | string |
Statuses#
| status | Meaning |
|---|---|
draft | Created, not issued. The credit can't be used yet. |
issued | Issued with a balance available. |
applied | Fully used, mostly applied to invoices. |
refunded | Fully used, mostly paid back to the customer. |
void | Voided before any of it was used. |
Create a credit note#
/api/v1/credit-notes| Field | Type | Description |
|---|---|---|
customerIdoptional | string | The customer's CentraPoint ID. Send at most one of customerId or customerExternalReference; one is required unless you send invoiceId. |
customerExternalReferenceoptional | string | Your reference of an existing customer. An unknown customer returns 400. |
invoiceIdoptional | string | Credit against this invoice. The customer defaults to the invoice's (and must match), the currency is the invoice's, and the default tax rate is the invoice's rate. Credit notes on one invoice can't add up to more than its total. |
lineItemsrequired | object[] | 1–200 lines, same rules as invoice lines, including optional details and periodStart / periodEnd. Without an invoice, the default taxRate is your organisation's tax rate. |
currencyoptional | string | ISO 4217 code, default ZAR (ignored in favour of the invoice's currency; a different one returns 400). |
taxInclusiveoptional | boolean | Default false. |
periodStart, periodEndoptional | string (YYYY-MM-DD) | Period being credited, inclusive. Send both or neither; periodEnd must be on or after periodStart. Default: the invoice's period when you send invoiceId, else none. |
reasonoptional | string | Up to 1000 chars. |
notesoptional | string | Up to 4000 chars. |
issueoptional | boolean | Default false (draft). true issues it immediately. |
curl -X POST "https://app.centrapoint.co.za/api/v1/credit-notes" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: 4e8a2c6f-1d3b-4f9a-b7e5-8c0d2a4f6b19" \
-H "Content-Type: application/json" \
-d '{
"invoiceId": "cmg2i9n0v0005inv0001abcd",
"reason": "Hosting downtime 12-14 September",
"lineItems": [
{
"description": "Service credit - downtime",
"quantity": 1,
"unitPrice": 200
}
],
"issue": true
}'Returns 201 with the credit note object. Send an Idempotency-Key so a retry doesn't create a second credit note.
List credit notes#
/api/v1/credit-notes| Field | Type | Description |
|---|---|---|
statusoptional | string | draft, issued, applied, refunded or void. |
customerIdoptional | string | Only this customer's credit notes. |
invoiceIdoptional | string | Only credit notes against this invoice. |
limit, startingAfteroptional | Keyset pagination: the response is { data, hasMore, nextCursor }, newest first. |
curl -X GET "https://app.centrapoint.co.za/api/v1/credit-notes?status=issued" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Get a credit note#
/api/v1/credit-notes/{id}curl -X GET "https://app.centrapoint.co.za/api/v1/credit-notes/cmg3c7d8e0002crn0001abcd" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Issue a credit note#
/api/v1/credit-notes/{id}/issueIssues a draft so its credit can be used. No body is needed. Other statuses return 400. Emits credit_note.issued.
Void a credit note#
/api/v1/credit-notes/{id}/voidVoids a draft or issued credit note that hasn't been used (anything applied or refunded returns 400). Optional body { "reason": "…" } (up to 500 chars) is added to the notes. Voiding a void credit note returns it unchanged. Emits credit_note.voided.
Apply credit to an invoice#
/api/v1/credit-notes/{id}/apply| Field | Type | Description |
|---|---|---|
invoiceIdrequired | string | An unpaid invoice of the same customer, in the same currency. |
amountrequired | number | Greater than 0, at most the credit balance and the invoice's outstanding balance. |
curl -X POST "https://app.centrapoint.co.za/api/v1/credit-notes/cmg3c7d8e0002crn0001abcd/apply" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: a3c5e7f9-2b4d-4f6a-8c1e-3d5f7a9b1c02" \
-H "Content-Type: application/json" \
-d '{
"invoiceId": "cmg2i9n0v0005inv0051abcd",
"amount": 100
}'Records an invoice payment with method credit_note (the invoice gets invoice.paid or invoice.partially_paid as usual) and returns the updated credit note. Emits credit_note.applied.
Pay credit back#
/api/v1/credit-notes/{id}/refundPays some or all of the balance back to the customer. Every request has a method and an amount (greater than 0, at most the balance); the other fields depend on the method. Returns the updated credit note and emits credit_note.refunded. The credit note must be issued.
Against a payment#
| Field | Type | Description |
|---|---|---|
methodrequired | string | payment |
amountrequired | number | At most what is left to refund on that payment. |
transactionReferencerequired | string | Reference of one of the customer's complete or partially_refunded payments (see the Transactions API). |
referenceoptional | string | The gateway's refund reference, kept on the refund. |
Records a refund on the payment (which becomes refunded or partially_refunded and sends the matching payment.* webhook). CentraPoint does not move the money: process the refund in the gateway's own portal.
curl -X POST "https://app.centrapoint.co.za/api/v1/credit-notes/cmg3c7d8e0002crn0001abcd/refund" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: b7d9f1a3-4c6e-4a8b-9d2f-5e7a9c1b3d46" \
-H "Content-Type: application/json" \
-d '{
"method": "payment",
"amount": 130,
"transactionReference": "CP-20260925-9F3A1C7B",
"reference": "PF-REFUND-88121"
}'By payout#
| Field | Type | Description |
|---|---|---|
methodrequired | string | payout |
amountrequired | number | ZAR credit notes only. |
actionDaterequired | string (YYYY-MM-DD) | When Netcash should pay. Not in the past. |
bankrequired | object | accountHolder, accountNumber, branchCode, accountType (current, savings or transmission), optional bankName. Validated like the dashboard; stored encrypted and never returned. |
beneficiaryNameoptional | string | Up to 50 chars. Default the account holder. |
beneficiaryEmailoptional | string | Optional. |
providerIdoptional | string | Your Netcash Creditor & Salary Payments gateway. Default: the first enabled one (400 if none). |
Schedules a payout of kind refund linked to the credit note (it appears in payouts). The amount is reserved immediately and released again if the payout is cancelled or fails.
curl -X POST "https://app.centrapoint.co.za/api/v1/credit-notes/cmg3c7d8e0002crn0001abcd/refund" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: c1e3a5b7-6d8f-4b0a-a2c4-7e9b1d3f5a68" \
-H "Content-Type: application/json" \
-d '{
"method": "payout",
"amount": 130,
"actionDate": "2026-10-01",
"bank": {
"accountHolder": "T Nkosi",
"accountNumber": "62000000000",
"branchCode": "250655",
"accountType": "current",
"bankName": "FNB"
},
"beneficiaryEmail": "[email protected]"
}'Recorded manually#
| Field | Type | Description |
|---|---|---|
methodrequired | string | manual |
amountrequired | number | |
manualMethodoptional | string | How it was paid, e.g. eft (default) or cash. Up to 30 chars. |
referenceoptional | string | E.g. your bank statement reference. |
Records credit you paid back outside CentraPoint, for example an EFT from your business bank account.
Download the credit note PDF#
/api/v1/credit-notes/{id}/pdfReturns the branded credit note PDF (application/pdf, as an attachment, Cache-Control: private, no-store) or 404.
curl -o credit-note.pdf \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
"https://app.centrapoint.co.za/api/v1/credit-notes/cmg3c7d8e0002crn0001abcd/pdf"Webhook events#
credit_note.created, credit_note.issued, credit_note.applied, credit_note.refunded (any pay-back method) and credit_note.voided are sent to your webhook endpoints with the credit note object as data, whether the change came from the API or the dashboard. Creating with issue: true sends both created and issued. When a payout for a credit note is cancelled or fails, you receive payout.cancelled / payout.failed; fetch the credit note for its restored balance.
Errors#
| Status | error | When |
|---|---|---|
| 400 | invalid_request | Validation failed; customer, invoice or payment not found or belonging to another customer; credit above the invoice total; only one of periodStart/periodEnd, or periodEnd before periodStart; currency mismatch; not issued; amount above the balance; payment not refundable; invalid bank details; no payout gateway; non-ZAR payout; action date in the past; voiding a used credit note. |
| 403 | plan_restricted / account_restricted | Plan lacks the API or Invoicing, or the account is read-only (writes). |
| 404 | not_found | No credit note with this ID or number in your organisation. |
| 409 | idempotency_conflict | Idempotency-Key reused with a different body. |
| 401 / 429 / 500 | unauthorized / rate_limited / internal_error | See Errors |