API Reference (v0.37)
The frontend calls a same-origin JSON API under /api. Mutating requests
use the x-csrf-token header unless explicitly exempted. The CSRF token
is fetched once from GET /api/auth/csrf-token on startup and stored in
a module-level memory cache.
This page documents the new endpoints added in v0.35-v0.37 and gives
worked curl examples for the high-impact ones. For the full route
inventory (user, data, admin, middleware), see
API Reference.
Where do public endpoints live?
| Prefix |
Purpose |
/api/auth |
Login, mode discovery, session state, and authenticated auth actions |
/api/auth/oidc |
OIDC login and callback |
/api/about |
Public app metadata |
/api/privacy |
Public privacy content |
/api/version |
Version and release history |
/api/calendar/feed.ics?token=... |
Personal calendar subscription feed (no session) |
Where do user endpoints live?
| Prefix |
Purpose |
/api/tracker |
Monthly tracker rows, sparklines, cashflow, and upcoming bills |
/api/bills |
Bills, templates, history ranges, balances, autopay verify, catalog link, and bill transaction views |
/api/payments |
Payments, quick pay, bulk pay, restore, autopay suggestions, undo-auto, and recent-auto |
/api/categories |
Category CRUD and restore |
/api/calendar |
Calendar data, feed CRUD, and feed preview |
/api/summary |
Summary and income planning |
/api/monthly-starting-amounts |
Starting-cash planning |
/api/analytics |
Analytics summaries |
/api/snowball |
Debt settings, ordering, and projections |
/api/spending |
Spending categories, budgets, copy-last-month |
/api/settings |
Per-user settings (including search_bars_collapsed) |
/api/profile |
Profile, password, display name, 2FA, WebAuthn, export history, and import history |
/api/user |
Demo-data seed and cleanup |
/api/transactions |
Manual transactions, matching, ignore state, updates, and bulk unmatch |
Where do data endpoints live?
| Prefix |
Purpose |
/api/data-sources |
SimpleFIN connect, account controls, sync, backfill, and disconnect |
/api/matches |
Match suggestions, rejection, confirm, and unmatch |
/api/subscriptions |
Catalog, user descriptors, recommendations, and feedback |
/api/import, /api/imports |
CSV, XLSX, and user-database staged import |
/api/export |
User-owned SQLite and Excel exports |
Where do admin endpoints live?
| Prefix |
Purpose |
/api/admin |
Users, backups, cleanup, auth methods, bank-sync settings, security settings, and migration rollback |
/api/profile/settings |
User notification settings and per-user login geolocation preference |
/api/status |
Admin-only system status |
/api/about-admin |
Admin-only roadmap, development log, and forced update check |
/api/notifications |
Admin SMTP settings and user reminder preferences |
How is the middleware stack applied?
Most user routes apply CSRF validation, requireAuth, and requireUser.
Admin routes apply CSRF validation, requireAuth, requireAdmin, and an
admin action rate limit. The Data → Bank Sync routes additionally apply
the syncLimiter (10 requests per 15 minutes per user). See
Security for the full list.
What new endpoints were added in v0.35-v0.37?
Bills
| Method |
Path |
Notes |
POST |
/api/bills/:id/verify-autopay |
Mark autopay as manually verified; updates bills.autopay_verified_at |
PATCH |
/api/bills/:id/catalog-link |
Set or clear bills.catalog_id; used by the Service Catalog Re-link dialog |
Payments
| Method |
Path |
Notes |
GET |
/api/payments/recent-auto |
Last 7 days of provider_sync auto-matches for the Auto-matched review panel |
POST |
/api/payments/:id/undo-auto |
Reverse a provider_sync auto-match; restores bill balance and reverts the transaction |
PATCH |
/api/payments/:id/attribute-to-month |
Reattribute a provider_sync payment to a different month without changing amount or bank link |
Transactions
| Method |
Path |
Notes |
POST |
/api/transactions/unmatch-bulk |
Bulk-unmatch linked transactions; handles mixed provider_sync and transaction_match in a single DB transaction |
Calendar Feed
| Method |
Path |
Notes |
GET |
/api/calendar/feed |
Current per-user feed token and URL (or null if none) |
POST |
/api/calendar/feed |
Create the feed token if one does not exist |
POST |
/api/calendar/feed/regenerate |
Revoke the existing token and issue a new URL |
DELETE |
/api/calendar/feed |
Revoke the active feed URL |
GET |
/api/calendar/feed/preview |
Next 10 events the feed will emit |
GET |
/api/calendar/feed.ics?token=... |
Public ICS feed; no session, bearer-style URL |
Service Catalog
| Method |
Path |
Notes |
GET |
/api/subscriptions/catalog |
List catalog entries with merged user descriptors |
POST |
/api/subscriptions/catalog/:id/descriptors |
Add a custom bank descriptor for the current user |
DELETE |
/api/subscriptions/catalog/:id/descriptors/:descriptor |
Remove a custom bank descriptor |
POST |
/api/subscriptions/recommendations/:id/feedback |
Record accept / decline / link-existing / relink / unlink for the recommendation feedback table |
Profile and 2FA
| Method |
Path |
Notes |
GET |
/api/auth/webauthn/status |
Enabled flag + credential count |
GET |
/api/auth/webauthn/credentials |
List registered keys with name, AAGUID, backup flags, timestamps |
GET |
/api/auth/webauthn/setup |
Begin registration; returns options + challenge id |
POST |
/api/auth/webauthn/enable |
Complete registration; verifies attestation and stores credential |
DELETE |
/api/auth/webauthn/credentials/:credentialId |
Remove one key; auto-disables WebAuthn when last key is removed |
POST |
/api/auth/webauthn/disable |
Remove all keys; requires password confirmation |
POST |
/api/auth/webauthn/challenge |
Verify an assertion and create a session |
Profile Privacy
| Method |
Path |
Notes |
GET |
/api/profile/settings |
Get user notification settings and geolocation_enabled |
PATCH |
/api/profile/settings |
Update user notification settings and geolocation_enabled |
How do I call verify-autopay?
curl -X POST http://localhost:3030/api/bills/42/verify-autopay \
-H "Content-Type: application/json" \
-H "x-csrf-token: $TOKEN" \
-b cookies.txt
Response:
{ "ok": true, "autopay_verified_at": "2026-06-07T15:21:33.000Z" }
How do I bulk-unmatch a Netflix rule that caught the wrong rows?
curl -X POST http://localhost:3030/api/transactions/unmatch-bulk \
-H "Content-Type: application/json" \
-H "x-csrf-token: $TOKEN" \
-b cookies.txt \
-d '{
"bill_id": 42,
"transaction_ids": [105, 106, 107],
"remove_merchant_rule": false
}'
Response:
{ "ok": true, "unmatched_count": 3, "balance_restored": 49.97 }
How do I create a calendar feed token?
curl -X POST http://localhost:3030/api/calendar/feed \
-H "Content-Type: application/json" \
-H "x-csrf-token: $TOKEN" \
-b cookies.txt \
-d '{ "label": "iPhone" }'
Response:
{
"ok": true,
"url": "https://bills.example.com/api/calendar/feed.ics?token=...",
"label": "iPhone",
"created_at": "2026-06-07T15:21:33.000Z"
}
Token returned once
BillTracker returns the feed URL only at creation time. Store it
immediately — there is no way to recover the raw URL from the API
later (the token is stored hashed). Use regenerate to issue a new
URL if the original is lost.
See also
Next steps