Skip to content
AccountFUNDocs

Expense claims

The expense-claim endpoints let staff file out-of-pocket expenses through an integration or an AI assistant, attach the receipt, and — when the connected user can approve — approve their own claim. The final approval creates a supplier bill and posts it to the ledger, exactly like approving in AccountFUN. A base-currency claim’s bill is posted straight away; a foreign-currency claim’s bill is left as a draft so finance can set the exchange rate before posting.

Reading and creating claims requires expense_claims:read / expense_claims:write; approving posts to the books, so it needs its own scope, expense_claims:approve, and the authorizing user’s role must have the Approve Expense Claims permission (the built-in Admin and Accountant roles have it by default; Standard, Sales and Purchase don’t). See Authentication.

MethodPathScopeDescription
GET/api/v1/expense-claimsexpense_claims:readList claims (paginated). A role without Approve Expense Claims sees only its own.
POST/api/v1/expense-claimsexpense_claims:writeCreate a draft claim.
POST/api/v1/expense-claims/{id}/approveexpense_claims:approveApprove your own claim (a draft is submitted first).
GET/api/v1/expense-claims/{id}/attachmentsexpense_claims:readList the receipts attached to a claim.
POST/api/v1/expense-claims/{id}/attachmentsexpense_claims:writeAttach receipts to a claim.

Related lookups you will usually need: contacts (the supplier) and the chart of accounts (the expense account). AI assistants file and approve claims through the MCP server.


Returns a paginated list for the token’s organization, newest first. Summary fields only. A role without the Approve Expense Claims permission is scoped to the claims it filed itself; the claimantId filter is ignored for those roles.

Terminal window
curl "https://app.accountfun.com/api/v1/expense-claims?status=SUBMITTED" \
-H "Authorization: Bearer $ACCESS_TOKEN"
ParameterTypeDefaultDescription
statusstring—Filter by status: DRAFT, SUBMITTED, APPROVED, PAID, DECLINED, or VOIDED.
claimantIdstring—Only claims for a specific member. Ignored by a role restricted to its own claims.
contactIdstring—Only claims spent with a specific supplier.
pageinteger1Page number (1-based, max 10000).
limitinteger25Page size (max 200).
{
"expenseClaims": [
{
"id": "9b1e4c2a-...",
"claimNumber": "EC-0007",
"claimantId": "...",
"status": "SUBMITTED",
"description": "Taxi to client meeting",
"spentAt": "2026-09-15",
"total": "42.5000",
"currency": "HKD",
"billId": null,
"createdAt": "2026-10-07T03:12:44.120Z",
"contact": { "id": "...", "name": "City Taxi" }
}
],
"pagination": { "page": 1, "limit": 25, "total": 1, "totalPages": 1 }
}

Creates a draft claim. It is not posted to the books: the ledger only moves when the claim reaches final approval and AccountFUN creates the linked supplier bill (posted immediately for a base-currency claim, or left as a draft for a foreign-currency one).

A staff role always files for itself — a claimantId other than the token user is ignored. A role with Approve Expense Claims may set claimantId to another member to file on their behalf, in which case that claim can only be approved inside AccountFUN.

Terminal window
curl -X POST https://app.accountfun.com/api/v1/expense-claims \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"claimantId": "00000000-0000-0000-0000-000000000001",
"description": "Taxi to client meeting",
"spentAt": "2026-09-15",
"contactId": "00000000-0000-0000-0000-0000000000c1",
"accountId": "00000000-0000-0000-0000-0000000000a1",
"amount": "42.50",
"taxMode": "inclusive"
}'
FieldTypeRequiredDescription
claimantIdstringYesThe member the claim is for. A staff role may only claim for itself.
descriptionstringYesWhat the expense was for. Max 2000 characters.
spentAtdateYesThe date the expense was incurred, "YYYY-MM-DD".
contactIdstringYesThe supplier the money was spent with. Must be an active contact in the token’s organization.
accountIdstringYesThe expense account to code the claim to. Must be an account in the token’s organization.
amountstringYesThe amount, greater than zero.
taxModestringYesexclusive (amount excludes tax) or inclusive (amount includes tax).
taxRateIdstringNoAn active tax rate from GET /api/v1/tax-rates. Omit, null, or "" for no tax.
currencystringNo3-letter ISO 4217 code. Defaults to the organization’s base currency. Must be enabled.

spentAt may also be sent as an ISO 8601 datetime; the calendar date as written is used.

The created claim in the same shape as the API detail object, including its claimNumber and computed subtotal / taxAmount / total.

{
"expenseClaim": {
"id": "9b1e4c2a-...",
"claimNumber": "EC-0007",
"claimantId": "...",
"status": "DRAFT",
"description": "Taxi to client meeting",
"spentAt": "2026-09-15",
"amount": "42.5000",
"taxMode": "inclusive",
"subtotal": "42.5000",
"taxAmount": "0.0000",
"total": "42.5000",
"currency": "HKD",
"billId": null,
"contact": { "id": "...", "name": "City Taxi" },
"account": { "id": "...", "code": "493", "name": "Travel - National" },
"taxRate": null,
"...": "..."
}
}
StatusCause
400Invalid body — the details object names each bad field, including any id that isn’t a valid id or an amount that isn’t positive.
400The supplier is deactivated, the currency isn’t enabled, or the account can’t be used for an expense claim (a bank, receivable, asset or system control account — choose an expense account).
403The supplier, account or tax rate doesn’t belong to this organization, the claimant isn’t a member, or the spent-at date falls on or before the organization’s lock date.
403The role lacks the Create Expense Claims permission.

Approves the caller’s own claim. For a draft claim the API submits it to its approval chain and records the decision in the same atomic call; for a claim already submitted, it records the decision only. When that approval completes the chain, AccountFUN creates the linked supplier bill — posted straight away for a base-currency claim. A foreign-currency claim is posted with the system exchange rate, or left as a draft for finance to check or amend the rate before posting, when the organization turns off its Post foreign-currency claims automatically setting (see Settings).

Requires the expense_claims:approve scope and the Approve Expense Claims permission. No body.

Terminal window
curl -X POST https://app.accountfun.com/api/v1/expense-claims/9b1e4c2a-.../approve \
-H "Authorization: Bearer $ACCESS_TOKEN"
{
"expenseClaimId": "9b1e4c2a-...",
"final": true,
"outcome": "completed",
"billId": "7c0e5a1f-...",
"journalEntryId": "...",
"postingDeferred": false
}
FieldMeaning
finaltrue when the decision completed the chain and created the bill.
outcomecompleted (the claim is approved) or advanced (it moved to the next approval level).
billIdPresent only when the decision finalized the claim.
journalEntryIdThe posted ledger entry — present when the bill was posted (base-currency claims, or foreign-currency claims when the organization auto-posts them). Absent when the bill was left as a draft for finance to set the exchange rate.
postingDeferredtrue when the bill was created as a draft for finance to set the exchange rate (a foreign-currency claim the organization does not auto-post). The claim is still APPROVED.
StatusCause
403insufficient_scope — the token doesn’t carry expense_claims:approve, or the user’s role doesn’t have the Approve Expense Claims permission.
403The claim was filed by another member — API/MCP approval is limited to your own claims. Approve it in AccountFUN.
403Separation of duties — you can’t approve your own claim unless you’re an admin or the organization’s only approver.
404No claim with that id in the token’s organization.
409The claim isn’t in a decidable state, or the organization’s Accounts Payable / tax system accounts are missing.

Attach one or more files to a claim. File types, size limits and virus scanning follow the same rules as attaching receipts to a bill: PDF, PNG, JPEG, XLSX, XLS, DOCX, DOC, CSV; 5 MB per file, 25 MB per request, 10 attachments per claim, and the organization’s storage quota. Only the claimant can change a claim’s receipts.

Terminal window
curl -X POST https://app.accountfun.com/api/v1/expense-claims/9b1e4c2a-.../attachments \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-F "file=@taxi-receipt.pdf"
Terminal window
curl -X POST https://app.accountfun.com/api/v1/expense-claims/9b1e4c2a-.../attachments \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"files\": [{\"fileName\": \"taxi-receipt.jpg\", \"contentBase64\": \"$(base64 -w0 taxi-receipt.jpg)\"}]}"
{
"attachments": [
{
"id": "...",
"originalName": "taxi-receipt.pdf",
"mimeType": "application/pdf",
"fileSize": 48213,
"createdAt": "2026-10-07T03:13:10.004Z"
}
]
}

Rejected files come back in a warnings array alongside the stored ones.

Terminal window
curl https://app.accountfun.com/api/v1/expense-claims/9b1e4c2a-.../attachments \
-H "Authorization: Bearer $ACCESS_TOKEN"

Returns { "attachments": [ … ] } oldest first, each with id, originalName, mimeType, fileSize, scanStatus, and createdAt.


StatusMeaning
DRAFTSaved, not submitted.
SUBMITTEDMoving through the approval chain.
APPROVEDFinal approval reached — a linked supplier bill was created (posted immediately for a base-currency claim, or left as a draft for a foreign-currency one).
PAIDThe linked bill has been paid.
DECLINEDAn approver rejected it.
VOIDEDCancelled.

Over the API you can create a claim and approve your own; editing, declining, voiding and reimbursing are done inside AccountFUN.