Skip to content
AccountFUNDocs

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.

MethodPathScopeDescription
POST/api/v1/bank-transactionsbank_transactions:writePost a spend_money or receive_money entry.
POST/api/v1/transfersbank_transactions:writeTransfer money between two bank accounts.
GET/api/v1/transactions/{id}bank_transactions:readFetch 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.


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.

Terminal window
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"
}
]
}'
FieldTypeRequiredDescription
typestringYesspend_money (money out) or receive_money (money in).
bankAccountIdstringYesThe bank account the money moves through.
contactIdstringYesThe contact the money is with.
datedate (YYYY-MM-DD)YesThe transaction date.
linesarrayYes1–20 lines (see below).
referencestringNoFree-text reference on the journal entry.
descriptionstringNoDescription on the journal entry.
taxModestringNonone, exclusive or inclusive — how the line amounts relate to tax.
exchangeRatestringNoBank-to-base rate for a foreign-currency bank account. Omit for the system rate.
FieldTypeRequiredDescription
accountIdstringYesThe account to code the line to — an expense or asset account for spend_money, an income or asset account for receive_money.
amountstringYesSigned amount, in the bank account’s currency: positive for a spend line, negative for an offsetting line (e.g. a discount).
descriptionstringNoLine description.
taxRateIdstringNoA tax rate from GET /api/v1/tax-rates. Omit for no tax.
quantitystringNoInformational quantity.
unitAmountstringNoInformational unit amount.
trackingOption1IdstringNoTracking option 1.
trackingOption2IdstringNoTracking 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.

{
"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}.

StatusCause
400Invalid body — the details object names each bad field.
400The net line total isn’t positive, an account can’t be used on a bank transaction, or a date is invalid.
403The role lacks the Bank Accounts permission, the bank account isn’t in this organization, or the date falls on or before the lock date.
404The bank account or a referenced record does not exist in the token’s organization.

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.

Terminal window
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"
}'
FieldTypeRequiredDescription
fromAccountIdstringYesThe bank account the money leaves.
toAccountIdstringYesThe bank account the money arrives in. Must differ from fromAccountId.
amountstringYesAmount in the source account’s currency.
datedate (YYYY-MM-DD)YesThe transfer date.
referencestringNoFree-text reference.
descriptionstringNoDescription on the journal entry.
exchangeRatestringNoSource-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.

{
"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.

StatusCause
400Invalid body, the two accounts are the same, an amount isn’t a positive number, or a cross-currency rate implies a >5% residual.
403The 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.
404A bank account does not exist in the token’s organization.

Returns the posted journal entry behind a payment, spend/receive, transfer or manual journal, with every debit/credit line.

Terminal window
curl https://app.accountfun.com/api/v1/transactions/je-7f3a91 \
-H "Authorization: Bearer $ACCESS_TOKEN"
{
"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.