Bank transactions
The bank-transaction endpoints post money movements straight to the ledger with no bill or invoice behind them: a bank fee, cash expense or owner drawing (Spend Money), interest, a refund or an owner contribution (Receive Money), or money moved between two of the organization’s bank accounts (Transfer Money). They are the API equivalent of the same actions inside AccountFUN.
GET /api/v1/transactions/{id} reads the posted journal entry — including the
journalEntryId a payment, spend, receive or transfer returned — with its
debit/credit lines.
Both write endpoints need the bank_transactions:write scope, an opt-in
on the consent screen, and the authorizing user’s role must have the Bank
Accounts permission. Reading a transaction needs bank_transactions:read
(with the same role ceiling). See Authentication.
Endpoints
Section titled “Endpoints”| Method | Path | Scope | Description |
|---|---|---|---|
POST | /api/v1/bank-transactions | bank_transactions:write | Post a spend_money or receive_money entry. |
POST | /api/v1/transfers | bank_transactions:write | Transfer money between two bank accounts. |
GET | /api/v1/transactions/{id} | bank_transactions:read | Fetch a posted journal entry with its lines. |
Related lookups you will usually need: the chart of accounts (the bank account and each line’s account), contacts (who the money was with) and tax rates. AI assistants can use all of this through the MCP server.
Spend money / Receive money
Section titled “Spend money / Receive money”Posts one balanced spend_money (money out) or receive_money (money in)
journal entry against a bank account. Use this when there’s no bill or
invoice: for a supplier invoice or receipt, create a
bill instead; to settle an invoice or bill, record a
payment.
Request
Section titled “Request”curl -X POST https://app.accountfun.com/api/v1/bank-transactions \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: bankfee-2026-10-08" \ -d '{ "type": "spend_money", "bankAccountId": "00000000-0000-0000-0000-00000000000b", "contactId": "00000000-0000-0000-0000-0000000000c1", "date": "2026-10-08", "reference": "STMT-2026-10", "description": "Monthly account fee", "lines": [ { "accountId": "00000000-0000-0000-0000-000000000077", "amount": "12.50", "description": "Bank charges" } ] }'Body parameters
Section titled “Body parameters”| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | spend_money (money out) or receive_money (money in). |
bankAccountId | string | Yes | The bank account the money moves through. |
contactId | string | Yes | The contact the money is with. |
date | date (YYYY-MM-DD) | Yes | The transaction date. |
lines | array | Yes | 1–20 lines (see below). |
reference | string | No | Free-text reference on the journal entry. |
description | string | No | Description on the journal entry. |
taxMode | string | No | none, exclusive or inclusive — how the line amounts relate to tax. |
exchangeRate | string | No | Bank-to-base rate for a foreign-currency bank account. Omit for the system rate. |
Line parameters
Section titled “Line parameters”| Field | Type | Required | Description |
|---|---|---|---|
accountId | string | Yes | The account to code the line to — an expense or asset account for spend_money, an income or asset account for receive_money. |
amount | string | Yes | Signed amount, in the bank account’s currency: positive for a spend line, negative for an offsetting line (e.g. a discount). |
description | string | No | Line description. |
taxRateId | string | No | A tax rate from GET /api/v1/tax-rates. Omit for no tax. |
quantity | string | No | Informational quantity. |
unitAmount | string | No | Informational unit amount. |
trackingOption1Id | string | No | Tracking option 1. |
trackingOption2Id | string | No | Tracking option 2. |
Line amounts are signed decimal strings in the bank account’s currency, and the net total must be positive — so every entry has a clear direction.
Response — 201 Created
Section titled “Response — 201 Created”{ "journalEntry": { "id": "je-7f3a91", "type": "spend_money", "date": "2026-10-08", "reference": "STMT-2026-10", "description": "Monthly account fee", "currency": "USD" }}The posted entry can be read in full with
GET /api/v1/transactions/{id}.
Errors
Section titled “Errors”| Status | Cause |
|---|---|
400 | Invalid body — the details object names each bad field. |
400 | The net line total isn’t positive, an account can’t be used on a bank transaction, or a date is invalid. |
403 | The role lacks the Bank Accounts permission, the bank account isn’t in this organization, or the date falls on or before the lock date. |
404 | The bank account or a referenced record does not exist in the token’s organization. |
Transfer money between bank accounts
Section titled “Transfer money between bank accounts”Posts a balanced transfer journal entry between two of the organization’s
bank accounts. Both accounts must be Bank accounts in the token’s
organization and must be different.
Request
Section titled “Request”curl -X POST https://app.accountfun.com/api/v1/transfers \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: transfer-2026-10-08-payroll" \ -d '{ "fromAccountId": "00000000-0000-0000-0000-00000000000b", "toAccountId": "00000000-0000-0000-0000-00000000000c", "amount": "5000.00", "date": "2026-10-08", "reference": "Payroll funding" }'Body parameters
Section titled “Body parameters”| Field | Type | Required | Description |
|---|---|---|---|
fromAccountId | string | Yes | The bank account the money leaves. |
toAccountId | string | Yes | The bank account the money arrives in. Must differ from fromAccountId. |
amount | string | Yes | Amount in the source account’s currency. |
date | date (YYYY-MM-DD) | Yes | The transfer date. |
reference | string | No | Free-text reference. |
description | string | No | Description on the journal entry. |
exchangeRate | string | No | Source-to-destination rate for a cross-currency transfer. Omit for the day’s rate. |
For a cross-currency transfer, amount is measured in the source
currency and the destination receives amount × exchangeRate. A rate (yours
or the day’s) that implies an FX residual of more than 5% is refused with
400 — verify the rate and retry with a corrected exchangeRate.
Response — 201 Created
Section titled “Response — 201 Created”{ "transfer": { "journalEntryId": "je-9b21c4", "fromAccountId": "00000000-0000-0000-0000-00000000000b", "toAccountId": "00000000-0000-0000-0000-00000000000c", "sourceCurrency": "USD", "destinationCurrency": "USD", "sourceAmount": "5000.00", "destinationAmount": "5000.00", "exchangeRate": null }}exchangeRate is the effective source-to-destination rate when the two
accounts are in different currencies, and null for a same-currency transfer.
Errors
Section titled “Errors”| Status | Cause |
|---|---|
400 | Invalid body, the two accounts are the same, an amount isn’t a positive number, or a cross-currency rate implies a >5% residual. |
403 | The role lacks the Bank Accounts permission, an account isn’t a bank account in this organization, or the date falls on or before the lock date. |
404 | A bank account does not exist in the token’s organization. |
Fetch a transaction
Section titled “Fetch a transaction”Returns the posted journal entry behind a payment, spend/receive, transfer or manual journal, with every debit/credit line.
curl https://app.accountfun.com/api/v1/transactions/je-7f3a91 \ -H "Authorization: Bearer $ACCESS_TOKEN"Response — 200 OK
Section titled “Response — 200 OK”{ "transaction": { "id": "je-7f3a91", "type": "spend_money", "date": "2026-10-08", "reference": "STMT-2026-10", "description": "Monthly account fee", "isReversal": false, "reversalOfId": null, "isReversed": false, "isReconciled": false, "contact": { "id": "...", "name": "City Bank" }, "createdAt": "2026-10-08T09:14:31.002Z", "lines": [ { "id": "...", "account": { "id": "...", "code": "493", "name": "Bank Charges" }, "debit": "12.50", "credit": "0.00", "currency": "USD", "exchangeRate": "1", "description": "Bank charges", "taxRate": null }, { "id": "...", "account": { "id": "...", "code": "090", "name": "Business Account" }, "debit": "0.00", "credit": "12.50", "currency": "USD", "exchangeRate": "1", "description": null, "taxRate": null } ] }}Access follows the in-app transaction rule — the role must be able to see the
entry through its banking, reporting, document, managed-accounts or fixed-asset
access. A role that can’t see it gets 403; an unknown id gets 404.
isReconciled is true when any line has been matched to a bank statement.