Payments
The payments endpoints let your integration record money that settles invoices
and bills — a customer receipt (receivable) or a supplier payment
(payable) — attach the remittance advice, add a note, and reverse a payment
that was recorded by mistake.
Reading requires the payments:read scope; recording, reversing, attaching
files and adding notes require payments:write. Unlike the plain read/write
scopes, payments:write is an opt-in: the consent screen lists it under
Only if you tick it:, and the authorizing user’s role must have the
Record Payments permission. Reversing also needs the Void Documents
permission. See Authentication.
Payments follow the side of the document they settle. A receivable payment
is sales (the role must see sales documents); a payable payment is
purchases (the role must see purchase documents). A token whose role sees
neither gets 403 on every payments call, and a list returns only the
directions the role can see.
Endpoints
Section titled “Endpoints”| Method | Path | Scope | Description |
|---|---|---|---|
GET | /api/v1/payments | payments:read | List payments (paginated). |
POST | /api/v1/payments | payments:write | Record a customer receipt or supplier payment. |
GET | /api/v1/payments/{id} | payments:read | Fetch one payment with its allocations. |
POST | /api/v1/payments/{id}/reverse | payments:write | Reverse a payment and restore the documents it settled. |
GET | /api/v1/payments/{id}/attachments | payments:read | List the payment’s attached files. |
POST | /api/v1/payments/{id}/attachments | payments:write | Attach files to the payment (multipart or JSON base64). |
POST | /api/v1/payments/{id}/upload-links | payments:write | Mint a 15-minute, upload-only link for someone who holds the file. |
GET | /api/v1/payments/{id}/notes | payments:read | List the payment’s History & Notes. |
POST | /api/v1/payments/{id}/notes | payments:write | Add a note to the payment’s History & Notes. |
Related lookups you will usually need: contacts (the customer or supplier), the chart of accounts (the bank account) and the documents being settled — invoices or bills. AI assistants can use all of this through the MCP server.
List payments
Section titled “List payments”Returns a paginated list of payments for the token’s organization, newest first. Only the directions the caller’s role can see are returned. The list includes summary fields and the contact — not the per-invoice allocations — so fetch a single payment to see what it settled.
Request
Section titled “Request”curl "https://app.accountfun.com/api/v1/payments?paymentType=receivable&limit=25" \ -H "Authorization: Bearer $ACCESS_TOKEN"Query parameters
Section titled “Query parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
paymentType | string | — | receivable (customer receipts) or payable (supplier payments). |
contactId | string | — | Filter to payments for a specific contact (a contact id). |
page | integer | 1 | Page number (1-based, max 10000). |
limit | integer | 25 | Page size (max 200). |
Response — 200 OK
Section titled “Response — 200 OK”{ "payments": [ { "id": "9d2f7c1e-...", "paymentType": "receivable", "date": "2026-10-08", "amount": "980.00", "currency": "USD", "exchangeRate": "1", "reference": "BANK-REF-4471", "contact": { "id": "00000000-0000-0000-0000-000000000001", "name": "Northwind Traders" }, "bankAccountId": "00000000-0000-0000-0000-00000000000b", "isReversed": false, "createdAt": "2026-10-08T09:14:31.002Z" } ], "pagination": { "page": 1, "limit": 25, "total": 1, "totalPages": 1 }}| Field | Description |
|---|---|
payments[].paymentType | receivable (money in from a customer) or payable (money out to a supplier). |
payments[].amount | Payment total, in currency. |
payments[].isReversed | true once the payment has been reversed. |
payments[].bankAccountId | The bank account the money moved through. |
Record a payment
Section titled “Record a payment”Records a customer receipt against one or more invoices, or a supplier payment against one or more bills, and posts it to the ledger immediately — this is the same action as Record Payment inside AccountFUN, not a draft.
An allocation can’t exceed the document’s outstanding balance (400). For
money paid before the invoice or bill exists, use a
prepayment instead.
Request
Section titled “Request”curl -X POST https://app.accountfun.com/api/v1/payments \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: receipt-inv-101" \ -d '{ "paymentType": "receivable", "contactId": "00000000-0000-0000-0000-000000000001", "bankAccountId": "00000000-0000-0000-0000-00000000000b", "date": "2026-10-08", "amount": "980.00", "reference": "BANK-REF-4471", "allocations": [ { "invoiceId": "1a2b3c4d-...", "amount": "490.00" }, { "invoiceId": "5e6f7a8b-...", "amount": "490.00" } ] }'Body parameters
Section titled “Body parameters”| Field | Type | Required | Description |
|---|---|---|---|
paymentType | string | Yes | receivable (allocations use invoiceId) or payable (allocations use billId). |
contactId | string | Yes | The customer (receivable) or supplier (payable). Must belong to the token’s organization. |
bankAccountId | string | Yes | The bank account that received or sent the money. |
date | date (YYYY-MM-DD) | Yes | The payment date. |
amount | string | Yes | The total payment amount, in currency. |
allocations | array | Yes | One or more documents this payment settles (see below). |
currency | string | No | 3-letter ISO 4217 code. Defaults to the documents’ currency, or the base currency. |
exchangeRate | string | No | Rate from the payment currency to the base currency. Omit for the system rate. |
bankExchangeRate | string | No | Bank-to-base rate when the bank account is in a third currency. Omit for the system rate. |
reference | string | No | Free-text reference, e.g. the bank’s reference. |
Allocation parameters
Section titled “Allocation parameters”| Field | Type | Required | Description |
|---|---|---|---|
invoiceId | string | receivable only | The invoice this share of the payment settles. |
billId | string | payable only | The bill this share of the payment settles. |
amount | string | Yes | Amount applied to the document, in the document’s currency. Can’t exceed its balance due. |
All money values are strings ("980.00", not 980), like every other
v1 endpoint.
Response — 201 Created
Section titled “Response — 201 Created”{ "payment": { "id": "9d2f7c1e-...", "paymentType": "receivable", "date": "2026-10-08", "amount": "980.00", "currency": "USD", "exchangeRate": "1", "reference": "BANK-REF-4471", "contact": { "id": "...", "name": "Northwind Traders" }, "bankAccount": { "id": "...", "code": "090", "name": "Business Account" }, "allocations": [ { "id": "...", "amount": "490.00", "invoice": { "id": "...", "invoiceNumber": "INV-0101" }, "bill": null }, { "id": "...", "amount": "490.00", "invoice": { "id": "...", "invoiceNumber": "INV-0102" }, "bill": null } ], "isReversed": false, "createdAt": "2026-10-08T09:14:31.002Z", "updatedAt": "2026-10-08T09:14:31.002Z" }}Settled documents move to PAID when their balance reaches zero, and their
amountPaid / balanceDue update immediately.
Errors
Section titled “Errors”| Status | Cause |
|---|---|
400 | Invalid body — the details object names each bad field. |
400 | An allocation exceeds the document’s balance, or a document can’t be settled in its current state. |
403 | The role can’t see the payment’s document area (sales for receivable, purchases for payable). |
403 | The contact, bank account or a document does not belong to this organization. |
403 | The date falls on or before the organization’s lock date. |
404 | A referenced invoice or bill does not exist in the token’s organization. |
Retrying a payment safely
Section titled “Retrying a payment safely”POST /api/v1/payments supports the Idempotency-Key header. Send a unique
key per logical payment (up to 255 characters from A–Z a–z 0–9 . _ -) and a
retry with the same key and body replays the original response instead of
recording a second payment.
- A repeat with the same key but a different body returns
409(idempotency_fingerprint_mismatch) — use a new key for a new payment. - A repeat while the first request is still running returns
409(idempotency_in_flight) — retry shortly. - The key and its response are kept for 24 hours. A
5xxis never stored, so a failed request can be retried with the same key.
See Idempotency and retries for the shared rules.
Fetch a single payment
Section titled “Fetch a single payment”curl https://app.accountfun.com/api/v1/payments/9d2f7c1e-... \ -H "Authorization: Bearer $ACCESS_TOKEN"Returns { "payment": { … } } in the full shape above: the contact, bank
account and each allocation, with the invoice or bill it settled. A payment in
another organization — or an id that isn’t a valid id — returns 404.
Reverse a payment
Section titled “Reverse a payment”Posts the mirrored reversal, restores the balance of every invoice or bill the
payment settled, and marks the payment reversed. This is the same action as
reversing a payment inside AccountFUN, and needs the payments:write scope
plus the live Void Documents permission.
POST /api/v1/payments/{id}/reverseNo body.
curl -X POST https://app.accountfun.com/api/v1/payments/9d2f7c1e-.../reverse \ -H "Authorization: Bearer $ACCESS_TOKEN"Response — 200 OK
Section titled “Response — 200 OK”{ "reversalEntryId": "je-abc123", "paymentId": "9d2f7c1e-..." }Errors
Section titled “Errors”| Status | Cause |
|---|---|
400 | The payment can’t be reversed in its current state. |
403 | Missing the payments:write scope, the record_payment permission, or the void permission. |
404 | No payment with that id in the token’s organization. |
409 | The payment is already reversed, reconciled to a bank statement, part of a batch, or was collected/refunded through a payment provider. |
Attach files
Section titled “Attach files”Attach one or more files to a payment at any time — typically the remittance advice or the bank’s confirmation. The same rules as bill attachments apply:
- File types: PDF, PNG, JPEG, XLSX, XLS, DOCX, DOC, CSV; the content must match the extension.
- Limits: 5 MB per file, 25 MB per request, 10 attachments per payment, and the organization’s storage quota.
- Attachments follow the shared file processing rules: documents are antivirus-checked and can remain pending until cleared; images are resized and re-encoded as JPEG with metadata removed.
Multipart upload
Section titled “Multipart upload”curl -X POST https://app.accountfun.com/api/v1/payments/9d2f7c1e-.../attachments \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -F "file=@remittance.pdf"JSON upload (base64)
Section titled “JSON upload (base64)”curl -X POST https://app.accountfun.com/api/v1/payments/9d2f7c1e-.../attachments \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"files\": [{\"fileName\": \"remittance.pdf\", \"contentBase64\": \"$(base64 -w0 remittance.pdf)\"}]}"| Field | Type | Description |
|---|---|---|
files[].fileName | string | File name with its extension — the extension decides the file type. |
files[].contentBase64 | string | The file’s bytes, base64-encoded. A data:…;base64, prefix is accepted. |
201 returns { "attachments": [ … ] } with each file’s id,
originalName, mimeType, fileSize, createdAt — and a warnings array
when some files were rejected. 400 if no file was stored or the payment
already has 10; 403 for a view-only role; 404 for an unknown payment;
413 over the size limit or when the storage quota is full; 503 while virus
scanning is unavailable.
List attachments
Section titled “List attachments”curl https://app.accountfun.com/api/v1/payments/9d2f7c1e-.../attachments \ -H "Authorization: Bearer $ACCESS_TOKEN"Returns { "attachments": [ … ] }, oldest first, with each file’s id,
originalName, mimeType, fileSize, scanStatus and createdAt.
Upload links
Section titled “Upload links”When the caller can’t send the file itself — an AI assistant in a chat has seen the remittance but doesn’t hold the original — mint a short-lived link and hand it to whoever has the file:
curl -X POST https://app.accountfun.com/api/v1/payments/9d2f7c1e-.../upload-links \ -H "Authorization: Bearer $ACCESS_TOKEN"No body. Response — 201 Created:
{ "uploadLink": { "url": "https://app.accountfun.com/upload/9f2c…", "uploadUrl": "https://app.accountfun.com/upload/9f2c…/files", "expiresAt": "2026-10-08T10:15:00.000Z", "maxFiles": 5 }}The link works for 15 minutes, takes up to 5 files, can only add
files to that one payment, and needs no sign-in. url opens a page where a
person picks the file; uploadUrl takes the files directly as
multipart/form-data with no Authorization header
(curl -F "file=@remittance.pdf" https://app.accountfun.com/upload/9f2c…/files).
It stops working when the app is disconnected or loses payments:write, or
when its creator can no longer change the payment. See
bill upload links for the full lifecycle.
Read and add notes in the payment’s History & Notes:
curl -X POST https://app.accountfun.com/api/v1/payments/9d2f7c1e-.../notes \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"body": "Received in full; remittance advice attached."}'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
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). Your app’s name is the one registered under API & Developers. This covers payments recorded and reversed — the ledger entry names your app too — files attached, upload links used, and notes added. These entries appear in the payment’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.