Skip to main content
Glama
649,985 tools. Updated 2026-10-08 21:14

"Intuit" matching MCP tools:

  • Connect QuickBooks Online by generating an OAuth authorization URL for your Intuit app, or use the recorded fixture to complete the sandbox test environment.
    MIT
  • Retrieve a list of all connected accounting companies from QuickBooks Online or Xero. Use the returned company IDs for subsequent data imports.
    MIT
  • Search a company's Blind discussions by specific keyword to retrieve matching posts, returning an empty result when no threads match.
    MIT
  • Close an Intuit packet by sending a message and optional structured inputs to the domain-agent dispatcher, scoped to your JWT, tenant, and company.
    Apache 2.0
    Destructive
  • Run a health check on the Intuit domain agent by submitting a free-text objective or structured JSON input through the dispatcher, scoped to your JWT, tenant, and company.
    Apache 2.0
    Destructive
  • Reconcile Intuit payments by submitting a free-text objective to the domain-agent dispatcher, which processes it under your tenant and company scope to resolve discrepancies.
    Apache 2.0
    Destructive

Matching MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables full CRUD operations on 29 QuickBooks Online entity types and 11 financial reports via natural language, allowing users to manage customers, invoices, payments, and more through MCP-compatible clients.
    Apache 2.0
  • Execute a governed Intuit connector operation within a specific project and account context. Use it to run read or write actions while enforcing authority, idempotency, and approval controls.
    Apache 2.0
    Destructive
  • Captures a snapshot of the controller by processing a free-text objective and optional JSON inputs. Returns the controller state through the domain-agent dispatcher.
    Apache 2.0
    Destructive
  • Execute an Intuit writeback plan by providing a free-text objective and optional structured inputs. It routes through the domain-agent dispatcher under your JWT, tenant, and company scope.
    Apache 2.0
    Destructive
  • Run a controller review action within the Intuit domain. Trigger this to assess or audit controller logic and related components.
    Apache 2.0
    Destructive
  • Plans domain intelligence actions by sending a free-text objective and optional structured inputs through the domain-agent dispatcher, returning a plan scoped to your tenant and company.
    Apache 2.0
    Destructive
  • Generate a cash application plan by submitting an objective message and optional structured inputs, recommending how to allocate customer payments to open invoices.
    Apache 2.0
    Destructive
  • Manage the household's reference data, plans, documents, and bank connections — the CRUD side of cashflow. 16 entity families, each with its own action set; an unsupported (entity, action) pair is rejected with the list of what that entity does support. ENTITY MAP: category→global taxonomy, READ-ONLY (list, plus this household's own tags/notes on it) · category_group→its parent groups, list only · party→merchants · tag→transaction tags · account→rename, hide/unhide, tag, note · recurring_series→bills & subscriptions · rule→transaction rules (preview, then create with the returned token) · plan→the annual plan (propose a draft from actuals, then upsert) · adjustment→overlay entries that normalize reported actuals without touching transactions · transfer_link→match two legs of one transfer · document→Paper Trail: file, find, read_text, version, tie_out, substantiate, export · import→bank statements (OFX/QFX/QBO + Apple Card, Apple Savings, Rocket Money, Wells Fargo, Monarch CSVs) · bank_connection→list, sync or disconnect bank connections · feedback→file a bug/feature/ux note · position→private holdings (angel checks, fund commitments, advisor equity) · position_event→what moved one (commitment, call, distribution, fee, mark…) Reads live in the query tool; per-transaction classification lives in annotate. Use admin for the entities themselves. CATEGORIES ARE A FIXED SET, AND READ-ONLY: the category taxonomy is the same for every user and cannot be changed. { entity: "category" } supports list, add_tag, remove_tag, set_note, remove_note; { entity: "category_group" } supports list only. create, rename, merge and delete are all rejected on both. An unrecognized spending type belongs under the closest existing category — record the nuance with set_note or add_tag, which are user data about a category rather than a change to it. To move transactions BETWEEN categories use annotate { action: "categorize" } or a rule, not a merge. This also applies to annotate: { action: "categorize", category_name } only ever matches an existing category, it never makes one. Parties, tags, accounts, and rules are unaffected — those are still created, renamed, merged and deleted freely. Activate/deactivate rules and recurring series via action:"update" with active:true|false. When reporting back to the user, translate to plain English. LIST CONNECTIONS: { entity: "bank_connection", action: "list" } returns each connected bank with status (ok / syncing / needs_reconnect / warning, plus msg), last_sync and ago (when we last checked with the bank), last_new and new_ago (when the bank last sent new or changed transactions; absent if it never has), next_by (around when it is next checked on its own; absent while a connection error stands), and its accounts. A not_connected row (no id, last_activity instead of last_sync) is a bank whose accounts no connection feeds any more — its numbers stopped updating, and the fix is connecting that bank again, not a reconnect. Answers "is my bank connected?" and "when did it last get anything new?" in text; the accounts tool shows the same as a dashboard. SYNC: { entity: "bank_connection", action: "sync" } checks every active bank connection now (pass id for one). Rarely needed: new transactions arrive automatically when the bank posts them, and every connection is re-checked at least daily, so sync only when the user reports a specific missing transaction — never on a schedule or before every read. A sync cannot bring in anything the bank has not released yet. Returns added/modified/removed counts per connection with the same status/last_sync/last_new/next_by as list, and a note — a sync that found nothing says when the bank last sent something new. DISCONNECT: { entity: "bank_connection", action: "disconnect", id: "<plaid-item-id>" } revokes the bank connection at Plaid and removes it locally. Returns { ok: true, institution } on success. FEEDBACK: { entity: "feedback", action: "create", type: "bug"|"feature"|"ux", name: "title", description: "details", tool: "query"|"annotate"|"admin", context: "JSON" }. type and name (the title, max 200 chars) are both REQUIRED; description is capped at 2000. Fire-and-forget — no list/update/delete. Rate limited to 30/day. IMPORT: { entity: "import", action: "import", file_content: "<raw statement file>" } imports a bank export. The format is auto-detected from the content — OFX/QFX/QBO from any bank, plus Apple Card, Apple Savings, Rocket Money, Monarch and Wells Fargo checking CSVs; anything else is rejected with detected_format. (csv_content is the same field under its older name.) Pass dry_run: true first to preview without writing — it reports valid/invalid/duplicate rows and sample mapped rows. Re-importing overlapping data is de-duplicated. - Apple Card is SINGLE-account: by default transactions land in an "Apple Card" account created on first import; the response returns account_id. Pass account: "<id or name>" to target a specific manual account instead (connected/bank-synced accounts are rejected). The preview also reports how much will move from spending to transfers; importing the card moves your Apple Card payments (made from checking) from spending to transfers so they don't double-count against the card's purchases. - Apple Savings is SINGLE-account: by default transactions land in an "Apple Savings" account created on first import — the same account an Apple Savings OFX/QFX/QBO import uses, so importing both exports of a month doesn't double-count. Pass account: "<id or name>" to target another manual account. Interest is income, Daily Cash deposits are card rewards, and ACH moves to or from a linked bank are transfers; any other activity type imports uncategorized and is named in unmapped_activity_types. - Rocket Money is MULTI-account: a single file carries many accounts (each row names its account/institution/type/number), and accounts are matched or created automatically — the account override does NOT apply. Transfers and ignored rows are taken from the file. Accounts already connected via Plaid are SKIPPED (importing a CSV there would double-count synced data) and reported under skipped_connected_accounts / warnings. The response returns accounts[] (name/status/account_id), accounts_created, imported, and skipped_duplicates. - OFX/QFX/QBO are ONE format in three extensions and are the BEST export to use where a bank offers it: each transaction carries the issuer's own stable id, so re-importing the same file (or the .qfx after the .ofx) updates those rows instead of duplicating them, and a month imported from OFX reconciles with the same month imported from CSV — neither double-counts the other. Accounts resolve from the file's own institution, so account is optional for a single-statement file and rejected for a multi-statement one. Prefer .ofx over .qfx/.qbo: the Intuit variants cut merchant names off at 32 characters, and the import warns when it sees that. - Wells Fargo checking is SINGLE-account and the file omits account identity: pass account:"<id or exact name>". A Plaid-connected target also requires allow_connected:true; exact overlapping observations load into Silver and are linked/hidden, while statement-only history remains visible. STATUS=Pending is preserved. UPLOAD (avoid pasting big files): instead of inlining csv_content, stage the file out-of-band so its bytes never go through context. { entity: "import", action: "request_upload", filename: "<name>.ofx|.csv" } returns a one-time upload_url + a ready-to-run curl (PUT the file from your sandbox: curl -X PUT -T <path> <url>); the PUT responds with an upload_id. Then import by reference: { entity: "import", action: "import", upload_id: "<id>", dry_run: true } to preview, then without dry_run to commit. Provide exactly one of file_content and upload_id. The upload link is short-lived and self-authenticating (no token needed for the PUT). Prefer this for anything non-trivial — pasting a file inline truncates and burns context. PRIVATE BOOK: what the household owns that has not resolved yet — angel checks, fund commitments, advisor equity — as EVENT LOGS, so cost basis, unfunded and DPI are folds over dated events rather than typed numbers. Read it with query { private_book: true }. Field-level rules live on the position, positions, event, events and statement_check params. - Position: { entity:"position", action:"create", position: { name, issuer, holder, … } }, or positions:[…] (up to 100) for a batch. issuer, holder and vehicle are declared, never resolved to a party; one company held through two vehicles is two positions under one issuer. Declare segment rather than guessing it. strike/expiry belong to option / warrant / advisor_equity only; changing the instrument under a stored strike is refused unless both are cleared with null in the same call. update by id (null clears a field) answers with the row's identity plus only the fields THAT CALL set, read back as stored — everything untouched is one get away. get (position + events + folded figures), list (include_resolved:true for exited ones), delete (removes its events). - Terms: record each term WITH its provenance — basis document (+ document_id and page), assumed, or missing — in the source's own wording, never parsed. Then query { private_book, terms_basis:["assumed","missing"] } IS the what-only-you-can-answer list; do not keep that in a note. A term you looked for and could not find is basis "missing", not a remove_terms. - Event: { entity:"position_event", action:"create", event: { position_id, kind, amount, effective_date, … } }. amount >= 0. A CAPITAL CALL has three states: the commitment; the NOTICE (kind contribution, status:"pending", effective_date = due date — it shows in the forecast and as past_due, not in paid-in); the WIRE (status settled, supersedes_id = the notice, transaction_id = the bank row), which marks the notice superseded. A MARK is an opinion: mark_source is required and it is never summed — record every statement's NAV as its own mark so a stale one can be seen. Two marks on one as-of date: the one recorded in the LATER CALL wins, so record competing same-day opinions in separate calls, not one batch. A resolved position's last mark is its final word and never goes stale. Every event row carries recorded (when it was entered). - Statement batch: { events:[…], position_id?, statement_check } — refused with identity_mismatch when the statement's own arithmetic does not tie, and with book_mismatch when its contributions or distributions disagree with the book. Fees are never compared (the book's fee kind is out-of-pocket only). The response echoes { scope, scope_source: "declared"|"inferred", book: "ok"|"not_compared" }. statement_check is a gate, not a record — only the events and their verbatim lines are stored. - transaction_id / document_id must be this household's own rows; a foreign id is refused by name. Currency is per position and totals never cross currencies. DISCOVERY: { entity: "category"|"party"|"tag"|..., action: "list" } returns reference data for the user. All entity types support list. PARTY LIST: Supports search, limit (default 50), and cursor for pagination. Response includes cursor/has_more when more results exist — pass cursor to fetch the next page. The same paging applies to every list in party, rule, tag, recurring_series, position, position_event, adjustment, document (position returns n for the page and matched for the total); category, category_group, account, plan, bank_connection always return the full set. RECURRING LIST: next agrees with query { recurring:true }: for active, recently seen bills, it is the next date on or after today; expected carries the original date when next rolls forward. Cancelled bills keep their last expected date. Active bills that stopped charging keep that date too, flagged stale:true; never-seen bills are also stale. PARTY DUPLICATE REVIEW: query { detail:true, tag:"dup-candidate" } surfaces sample transactions from party-name clusters the diagnostic clusterer (query { clusters:true }) flagged as likely one merchant split across spelling variants. - Resolve via merge: { entity:"party", action:"merge_cluster", merge_into_id:"<target-id>", member_ids:["<id>", ...] } folds every member into the target in one atomic call — re-points enrichments + plan references, clears the dup-candidate tag on affected transactions, deletes the member party rows. { action:"merge", id, merge_into_id } is the single-pair form (same underlying merge). Both responses include suggest_rule when the merged names share a literal prefix: { description_pattern, party_name, reason } — pass description_pattern straight into the RULE WORKFLOW's preview step when it's present. A plain merge only fixes what already exists; a rule also prevents the same merchant from re-fragmenting on the next import, so treat suggest_rule as a prompt to consider creating one, especially for an established/recurring merchant (a one-off historical cluster not worth a permanent rule is fine as a bare merge). - Dismiss a false positive: { entity: "annotate" (tool), action:"untag", tag_name:"dup-candidate" } on the flagged transaction — writes a suppression tombstone so the same cluster isn't re-flagged. RULE LIST: Supports search (matches name, description_pattern, or party_pattern), limit (default 50), and cursor for pagination. Response includes cursor/has_more when more results exist. Each rule reports wins (how many transactions it decides now). include_matches:true adds matches (how many transactions its conditions match now — the number rule preview's total gives, counting ignored rows and rows hidden as duplicates too) and last_match (the newest one's date); both are counted fresh from the transactions as they are, including each one's current merchant, so re-applying never changes them and a rule that renames the merchant it keys on can win rows it no longer matches. include_matches reads every transaction: pair it with search or a small limit. RULE WORKFLOW: preview → create/update (with token). A create OR update WITHOUT a token writes nothing and is REJECTED — never silently previewed (so an "add set_party" edit can't quietly no-op). Create auto-applies the rule. - Preview (action:"preview", or preview:true on create/update) returns: { preview:true, total, matched, token, txns: [...], conflicts?: [{ id, name, wins, loses }] }. Each txn may have conflict (rule name) and conflict_outcome ("wins"|"loses"). Specificity-based: longer pattern wins. txn.raw is the bank's original text (what a rule's description_pattern matches); name_in is the source's own shorter description, which description_pattern also tests (absent when it is the same as raw). ign:true marks a transaction hidden from reports (ignored) — it still counts in total, and the rule will still apply to it. - Create requires: token from preview + at least one condition + at least one action. name is optional — left off, it defaults to what the rule matches and does ("eBay → Other Income"). Actions: set_category_name, set_party_name, set_is_transfer, set_is_ignored, set_is_flagged, set_tag_name, remove_tag_name (strips a system auto/rule tag from matches; not a user's manual tag; mutually exclusive with set_tag_name). Returns { created, applied }. The token binds the previewed conditions AND actions — change either and the write is rejected, so preview with the same actions you intend to apply. - PATTERN CHOICE: description_pattern (if_desc) matches the cleaned description AND falls back to the raw bank memo — raw-anchored, survives Plaid merchant churn. party_pattern (if_party) matches ONLY the derived party name, which Plaid can rename on a resync, silently breaking the rule (#1211). For consolidation/renaming, prefer if_desc; a create/update targeting an entity-backed party returns a warning. query { health:true } → stale_party_rules flags a party rule whose merchant kept showing up after the rule's last win without the rule matching it (missed + missed_example show those charges), or that matches no transactions. A merchant that simply went quiet is not flagged. - BEFORE creating, search existing rules (action:"list", search:"<merchant>") for the same pattern. If one exists, UPDATE it (action:"update", id) instead of creating a parallel rule — duplicate/overlapping rules pile up and the older one silently wins. A create with conditions identical to an existing active rule is refused unless confirm_duplicate:true; a create for a merchant that already has a rule still succeeds but returns a warning. - AUDIT: { entity:"rule", action:"list", audit:true } returns groups (same-merchant rules; exact:true = identical conditions, exact:false = differing) and shadowed rules (their conditions match transactions but they decide none — a more specific rule or a manual edit takes every one). Run it to find redundancy. - Update: { entity: "rule", action: "update", id: "<rule-id>", ...changes }. Same round-trip as create (preview:true, then re-send WITH the token); the token binds the merged conditions (existing + updates) AND the actions. active:true|false needs no token — one call that re-applies or clears the rule's effects. ACCOUNT VISIBILITY: { entity: "account", action: "hide", id: "<account-id>" } hides an account from queries and listings. "unhide" reverses it. List with include_hidden:true to see hidden accounts (flagged hidden:true). TAGS: { entity: "account"|"category", action: "add_tag"|"remove_tag", id, tag } manages tags on accounts and categories. Tag is lowercased and hyphen-joined (e.g. "Emergency Fund" → "emergency-fund"). Canon tags for accounts: operating, bills, emergency-fund, savings-goal, brokerage, retirement. Canon for categories: essential, discretionary. Custom tags are allowed; non-canon adds return is_canon_tag:false. List responses on account/category include tags: string[]. NOTES: { entity: "account"|"category", action: "set_note"|"remove_note", id, note } manages a free-form text note on each account or category. Single note per entity — set_note replaces any existing note (UPSERT). Empty/whitespace notes are rejected. List responses on account/category include note: string when present. Useful for context like "joint account, both partners contribute" or "Software category includes hosting + dev tools". PLAN: the household's annual financial plan — one declarative document per year (income items, tag-bound events, ONE everyday-base number, guardrails, exclusions). Amounts in dollars; category/group/party referenced by id; tags by name. Tags in the document (events, matches, guardrail scopes, exclusions) reference TRANSACTION tags; guardrail scopes and exclusions may instead use { category_tag: "..." } to target CATEGORY tags (the essential/discretionary canon) — { tag } and { category_tag } are different namespaces. Plans are keyed by year — name is rejected (year defaults to the current year). Upsert rejects a guardrail/exclusion scope naming the other namespace (a { tag } that is only a category tag, or vice versa); it warns (not errors) on other tags matching nothing and on events whose bindings overlap. - Propose (draft from actuals): { entity: "plan", action: "propose", year? } → { document, basis, notes } — a draft plan built from the household's own last-12-months actuals (everyday base from trailing expenses, income from recurring deposits, events from annual/semiannual bills, guardrails on the top groups at last year's levels). Read-only: nothing is written. Review + edit the returned document, then pass it to upsert. Year defaults to NEXT year. Use this instead of authoring a plan from a blank page. - Upsert: { entity: "plan", action: "upsert", document: {...} }. First upsert for a year writes the plan as written; upserting over an existing plan REQUIRES reason and records a dated revision (the original is never edited). The server computes the seasonal base shape from the prior year's history (falls back to flat with shape_note when history is thin). Get output is valid upsert input (one exception: a stored scope naming the other tag namespace is rejected until fixed in that revise): server-computed base fields (shape, shape_source, shape_note) are accepted and ignored on write — recomputed every upsert. - Get: { entity: "plan", action: "get", year? } → latest document. revision: 1|"original" for the plan as written; "diff" for original-vs-latest structural diff + reason trail. No plan for that year → { error, hint } pointing at propose. - List: { entity: "plan", action: "list" } → one row per year with revision count. - Resolve an exception: revise the plan (upsert with reason) so the inputs change and the breached exception evaporates on the next plan_status read. Open exception keys are listed in query { plan_status: true } exceptions[]. - Delete: { entity: "plan", action: "delete", year } — removes the whole plan year (all revisions); reports the revision count. Requires an explicit year (or id); for mistakes, not for revising. - Status reads live in the query tool: query { plan_status: true }. ADJUSTMENT: an overlay that normalizes reported actuals WITHOUT editing real transactions — actuals stay the immutable "as-booked" truth; adjustments fold in only when a report asks for the adjusted view. CRUD via { entity: "adjustment", action: "list"|"create"|"update"|"delete", adjustment: {...} } — the payload goes under the "adjustment" key (NOT "document", that's for plans). Amounts in DOLLARS; periods as YYYY | YYYY-MM | YYYY-MM-DD; free-text label is "note" (aliases: memo, rationale). TARGET A CATEGORY (category_id OR category_name; aliases category / group / group_name) — this is what makes a reclass/imputation show up in the category breakdown (top_cats) and in grouped by:category; without it only the headline total moves. Three types: - accrual (period-shift): { type: "accrual", direction, amount, source_period, target_period, category_name? } — moves a flow from source_period to target_period (e.g. a January bonus earned the prior year). Nets to zero across a range spanning both. - imputation: { type: "imputation", direction: "outflow", amount, target_period, category_name?, funding_account_id? } — books a real off-feed expense (in category_name, e.g. "Property Tax") plus an offsetting investment withdrawal. funding_account_id is OPTIONAL (validated if given; the withdrawal leg books regardless), so off-feed sources you don't track need no stand-in account. - reclass (alias "exclude"): { type: "reclass", direction, amount, target_period, category_name? } — excludes/removes a one-off from the series (e.g. an estimated-tax check distorting operating spend). Set category_name so it reconciles in the category breakdown. - Preview before writing: pass dry_run:true to create — returns the computed legs + net effect without inserting. - Soft-retire with update { id, adjustment: { status: "retired" } } to drop it from adjusted reports while keeping the audit trail; only status="applied" entries fold in. - See the result in the query tool: query { view: "adjusted" } (alias "actual" for as_booked) swaps the headline totals (and their prior-period comparisons) in summary, grouped (single by:["group"|"category"]), and time-series modes; query { reconcile: true } returns the as-booked↔adjusted bridge (summary + time-series). DOCUMENT (Paper Trail): the household's permanent document store — statements, receipts, invoices, forms, policies and contracts, filed against the transactions and accounts they explain. Params are FLAT (doc_type, title, issuer, ...), NOT nested under a "document" key — that key belongs to plans. - FILING IS TWO CALLS, and the bytes never go through context. { entity: "document", action: "request_upload", filename: "receipt.pdf" } returns upload_url + a ready-to-run curl (PUT the file from your sandbox); the PUT responds with an upload_id. Then { action: "create", upload_id, doc_type, title, issuer, period_start, period_end, tax_year, link_transaction_ids, link_account_ids }. There is no inline-content option: never paste a PDF into a tool call. - FILING MANY IS STILL TWO CALLS. { action: "request_upload", files: ["q1.pdf", "q2.pdf", ...] } mints a slot per file at once (up to 25); the response supplies uploads[] {filename, upload_url} and one curl_template (replace <LOCAL_PATH> and <UPLOAD_URL> per slot); PUT each to its own upload_url; then ONE { action: "create", documents: [{ upload_id, title, ... }, ...] }. Top-level document fields are DEFAULTS every entry inherits and may override — { issuer: "Scribble Ventures", tax_year: 2025, documents: [{ upload_id, title: "Q1 report" }, ...] } — except supersedes_id, which is never inherited. The batch answers with n + documents[] (each carrying its index), and one document still answers with document + download_url. Filing is PER DOCUMENT: a bad entry comes back in errors with its index and does not stop the rest, and re-sending is safe (filing the same bytes twice updates that document rather than duplicating it). Naming one upload_id twice in a batch is refused outright. Do NOT merge separate documents into one PDF to save calls — a statement and a report filed as one blob can no longer be superseded or linked apart. - LINKAGE IS THE PRODUCT, and it is EXPLICIT. You name the transactions and accounts a document is evidence for; nothing is inferred from the description, the party or the amount. A link to a transaction or account outside this household is refused, not skipped. - doc_type is DECLARED, not detected: statement | receipt | invoice | tax_form | policy | contract | disclosure | notice | other. There is no classifier — set it from what the user tells you, and say so rather than guessing confidently. - STATEMENT PERIODS ARE READ FOR YOU: filing a doc_type "statement" PDF without period_start/period_end parses the billing cycle out of the document (a closing date + days-in-cycle, a numeric two-date period such as Chase's opening/closing dates, Navy Federal's and Wells Fargo cards' statement period or Citi's billing period, an explicit range, or Wells-Fargo-style beginning/ending balance dates). The response echoes period_source:"extracted" and period_form — CONFIRM the dates with the user rather than assuming them. A period you pass is never overwritten — but if it disagrees with the cycle the document itself declares, the response carries period_extracted + period_note so you can re-file with the right dates (hand-typed periods are the main source of off-by-a-day cycles). A non-PDF or an unknown form just files without one, and tie_out reads the stored period back to decide which ledger rows a statement covers. - FIND: { action: "list", account?, start?, end?, doc_type?, tax_year?, issuer?, search?, link_transaction_ids?, include_superseded?, limit?, cursor? }. Returns n (this page), total (all matching documents), has_more and cursor when more remain; default 50, max 500. Continue with cursor and the same filters. "search" matches the METADATA a filer typed — title, issuer, filename, note — not the document body; to read what a document actually says, use read_text. Dates match by PERIOD OVERLAP (a March statement matches a search for 15 March); a document filed with no period_start is not date-searchable. { action: "get", id } adds a short-lived download_url. - READ WHAT IT SAYS: { action: "read_text", id } returns the document's text — the numbers inside a K-1, a statement's balances — without downloading anything. PDFs are read in reading order; a stored text file comes back verbatim. Optional from_page/to_page (1-based, inclusive; 40-page cap) and max_chars (default 50,000; the response says truncated:true when it bit — narrow the pages rather than raising it). Optional find:"term" returns ONLY the pages containing it (case-insensitive), with match_pages and the matching lines — the way to check one sentence in a 13-page FAQ without reading it all (match_n:0 when it is not there). A scan or a photo is refused BY NAME as no_text/not_text: those need OCR, which only the reconcile CLI can run. A window past the end refuses as out_of_range with the document's page count. - VERSIONS: pass supersedes_id on create for a correction or re-issue. The old edition is marked superseded (hidden from list unless include_superseded) and its links move to the new one. - TIE_OUT: { action: "tie_out", id } ties a filed statement's OWN transaction table out against the ledger, row by row, one report per linked account. The workflow: file the statement (linked to its account via link_account_ids), then tie_out by document id — matched counts the rows with ledger twins, unexplained lists statement rows with NO ledger twin (candidate ledger gaps — the thing worth investigating), ledger_only lists ledger rows the statement doesn't show, explained counts rows whose only twin the ledger deliberately hides (dedup losers). verdict is "clean" or "discrepancies". It compares rows, not balances. Read-only. A scanned statement with no text layer is refused by name (no_text) — the reconcile CLI is the OCR-capable door for those. - SUBSTANTIATE: { action: "substantiate", account?, start?, end? } asks which charges have a document filed as evidence — vouching, from the charge out to its support. Returns is_onto (every charge has at least one document), is_one_to_one (nothing carries more than one of the other), is_bijection (both, plus no unattached documents), plus without_document — the charges nothing explains. - EXPORT: { action: "export" } returns a page of the archive MANIFEST — filed documents with their links, hash and byte size, plus n (this page), total (all matches), has_more and cursor when more remain. Default 50, max 500; continue with cursor and the same filters. Always available, and it takes the same filters as list (doc_type, tax_year, issuer, search, account, start/end, link_transaction_ids, include_superseded, limit, cursor). Bytes are not included and download_urls are NOT emitted by default: pass with_urls:true if you need them, knowing each one is a live bearer token and the whole payload lands in the transcript. For one document use { action: "get", id }; for a real offline archive run the export-documents CLI. - RECONSTRUCT: { action: "reconstruct", id } turns a filed statement's own transaction table into ledger rows — the tool for a period no feed covers (a dead bank connection, history older than Plaid reaches). DRY-RUN BY DEFAULT: it reports what it would insert and writes nothing until dry_run:false. It refuses when the statement's cycle already holds visible rows for that account, because a statement's descriptors do not reliably dedup against an aggregator's — "force" overrides that and WILL insert duplicates by design, so the response carries a batch_id for "undo-import --batch-id" to roll back. Every section must pass the statement's own printed arithmetic before anything is written. Use "section" to pick one account out of a combined statement when the ledger account has no mask. - DELETE: { action: "delete", id } is real — the row, its links and the stored bytes all go. - RELATED: query { tax_documents: true } PREDICTS which tax forms a household should expect from its income signals, and now attaches what is on file — each expected row carries filed when a document filed for that tax year NAMES that form, plus also_filed for the ones no prediction claimed. So the query mode answers BOTH "what am I still waiting for" and "what do I have" for tax forms; use this entity to file, version, download, tie out or substantiate any document, tax form or not. Filing with an accurate title and tax_year is what lets the prediction find it. TRANSFER_LINK: the matched-pair overlay for internal transfers. The matcher auto-pairs the two legs of a move between your own accounts (outflow from one, inflow to another) so they cancel in the Transfers line; this surface reviews and corrects those pairs. { entity: "transfer_link", action: "list", link_status?: "suggested"|"confirmed"|"rejected" } lists links (from/to account, amt, dt, status). { action: "confirm", transfer_link_id } promotes an ambiguous "suggested" pair to confirmed and flags both legs as a transfer. { action: "reject", transfer_link_id } marks a false pair rejected and undoes any flagging — rejects are STICKY (the matcher never re-suggests them). { action: "link", outflow_txn_id, inflow_txn_id } manually pairs two transactions the matcher missed (must be opposite directions, different accounts, equal amounts).
    Connector
    Destructive
    API key