Transactions

statements.review

Decide what happens to uploaded statements, with idempotencyKey, decision and either id with expectedRevision or items (up to 100 of { id, expectedRevision }). assign (with accountId) checks the saved reading again for that account without reading the file, and with remember: true also saves the statement's account number and cardholders' cards on that account (never one already on another account) and checks the other statements waiting on it again; new_account (administrators only, with the accounting:admin scope for API keys) adds the account the statement is for once, from the first statement's newAccount with any of name, provider, currency, lastFour and accountType in newAccount overriding it, saves its last four digits so later statements match it, assigns every named statement to it, checks every other statement waiting on that account again, and answers with the account and how many statements it is checking (rechecking); read_again reads the file again (model: zai/glm-5.3-flash by default, or openai/gpt-6-luna, google/gemini-3.8-flash or openai/gpt-6.1-sol) and reads the account number, each cardholder's card and every line afresh; an imported statement keeps its account; keep keeps a statement that needs review as the original without importing its lines; flag (with an optional note) puts it in front of a person; unflag removes the flag; confirm records that a person checked it was read correctly. Nothing is booked unless the lines add up to the statement's balances, and an imported statement's account can't change here. With items, the answer lists each statement changed and each one skipped with why.

POST/api/v1/accounting/statements.review

Permissions

accounting:readaccounting:write

Who can call it

admin, finance

Retries

Idempotency key required, with expectedRevision

MCP

accounting_statements_review

Fields

  • idstring (ID)

    The record's ID.

  • expectedRevisioninteger

    The record's current revision, from the last time you read it. If someone changed the record since, the request is refused with a conflict so you can reload and check before trying again.

    at most 9007199254740991 · greater than 0

  • itemsarray of objects

    1–100 items

  • idempotencyKeystringRequired

    Any unique text you generate once per intended change, so a retried request only happens once. Send it as the Idempotency-Key header instead if you prefer; if you send both they must match.

    8–200 characters

  • decisionenumRequired

    What you decided.

    assignnew_accountread_againkeepflagunflagconfirm
  • accountIdstring (ID)

    The ID of a bank, card or payment account, from accounts.list.

  • notestring

    A short note, kept with the record.

    at most 500 characters

  • newAccountobject

    No other fields

  • modelenum
    openai/gpt-6.1-solopenai/gpt-6-lunagoogle/gemini-3.8-flashzai/glm-5.3-flash
  • rememberboolean

Example

curl https://app.getoatmilk.com/api/v1/accounting/statements.review \
  -H "Authorization: Bearer $OATMILK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "decision": "assign",
  "items": [
    {
      "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
      "expectedRevision": 3
    }
  ],
  "accountId": "4d5e6f7a-8b9c-4d0e-8f1a-2b3c4d5e6f7a"
}'
Response
{
  "data": { … }
}

Try it

Try it

Checks your input with this action’s real schema and answers like the API, with synthetic data. No key needed, and nothing changes.

POST/api/v1/accounting/statements.review
curl https://app.getoatmilk.com/api/v1/accounting/statements.review \
  -H "Authorization: Bearer $OATMILK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "decision": "assign",
  "items": [
    {
      "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
      "expectedRevision": 3
    }
  ],
  "accountId": "4d5e6f7a-8b9c-4d0e-8f1a-2b3c4d5e6f7a"
}'

More in Transactions.