# Prepayments

> Read, create, submit, approve, void, allocate, refund and reverse refunds of customer and supplier prepayments through the AccountFUN public API.

Source: https://www.accountfun.com/docs/api/prepayments/

The prepayments endpoints cover money that changes hands **before** an invoice or bill exists — a supplier deposit, a customer advance, an overpayment. A prepayment is created as a draft, posted through an approval step, then applied to the documents it belongs to (or refunded) later.

Two directions exist:

| Type      | Who                                              | Side of the books | Settles  |
| --------- | ------------------------------------------------ | ----------------- | -------- |
| `spend`   | Money paid **to a supplier** as an advance       | Purchases         | Bills    |
| `receive` | Money received **from a customer** as an advance | Sales             | Invoices |

Reading requires `prepayments:read`; creating and submitting require `prepayments:write` (an **opt-in** on the consent screen). **Approving and voiding** post to the ledger and need `prepayments:approve` (opt-in; the role needs **Approve Documents**). **Allocating, un-allocating, refunding and reversing a refund** move money and need `prepayments:settle` (opt-in; the role needs **Record Payments**). The role must see the prepayment’s side of the books, and a list returns only the directions the role can see. See [Authentication](https://www.accountfun.com/docs/api/authentication/).

Retry safety

Creating, allocating and refunding a prepayment 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 money twice.

## Endpoints

| Method   | Path                                                  | Scope                 | Description                                               |
| -------- | ----------------------------------------------------- | --------------------- | --------------------------------------------------------- |
| `GET`    | `/api/v1/prepayments`                                 | `prepayments:read`    | List prepayments (paginated, searchable).                 |
| `POST`   | `/api/v1/prepayments`                                 | `prepayments:write`   | Create a draft prepayment.                                |
| `GET`    | `/api/v1/prepayments/{id}`                            | `prepayments:read`    | Fetch one prepayment with lines, allocations and refunds. |
| `POST`   | `/api/v1/prepayments/{id}/submit`                     | `prepayments:write`   | Move a draft to `SUBMITTED`.                              |
| `POST`   | `/api/v1/prepayments/{id}/approve`                    | `prepayments:approve` | Approve (post) a draft or submitted prepayment.           |
| `POST`   | `/api/v1/prepayments/{id}/void`                       | `prepayments:approve` | Void a prepayment (reversing a posted one first).         |
| `POST`   | `/api/v1/prepayments/{id}/allocate`                   | `prepayments:settle`  | Apply the prepayment to invoices or bills.                |
| `DELETE` | `/api/v1/prepayments/{id}/allocations/{allocationId}` | `prepayments:settle`  | Un-allocate one application.                              |
| `POST`   | `/api/v1/prepayments/{id}/refund`                     | `prepayments:settle`  | Refund the prepayment from a bank account.                |
| `POST`   | `/api/v1/prepayments/{id}/refunds/{refundId}/reverse` | `prepayments:settle`  | Reverse a refund recorded by mistake.                     |

Related lookups you will usually need: [contacts](https://www.accountfun.com/docs/api/contacts/) (the supplier or customer), the [chart of accounts](https://www.accountfun.com/docs/api/chart-of-accounts/) (the bank account and each line’s account), [tax rates](https://www.accountfun.com/docs/api/tax-rates/), and the documents being settled — [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/).

***

## Prepayment statuses

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

***

## List prepayments

Returns a paginated list for the token’s organization, newest first. Only the directions the caller’s role can see are returned.

### Request

```bash
curl "https://app.accountfun.com/api/v1/prepayments?prepaymentType=receive&search=deposit" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Query parameters

| Parameter        | Type    | Default | Description                                                                  |
| ---------------- | ------- | ------- | ---------------------------------------------------------------------------- |
| `status`         | string  | —       | Filter by status: `DRAFT`, `SUBMITTED`, `APPROVED`, `ALLOCATED` or `VOIDED`. |
| `prepaymentType` | string  | —       | `spend` (supplier advances) or `receive` (customer advances).                |
| `contactId`      | string  | —       | Filter to prepayments for a specific contact.                                |
| `search`         | string  | —       | Case-insensitive match on the prepayment number, reference or contact name.  |
| `page`           | integer | `1`     | Page number (1-based, max `10000`).                                          |
| `limit`          | integer | `25`    | Page size (max `200`).                                                       |

### Response — `200 OK`

```json
{
  "prepayments": [
    {
      "id": "a1b2c3d4-...",
      "prepaymentNumber": "PP-0003",
      "prepaymentType": "receive",
      "status": "APPROVED",
      "reference": "DEPOSIT-1042",
      "currency": "USD",
      "total": "1000.00",
      "amountApplied": "0.00",
      "balanceRemaining": "1000.00",
      "date": "2026-10-08",
      "contact": { "id": "...", "name": "Northwind Traders", "email": "ap@northwind.example" },
      "createdAt": "2026-10-08T09:30:00.120Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "totalPages": 1 }
}
```

| Field                            | Description                                 |
| -------------------------------- | ------------------------------------------- |
| `prepayments[].total`            | Prepayment total including tax.             |
| `prepayments[].amountApplied`    | Amount allocated or refunded so far.        |
| `prepayments[].balanceRemaining` | Unapplied amount (`total − amountApplied`). |

***

## Create a prepayment

Creates a **`DRAFT`** prepayment. The bank account must be a **Bank** account in the prepayment’s currency. Posting it is a separate step ([submit](#submit-a-prepayment) and [approve](#approve-a-prepayment), or approve a draft directly).

### Request

```bash
curl -X POST https://app.accountfun.com/api/v1/prepayments \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: deposit-order-11" \
  -d '{
    "prepaymentType": "receive",
    "contactId": "00000000-0000-0000-0000-000000000001",
    "bankAccountId": "00000000-0000-0000-0000-00000000000b",
    "date": "2026-10-08",
    "reference": "DEPOSIT-1042",
    "currency": "USD",
    "taxMode": "none",
    "lines": [
      {
        "description": "Deposit for order #1042",
        "quantity": "1",
        "unitAmount": "1000.00",
        "accountId": "00000000-0000-0000-0000-00000000000a",
        "taxRateId": null
      }
    ]
  }'
```

### Body parameters

| Field              | Type                | Required | Description                                                                      |
| ------------------ | ------------------- | -------- | -------------------------------------------------------------------------------- |
| `prepaymentType`   | string              | Yes      | `spend` (a supplier advance) or `receive` (a customer advance).                  |
| `contactId`        | string              | Yes      | The supplier or customer. Must be active and belong to the token’s organization. |
| `bankAccountId`    | string              | Yes      | The Bank account the cash is paid from / received into.                          |
| `date`             | date (`YYYY-MM-DD`) | Yes      | The prepayment 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 bank account’s 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.             |
| `prepaymentNumber` | string              | No       | Override the organization’s numbering (e.g. `PP-0003`).                          |
| `projectId`        | string              | No       | Group the prepayment under an open project.                                      |

### Line parameters

| Field         | Type   | Required | Description                                                                                                 |
| ------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------- |
| `quantity`    | string | Yes      | Numeric string, e.g. `"1"`.                                                                                 |
| `unitAmount`  | string | Yes      | Numeric string, e.g. `"1000.00"`.                                                                           |
| `accountId`   | string | Yes      | The account the line names.                                                                                 |
| `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%"`).                                                         |

### Response — `201 Created`

```json
{
  "prepayment": {
    "id": "a1b2c3d4-...",
    "prepaymentNumber": "PP-0003",
    "prepaymentType": "receive",
    "status": "DRAFT",
    "reference": "DEPOSIT-1042",
    "currency": "USD",
    "subtotal": "1000.00",
    "taxTotal": "0.00",
    "total": "1000.00",
    "amountApplied": "0.00",
    "balanceRemaining": "1000.00",
    "date": "2026-10-08",
    "projectId": null,
    "journalEntryId": null,
    "bankAccountId": "00000000-0000-0000-0000-00000000000b",
    "postedAt": null,
    "voidedAt": null,
    "contact": { "id": "...", "name": "Northwind Traders", "email": "ap@northwind.example" },
    "bankAccount": { "id": "...", "code": "090", "name": "Business Account", "currency": null },
    "lines": [ "…" ],
    "allocations": [],
    "refunds": []
  }
}
```

### Errors

| Status | Cause                                                                                                                       |
| ------ | --------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid body — the `details` object names each bad field.                                                                   |
| `400`  | The bank account isn’t a Bank account, isn’t in the prepayment’s currency, or the contact can’t be used for this type.      |
| `403`  | The contact, bank account or an account does not belong to this organization, or the role can’t see this side of the books. |
| `403`  | The date falls on or before the organization’s lock date.                                                                   |
| `409`  | A prepayment rule was violated (for example a duplicate prepayment number).                                                 |

***

## Fetch a single prepayment

```bash
curl https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-... \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

Returns `{ "prepayment": { … } }` with its contact, bank account and lines, the allocations (each with `amount`, `appliedAt`, `isReversed` and the invoice or bill it reduced) and any refunds (each with `amount`, `date` and `isReversed`). An un-allocated row is kept as history and shows `isReversed: true` rather than disappearing.

***

## Submit a prepayment

Moves a `DRAFT` prepayment to `SUBMITTED` so it can be posted. Needs the `prepayments:write` scope.

```bash
curl -X POST https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../submit \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

Response — `200 OK`: `{ "success": true }`.

***

## Approve a prepayment

Posts a `DRAFT` or `SUBMITTED` prepayment to the ledger — the prepayment asset/liability against the bank account. Requires the `prepayments:approve` scope and the **Approve Documents** permission.

```bash
curl -X POST https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../approve \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Response — `200 OK`

```json
{
  "prepaymentId": "a1b2c3d4-...",
  "status": "APPROVED",
  "journalEntryId": "je-11ee22"
}
```

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

### Errors

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

***

## Void a prepayment

Voids a prepayment. A posted (`APPROVED`) one is reversed; a draft or submitted one is simply marked voided. A prepayment that has been applied to invoices or bills must have its allocations reversed first. Requires the `prepayments:approve` scope.

```bash
curl -X POST https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../void \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Response — `200 OK`

```json
{
  "prepaymentId": "a1b2c3d4-...",
  "voided": true,
  "reversalEntryId": "je-33ff44"
}
```

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

***

## Allocate a prepayment

Applies an `APPROVED` prepayment to invoices (`receive`) or bills (`spend`), fully or in part. Requires the `prepayments:settle` scope and the **Record Payments** permission. Supports `Idempotency-Key`.

### Request

```bash
curl -X POST https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../allocate \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pp-0003-allocate" \
  -d '{
    "allocations": [
      { "invoiceId": "1a2b3c4d-...", "amount": "1000.00" }
    ],
    "date": "2026-10-15"
  }'
```

### Body parameters

| Field          | Type                | Required | Description                                                |
| -------------- | ------------------- | -------- | ---------------------------------------------------------- |
| `allocations`  | array               | Yes      | One or more applications to documents (see below).         |
| `date`         | date (`YYYY-MM-DD`) | No       | Date the allocation 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 (receive prepayments only). |
| `billId`         | string | The bill to apply to (spend prepayments only).      |
| `amount`         | string | Amount applied, in the prepayment currency.         |

### Response — `200 OK`

```json
{
  "prepaymentId": "a1b2c3d4-...",
  "prepaymentStatus": "ALLOCATED",
  "allocations": [
    { "prepaymentId": "a1b2c3d4-...", "invoiceId": "1a2b3c4d-...", "billId": null, "amount": "1000.00" }
  ],
  "documentUpdates": [
    {
      "documentId": "1a2b3c4d-...",
      "documentType": "invoice",
      "amountPaid": "1000.00",
      "balanceDue": "0.00",
      "status": "PAID"
    }
  ]
}
```

### Errors

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

***

## Un-allocate a prepayment

Undoes one application of an `APPROVED` / `ALLOCATED` prepayment: posts the mirror entry dated the organization’s today, restores the document’s balance and the prepayment’s remaining balance, and keeps the allocation row as reversed history. Requires the `prepayments:settle` scope.

```plaintext
DELETE /api/v1/prepayments/{id}/allocations/{allocationId}
```

No body.

```bash
curl -X DELETE "https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../allocations/66aa77bb-..." \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Response — `200 OK`

```json
{
  "prepaymentId": "a1b2c3d4-...",
  "allocationId": "66aa77bb-...",
  "journalEntryId": "je-88cc99",
  "prepaymentStatus": "APPROVED",
  "amountApplied": "0.00",
  "balanceRemaining": "1000.00"
}
```

### Errors

| Status | Cause                                                                                                 |
| ------ | ----------------------------------------------------------------------------------------------------- |
| `400`  | The allocation can’t be reversed (already reversed, or the prepayment isn’t in an allocatable state). |
| `403`  | Missing `prepayments:settle` or the **Record Payments** permission.                                   |
| `404`  | The prepayment or allocation doesn’t exist in the token’s organization.                               |

***

## Refund a prepayment

Records a cash refund of an `APPROVED` / `ALLOCATED` prepayment from a Bank account — money moving back to the customer (`receive`) or coming back from the supplier (`spend`). Requires the `prepayments:settle` scope and the **Record Payments** permission. Supports `Idempotency-Key`.

### Request

```bash
curl -X POST https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../refund \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pp-0003-refund" \
  -d '{
    "bankAccountId": "00000000-0000-0000-0000-00000000000b",
    "amount": "1000.00",
    "currency": "USD",
    "date": "2026-10-20",
    "appliedAmount": "1000.00",
    "reference": "REFUND-DEPOSIT-1042"
  }'
```

### Body parameters

| Field           | Type                | Required | Description                                               |
| --------------- | ------------------- | -------- | --------------------------------------------------------- |
| `bankAccountId` | string              | Yes      | The Bank account the refund is paid from / received into. |
| `amount`        | string              | Yes      | Refund amount.                                            |
| `currency`      | string              | Yes      | ISO 4217 code; must match the bank account’s currency.    |
| `date`          | date (`YYYY-MM-DD`) | Yes      | Refund date.                                              |
| `appliedAmount` | string              | Yes      | Prepayment balance consumed, in the prepayment currency.  |
| `exchangeRate`  | string              | No       | Rate to the base currency. Defaults to `1`.               |
| `reference`     | string              | No       | Free-text reference.                                      |

### Response — `200 OK`

```json
{
  "refundId": "rf-77ee88",
  "journalEntryId": "je-aabbcc",
  "prepaymentStatus": "ALLOCATED",
  "amountApplied": "1000.00",
  "balanceRemaining": "0.00"
}
```

### Errors

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

***

## Reverse a prepayment refund

Undoes an incorrectly recorded prepayment refund: posts the mirror entry dated the refund date, restores the prepayment’s remaining balance and marks the refund reversed. Requires the `prepayments:settle` scope.

```plaintext
POST /api/v1/prepayments/{id}/refunds/{refundId}/reverse
```

No body.

```bash
curl -X POST "https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../refunds/rf-77ee88/reverse" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Response — `200 OK`

```json
{
  "refundId": "rf-77ee88",
  "reversalEntryId": "je-ddeeff",
  "prepaymentId": "a1b2c3d4-...",
  "prepaymentStatus": "APPROVED",
  "amountApplied": "0.00",
  "balanceRemaining": "1000.00"
}
```

### Errors

| Status | Cause                                                                             |
| ------ | --------------------------------------------------------------------------------- |
| `400`  | The refund can’t be reversed (already reversed, or the prepayment state changed). |
| `403`  | Missing `prepayments:settle` or the **Record Payments** permission.               |
| `404`  | The prepayment or refund doesn’t exist in the token’s organization.               |

***

## 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 prepayments created, submitted, approved, voided, allocated, un-allocated, refunded and reversed — the ledger postings name your app too. These entries appear in the organization’s **Audit History**. Every API request is also logged, and the logs are kept for 30 days.

## Worked example — a customer deposit

1. Maya’s customer pays a `$1,000` deposit for work that hasn’t been invoiced yet. Record it: `POST /api/v1/prepayments` with `prepaymentType: "receive"`, the customer, the bank account and one line.
2. Submit and approve it — `POST …/submit`, then `POST …/approve` with `prepayments:approve` — so the money is in the books.
3. When the invoice is issued, apply the deposit: `POST …/allocate` with `{ "allocations": [{ "invoiceId": "…", "amount": "1000.00" }] }`. The invoice’s `balanceDue` drops by the applied amount.
4. If the work is cancelled instead, refund the deposit: `POST …/refund` with the bank account, amount and `appliedAmount`. If the refund was a mistake, `POST …/refunds/{refundId}/reverse` restores the balance.
