API reference
Routes exposed by the local server. Everything is served from
http://127.0.0.1:3000 by default.
Two prefixes are fenced/api/* and /__ai* return
a JSON 404 rather than falling through to the SPA, so a typo surfaces as an error instead
of an HTML page. /__ai* has no handler at all — it is reserved.
Application routes #
/api/health
none
Local server and Supabase health. Cached for 15 seconds.
/api/version
none
Version, git SHA, commit message, and pwa_cache — the live
service-worker cache name, useful for confirming a client is not stale.
/api/ai-config
none
Returns {gemini, groq} booleans indicating which AI keys are
configured. No key material is exposed.
/api/check-update
none
Compares the local build stamp against GitHub. Falls back to SHA comparison.
/api/update-status
none to call
Reports whether an update is safe to run:
{
"ok": true,
"authorized": true,
"admin_available": false,
"dirty": true,
"dirty_count": 2,
"dirty_files": ["server.mjs", "public/sw.js"],
"branch": "main"
}
/api/update-now
admin cookie or loopback
Runs isotope update detached. Authorised by an admin cookie
or a loopback connection — 127.0.0.1/::1 with no
x-forwarded-* header. LAN and remote callers get 403.
| Status | Meaning |
|---|---|
202 | Update started; the client should poll /api/version. |
403 | Not authorised. Body includes admin_available so the UI only offers unlock when unlock can work. |
409 | confirmation_required — the git tree is dirty. Retry with ?confirm=1. |
Update stashes local changesisotope update runs
git pull, which auto-stashes modifications. The 409 gate exists so this is
never silent. Recover with git stash pop.
/api/pip/state
none
/api/pip/action
none
Picture-in-Picture timer state and control actions.
Auth routes #
/__auth/signup
rate limited
Creates the account and bootstraps every satellite row. Note the email is sent in a
field named username — it is the signup form's field name.
curl -X POST http://127.0.0.1:3000/__auth/signup \
-H 'Content-Type: application/json' \
-d '{"username":"you@example.com","password":"at-least-6-chars"}'
/__auth/login
rate limited
Password grant, then bootstraps any missing satellite rows.
/__auth/check
rate limited
Is an email already registered. Rate limited because it answers an existence question.
/__auth/bootstrap
bearer token
Returns the full profile bundle used to hydrate the app.
/__auth/snapshot
bearer token
Uploads a cloud snapshot of local data.
/__auth/backup/best
bearer token
Returns the best available backup, chosen by richness before recency.
/__auth/backup/latest
bearer token
/__auth/backup
bearer token
/__auth/restore-best-backup
bearer token
/__auth/import
bearer token
/__auth/profile
bearer token
/__auth/profile
bearer token
Profile read and write. Avatar data URLs are mirrored to Storage server-side, since a direct browser upload is unreliable on some networks.
Leaderboard #
/__leaderboard
user JWT
Built server-side using the caller's own JWT — never the service key. Returns rankings for the requested period plus the caller's own rank.
Admin routes #
All /__admin/* routes require ADMIN_MODE_READY
(ENABLE_ADMIN_MODE=true and a service-role key) plus
isAdminAuthed. The one exception is
/__admin/browser-proof-result, authorised by a per-run token.
| Route | Method | Purpose |
|---|---|---|
/__admin/login | GET, POST | Unlock via ADMIN_SECRET or a Supabase admin session. |
/__admin/verify | GET | Automated test suite across schema, RPCs, RLS and endpoints. |
/__admin/patch | GET | SQL patch manager. Serves community-patch-v6.sql. |
/__admin/apply-sql | POST | Executes SQL via the Management API. Effectively remote DDL. |
/__admin/schema | GET | Downloads isotope-complete.sql. |
/__admin/roles | GET, POST, DELETE | Grant and revoke admin roles. |
/__admin/sync | GET | Backup diagnostics console. |
/__admin/storage | GET | Storage console with cleanup preview and apply. |
/__admin/browser-proof | GET | Starts a real-browser verification run. |
Supabase proxy #
/__supa/*
caller JWT, or service key for admins
Forwards to your Supabase project. Several edge-function paths are intercepted
deliberately: leaderboard, analytics and finish-session return 502 rather
than fabricate data, while payment and portal paths return inert 200
stubs.
Other #
| Route | Method | Notes |
|---|---|---|
/__isotope/ping | GET | Liveness probe. Used by CI and the install scripts. |
/__errors | POST | Unauthenticated log sink. Appends to ~/.isotope/logs/browser-errors.log, capped at 1 MB per request. |
/__pip/state | POST | Browser to server PiP snapshot. |
/__pip/events | GET | Server-sent events to browser tabs. |
/sw.js | GET | Service worker with build placeholders substituted per request. |