# Inbox and uploads

> Receipts, file uploads, company mail, connected inboxes and processing jobs.

MCP toolset: `inbox` (https://app.getoatmilk.com/api/mcp?toolset=inbox)

## documentRequests

- [`documentRequests.list`](https://app.getoatmilk.com/docs/api/documentRequests.list.md) — Read this organization's document requests and their receipt status.

- [`documentRequests.recipients`](https://app.getoatmilk.com/docs/api/documentRequests.recipients.md) — Search active contractors and team members by name or email for a document request.

- [`documentRequests.revoke`](https://app.getoatmilk.com/docs/api/documentRequests.revoke.md) — Revoke an outstanding document request and cancel queued delivery.

- [`documentRequests.send`](https://app.getoatmilk.com/docs/api/documentRequests.send.md) — Email a document request with an expiring private upload link and an authenticated reply path. Requires a recipient and idempotency key.

## emails

- [`emails.submitBatch`](https://app.getoatmilk.com/docs/api/emails.submitBatch.md) — Submit original RFC822 emails using idempotencyKey and emails [{rawEmail,filename,metadata}]. Up to 20 emails and 3 MB total per request. Claimed sender metadata never authorizes a different user. Preserves original email bytes and returns processing jobs.

## evidence

- [`evidence.download`](https://app.getoatmilk.com/docs/api/evidence.download.md) — Get an authorized short-lived private evidence download by evidenceId.

## evidence.inboxSearch

- [`evidence.inboxSearch.cancel`](https://app.getoatmilk.com/docs/api/evidence.inboxSearch.cancel.md) — Stop an inbox search with id and idempotencyKey. Purchases not yet searched are cancelled, and no further inbox is read; one being read finishes and copies nothing more. Only the member who started it or an administrator can stop it.

- [`evidence.inboxSearch.get`](https://app.getoatmilk.com/docs/api/evidence.inboxSearch.get.md) — Read an inbox search (id), or the latest search of each purchase (entryIds, comma-separated, up to 100): its status, runId, and each purchase's state and outcome with counts of emails found and screened. Contributors see only their own searches. Mail content is never returned, except the sender, subject and date of a receipt that was copied into company mail, for people who may read company mail.

- [`evidence.inboxSearch.start`](https://app.getoatmilk.com/docs/api/evidence.inboxSearch.start.md) — Search the caller's own connected Gmail or Outlook inbox for the receipt, invoice, or order confirmation of purchases that still need one, with entryIds (1 to 25) and idempotencyKey. Integrations also need the mailboxes:search scope; plain read and write access never grants it. Only the caller's own inbox is ever searched, and the request is the consent for this search only: each of their inboxes is read at most once per purchase and at most one email is copied for it, and it never changes daily checks or the investigator's consent. A purchase on another member's card is not searched (it stays with that member's ask), and a contributor can only search purchases on their own cards. A merchant email or nearby processor order may be copied after financial screening. On a member-requested search only, a recent Gmail forward whose preview is truncated may instead be copied after a bounded raw read proves the single forwarded original has a confirmed order, nearby original date, merchant, exact bank-currency grand total and card suffix, and the credential screen clears it; one later judged not to be financial evidence is removed again. The purchase it was found for is suggested to matching first, which still compares it with every likely transaction: it is attached only when matching would pick that purchase anyway, and left for review otherwise. Returns the search with each purchase's state (searching, reading, attached, review, not found or skipped) and its runId. With no usable inbox the search waits for the caller to connect or resume one (status waiting_for_inbox) and says which providers are available. A member can start 60 searches an hour, run five at once and search 250 purchases a day.

## inbox

- [`inbox.address`](https://app.getoatmilk.com/docs/api/inbox.address.md) — Read the address you forward receipts and invoices to. It's the organization's accounting address; anything sent to it from your verified email is filed as yours. Needs only accounting:read. Finance reads every receiving address with mail.inboundAddresses.

- [`inbox.list`](https://app.getoatmilk.com/docs/api/inbox.list.md) — List receipt submissions and their review or processing state.

## intake

- [`intake.classify`](https://app.getoatmilk.com/docs/api/intake.classify.md) — Suggest what an uploaded file is and where it belongs from file-type and name rules, CSV columns, readable text and the accounting classifier. Returns kind, probability, accepted, reasons and a destination such as the bank account a statement belongs to. Nothing is filed until intake.process.

- [`intake.complete`](https://app.getoatmilk.com/docs/api/intake.complete.md) — Verify an uploaded intake file's size, SHA-256 hash and type by id with an idempotency key. Returns the item, ready to classify or file.

- [`intake.dismiss`](https://app.getoatmilk.com/docs/api/intake.dismiss.md) — Dismiss an uploaded file that should not be filed. With removeOriginal: true, the stored original is deleted too, for an accidental upload. Adding the same file again brings it back (and uploads it again when its original was removed). Filed files can't be dismissed.

- [`intake.fromMail`](https://app.getoatmilk.com/docs/api/intake.fromMail.md) — File an attachment of an email in the workspace's mail (messageId, evidenceId, idempotencyKey) through universal intake: it becomes an uploaded file like a dropped one, ready for intake.classify and intake.process, and remembers the email it came from. Attachments of mail held for an administrator (quarantined, or holding sign-in or security details) can't be filed. The same file already added returns that upload with duplicate: true.

- [`intake.get`](https://app.getoatmilk.com/docs/api/intake.get.md) — Read one uploaded file with its suggestion, decision and result. Contributors can read only their own uploads.

- [`intake.inline`](https://app.getoatmilk.com/docs/api/intake.inline.md) — Add any file Oatmilk should file in one call, for clients that can't upload to a link: filename, mimeType, contentBase64 (the file's bytes in base64, at most 2 MB), idempotencyKey and optional presetKind. Oatmilk checks the bytes, stores them privately and completes the upload, as intake.prepare, the upload and intake.complete do; a file already added returns duplicate: true. Then call intake.classify and intake.process. Retrying with the same key and file is safe. Contributors add receipts only. Larger files use intake.prepare.

- [`intake.list`](https://app.getoatmilk.com/docs/api/intake.list.md) — List uploaded files and where each one went. Filter with status (open, done, dismissed, all or one status), mine, search and since. Contributors see only their own uploads.

- [`intake.prepare`](https://app.getoatmilk.com/docs/api/intake.prepare.md) — Prepare a private upload for any file Oatmilk should file: a receipt, vendor bill, issued invoice, bank statement, contractor agreement, tax or company document. Supply filename, mimeType, sizeBytes, sha256, idempotencyKey and optional presetKind. A file already added to the organization returns duplicate: true with addedAt. Otherwise PUT the unchanged bytes to uploadUrl, then call intake.complete. Contributors can file receipts only.

- [`intake.process`](https://app.getoatmilk.com/docs/api/intake.process.md) — File an uploaded item as a confirmed kind (receipt, vendor_bill, issued_invoice, bank_statement, contractor_agreement, tax_document, company_document or other) with an optional target: accountId or newAccount for a CSV statement; contractorId, or newContractor (displayName, email, optional legalName, and confirmedNew once a person checked they aren't someone with the same or a close name), for an agreement, a tax document or another record kept for a contractor; taxYear for a tax document; paymentAccountId for a receipt. An agreement for a contractor that matches the one already on file (same start and end dates, rate and role) is refused with SAME_AGREEMENT until sameAgreement says what to do: link (file this upload as that agreement, adding nothing), replace (keep this copy as the agreement and void the uploaded one on file; not for one signed in Oatmilk) or keep (keep both, without reading this one's terms). Receipts and bills enter receipt processing, CSV statements are imported, agreements are kept as signed agreements, and other records go to the documents store. An issued invoice waits for review in the invoice importer; send invoiceIds once it is imported. Idempotent. Contributors can file receipts only.

- [`intake.read`](https://app.getoatmilk.com/docs/api/intake.read.md) — Read what an uploaded file says, by id, without filing or changing it: its words (text, at most 20,000 characters, with truncated true when cut short), its page count (pages), how many pages were read (readPages), whether the whole file was read (complete), and any warnings. Photos and PDFs are read with vision once and the reading is kept, so classifying the file later doesn't read it again; CSV, text, Word and email files are read directly. Spreadsheets come back without text. Payment and sign-in links are hidden, and a file holding sign-in or security details is refused. Contributors can read only their own uploads.

## jobs

- [`jobs.get`](https://app.getoatmilk.com/docs/api/jobs.get.md) — Get truthful asynchronous processing status by jobId.

## mail.activity

- [`mail.activity.get`](https://app.getoatmilk.com/docs/api/mail.activity.get.md) — Read the details of one entry in a visible email's activity, with id (the email) and eventId (the entry's id from mail.get activity): what Oatmilk's review concluded and how sure it was, a person's answer, how an entry was recorded and why, or which draft fields changed. Never returns the email's text.

## mail

- [`mail.approve`](https://app.getoatmilk.com/docs/api/mail.approve.md) — Approve a cleared financial draft for accounting with explicit treatment and evidence provenance.

- [`mail.askAdmin`](https://app.getoatmilk.com/docs/api/mail.askAdmin.md) — Ask the organization's other administrators by email to approve the new sender of a financial email, with id and idempotencyKey. Sends at most one request per member for each email and never approves the sender itself.

- [`mail.attachEvidence`](https://app.getoatmilk.com/docs/api/mail.attachEvidence.md) — Attach a cleared financial email to an existing bank purchase with current revisions and a reason. Keeps the original document kind and tax uncertainty; creates no expense and never reuses evidence for another purchase.

- [`mail.download`](https://app.getoatmilk.com/docs/api/mail.download.md) — Prepare an explicit short-lived download of authorized company mail evidence.

- [`mail.get`](https://app.getoatmilk.com/docs/api/mail.get.md) — Read visible company mail with immutable evidence metadata, unbooked financial drafts, the email's activity log, Oatmilk's latest review (with its one open question, if any) and how adding it to the books is going.

- [`mail.inboundAddresses`](https://app.getoatmilk.com/docs/api/mail.inboundAddresses.md) — List the organization's receiving email addresses. Contributors see only the accounting address.

- [`mail.list`](https://app.getoatmilk.com/docs/api/mail.list.md) — Search visible company mail with search: literal text in the subject, sender, body, attachment filenames and extracted document text. searchScope headers limits it to subject and sender. archived false (default) searches inbox mail, true archived mail, all both. Results include items and total; use limit and offset to continue, then mail.get for full details. Restricted messages require explicit security permission. Connected personal inbox receipt searches use evidence.inboxSearch.start/get instead.

- [`mail.purchaseCandidates`](https://app.getoatmilk.com/docs/api/mail.purchaseCandidates.md) — Find existing bank purchases to attach an authorized financial email as supporting evidence. Candidates remain separate; selecting a match requires human review.

- [`mail.rerun`](https://app.getoatmilk.com/docs/api/mail.rerun.md) — Process an email again from its saved original, with id, expectedRevision, idempotencyKey and from: everything (screen, classify, read the documents with vision, fraud check and second opinion; the default, also called reclassify), reading (keep the classifier's answer and read the documents again) or review (keep the reading and ask Oatmilk's second opinion again). Every later step runs again with the workspace's current memory, people, vendors and bank lines. An email already added to the books can't be processed again: use matching.rerunEntry for its entry. A person's corrected draft is kept. Returns jobId and generation; follow the steps with runs.get (subjectType mail, subjectId the email id), then read the result with mail.get.

- [`mail.rerunMany`](https://app.getoatmilk.com/docs/api/mail.rerunMany.md) — Process up to 50 emails again in one request, with items [{id, expectedRevision}], from (everything, reading or review, as in mail.rerun) and idempotencyKey. Each email gets its own job; returns queued [{id, jobId, generation}] and failed [{id, code, message}] so one stale or already-added email doesn't stop the rest.

- [`mail.retry`](https://app.getoatmilk.com/docs/api/mail.retry.md) — Queue company mail rescreening while preserving original evidence and human draft corrections. mail.rerun does the same and can start from a later step.

- [`mail.update`](https://app.getoatmilk.com/docs/api/mail.update.md) — Mark company mail read, archived or spam with revision and idempotency checks.

## mail.drafts

- [`mail.drafts.create`](https://app.getoatmilk.com/docs/api/mail.drafts.create.md) — Create an unbooked human financial draft from eligible cleared mail after an explicit review reason.

- [`mail.drafts.update`](https://app.getoatmilk.com/docs/api/mail.drafts.update.md) — Save reviewed company financial facts with current message and draft revisions.

## mail.fraud

- [`mail.fraud.decide`](https://app.getoatmilk.com/docs/api/mail.fraud.decide.md) — Decide about an email's fraud warning with id, expectedRevision, decision (genuine or fraud) and idempotencyKey. genuine clears the warning so a person can add the email to the books; fraud archives it, turns automation off for it and keeps it out of the books. Both are written to the email's activity with who decided. Nothing is ever approved automatically.

- [`mail.fraud.rescan`](https://app.getoatmilk.com/docs/api/mail.fraud.rescan.md) — Check recent company mail for fraud again with the current rules: days (1 to 30, default 14) and limit (1 to 100, default 50), within a short time budget. Returns checked, flagged, raised, skipped and more. It adds or keeps warnings (an earlier reviewer clearing stands only for the same weak history signals), keeps every person's decision, and turns automation off for flagged mail.

## mail.review

- [`mail.review.answer`](https://app.getoatmilk.com/docs/api/mail.review.answer.md) — Answer the one question Oatmilk's review asked about an email, with id, reviewId, choiceId (a, b or c) and idempotencyKey. The choice's effect comes from the stored question: leave the draft, fix it, fix it and add it to the books through the same checks as mail.approve, or archive the email. Choices that change date, currency, total or tax only update the draft; a separate full draft review is required before booking.

- [`mail.review.memory`](https://app.getoatmilk.com/docs/api/mail.review.memory.md) — Save or dismiss the memory entry Oatmilk suggested while reviewing an email, with id, reviewId, decision (save or dismiss) and idempotencyKey. Nothing is added to the organization's memory unless an administrator saves it.

## mail.rules

- [`mail.rules.list`](https://app.getoatmilk.com/docs/api/mail.rules.list.md) — Read exact sponsored vendor sender rules. Administrator access required.

- [`mail.rules.save`](https://app.getoatmilk.com/docs/api/mail.rules.save.md) — Manage exact vendor sender authorization with an active finance sponsor and revision checks.

## mailboxes.connect

- [`mailboxes.connect.link`](https://app.getoatmilk.com/docs/api/mailboxes.connect.link.md) — Get the link where the signed-in member connects their own Gmail or Outlook inbox in Oatmilk, with optional provider and dailyChecks. Nothing is connected and no sign-in starts: connecting asks the inbox owner to agree in the provider's own window, so only they can do it. Give the person the url; connected inboxes then appear in mailboxes.list.

- [`mailboxes.connect.start`](https://app.getoatmilk.com/docs/api/mailboxes.connect.start.md) — Start connecting the signed-in member's own Gmail or Outlook inbox with read-only access. Returns the provider's consent URL; the member finishes in the browser. dailyChecks (default on for Connected inboxes, explicitly off for onboarding and Find in my inbox) decides whether Oatmilk checks the new inbox every day, starting 90 days back; without it the inbox is read only when the member asks, from today. Reconnecting an inbox keeps it paused if it was, and only turns daily checks on, never off. Optional returnTo (a workspace page or /onboarding) brings them back there, popup reports back to the page that opened the window and closes it, and inboxSearchId starts that member's waiting inbox search as soon as the inbox connects. mode temporary (with inboxSearchId, never dailyChecks) asks for read-only access for that one search instead: no offline access, the token is held sealed for at most an hour, bound to that search and member, never checked daily or by anything else, never listed as a connected inbox, and revoked (where the provider allows) and wiped when the search finishes, is stopped or expires. These choices stay on the server behind a single-use nonce, and the exchange uses PKCE. Dashboard only.

## mailboxes

- [`mailboxes.disconnect`](https://app.getoatmilk.com/docs/api/mailboxes.disconnect.md) — Disconnect a connected inbox and delete its stored access at once, with id, expectedRevision and idempotencyKey. Emails already imported stay in company mail. Only the member who connected it or an administrator can disconnect it.

- [`mailboxes.list`](https://app.getoatmilk.com/docs/api/mailboxes.list.md) — List connected Gmail and Outlook inboxes: provider, address, who connected it, whether it is paused (scan_enabled false), checked daily (daily_checks) and offered for other members' receipts (search_for_others), the last scan, how many financial emails were imported, the latest check (a run with its status and summary), whether it is still catching up on older mail, whether scheduled checks are on, and which providers this deployment supports. Contributors see only their own. Tokens are never returned.

- [`mailboxes.scan`](https://app.getoatmilk.com/docs/api/mailboxes.scan.md) — Check your own connected inbox for receipts and invoices now instead of waiting for the daily check; nobody can check another member's inbox, a paused one must be resumed first, and integrations need the mailboxes:search scope. Only financial emails are imported. Returns right away with the check's runId (status started, or busy with the running check's runId when one is already reading the inbox); follow it with runs.get for its steps and counts.

- [`mailboxes.update`](https://app.getoatmilk.com/docs/api/mailboxes.update.md) — Change a connected inbox with id, expectedRevision and idempotencyKey: scanEnabled pauses (false) or resumes (true) all reading, dailyChecks turns daily checks on (reading back 90 days) or off, searchForOthers lets Autopilot search it for other members' receipts, and scanFrom changes how far back it reads. Only the member who connected it can resume it or widen what is read, and only from the dashboard; an administrator can pause it or turn those off, and integrations can only narrow.

## submissions

- [`submissions.get`](https://app.getoatmilk.com/docs/api/submissions.get.md) — Get a submission by submissionId, including its evidence, jobs, and resulting entry references even when extraction failed.

- [`submissions.release`](https://app.getoatmilk.com/docs/api/submissions.release.md) — Release quarantined accounting intake after administrator review. Restricted mail also requires security consent.

- [`submissions.retry`](https://app.getoatmilk.com/docs/api/submissions.retry.md) — Retry preserved receipt processing using submissionId, revision and idempotencyKey.

- [`submissions.tripSuggestions`](https://app.getoatmilk.com/docs/api/submissions.tripSuggestions.md) — Suggest visible trips for one receipt using submissionId and sourceFactIndex. Compares the receipt date and printed location even when currency is unknown; returns confidence and a reason without linking anything.

## uploads

- [`uploads.confirm`](https://app.getoatmilk.com/docs/api/uploads.confirm.md) — Confirm uploaded evidence using submissionId and idempotencyKey. Returns a durable processing job ID; completion must be checked separately.

- [`uploads.inline`](https://app.getoatmilk.com/docs/api/uploads.inline.md) — Add a receipt, invoice or original email in one call, for clients that can't upload to a link: filename, mimeType, contentBase64 (the file's bytes in base64, at most 2 MB), idempotencyKey, and optional receiptFor (the purchase it belongs to, as in uploads.prepare) and paymentAccountId. Oatmilk checks the bytes, stores them privately and starts processing; it returns submissionId and jobId. Retrying with the same key and file is safe. Larger files use uploads.prepare and uploads.confirm.

- [`uploads.prepare`](https://app.getoatmilk.com/docs/api/uploads.prepare.md) — Prepare a private receipt or original email upload. Supply filename, mimeType, sizeBytes, sha256, idempotencyKey. If alreadyUploaded is true, the immutable original was verified: skip PUT and still confirm the returned submissionId. Otherwise upload unchanged bytes to uploadUrl, then confirm. Reuse the same idempotency key and payload on retry; changed payloads conflict. Authenticated identity is retained regardless of email headers. To add the receipt for one purchase, pass receiptFor with that entry id: it must still need a receipt or invoice (contributors: a purchase on their own card), the upload goes on its account, and matching compares the receipt with that purchase only.
