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.
Endpoints
Section titled “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 (the supplier or customer), the chart of accounts (the bank account and each line’s account), tax rates, and the documents being settled — invoices or bills. AI assistants can use all of this through the MCP server.
Prepayment statuses
Section titled “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
Section titled “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
Section titled “Request”curl "https://app.accountfun.com/api/v1/prepayments?prepaymentType=receive&search=deposit" \ -H "Authorization: Bearer $ACCESS_TOKEN"Query parameters
Section titled “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
Section titled “Response — 200 OK”{ "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
Section titled “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 and approve, or
approve a draft directly).
Request
Section titled “Request”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
Section titled “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
Section titled “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. Omit for no tax. |
discount | string | No | A flat amount ("5.00") or a percentage ("10%"). |
Response — 201 Created
Section titled “Response — 201 Created”{ "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
Section titled “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
Section titled “Fetch a single prepayment”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
Section titled “Submit a prepayment”Moves a DRAFT prepayment to SUBMITTED so it can be posted. Needs the
prepayments:write scope.
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
Section titled “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.
curl -X POST https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../approve \ -H "Authorization: Bearer $ACCESS_TOKEN"Response — 200 OK
Section titled “Response — 200 OK”{ "prepaymentId": "a1b2c3d4-...", "status": "APPROVED", "journalEntryId": "je-11ee22"}journalEntryId is null for a zero-value prepayment.
Errors
Section titled “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
Section titled “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.
curl -X POST https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../void \ -H "Authorization: Bearer $ACCESS_TOKEN"Response — 200 OK
Section titled “Response — 200 OK”{ "prepaymentId": "a1b2c3d4-...", "voided": true, "reversalEntryId": "je-33ff44"}reversalEntryId is null when the prepayment was never posted.
Allocate a prepayment
Section titled “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
Section titled “Request”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
Section titled “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
Section titled “Response — 200 OK”{ "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
Section titled “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
Section titled “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.
DELETE /api/v1/prepayments/{id}/allocations/{allocationId}No body.
curl -X DELETE "https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../allocations/66aa77bb-..." \ -H "Authorization: Bearer $ACCESS_TOKEN"Response — 200 OK
Section titled “Response — 200 OK”{ "prepaymentId": "a1b2c3d4-...", "allocationId": "66aa77bb-...", "journalEntryId": "je-88cc99", "prepaymentStatus": "APPROVED", "amountApplied": "0.00", "balanceRemaining": "1000.00"}Errors
Section titled “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
Section titled “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
Section titled “Request”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
Section titled “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
Section titled “Response — 200 OK”{ "refundId": "rf-77ee88", "journalEntryId": "je-aabbcc", "prepaymentStatus": "ALLOCATED", "amountApplied": "1000.00", "balanceRemaining": "0.00"}Errors
Section titled “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
Section titled “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.
POST /api/v1/prepayments/{id}/refunds/{refundId}/reverseNo body.
curl -X POST "https://app.accountfun.com/api/v1/prepayments/a1b2c3d4-.../refunds/rf-77ee88/reverse" \ -H "Authorization: Bearer $ACCESS_TOKEN"Response — 200 OK
Section titled “Response — 200 OK”{ "refundId": "rf-77ee88", "reversalEntryId": "je-ddeeff", "prepaymentId": "a1b2c3d4-...", "prepaymentStatus": "APPROVED", "amountApplied": "0.00", "balanceRemaining": "1000.00"}Errors
Section titled “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
Section titled “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
Section titled “Worked example — a customer deposit”- Maya’s customer pays a
$1,000deposit for work that hasn’t been invoiced yet. Record it:POST /api/v1/prepaymentswithprepaymentType: "receive", the customer, the bank account and one line. - Submit and approve it —
POST …/submit, thenPOST …/approvewithprepayments:approve— so the money is in the books. - When the invoice is issued, apply the deposit:
POST …/allocatewith{ "allocations": [{ "invoiceId": "…", "amount": "1000.00" }] }. The invoice’sbalanceDuedrops by the applied amount. - If the work is cancelled instead, refund the deposit:
POST …/refundwith the bank account, amount andappliedAmount. If the refund was a mistake,POST …/refunds/{refundId}/reverserestores the balance.