All routes are served by FastAPI under /api (backend/app/main.py
registers one router per resource from backend/app/routers/). Interactive
OpenAPI documentation with request/response schemas is available from a
running backend at http://localhost:8001/docs; the Pydantic models behind
every payload are in backend/app/schemas.py.
In Docker Compose the frontend nginx proxies /api from port 3000, so the
same paths work against http://localhost:3000.
| Method |
Path |
Purpose |
| GET |
/api/health |
Liveness check |
| Method |
Path |
Purpose |
| GET |
/api/meta |
Current application version ({"version": "X.Y.Z"}) |
| GET |
/api/meta/release-notes |
In-app release notes, newest first (version, date, title, markdown body) |
Both are backed by backend/app/release_notes.py, the version’s single
source of truth, which is updated as part of every release.
| Method |
Path |
Purpose |
| POST |
/api/sessions |
Create a session |
| GET |
/api/sessions |
List sessions |
| GET |
/api/sessions/{id} |
Get one session |
| PATCH |
/api/sessions/{id} |
Update name, notes, meeting type/context, group, state |
| DELETE |
/api/sessions/{id} |
Delete a session and its children |
| GET |
/api/sessions/{id}/segments |
List call segments |
| GET |
/api/sessions/{id}/segments/{n}/audio |
Download a segment’s recorded WAV |
| GET |
/api/sessions/{id}/token-usage |
Usage totals with per-source and per-model breakdowns |
| POST |
/api/sessions/{id}/enhance-insights |
Re-run insight enrichment after speaker changes; started in the background, returns the run summary |
| GET |
/api/sessions/{id}/enhance-insights/{run_id} |
Poll a started enhance run: status, dirty flag, and whether the briefing was updated |
| GET |
/api/sessions/{id}/agents |
Effective per-session agent list |
| PUT |
/api/sessions/{id}/agents |
Set per-session agent enable/disable overrides |
Usage is persisted per provider response and shown in the post-call
Tokens tab, which reports estimated cost rather than raw counts. Sessions
without recorded LLM activity return zero totals and empty by_source /
by_model lists; historical sessions are not backfilled.
Not every model bills per token. OpenAI Realtime transcription
(gpt-live-transcribe) publishes a per-minute rate and reports audio duration
instead of token counts, so each row also carries audio_seconds, which is
zero for every token-billed model. GET /api/models/pricing exposes the
matching per_minute rate alongside the per-million token rates; a model
priced one way has null for the other. Cost estimates sum both, so a row can
show zero tokens and a non-zero cost.
| Method |
Path |
Purpose |
| GET |
/api/groups |
List groups |
| POST |
/api/groups |
Create a group |
| PATCH |
/api/groups/{id} |
Rename/update a group |
| DELETE |
/api/groups/{id} |
Delete a group |
| Method |
Path |
Purpose |
| POST |
/api/sessions/{id}/directives |
Add a directive |
| GET |
/api/sessions/{id}/directives |
List directives |
| PATCH |
/api/sessions/{id}/directives/{directive_id} |
Edit or (de)activate |
| DELETE |
/api/sessions/{id}/directives/{directive_id} |
Remove |
| Method |
Path |
Purpose |
| POST |
/api/sessions/{id}/documents |
Upload a document (summarized for agent context) |
| GET |
/api/sessions/{id}/documents |
List documents |
| DELETE |
/api/sessions/{id}/documents/{document_id} |
Remove |
| Method |
Path |
Purpose |
| POST |
/api/sessions/{id}/speakers |
Register a speaker |
| GET |
/api/sessions/{id}/speakers |
List speakers |
| PATCH |
/api/sessions/{id}/speakers/{speaker_id} |
Rename, set role/type/display name |
| POST |
/api/sessions/{id}/speakers/{speaker_id}/merge |
Merge into another speaker |
| DELETE |
/api/sessions/{id}/speakers/{speaker_id} |
Remove |
| Method |
Path |
Purpose |
| POST |
/api/sessions/{id}/transcripts |
Append a transcript entry manually |
| GET |
/api/sessions/{id}/transcripts |
List transcript entries |
| PATCH |
/api/sessions/{id}/transcripts/{transcript_id} |
Edit text or speaker attribution |
| Method |
Path |
Purpose |
| GET |
/api/sessions/{id}/questions |
List insights (all item types) |
| PATCH |
/api/sessions/{id}/questions/{question_id} |
Mark answered/dismissed, edit |
| Method |
Path |
Purpose |
| POST |
/api/sessions/{id}/ask |
Answer one question against the running call and save the answer |
The body is {"model_id": "...", "question": "..."}. Context is assembled
recency-first from the session’s transcript, live insights, strategic signals,
directives, and the persisted documents.summary values – never a fresh
summarization call. The answer is persisted as an asked insight
(agent_source live_chat, starred, answered), with the answering model
and elapsed time in rationale; answers over 4000 characters are truncated
with a marker. Separate from /api/chat, which is cross-session and
briefing-led.
| Method |
Path |
Purpose |
| GET |
/api/sessions/{id}/synthesis |
Get the saved session synthesis (or null) |
| POST |
/api/sessions/{id}/synthesis/refresh |
Regenerate the synthesis |
Both take mode (live or post_call, default post_call): live is the
strategic-signal cycle, post_call the briefing. GET also takes
include_history; without it the response carries only
signal_history_count, so the caller can render the History control without
paying for the rows. Signals accumulate in signal_history with a per-signal
count, first_seen, and last_seen rather than being replaced each cycle.
| Method |
Path |
Purpose |
| POST |
/api/sessions/{id}/import/transcript |
Import .txt, .md, or .docx transcript |
| POST |
/api/sessions/{id}/import/audio |
Import .wav, .mp3, .m4a, .ogg, .flac audio through the live pipeline |
| Method |
Path |
Purpose |
| POST |
/api/sessions/{id}/analyze |
Run post-import analysis over the transcript (routers/analyze.py) |
| POST |
/api/sessions/{id}/retranscribe |
Replay stored segment audio through a batch-capable model; replaces existing transcript entries (routers/retranscribe.py) |
| Method |
Path |
Purpose |
| GET |
/api/sessions/{id}/artifacts/transcript-export |
Transcript as TXT |
| GET |
/api/sessions/{id}/artifacts/questions-export |
Insights as one XLSX, enriched columns folded in |
| GET |
/api/sessions/{id}/artifacts/summary-export |
Summary as HTML |
| Method |
Path |
Purpose |
| GET |
/api/agents |
List agent configs |
| GET |
/api/agents/{slug} |
Get one agent config |
| PATCH |
/api/agents/{slug} |
Update enabled, model, interval, prompt |
| POST |
/api/agents/reset/{slug} |
Restore the seeded prompt |
| Method |
Path |
Purpose |
| GET |
/api/models |
Model registry with capabilities and key requirements |
| GET |
/api/models/pricing |
Published USD-per-1M-token rates keyed by model id, plus the as-of date (standard text-tier rates; null = no published pricing) |
| Method |
Path |
Purpose |
| GET |
/api/privacy |
Current Privacy First state: local_only, the effective batch transcription model, and an impact summary of what enabling it keeps and disables |
| PUT |
/api/privacy |
Set {"local_only": true|false}; returns the same payload |
Providers: google, openai, openai-compatible (the legacy single
self-hosted server; its key is optional). Keys are stored encrypted (see
Configuration).
| Method |
Path |
Purpose |
| GET |
/api/credentials |
List configured providers (masked) |
| PUT |
/api/credentials/{provider} |
Save/replace a key |
| DELETE |
/api/credentials/{provider} |
Remove a key |
| POST |
/api/credentials/{provider}/test |
Validate the stored key against the provider |
| GET |
/api/credentials/openai-compatible/endpoint |
Legacy single-endpoint base URL and wire model id |
| PUT |
/api/credentials/openai-compatible/endpoint |
Update them; omitted fields are untouched, empty strings clear back to env/default |
The openai-compatible/endpoint routes predate named endpoints and are
superseded by /api/endpoints; existing legacy configurations are migrated
to a named endpoint on startup.
| Method |
Path |
Purpose |
| GET |
/api/endpoints |
List endpoints, their models, and last test result |
| POST |
/api/endpoints |
Register an endpoint (name, base URL, optional API key, served models) |
| PUT |
/api/endpoints/{id} |
Patch it; omitted fields keep their value, an empty api_key clears the stored key |
| DELETE |
/api/endpoints/{id} |
Retire an endpoint; agents still pointing at its models report it as missing until repointed |
| POST |
/api/endpoints/{id}/test |
Probe {base_url}/models and record the outcome for the status badge |
| POST |
/api/endpoints/probe |
Probe an unsaved base URL and list the models it serves |
Each model listed on an endpoint becomes a registry entry with the id
endpoint:<slug>:<served model name> (see Configuration).
DELETE is a soft delete: the row is tombstoned (deleted_at set, stored key
cleared) rather than removed
(delete_endpoint() in backend/app/services/custom_endpoints.py).
| Method |
Path |
Purpose |
| GET |
/api/offerings |
List/filter the offerings catalog |
| GET |
/api/offerings/vendors |
Distinct vendors |
| GET |
/api/offerings/categories |
Distinct categories |
| GET |
/api/offerings/tags |
Distinct tags in use |
| POST |
/api/offerings |
Create an offering |
| PATCH |
/api/offerings/{offering_id} |
Update an offering |
| DELETE |
/api/offerings/{offering_id} |
Remove an offering |
| POST |
/api/offerings/import |
Bulk import from CSV/XLSX |
| POST |
/api/offerings/seed |
Load the seed catalog (?replace=true to overwrite) |
| Method |
Path |
Purpose |
| GET |
/api/knowledge |
List knowledge sources |
| POST |
/api/knowledge |
Create a source |
| GET |
/api/knowledge/{source_id} |
Get a source |
| PATCH |
/api/knowledge/{source_id} |
Update a source |
| DELETE |
/api/knowledge/{source_id} |
Remove a source and its records |
| GET |
/api/knowledge/{source_id}/records |
List records |
| POST |
/api/knowledge/{source_id}/records |
Add a record |
| PATCH |
/api/knowledge/records/{record_id} |
Update a record |
| DELETE |
/api/knowledge/records/{record_id} |
Remove a record |
| POST |
/api/knowledge/{source_id}/records/import |
Bulk import records from CSV/XLSX |
| POST |
/api/knowledge/{source_id}/files |
Upload a file, converted to Markdown records |
| Method |
Path |
Purpose |
| POST |
/api/chat |
Ask questions over selected sessions’ settled briefings, non-dismissed insights, and speaker-attributed transcripts; briefings guide interpretation while transcripts ground facts and quotations |
| Method |
Path |
Purpose |
| GET |
/api/diagnostics/diarization |
Diarizer capability and runtime config |
| PATCH |
/api/diagnostics/diarization/config |
Update diarizer runtime config |
| GET |
/api/diagnostics/diarization/voice-profile |
Whether a local voice profile is enrolled |
| PUT |
/api/diagnostics/diarization/voice-profile |
Replace the voice profile from an uploaded clip (audio discarded, only the embedding is kept) |
| DELETE |
/api/diagnostics/diarization/voice-profile |
Delete the enrolled voice profile |
| GET |
/api/diagnostics/transcription |
Batch transcription config |
| GET |
/api/diagnostics/transcription/readiness |
Whether the selected transcription models have usable credentials |
| GET |
/api/diagnostics/capacity |
Call-start capacity admission verdict: measured headroom for the selected config (?track_count=1|2, default 2) |
| PATCH |
/api/diagnostics/transcription/config |
Update the batch transcription model and/or the live-caption (audio gateway) model |
| POST |
/api/diagnostics/diarization/sortformer/benchmark |
Benchmark Sortformer on an uploaded file (needs at least 15 seconds of audio) |
| GET |
/api/diagnostics/local-fit |
On-prem text models available to test plus each scored agent’s current cycle interval |
| POST |
/api/diagnostics/local-fit/run |
Time a role-sized call on each on-prem text model and score keep-up per live agent role |
| POST |
/api/diagnostics/local-fit/apply |
Apply recommended cycle intervals to the scored agents (speed tuning) |
| POST |
/api/diagnostics/local-fit/asr |
Measure real-time factor for the local ONNX ASR models on an uploaded speech clip |
Desktop auto-update routes. Every route except the status read requires the
X-Backchannel-Instance header to match the launcher-issued instance token
(403 otherwise), so they are effectively available only under the desktop
launcher (BACKCHANNEL_DESKTOP=1).
| Method |
Path |
Purpose |
| GET |
/api/updates |
Update status; a ready update also reports blocked_reason when active work defers install |
| POST |
/api/updates/check |
Force an update check |
| POST |
/api/updates/grant |
Submit a signed update grant and start the download |
| DELETE |
/api/updates/download |
Cancel an in-progress download |
| POST |
/api/updates/apply |
Install the downloaded update; 409 while a call or other active work is running |
The live-call WebSocket endpoint /ws/{session_id} is documented separately
in WebSocket Protocol.