# ICD-API — Chat Switchboard Backend API Contract **Version:** 0.28.0 **Updated:** 2026-03-11 **Audience:** Frontend developers, integrators, API consumers > **Organization principle:** Each file is one domain — the complete story. > Every endpoint that touches Knowledge Bases is in `knowledge.md`, every > endpoint that touches Personas is in `personas.md`, etc. ## Files | File | Domain | Endpoints | |------|--------|-----------| | [auth.md](auth.md) | Auth — login, register, refresh, OIDC, mTLS | 6 | | [channels.md](channels.md) | Channels, messages, completions, participants, folders, presence | ~35 | | [personas.md](personas.md) | Personas, persona groups, avatars, KB bindings, tool grants | ~20 | | [knowledge.md](knowledge.md) | Knowledge bases, documents, search, channel/persona bindings | ~12 | | [notes.md](notes.md) | Notes, wikilinks, graph, search, folders | ~10 | | [workspaces.md](workspaces.md) | Workspaces, file ops, git, credentials | ~20 | | [projects.md](projects.md) | Projects, channel/KB/note associations | ~14 | | [memory.md](memory.md) | Memory extraction, review, admin | 7 | | [providers.md](providers.md) | Provider configs, health, capabilities, routing policies | ~25 | | [models.md](models.md) | Enabled models, user preferences | 4 | | [notifications.md](notifications.md) | Notifications, preferences | 7 | | [extensions.md](extensions.md) | Extensions, user settings, admin | 8 | | [profile.md](profile.md) | User profile, avatar, password, app settings | 7 | | [teams.md](teams.md) | Teams, members, groups, permissions, grants | ~25 | | [admin.md](admin.md) | Platform admin — users, settings, stats, audit, usage, vault | ~25 | | [utility.md](utility.md) | Health, export, files, storage | ~12 | | [workflows.md](workflows.md) | Workflow definitions, stages, instances, assignments, entry | ~20 | | [tasks.md](tasks.md) | Task definitions, runs, scheduler, team tasks | ~14 | | [surfaces.md](surfaces.md) | Surface registry, extension surfaces | 6 | | [websocket.md](websocket.md) | WebSocket protocol, events, rooms | — | | [enums.md](enums.md) | All enum values, policies | — | ## Conventions ### Base URL ``` {scheme}://{host}{BASE_PATH}/api/v1 ``` `BASE_PATH` is empty by default. In path-routed K8s deployments (e.g. `/staging/`), all routes shift accordingly. The frontend reads `BASE_PATH` from a `` tag injected by the Go template engine. ### Authentication JWT bearer tokens. Every request to a `protected` or `admin` route requires: ``` Authorization: Bearer {access_token} ``` **Access token:** HS256 JWT, 15-minute TTL. Claims: `user_id`, `email`, `role`, `exp`, `iat`, `jti`. **Refresh token:** Opaque, DB-stored, 7-day TTL. Used to obtain new access tokens without re-login. **WebSocket fallback:** `?token={access_token}` query parameter when the `Authorization` header isn't available. **Cookie sync:** On every token save/refresh, the frontend writes `sb_token` as a cookie. Go template page routes read this cookie via `AuthOrRedirect` middleware for server-rendered surfaces. ### Auth Modes | Mode | `AUTH_MODE` | How it works | |------|------------|--------------| | Builtin | `builtin` (default) | Username/password, bcrypt, JWT | | mTLS | `mtls` | Reverse proxy cert headers, auto-provision | | OIDC | `oidc` | Authorization code flow (Keycloak etc.) | All three modes issue the same JWT after authentication. Downstream middleware is auth-mode-agnostic. ### Authorization Tiers | Tier | Middleware | Who | |------|-----------|-----| | Public | none | Anyone (health, login, register, public settings) | | Session | `AuthOrSession()` | JWT user OR anonymous session cookie (workflow visitors) | | Authenticated | `Auth()` | Any logged-in user | | Permission | `RequirePermission(perm)` | User whose groups grant `perm` | | Team Admin | `RequireTeamAdmin()` | Admin of the specific team | | Platform Admin | `RequireAdmin()` | Users with `role = "admin"` | ### Error Envelope All errors return: ```json { "error": "human-readable message" } ``` Standard HTTP status codes: 400 (bad request), 401 (not authenticated), 403 (not authorized), 404 (not found), 409 (conflict), 500 (server error), 502 (upstream provider failure). ### Pagination Envelope Endpoints that paginate return: ```json { "data": [...], "page": 1, "per_page": 50, "total": 142, "total_pages": 3 } ``` Query params: `?page=1&per_page=50`. Not all list endpoints paginate — some return `{ "data": [...] }` or a bare array in a named key. ### ID Format All resource IDs are UUIDv4 strings, generated application-side via `store.NewID()` (Go `uuid.New()`). This ensures compatibility across both Postgres and SQLite backends. ### Timestamps ISO 8601 with timezone: `"2025-06-15T14:30:00Z"`. Stored as `TIMESTAMPTZ` (Postgres) or `TEXT` (SQLite). ## Page Routes (Non-API) Server-rendered Go template surfaces. Not REST endpoints — return HTML. | Route | Surface | Description | |-------|---------|-------------| | `/login` | Login | Standalone login/register page | | `/` | Chat | Main chat interface | | `/chat/:chatID` | Chat | Chat with specific channel loaded | | `/editor` | Editor | Workspace file editor | | `/editor/:wsId` | Editor | Editor with specific workspace | | `/notes` | Notes | Notes interface | | `/notes/:noteId` | Notes | Notes with specific note loaded | | `/admin` | Admin | Platform administration | | `/admin/:section` | Admin | Admin with specific section | | `/settings` | Settings | User settings | | `/settings/:section` | Settings | Settings with specific section | | `/w/:id` | Workflow Landing | Branded workflow entry page | | `/w/:id/:slug` | Workflow Landing | Slug-suffixed workflow entry | | `/s/:slug` | Extension Surface | Dynamic surface from registry | All page routes (except `/login`, `/w/`) require authentication via `AuthOrRedirect` middleware. Admin routes additionally require `RequireAdminPage()`. Workflow landing pages use `AuthOrSession`.