# Credit notes

> Read, create, approve, void, allocate and refund customer and supplier credit notes through the AccountFUN public API.

Source: https://www.accountfun.com/docs/api/credit-notes/

The credit-notes endpoints let your integration issue credit notes to customers (`receivable`) or from suppliers (`payable`), post them to the ledger, apply them against open invoices or bills, refund the unused balance, and attach the signed document — without anyone having to click anything inside AccountFUN.

Reading requires `credit_notes:read`; creating a draft, attaching files and adding notes require `credit_notes:write`. **Approving and voiding** post (or unpost) to the ledger and need their own scope, `credit_notes:approve`. **Allocating and refunding** move money and need `credit_notes:settle`. The approve and settle scopes are **opt-ins** on the consent screen, and the authorizing user’s role must have the matching permission — **Approve Documents** for `credit_notes:approve`, **Record Payments** for `credit_notes:settle`. See [Authentication](https://www.accountfun.com/docs/api/authentication/).

Credit notes follow their side: a **receivable** note is a customer credit (sales) and settles invoices; a **payable** note is a supplier credit (purchases) and settles bills. The role must see that side of the books, and a list returns only the directions the role can see.

Retry safety

Creating, allocating and refunding a credit note each support the [`Idempotency-Key`](https://www.accountfun.com/docs/api/errors-and-limits/#idempotency-and-retries) header, so a timeout or retry can’t post the same credit twice.

## Endpoints

| Method | Path                                     | Scope                  | Description                                                        |
| ------ | ---------------------------------------- | ---------------------- | ------------------------------------------------------------------ |
| `GET`  | `/api/v1/credit-notes`                   | `credit_notes:read`    | List credit notes (paginated).                                     |
| `POST` | `/api/v1/credit-notes`                   | `credit_notes:write`   | Create a draft credit note.                                        |
| `GET`  | `/api/v1/credit-notes/{id}`              | `credit_notes:read`    | Fetch one credit note with lines, allocations and refunds.         |
| `POST` | `/api/v1/credit-notes/{id}/approve`      | `credit_notes:approve` | Approve (post) a draft or submitted credit note.                   |
| `POST` | `/api/v1/credit-notes/{id}/void`         | `credit_notes:approve` | Void a credit note (reversing a posted one first).                 |
| `POST` | `/api/v1/credit-notes/{id}/allocate`     | `credit_notes:settle`  | Apply the credit to invoices or bills.                             |
| `POST` | `/api/v1/credit-notes/{id}/refund`       | `credit_notes:settle`  | Refund the credit from a bank account.                             |
| `GET`  | `/api/v1/credit-notes/{id}/attachments`  | `credit_notes:read`    | List the credit note’s attached files.                             |
| `POST` | `/api/v1/credit-notes/{id}/attachments`  | `credit_notes:write`   | Attach files (multipart or JSON base64).                           |
| `POST` | `/api/v1/credit-notes/{id}/upload-links` | `credit_notes:write`   | Mint a 15-minute, upload-only link for someone who holds the file. |
| `GET`  | `/api/v1/credit-notes/{id}/notes`        | `credit_notes:read`    | List the credit note’s History & Notes.                            |
| `POST` | `/api/v1/credit-notes/{id}/notes`        | `credit_notes:write`   | Add a note to the credit note’s History & Notes.                   |

Related lookups you will usually need: [contacts](https://www.accountfun.com/docs/api/contacts/) (the customer or supplier), the [chart of accounts](https://www.accountfun.com/docs/api/chart-of-accounts/) (each line’s account), [tax rates](https://www.accountfun.com/docs/api/tax-rates/), and the documents being credited — [invoices](https://www.accountfun.com/docs/api/invoices/) or [bills](https://www.accountfun.com/docs/api/bills/). AI assistants can use all of this through the [MCP server](https://www.accountfun.com/docs/api/mcp/).

***

## Credit-note statuses

| Status      | Meaning                                                                  |
| ----------- | ------------------------------------------------------------------------ |
| `DRAFT`     | Created but not yet posted to the ledger.                                |
| `SUBMITTED` | Awaiting approval.                                                       |
| `APPROVED`  | Posted to the ledger — the credit exists and can be applied or refunded. |
| `ALLOCATED` | Fully applied to invoices or bills.                                      |
| `VOIDED`    | Cancelled; a posted note is reversed out of the ledger.                  |

Over the API you can create, approve, void, allocate and refund. Editing a draft is done inside AccountFUN.

***

## List credit notes

Returns a paginated list for the token’s organization, newest first. Only the directions the caller’s role can see are returned. The list includes summary fields — **not** lines or allocations.

### Request

```bash
curl "https://app.accountfun.com/api/v1/credit-notes?creditNoteType=payable&status=APPROVED" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Query parameters

| Parameter        | Type    | Default | Description                                                                  |
| ---------------- | ------- | ------- | ---------------------------------------------------------------------------- |
| `status`         | string  | —       | Filter by status: `DRAFT`, `SUBMITTED`, `APPROVED`, `ALLOCATED` or `VOIDED`. |
| `creditNoteType` | string  | —       | `receivable` (customer credits) or `payable` (supplier credits).             |
| `contactId`      | string  | —       | Filter to credit notes for a specific contact.                               |
| `page`           | integer | `1`     | Page number (1-based, max `10000`).                                          |
| `limit`          | integer | `25`    | Page size (max `200`).                                                       |

### Response — `200 OK`

```json
{
  "creditNotes": [
    {
      "id": "3f8a2c1d-...",
      "creditNoteNumber": "CN-0007",
      "creditNoteType": "payable",
      "status": "APPROVED",
      "reference": "RETURN-4471",
      "currency": "USD",
      "total": "120.00",
      "amountAllocated": "0.00",
      "balanceRemaining": "120.00",
      "issueDate": "2026-10-08",
      "contact": { "id": "...", "name": "Northwind Supply" },
      "createdAt": "2026-10-08T09:20:11.400Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "totalPages": 1 }
}
```

| Field                            | Description                                   |
| -------------------------------- | --------------------------------------------- |
| `creditNotes[].total`            | Credit total including tax.                   |
| `creditNotes[].amountAllocated`  | Amount already applied to invoices/bills.     |
| `creditNotes[].balanceRemaining` | Unapplied amount (`total − amountAllocated`). |

***

## Create a credit note

Creates a **`DRAFT`** credit note. Posting it is a separate step ([approve](#approve-a-credit-note) or, inside AccountFUN, submit then approve).

### Request

```bash
curl -X POST https://app.accountfun.com/api/v1/credit-notes \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cn-return-4471" \
  -d '{
    "creditNoteType": "payable",
    "contactId": "00000000-0000-0000-0000-0000000000c1",
    "issueDate": "2026-10-08",
    "reference": "RETURN-4471",
    "currency": "USD",
    "taxMode": "inclusive",
    "lines": [
      {
        "description": "Returned goods — order #1042",
        "quantity": "1",
        "unitAmount": "120.00",
        "accountId": "00000000-0000-0000-0000-000000000077",
        "taxRateId": null
      }
    ]
  }'
```

### Body parameters

| Field              | Type                | Required | Description                                                                      |
| ------------------ | ------------------- | -------- | -------------------------------------------------------------------------------- |
| `creditNoteType`   | string              | Yes      | `receivable` (a credit to a customer) or `payable` (a credit from a supplier).   |
| `contactId`        | string              | Yes      | The customer or supplier. Must be active and belong to the token’s organization. |
| `issueDate`        | date (`YYYY-MM-DD`) | Yes      | The credit-note date.                                                            |
| `lines`            | array               | Yes      | One or more lines (see below).                                                   |
| `reference`        | string              | No       | Free-text reference.                                                             |
| `currency`         | string              | No       | 3-letter ISO 4217 code. Defaults to the organization’s base currency.            |
| `exchangeRate`     | string              | No       | Custom rate to the base currency. Omit for the prevailing rate.                  |
| `taxMode`          | string              | No       | `none`, `exclusive` or `inclusive` — how line amounts relate to tax.             |
| `creditNoteNumber` | string              | No       | Override the organization’s numbering (e.g. `CN-0007`).                          |

### Line parameters

| Field         | Type   | Required | Description                                                                                                 |
| ------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------- |
| `quantity`    | string | Yes      | Numeric string, e.g. `"1"`.                                                                                 |
| `unitAmount`  | string | Yes      | Numeric string, e.g. `"120.00"`.                                                                            |
| `accountId`   | string | Yes      | The account the line posts to.                                                                              |
| `description` | string | No       | Line description.                                                                                           |
| `taxRateId`   | string | No       | A tax rate from [`GET /api/v1/tax-rates`](https://www.accountfun.com/docs/api/tax-rates/). Omit for no tax. |
| `discount`    | string | No       | A flat amount (`"5.00"`) or a percentage (`"10%"`).                                                         |

All money and quantity values are **strings**, not numbers.

### Response — `201 Created`

```json
{
  "creditNote": {
    "id": "3f8a2c1d-...",
    "creditNoteNumber": "CN-0007",
    "creditNoteType": "payable",
    "status": "DRAFT",
    "reference": "RETURN-4471",
    "currency": "USD",
    "subtotal": "120.00",
    "taxTotal": "0.00",
    "total": "120.00",
    "amountAllocated": "0.00",
    "balanceRemaining": "120.00",
    "issueDate": "2026-10-08",
    "postedAt": null,
    "voidedAt": null,
    "journalEntryId": null,
    "contact": { "id": "...", "name": "Northwind Supply" },
    "lines": [ "…" ],
    "allocations": [],
    "refunds": []
  }
}
```

The full credit note is returned — the same shape as [Fetch a single credit note](#fetch-a-single-credit-note).

### Errors

| Status | Cause                                                                                                         |
| ------ | ------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid body — the `details` object names each bad field.                                                     |
| `400`  | The contact is deactivated, an account is archived, a tax rate is inactive, or the currency isn’t enabled.    |
| `403`  | The contact or an account does not belong to this organization, or the role can’t see this side of the books. |
| `403`  | The issue date falls on or before the organization’s lock date.                                               |
| `409`  | A credit-note rule was violated (for example a duplicate credit-note number).                                 |

***

## Fetch a single credit note

```bash
curl https://app.accountfun.com/api/v1/credit-notes/3f8a2c1d-... \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

Returns `{ "creditNote": { … } }` with its lines, the allocations (each with `amount`, `appliedAt` and the invoice or bill it reduced) and any refunds (each with `amount`, `date` and `isReversed`). A credit note in another organization — or an id that isn’t a valid id — returns `404`.

***

## Approve a credit note

Posts a `DRAFT` or `SUBMITTED` credit note to the ledger — the same action as clicking **Approve** inside AccountFUN. Requires the `credit_notes:approve` scope and the **Approve Documents** permission.

```bash
curl -X POST https://app.accountfun.com/api/v1/credit-notes/3f8a2c1d-.../approve \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Response — `200 OK`

```json
{
  "creditNoteId": "3f8a2c1d-...",
  "status": "APPROVED",
  "journalEntryId": "je-55d0e1"
}
```

`journalEntryId` is `null` for a zero-value note.

### Errors

| Status | Cause                                                                                                                                     |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | The credit note can’t be approved in its current state (already approved, allocated or voided).                                           |
| `403`  | `insufficient_scope` — the token doesn’t carry `credit_notes:approve`, or the role lacks **Approve Documents** or this side of the books. |
| `403`  | The issue date falls on or before the lock date.                                                                                          |
| `404`  | No credit note with that id in the token’s organization.                                                                                  |

***

## Void a credit note

Voids a credit note. A posted (`APPROVED` / `ALLOCATED`) note is **reversed** out of the ledger and its allocations are unwound first; a draft or submitted note is simply marked voided. Active refunds block voiding — reverse them first. Requires the `credit_notes:approve` scope.

```bash
curl -X POST https://app.accountfun.com/api/v1/credit-notes/3f8a2c1d-.../void \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Response — `200 OK`

```json
{
  "creditNoteId": "3f8a2c1d-...",
  "voided": true,
  "reversalEntryId": "je-77aa02"
}
```

`reversalEntryId` is `null` when the note was never posted.

### Errors

| Status | Cause                                                                                       |
| ------ | ------------------------------------------------------------------------------------------- |
| `400`  | The credit note can’t be voided in its current state.                                       |
| `403`  | Missing the `credit_notes:approve` scope, the approve permission, or the `void` permission. |
| `404`  | No credit note with that id in the token’s organization.                                    |
| `409`  | Active refunds block voiding, or the status changed concurrently.                           |

***

## Allocate a credit note

Applies an `APPROVED` credit note to invoices (receivable) or bills (payable), fully or in part. Requires the `credit_notes:settle` scope and the **Record Payments** permission. Supports `Idempotency-Key`.

### Request

```bash
curl -X POST https://app.accountfun.com/api/v1/credit-notes/3f8a2c1d-.../allocate \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cn-0007-allocate" \
  -d '{
    "allocations": [
      { "billId": "7c0e5a1f-...", "amount": "120.00" }
    ],
    "applicationDate": "2026-10-08"
  }'
```

### Body parameters

| Field             | Type                | Required | Description                                                |
| ----------------- | ------------------- | -------- | ---------------------------------------------------------- |
| `allocations`     | array               | Yes      | One or more applications to documents (see below).         |
| `applicationDate` | date (`YYYY-MM-DD`) | No       | Date the credit applies. Defaults to today.                |
| `exchangeRate`    | string              | No       | Rate to the base currency when applying across currencies. |

| Allocation field | Type   | Description                                      |
| ---------------- | ------ | ------------------------------------------------ |
| `invoiceId`      | string | The invoice to apply to (receivable notes only). |
| `billId`         | string | The bill to apply to (payable notes only).       |
| `amount`         | string | Amount applied, in the credit-note currency.     |

### Response — `200 OK`

```json
{
  "creditNoteId": "3f8a2c1d-...",
  "creditNoteStatus": "ALLOCATED",
  "allocations": [
    { "invoiceId": null, "billId": "7c0e5a1f-...", "amount": "120.00" }
  ],
  "documentUpdates": [
    {
      "documentId": "7c0e5a1f-...",
      "documentType": "bill",
      "amountPaid": "120.00",
      "balanceDue": "148.00",
      "status": "APPROVED",
      "previousBalanceDue": "268.00"
    }
  ]
}
```

`documentUpdates` reports each document’s balance before and after, so your integration doesn’t need a second read. A document whose balance reaches zero shows as `PAID`.

### Errors

| Status | Cause                                                                                                                                                 |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid body, the credit note isn’t approved, an allocation exceeds the remaining credit or the document’s balance, or the document can’t be settled. |
| `403`  | Missing `credit_notes:settle` or the **Record Payments** permission, or an invoice/bill is outside the organization.                                  |
| `404`  | The credit note doesn’t exist in the token’s organization.                                                                                            |

***

## Refund a credit note

Records a cash refund of an `APPROVED` / `ALLOCATED` credit note from a bank account — money going back to the customer, or coming back from the supplier. Requires the `credit_notes:settle` scope and the **Record Payments** permission. Supports `Idempotency-Key`.

### Request

```bash
curl -X POST https://app.accountfun.com/api/v1/credit-notes/3f8a2c1d-.../refund \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cn-0007-refund" \
  -d '{
    "bankAccountId": "00000000-0000-0000-0000-00000000000b",
    "amount": "120.00",
    "currency": "USD",
    "date": "2026-10-08",
    "appliedAmount": "120.00",
    "reference": "REFUND-4471"
  }'
```

### Body parameters

| Field              | Type                | Required | Description                                                                                     |
| ------------------ | ------------------- | -------- | ----------------------------------------------------------------------------------------------- |
| `bankAccountId`    | string              | Yes      | The Bank account the money is refunded from (customer credits) or paid into (supplier credits). |
| `amount`           | string              | Yes      | Refund amount, in the refund currency.                                                          |
| `currency`         | string              | Yes      | ISO 4217 refund currency.                                                                       |
| `date`             | date (`YYYY-MM-DD`) | Yes      | Refund date.                                                                                    |
| `appliedAmount`    | string              | Yes      | Amount consumed from the credit-note balance, in the **credit-note** currency.                  |
| `exchangeRate`     | string              | No       | Refund-to-base rate. Omit for the prevailing rate.                                              |
| `bankExchangeRate` | string              | No       | Bank-to-base rate when the bank account is in a third currency.                                 |
| `reference`        | string              | No       | Free-text reference.                                                                            |

### Response — `200 OK`

```json
{
  "refundId": "rf-1a2b3c",
  "journalEntryId": "je-c0ffee",
  "creditNoteStatus": "ALLOCATED",
  "amountAllocated": "120.00",
  "balanceRemaining": "0.00"
}
```

### Errors

| Status | Cause                                                                               |
| ------ | ----------------------------------------------------------------------------------- |
| `400`  | Invalid body, the note isn’t approved, or the refund exceeds the available balance. |
| `403`  | Missing `credit_notes:settle` or the **Record Payments** permission.                |
| `404`  | The credit note or bank account doesn’t exist in the token’s organization.          |

***

## Attach files

Attach the signed credit note or the supplier’s credit memo to any credit note — at any status. The same rules as [bill attachments](https://www.accountfun.com/docs/api/bills/#attach-receipts) apply: PDF, PNG, JPEG, XLSX, XLS, DOCX, DOC, CSV; 5 MB per file, 25 MB per request, 10 attachments per credit note. The shared [file processing rules](https://www.accountfun.com/docs/guides/files/#upload-security-and-processing) cover antivirus checks, pending scans, and image resizing and JPEG conversion.

```bash
curl -X POST https://app.accountfun.com/api/v1/credit-notes/3f8a2c1d-.../attachments \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -F "file=@credit-note.pdf"
```

JSON with base64 content works too (the `files[].fileName` / `files[].contentBase64` shape). `201` returns `{ "attachments": [ … ] }`; the list endpoint returns them oldest first with `scanStatus`.

### Upload links

When the caller can’t send the file itself — a chat assistant that saw the document but doesn’t hold it — mint a 15-minute, upload-only link:

```bash
curl -X POST https://app.accountfun.com/api/v1/credit-notes/3f8a2c1d-.../upload-links \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

No body. `201` returns `{ "uploadLink": { "url", "uploadUrl", "expiresAt", "maxFiles": 5 } }`. The link takes up to 5 files, can only add files to that one credit note, and stops working when the app is disconnected or loses `credit_notes:write`. See [bill upload links](https://www.accountfun.com/docs/api/bills/#upload-links) for the full lifecycle.

***

## Notes

Read and add notes in the credit note’s **History & Notes**:

```bash
curl -X POST https://app.accountfun.com/api/v1/credit-notes/3f8a2c1d-.../notes \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body": "Supplier agreed to the return; credit covers freight too."}'
```

`201` returns `{ "note": { "id", "body", "authorId", "viaApp", "createdAt" } }`. `GET` lists the notes newest first. `viaApp` names the app that wrote a note, or is `null` for one typed in AccountFUN. Notes are up to 2000 characters.

## History and audit trail

Everything your integration changes is recorded as the user who authorized it, **via** your app, with the time and where the request came from (IP address and user agent). This covers credit notes created, approved, voided, allocated and refunded — the ledger postings name your app too — files attached and notes added. These entries appear in the credit note’s **History & Notes** (shown as “Jane Lee — via Your App (API)”) and in the organization’s **Audit History**. Every API request is also logged, and the logs are kept for 30 days.

## Worked example — a supplier credit for a return

1. Goods worth `$120` go back to Northwind Supply. Create the payable note: `POST /api/v1/credit-notes` with `creditNoteType: "payable"` and the expense/asset account that was originally charged.
2. Approve it — `POST /api/v1/credit-notes/{id}/approve` with `credit_notes:approve` — so the credit is in the books.
3. Apply it to the outstanding bill: `POST /api/v1/credit-notes/{id}/allocate` with `{ "allocations": [{ "billId": "…", "amount": "120.00" }] }`. The response’s `documentUpdates` shows the bill’s new balance.
4. If the supplier pays the balance back in cash instead, call `POST /api/v1/credit-notes/{id}/refund` with the bank account, amount and `appliedAmount`.
5. Attach the supplier’s credit memo with the attachments endpoint or an upload link, and add a note — both show in History & Notes under the user’s name, via your app.
