Transactions
Entries, bank and card lines, categories, tags, accounts, reconciliation and statements.
115 actions
Give an AI assistant only these actions with the transactions MCP toolset.
https://app.getoatmilk.com/api/mcp?toolset=transactionsaccounts
- POST
accounts.createCreate an RBC or other manually imported bank account. - POST
accounts.lifecycleMark an account inactive from an explicit date or since its last verified statement, or reactivate it. Preserves historical records and earlier statement obligations. Requires the current revision and an idempotency key. - GET
accounts.listList available bank and payment accounts. - POST
accounts.updateSet an account display name using the current revision and an idempotency key. Provider identity and currency remain unchanged.
accounts.lifecycle
cards
- POST
cards.claimUpdate the caller's card claims atomically: identifierIds claims unassigned cards, releaseIdentifierIds releases only cards the caller personally claimed, seenIdentifierIds records what they reviewed, and idempotencyKey prevents duplicate saves. Other people's cards and finance-managed assignments cannot be changed; administrators reassign those in Cards. - GET
cards.claimableShow unassigned company cards (last four digits, printed name and account only), the caller's original mine list of last-four strings, and ownedCards for editing. Own cards are marked removable only when the caller linked them. No transaction details are returned. The caller may edit an earlier answer, or is asked about unseen unassigned cards when holding none. - GET
cards.listList the card and account numbers (last four digits) Oatmilk uses to tell which account paid, with each one's account, cardholder and whether a person or Autopilot added it, whether each account is a bank account or a credit card, the members who can hold a card (with their names), and suggested cardholders for cards nobody holds yet, matched from the name printed on the card. - POST
cards.saveAdd a card or account number (kind card_last4 or account_last4 and four digits) to an account, or change its label, cardholder or whether it is on, with idempotencyKey (and id with expectedRevision for changes). Receipts paid with that card are placed on its account. A number active on another account is refused. - POST
cards.setAccountTypeMark an account as a bank account or a credit card with accountId, accountType, expectedRevision and idempotencyKey. Payments between a bank account and a credit card are then treated as transfers.
cards.prompt
categories
- POST
categories.addRecommendedAdd the recommended categories the organization doesn't have yet, archived until someone turns them on. Supply idempotencyKey and optional keys to add only some. Existing categories are never renamed or moved. Finance access required. - POST
categories.createCreate an accounting category using name and idempotencyKey, with an optional top-level parentId (subcategories are one level deep), description (up to 500 characters, read by the AI) and rules: merchant words that always use this category. Requires finance access. - GET
categories.listList organization categories with parent_id, description, display path ("Events › Hackathons"), taxonomy_key, the caller's last_used_at and rule_count. Contributors see active categories only. - POST
categories.updateRename, move (parentId, or null for top level), describe or deactivate a category with a revision check, or choose it for automatic filing with useFor (income, bank_fees, other, contractors, interest_income). A category with active subcategories can't be deactivated. Finance access required.
entries
- POST
entries.attachReceiptAttach a receipt entry to an existing compatible bank entry without duplicating expenses. Requires both current revisions and an idempotency key. - POST
entries.bulkCategorizeCategorize a set of entries with their current revisions. Finance access required. - GET
entries.contextRead what Oatmilk knows about where and when a transaction happened, by entryId: the trip it belongs to, its place pin, whether it looks like a hotel hold (with the reason and the date a final charge is expected), and purchases within about a kilometre around the same dates. Contributors can read only transactions they own. - POST
entries.createManually create a receipt entry from preserved evidence when extraction needs correction. Requires the submission revision, exact minor-unit amounts and an idempotency key. - POST
entries.deleteDelete a transaction from the books with id, expectedRevision, reason (3 to 1000 characters), idempotencyKey and optional choices: bankLines keep (default, the line goes back to Reconcile) or exclude (a manual CSV line leaves the books too), receipts dismiss (default, labelled not a transaction) or keep, and email not_transaction (default, the company email is archived as general mail) or keep. A submitted reimbursement claim is withdrawn, the transaction leaves its trip and open questions close. It is voided, never erased: files, history and audit stay, and entries.restore puts it back. Refused when entries.delete.preview lists a blocker. Finance access required. - GET
entries.getGet an entry by id with its evidence and allocations. - GET
entries.listSearch accounting entries by query, status, account, category or date. Contributor results contain only their own entries. - POST
entries.restoreRestore a deleted transaction with id, expectedRevision (its revision after deleting), reason and idempotencyKey. Its bank matches, excluded bank lines, receipt labels, the email's folder, a withdrawn claim, its trip and its questions come back when nothing changed since; a bank line matched to something else since is a conflict. Finance access required. - POST
entries.retryStepRestart a supported processing step for one transaction using its current revision and an idempotency key. Inspect the activity before choosing only_step or from_here; unsupported modes, protected human decisions, closed periods, and stale revisions are rejected. Review restarts require an administrator. - POST
entries.updateEdit an entry using id, expectedRevision, idempotencyKey, merchant, date, amountMinor, currency, categoryId, paymentAccountId, type, status and notes. Closed periods cannot be changed. A matched entry keeps its amount, currency and account, and its type must follow the bank movement: money in is income, refund or transfer; money out is expense, fee, income_refund or transfer. Pass learn: false when putting an earlier value back, as Undo does, so the correction isn't retained as vendor learning.
entries.delete
entries.deleted
entries.evidence
- POST
entries.evidence.confirmVerify and append a prepared supporting original to its exact transaction with entryId, submissionId and idempotencyKey. Returns the preserved evidence and an extraction-only job; reading never creates purchases or changes financial fields. Duplicate originals on the same transaction are reused. - POST
entries.evidence.preparePrepare an immutable supporting-original upload for an active editable transaction. Supply entryId, filename, mimeType, sizeBytes, sha256 and a stable idempotencyKey. Skip PUT when alreadyUploaded, then confirm. Adds documents alongside existing originals without creating purchases or changing financial fields.
entries.hold
- POST
entries.hold.release.undoUndo Oatmilk's pairing of money back on a card with the hotel hold it gave back, by the money back's releaseEntryId with an idempotencyKey. The pair is never made again, a card fee booked with the hold is a fee again, the money back is reviewed again, and a hold it resolved is open again. Finance access required; a closed month blocks it. - POST
entries.hold.setSay whether a card charge is a hotel hold with entryId, state (confirmed_hold or not_a_hold) and an idempotencyKey. Confirming books the charge as a transfer, so it leaves expense totals and tax while staying visible and matched; pass resolvedByEntryId to say which later charge replaced it. Declining puts the purchase back. A person's decision is final: Oatmilk never overturns it. Closed periods can't change. Contributors can decide only transactions they own.
entries.place
entries.tags
exchangeRates
imports
- POST
imports.commitImport an RBC CSV with accountId, csv, filename, mapping and idempotencyKey. Preserves the original and deduplicates transactions. Autopilot classifies the new lines afterwards unless skipAi is true. - GET
imports.downloadGet an authorized short-lived download for the original statement or CSV import evidence. - POST
imports.previewValidate a CSV import using accountId, csv text and mapping with date, description, amount or debit/credit, and dateFormat. Returns errors without booking transactions.
imports.undo
- POST
imports.undo.applyUndo explicitly selected import-owned groups atomically using the current preview fingerprint, reason, and idempotency key. Keep reviewed or edited transactions and detach their incorrect imported bank links when safe; remove only proved untouched derived entries. Preserves originals and audit. Closed periods and payment dependencies block changes. - GET
imports.undo.historyRead paged organization import, Undo, and Restore history with actual ownership counts and audited reasons. Optional batch and account filters keep the list scoped. Restore eligibility is checked by its lazy preview. - GET
imports.undo.previewPreview selective Undo for one manual CSV or uploaded statement import, or guarded Restore for one complete Undo operation. Resolve batch, statement, transaction, or bank-row context inside the organization. Returns paged groups, treatment choices, blockers, and an exact whole-graph fingerprint while preserving originals. - POST
imports.undo.restoreRestore one entire Undo operation atomically using its current operation revision, inverse preview fingerprint, reason, and idempotency key. The server verifies exact after-state, current relationships, source ownership, and open periods. Later edits or conflicting allocations block restoration.
investigations.questions
- POST
investigations.questions.answerAnswer a question with its id, one of its optionId answers (or none_of_these when the person settled it by hand), an optional note of up to 1000 characters and an idempotencyKey. An offered answer does only what Oatmilk wrote down when it asked (confirm or decline a hold, put a receipt on a hotel's charge or take it off, link a transaction to a trip); none_of_these only closes the question. Every answer is audited, and a question closes once answered. Contributors can answer only questions about transactions they own. - GET
investigations.questions.listList the questions Oatmilk asked a person while investigating, newest first, optionally for one entryId or only the open ones. Each has a title, two to four answers, whether a note is allowed, and the answer when given. Contributors see only questions about transactions they own.
investigations.review
investigations
merchants
- POST
merchants.confirmConfirm what Oatmilk filled in for a merchant, optionally correcting displayName, websiteDomain, description, industry or kind in edits. Confirmed and corrected fields belong to the person and are never overwritten by a later lookup. Needs the merchant key and an idempotency key; pass expectedRevision from merchants.get to detect changes. - POST
merchants.enrichLook a merchant up on the web and fill in its profile: what it is, its website and industry, each backed by a quote from a page. Pass key for one merchant, or leave it out to look up the next businesses that were never looked up, up to the organization's limit. Runs in the background and returns a run id. Only the merchant's name is sent to the search; never amounts or who paid. Category changes are suggestions for a person to approve. - GET
merchants.getRead one merchant by its key: the profile, monthly spend per currency, the five latest transactions, the web pages the profile was read from, and any category suggestion waiting for review. Finance access required. - GET
merchants.listList the merchants the organization paid, with what Oatmilk knows about each (description, industry, website, kind), spend per currency net of refunds over the last 12 months or from/to dates, last paid date, category with its source (rule, history or confirmed) and whether it needs a look. Names written differently, such as "Slack Technologies, LLC" and "SLACK.COM", are one merchant. Filter with search or filter=needs_look. Finance access required.
merchants.settings
- GET
merchants.settings.getRead whether new merchants are looked up automatically and how many web searches one run may use. - POST
merchants.settings.updateTurn automatic merchant lookups on or off and set the most web searches one run may use (1 to 25). Needs the current revision after the first save. Administrator access required.
places
places.settings
- GET
places.settings.getRead whether Oatmilk looks for the location of older card purchases in the background: backfill, on by default. It places up to 20 purchases from the last 120 days every five minutes and asks a person only when it cannot tell. - POST
places.settings.updateTurn the background search for the location of older card purchases on or off with backfill (true or false) and an idempotencyKey. Turning it off never removes a place already saved. Administrator access required.
receipt.tax
reconciliation
- POST
reconciliation.closeExplicitly close an account period after its opening, movement and closing balances reconcile. Finance access required; reopening needs an administrator and the accounting:admin scope (reconciliation.reopen). - POST
reconciliation.createEntryCreate an entry from an imported bank transaction with an explicit type and optional category. Reuses existing entries on retry. - GET
reconciliation.listList reconciliation records and unmatched items using account and date filters. - POST
reconciliation.matchAllocate a bank transaction to an entry with entryId, transactionId, amountMinor in the receipt currency, expectedRevision and idempotencyKey. Cross-currency matches also require bankAmountMinor, exchangeRate (bank major units per receipt major unit), exchangeRateDate and exchangeRateSource. Finance must review foreign-exchange matches explicitly. - POST
reconciliation.reopenReopen a closed accounting period with an audited administrator reason. - POST
reconciliation.splitSplit an entry among categories using exact minor-unit amounts, revision and idempotency key. - POST
reconciliation.unmatchRemove an allocation using allocationId, expectedRevision and idempotencyKey. Finance only, with audit history.
reimbursements
- POST
reimbursements.approveApprove up to 100 submitted reimbursement claims in one atomic review, recording receipt validity and whether the claimant was an employee or officer at purchase for GST/HST treatment. - POST
reimbursements.bindRecipientBind an existing Wise recipient to an active member after verifying its name, currency and business profile. No bank details are returned. - GET
reimbursements.candidatesFor one outgoing bank transfer, list each active member with their approved unpaid claims in the transfer's currency and the exact set of claims that adds up to the transfer, when there is exactly one. Read only; linking still uses reimbursements.link. - POST
reimbursements.claimPurchaseCreate a personal expense claim for an active member from an existing unallocated receipt purchase, with its current revision, exact original evidence and explicit confirmation of who paid. Never creates or changes the expense. - POST
reimbursements.completePaymentComplete an awaiting-receipts bank reimbursement only with approved original receipt purchases for the same member, currency and exact total, using current payment, bank and entry revisions. - GET
reimbursements.forEntryRead the reimbursement claim and status for one purchase, if present. Members can read only their own. - GET
reimbursements.getRead one reimbursement claim and its purchase and payment status. Members can read only their own. - POST
reimbursements.identifyClassify one historical Wise transfer against approved member claims. A dry run returns evidence; apply links only one exact named payee and claim match. - POST
reimbursements.linkLink an existing outgoing bank transfer to approved expense claims with the same member, currency and exact total. The bank entry becomes a transfer, not another expense. - GET
reimbursements.listList reimbursement claims and their submitted, approved, rejected, prepared, funded, paid or returned status. Members see only their own claims; finance can review organization claims. - POST
reimbursements.matchPaymentMatch a funded Wise reimbursement to its imported transfer using Wise's exact transfer reference and source amount. The bank entry becomes a transfer. - POST
reimbursements.preparePrepare one Wise reimbursement for approved claims belonging to the same member and currency. Preparation never sends funds. - GET
reimbursements.recipientsList verified Wise recipient bindings for members without exposing account details. - POST
reimbursements.recordPaymentRecord an existing untouched outgoing bank payment to an explicitly confirmed active member as a reimbursement transfer awaiting receipt-backed claims. Never invents purchases or tax and never sends money. - POST
reimbursements.refreshRecipientRefresh the verified Wise recipient on an unsent prepared reimbursement after the recipient binding changes. Requires the payment revision and never sends funds. - POST
reimbursements.rejectReject a submitted reimbursement with a reason and expected revision. - POST
reimbursements.sendSend one prepared Wise reimbursement for approved claims belonging to one member and currency. Requires a current administrator, the accounting:admin integration scope, the payment's current revision and an idempotency key. A real Wise payout may occur; a sidebar agent asks the person who started its chat to approve this action. Never auto-sends. - POST
reimbursements.submitSubmit a reimbursement claim for a personally paid expense from your own original receipt. Oatmilk never duplicates the expense; check its status with reimbursements.list, reimbursements.get or reimbursements.forEntry. - POST
reimbursements.syncPaymentRead a previously funded Wise reimbursement status and update the claim only when Wise confirms payout or return. Never sends funds.
statements
- GET
statements.downloadGet a short-lived private link to a statement file by id. format original (the default): the unchanged original, an uploaded or Wise statement PDF or photo (pass inline: true to open it in the browser) or a CSV or Wise sync export. format pdf: a PDF of it, the original when it is one, otherwise a PDF Oatmilk renders from Wise's statement data, the CSV's lines or the photo, labelled as prepared by Oatmilk and kept for later downloads. Only statement files can be opened this way. Read-only. - GET
statements.linesRead statement lines. With id: the lines Oatmilk read from that statement file, whether they were checked against its period and its opening and closing balances (verified), whether they are in the books (booked), and the reason when they were not. With accountId, from and to (up to 400 days): the account's lines in the books for those dates, each with the id of a checked statement that covers its date (verifiedBy, or null), and the statement files of that period. Amounts are signed integer strings in minor units of the account's currency; money out is negative. Read-only. - GET
statements.listList the original statement files Oatmilk keeps (uploaded PDF and photo statements, Wise's own monthly statement PDFs, and CSV exports), each with its account, bank, last four digits, period, balances and status: queued, reading, imported (with how many lines were new and how many were already in the books), review (with its plain reason and reasonCode; a statement waiting on its account also has suggestedAccountId, the likeliest existing account, and newAccount, an account drafted from the statement with name, provider, currency, lastFour and accountType, when its number isn't saved on any account; reasonCode ACCOUNT_NEW means no account Oatmilk has could be it), duplicate (of which statement), kept or failed. Also says, for every account and month, whether a statement covers the whole month (statement), part of it (partial), only lines synced from Wise (feed), nothing (missing) or a time before the account's first activity (before). Each file also says whether a PDF can be downloaded (pdf: original, or rendered by Oatmilk from Wise's statement data, a CSV or a photo), how its lines were read (readWith: vision, or text for a reading from the PDF's text layer made before vision), the reader's own warnings, a person's mark (flagged with a note, or checked) and checks: why it waits for a person (review, failed, flagged, old_reader, unsure). Wise sync data is listed once per account and window (the newest copy). Filter with from and to (up to 36 months; the last 12 when left out), or allPeriods: true to find files across the entire saved history, accountId or accountIds (up to 50), includeCoverage: false for only the file list without account-month coverage (coverageIncluded: false and empty month grids; omitted or true retains full coverage), bank, status (or attention for review and failed, or check for every file that waits for a person; toCheck counts them), search, limit and offset. Read-only. - POST
statements.reviewDecide 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.
summaries
- GET
summaries.getRead the separately generated purchase summary and supporting source references. Never treats a summary as financial evidence. - POST
summaries.updateEdit, dismiss or retry a purchase summary independently of receipt processing and human notes, with its current revision and idempotency key.
tags.ai
- GET
tags.ai.listList what the project classifier suggested for a project (tagId, optional verdict likely or ask) that nobody has accepted or dismissed yet: each transaction's id, date, merchant, amount, currency and the classifier's probability. Accept with accounting_entries_tags_set add, or say no with dismiss. - POST
tags.ai.runAsk the project classifier which transactions belong to a project, with tagId, idempotencyKey, optional limit (1 to 100, default 40) and recheck (look again at transactions it already answered). It reads transactions in the project's dates (and the 30 days before), or for a project without dates those that mention its name, other names or keywords, and uses the project's description, keywords and Notion page text. Likely matches become suggestions; unsure ones become questions (accounting_tags_ai_list verdict ask). A sure match tags a transaction by itself only while Autopilot is on and may finish work, for a project with a start and end date around an open transaction with no tag, dated on or after the project was set up; earlier transactions only get suggestions. An answer without probabilities counts as unsure. Returns counts.
tags
- POST
tags.createCreate a project tag with name and idempotencyKey, and optionally parentId (a group; groups are one level deep), color (gray, red, orange, amber, green, teal, blue, purple or pink), description, aliases (other names people write), startsOn/endsOn (the event window) and budgetMinor with budgetCurrency. Active tag names are unique. - POST
tags.deleteDelete a project tag that was never used, with id, expectedRevision and idempotencyKey. A tag on any transaction, or holding other tags, can't be deleted: archive it or merge it instead. - GET
tags.getGet one project tag with the tags inside it, its totals, profit and loss by category, a monthly timeline and the merchant rules Oatmilk learned for it. A group includes the tags inside it, counting each transaction once. - GET
tags.listList project tags (which event or program a transaction is for): name, group (parent_id, one level deep), color, description, other names, event window (starts_on, ends_on), budget, archived state, the caller's last_used_at, and for finance spend, income, net and transaction counts by currency. A group's rollup counts each transaction once. Pass includeArchived to include archived tags. Contributors see active tags without totals or budgets. - POST
tags.mergeMerge one project tag into another with sourceId, targetId, the source's expectedRevision and idempotencyKey: every transaction tagged with the source gets the target instead (once), learned rules and the tags inside a merged group move too, and the source is archived. The audit records every transaction moved. - GET
tags.reportProfit and loss by project tag for optional from/to dates and currency: spend, income and transaction counts per tag and per group, the deduplicated tagged total, untagged transactions, and overlap (transactions tagged to more than one project, which count in each). Currencies stay separate. - GET
tags.suggestSuggest project tags for up to 100 entries (entryIds) from each tag's event window, learned merchant rules and notes or descriptions that mention the tag or its other names. Each suggestion has a score from 0 to 100 and its reasons. Suggestions don't count in totals until accepted with accounting_entries_tags_set. - POST
tags.updateChange a project tag with id, expectedRevision and idempotencyKey: rename, recolor, describe, set other names, move to a group or out of one (parentId null), set or clear the event window and budget, or archive and restore it (archived true or false). Archiving a group archives the tags inside it; restoring the group restores them.
tags.notion
- POST
tags.notion.linkLink a project to a Notion page or database row with page, sourceOfTruth (notion: name, dates, status, budget and description come from Notion; oatmilk: Oatmilk writes them to Notion) and idempotencyKey. Pass tagId (and optionally the project's expectedRevision) to link an existing project, or leave it out to create a project from the page (optionally parentId and color). For a database row, properties is required: the Notion property for each of dates, status, budget and description, or null to leave it out (accounting_tags_notion_preview suggests them; nothing is mapped silently). Linking syncs once straight away and never empties a filled field on either side: where one side is empty the filled value is kept, reads the page text as context for the classifier, and asks the classifier to suggest transactions for the project. - GET
tags.notion.previewRead a Notion page or database row before linking it to a project: supply page (a notion.so link or page ID) and, for an existing project, tagId. Returns its title, whether it is a row and in which database, suggested properties for dates, status, budget and description with every property that could hold each (choices) and the value each would read (propertyValues), the start of the page text the classifier would use, any problems, and with tagId the project's own values and what the first sync would change for each source of truth (firstSync). Review it, then pass the properties you chose to accounting_tags_notion_link. - POST
tags.notion.resolveResolve a sync conflict on one field (name, dates, status, budget or description) with tagId, field, keep (notion writes Notion's value to Oatmilk; oatmilk writes Oatmilk's value to Notion) and idempotencyKey. Then syncs the project. - POST
tags.notion.syncSync a linked project with Notion now, with tagId and idempotencyKey (linked projects also sync about hourly). Fields change only on the side that isn't the source of truth. A field the other side changed since they last agreed is not overwritten: it is returned in project.conflicts for a person to resolve with accounting_tags_notion_resolve. - POST
tags.notion.unlinkStop syncing a project with Notion, with tagId and idempotencyKey. The project keeps its current name, dates, budget and description; nothing changes in Notion.
tags.project
transactions
- POST
transactions.correctCorrect an unallocated CSV bank row with its revision, reason and idempotency key. Original statement evidence and previous import identities remain preserved. Closed periods and Wise rows cannot be edited. - GET
transactions.getGet one imported bank or card transaction by id: amount, date, account, statement text, what it is matched to (allocations with their transactions and entries), and the facts the bank supplied such as merchant, card, cardholder and exchange details. - GET
transactions.listSearch imported bank and card transactions with search text, accountId, currency, from/to dates, allocation (matched, unmatched or partial), direction (in or out), minAmount/maxAmount in minor units, limit and offset. Each line includes allocatedMinor and the entry ids it is matched to. - POST
transactions.restoreRestore a previously reversed CSV bank row with a revision check and audited reason. - POST
transactions.reverseExclude an erroneous unallocated CSV bank row with an audited reason. Preserves evidence and duplicate detection.
transactions.documents
trips
- POST
trips.createCreate a trip with title, startDate, optional endDate and placeLabel, and an idempotencyKey. Finance access required. - GET
trips.getRead one trip by id: its summary, every transaction in it with its role (lodging, hold, room_charge, meal, transport or other), confidence and note, and the place pins to draw on a map. Contributors see only their own transactions in it. - POST
trips.linkEntryPut a transaction in a trip with tripId, entryId, an optional role (lodging, hold, room_charge, meal, transport or other) and an idempotencyKey. A transaction is in one trip at a time; linking it here moves it. Contributors can link only transactions they own. - GET
trips.listList trips: purchases made while travelling, grouped by stay, with title, place, dates, status (upcoming, active or past), how many transactions belong to each, what it cost per currency (holds left out, hotel credits taken off) and its map centre. Contributors see only trips that include a transaction they own. - POST
trips.unlinkEntryTake a transaction out of a trip with tripId, entryId and an idempotencyKey. Oatmilk never puts it back. Contributors can unlink only transactions they own. - POST
trips.updateRename a trip or change its dates or place with id, the fields to change and an idempotencyKey. A trip a person edited is never rewritten by Oatmilk. Finance access required.