API reference
Every route mounts under /api/v1/ on your own instance — http://localhost:8000/api/v1/ by default — and returns errors in one unified shape. The schema below is generated from the live OpenAPI spec and drift-checked in CI; the running app serves its own copy at /openapi.json, plus Swagger UI at /docs.
Authentication is an RFC-6750 bearer token. The dashboard itself doesn’t need one; anything else — an agent, a script, another device — does:
curl -H "Authorization: Bearer $FINANCE_API_TOKEN" \ "http://localhost:8000/api/v1/summary?month=2026-03" | jq .Issuing, scoping, and revoking tokens is covered in Agent access. To try the API before installing anything, the demo journal is served read-only at https://gettidings.com/demo/api/v1 (no auth), with its schema at https://gettidings.com/demo/api/openapi.json.
Endpoints at a glance (118 routes)
config
-
GET /api/v1/config— Get runtime app configuration (storage, demo mode, user_id, features) -
PUT /api/v1/config— Update runtime app configuration -
POST /api/v1/config/test-openai— Validate an OpenAI API key and persist it to data/.env on success -
POST /api/v1/config/test-s3-backup— Verify an S3 bucket is a usable attachment-backup target
ingestion
-
POST /api/v1/transactions— Add a transaction manually (bypasses email pipeline) -
POST /api/v1/transactions/upload-eml— Upload a raw .eml file and parse via the email pipeline
transactions
-
GET /api/v1/transactions— List active (non-deleted) transactions for a month -
GET /api/v1/transactions/all— Combined active + attention + trash buckets for a month -
GET /api/v1/transactions/attention— Transactions needing review (uncategorized, not ignored, not deleted) -
GET /api/v1/transactions/bulk— Combined transactions across multiple months (max 12) -
PATCH /api/v1/transactions/bulk— Update categories on many transactions in a single request -
GET /api/v1/transactions/latest— Freshness probe — max DateFileName, optionally scoped to a month -
GET /api/v1/transactions/trash— Soft-deleted transactions for a month -
DELETE /api/v1/transactions/{tx_id}— Hard-delete a transaction (irreversible) -
PATCH /api/v1/transactions/{tx_id}— Partial update — category, state (active/ignored/trashed), and/or reviewed -
PUT /api/v1/transactions/{tx_id}/comment— Set or update the user comment on a transaction -
POST /api/v1/transactions/{tx_id}/delete— Toggle the soft-delete flag (move to trash / restore) -
GET /api/v1/transactions/{tx_id}/detail— Full transaction record including email body and headers -
PUT /api/v1/transactions/{tx_id}/fields— Update editable transaction fields (company, amount, transaction_type) -
POST /api/v1/transactions/{tx_id}/ignore— Toggle the ignored flag on a transaction -
POST /api/v1/transactions/{tx_id}/review— Mark a transaction's category as manually reviewed
categories
-
GET /api/v1/categories— List predefined categories
summary
-
GET /api/v1/summary— Monthly spending summary with previous-month comparison -
GET /api/v1/summary/trend— Multi-month spending trend (2-12 months)
budget
-
GET /api/v1/budget/config— Get budget targets and groups for a year -
PUT /api/v1/budget/config— Replace budget targets and groups for a year -
GET /api/v1/budget/historical-averages— Per-category historical monthly averages over the last N months -
GET /api/v1/budget/status— YTD budget pace status with per-category and per-group breakdown
insights
-
GET /api/v1/insights/context— Raw context dict the AI briefing uses (for inspection / external automation) -
POST /api/v1/insights/generate— Kick off background AI generation of a monthly spending briefing -
GET /api/v1/insights/saved— List saved insight briefings for a month -
GET /api/v1/insights/saved/{insight_id}— Get the markdown content of a saved insight briefing -
GET /api/v1/insights/status— Background generation status (idle/running/error)
overrides
-
GET /api/v1/overrides— List all category override rules -
POST /api/v1/overrides/consolidate— Atomically replace member overrides with a single canonical override -
GET /api/v1/overrides/duplicates— List override groups sharing a normalized merchant key -
GET /api/v1/overrides/match— Preview the tiered category resolver against current overrides + aliases -
GET /api/v1/overrides/suggestions— Suggest new override rules from manual category corrections -
POST /api/v1/overrides/suggestions/dismissed— Dismiss an override suggestion (it stops surfacing until a newer correction) -
DELETE /api/v1/overrides/suggestions/dismissed/{key}— Reverse a previous dismissal (suggestion may resurface) -
PUT /api/v1/overrides/{company}— Pin a company → category override -
DELETE /api/v1/overrides/{company}— Remove a company → category override
ignore-rules
-
GET /api/v1/ignore-rules— List all merchant auto-ignore rules -
POST /api/v1/ignore-rules— Add a merchant auto-ignore rule -
POST /api/v1/ignore-rules/apply— Backfill Ignored on existing transactions matching a rule (or all rules) -
GET /api/v1/ignore-rules/suggestions— Suggest ignore rules from merchants you habitually ignore by hand -
GET /api/v1/ignore-rules/suggestions/dismissed— List dismissed ignore-rule suggestions, newest first -
POST /api/v1/ignore-rules/suggestions/dismissed— Dismiss a suggested merchant so it stops being surfaced -
DELETE /api/v1/ignore-rules/suggestions/dismissed/{merchant}— Reverse a suggestion dismissal so the merchant may resurface -
DELETE /api/v1/ignore-rules/{pattern}— Remove a merchant auto-ignore rule
category-management
-
POST /api/v1/categories— Add a category, optionally placing it in a budget group -
GET /api/v1/categories/icons— Map of user-set category icon overrides -
PUT /api/v1/categories/icons— Set or update a category's icon override -
DELETE /api/v1/categories/icons— Remove a category's icon override (revert to default) -
GET /api/v1/categories/managed— List categories with their group memberships and version -
DELETE /api/v1/categories/{name}— Delete a category, optionally reassigning its transactions -
PUT /api/v1/categories/{name}/group— Move a category to a different budget group, or remove from all groups -
GET /api/v1/categories/{name}/usage— Counts of transactions, overrides, and budget membership for a category -
PUT /api/v1/categories/{old_name}— Rename a category and cascade across overrides, budget, transactions
groups
-
GET /api/v1/groups— Get budget category groups for a year -
PUT /api/v1/groups— Replace budget category groups for a year
search
-
GET /api/v1/transactions/export— Stream filtered transactions as CSV -
GET /api/v1/transactions/search— Cross-month transaction search with filters -
POST /api/v1/transactions/search-by-filter— Cross-month transaction search with array-shaped filters (POST body)
statements
-
POST /api/v1/statements/import— Execute import/enrich/update actions for statement transactions -
POST /api/v1/statements/upload— Upload a PDF statement, parse, and reconcile against transactions -
POST /api/v1/statements/{statement_id}/reparse— Re-parse a statement PDF, preserving prior user edits
statements-crud
-
GET /api/v1/statements— List all uploaded statements -
GET /api/v1/statements/{statement_id}— Get a statement with all its parsed transactions -
DELETE /api/v1/statements/{statement_id}— Delete a statement and its parsed transactions -
GET /api/v1/statements/{statement_id}/download— Download the original PDF for a statement -
PATCH /api/v1/statements/{statement_id}/transactions— Bulk-update statement transaction actions -
PATCH /api/v1/statements/{statement_id}/transactions/{row_id}— Update a single statement transaction's action (auto-save), keyed by row_id
attachments
-
GET /api/v1/attachments— List attachments, optionally filtered by link status and kind -
POST /api/v1/attachments— Upload a receipt or document, optionally linked to a transaction -
DELETE /api/v1/attachments/{attachment_id}— Delete an attachment and its file from disk -
GET /api/v1/attachments/{attachment_id}/candidates— Rank the transactions a parsed receipt might explain -
GET /api/v1/attachments/{attachment_id}/file— Download the attachment file, served inline with our stored content-type -
POST /api/v1/attachments/{attachment_id}/link— Link an attachment to a transaction, or unlink it -
POST /api/v1/attachments/{attachment_id}/parse— Parse a receipt attachment with the configured AI provider -
GET /api/v1/transactions/{tx_id}/attachments— List attachments linked to a transaction
income-statement
-
GET /api/v1/income-statement— Annual income vs. expenses view with projection and savings rate
tax
-
GET /api/v1/tax-pack— Calendar-year tax pack: claim-line totals with per-transaction evidence -
GET /api/v1/tax-pack/export— Download the year's tax pack as a zip of CSVs plus evidence files -
POST /api/v1/tax-pack/items— Force a transaction into a claim line, or exclude it from one -
DELETE /api/v1/tax-pack/items/{tx_id}— Clear a per-transaction tax override -
GET /api/v1/tax-pack/lines— Selectable claim lines for the include-override picker
merchants
-
GET /api/v1/merchants/intelligence— Recurring-charge detection, price-change alerts, committed burn rate
journal
-
GET /api/v1/journal— Day-grouped transaction timeline for a month
daily-summaries
-
GET /api/v1/journal/summaries— List saved AI day summaries for a month -
POST /api/v1/journal/summaries/generate— Kick off background AI generation of day summaries for a month -
GET /api/v1/journal/summaries/status— Background generation status (idle/running/error)
merchant-aliases
-
GET /api/v1/merchant-aliases— List all merchant aliases (raw → canonical mappings) -
PUT /api/v1/merchant-aliases/{raw_name}— Create or update a merchant alias (raw → canonical) -
DELETE /api/v1/merchant-aliases/{raw_name}— Delete a merchant alias by raw name
data
-
POST /api/v1/data/export— Stream a full-data backup zip (transactions + config) -
POST /api/v1/data/import/commit— Apply a previously-previewed import using the chosen strategy -
POST /api/v1/data/import/preview— Stage a backup upload and return a dry-run dedup summary -
GET /api/v1/data/s3-backup-status— Read the S3 attachment-backup config and last-run state
parse-failures
-
GET /api/v1/parse-failures— List quarantined parse failures (summaries only, no email body) -
POST /api/v1/parse-failures/retry-all— Re-run the deterministic parsers across a whole institution's quarantined backlog -
GET /api/v1/parse-failures/{failure_id}— Get a single quarantined parse failure, including the email body -
DELETE /api/v1/parse-failures/{failure_id}— Dismiss a quarantined parse failure -
POST /api/v1/parse-failures/{failure_id}/resolve— Record a hand-entered transaction for a quarantined email and mark it resolved -
POST /api/v1/parse-failures/{failure_id}/retry— Re-run the deterministic parsers against a quarantined email -
POST /api/v1/parse-failures/{failure_id}/to-fixture— Write a scrubbed test-fixture pair from a quarantined email (dev checkout only)
auth
-
POST /api/v1/auth/chatgpt/disconnect— Disconnect a previously-linked ChatGPT account -
POST /api/v1/auth/chatgpt/start— Begin the ChatGPT device-code sign-in via the Codex CLI -
GET /api/v1/auth/chatgpt/status— Poll the ChatGPT sign-in state
webapp-auth
-
POST /api/v1/auth/login— Issue a webapp session cookie -
POST /api/v1/auth/logout— Clear the caller's webapp session cookie -
POST /api/v1/auth/set-password— Set or change the webapp password (TOFU on first set) -
POST /api/v1/auth/sign-out-all— Bump session_version, invalidating all existing cookies
health
-
GET /api/v1/health— Liveness probe with last-activity snapshot
coverage
-
GET /api/v1/coverage— Per-institution bank-alert cadence and passive email-capture rate
activity
-
GET /api/v1/activity— List agent activity ledger entries, newest first -
POST /api/v1/activity/{entry_id}/revert— Revert a single ledger entry, restoring the resource's prior state -
GET /api/v1/whoami— Resolve the current caller's identity (token, session, TOFU, or dev-bypass)