{"openapi":"3.0.0","info":{"title":"Mandrel v2 API — App reference","version":"0.0.1","description":"Published HTTP operations (Auth, Collections, Records, API tokens, Search). Same paths as `openapi.json`; in-app reference title."},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"apiToken":{"type":"http","scheme":"bearer","bearerFormat":"mnd_…"}}},"paths":{"/auth/register":{"post":{"tags":["Auth"],"summary":"Register user"}},"/auth/login":{"post":{"tags":["Auth"],"summary":"Login"}},"/auth/refresh":{"post":{"tags":["Auth"],"summary":"Rotate session tokens"}},"/auth/logout":{"post":{"tags":["Auth"],"summary":"Logout (refresh body)"}},"/auth/forgot-password":{"post":{"tags":["Auth"],"summary":"Request password reset"}},"/auth/reset-password":{"post":{"tags":["Auth"],"summary":"Complete password reset"}},"/auth/change-password":{"post":{"tags":["Auth"],"security":[{"bearerAuth":[]}],"summary":"Change password (signed in)","description":"Requires current password. Sets a new password and signs out other sessions; this session stays valid until tokens expire."}},"/me":{"get":{"tags":["Auth"],"security":[{"bearerAuth":[]}],"summary":"Current user"},"patch":{"tags":["Auth"],"security":[{"bearerAuth":[]}],"summary":"Update profile","description":"Update `firstName` and/or `lastName`. Send empty string to clear a name. Email is not changed here."}},"/me/organizations":{"get":{"tags":["Auth"],"security":[{"bearerAuth":[]}],"summary":"Memberships","description":"Each organization includes roleId, roleName, and canCreateCollections (whether that role may create new collections in the org)."}},"/collections":{"get":{"tags":["Collections"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Search name/slug (trigram)"},{"name":"sort","in":"query","schema":{"type":"string","enum":["name","slug","created_at","updated_at"],"default":"name"}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"asc"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0}},{"name":"parent_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"has_parent","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}},{"name":"roots_only","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}}],"description":"List collections **readable by the caller** (Owner/Admin: all; other roles: RCP `can_read` only). Response includes `total`, `limit`, `offset`, and per-item summaries (`fieldCount`, `recordCount`, `childCount`, `parent`).","summary":"List collections (permission-filtered, searchable, paginated)"},"post":{"tags":["Collections"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Create collection","description":"Request body may include `fields[]`. When `fields[].type` is `calculated`, `calculationConfig` must follow the structured union (`calculationType`: formula, concat, child_sum, child_count, child_average). On collection create, concat targets use `concatFieldNames` (field UUIDs do not exist yet). Legacy `{ template }` alone is normalized server-side to a formula."}},"/org-search":{"get":{"tags":["Search"],"security":[{"bearerAuth":[]}],"summary":"Unified org search (collections and records)","description":"Session JWT only (no API token). Merges collection name/slug search with capped cross-collection record text search (recent readable collections). Client merges with local results as needed.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Search query"},{"name":"types","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated: `collection`, `record`. Omit for all."},{"name":"limit","in":"query","schema":{"type":"integer","default":25,"minimum":1,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0}}]}},"/collections/{collectionId}/analytics-helper":{"get":{"tags":["Collections"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"collectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"SQL analytics helper targets (main, parent, children, referenced) with column mappings"}},"/collections/{collectionId}":{"get":{"tags":["Collections"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Get collection"},"patch":{"tags":["Collections"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"collectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Update collection metadata (e.g. pdfTemplateConfig for print/PDF template JSON)","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"pdfTemplateConfig":{"type":"object","nullable":true,"additionalProperties":true}},"required":["pdfTemplateConfig"]}}}}},"delete":{"tags":["Collections"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"collectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Soft-delete collection and entire subtree (child collections via parent_collection_id); requires canDelete; rejects system collections","responses":{"200":{"description":"{ ok, deletedCollectionIds }"}}}},"/collections/{collectionId}/records":{"get":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"collectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}},{"name":"q","in":"query","description":"Full-text + fuzzy search on denormalized `search_concat` / `search_tsv`. Keyset `cursor` is ignored when set; use `offset` for paging.","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string","enum":["created_at","updated_at"]}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"cursor","in":"query","description":"Keyset: base64url JSON { t, id } from previous nextCursor","schema":{"type":"string"}},{"name":"include_deleted","in":"query","schema":{"type":"string","enum":["true","1"]},"description":"When true, include soft-deleted rows in list and count. Keyset `cursor` paging is disabled."},{"name":"filters","in":"query","description":"Column filters JSON: flat array (implicit AND between rules). Legacy `{\"groups\":[{\"filters\":[...],\"combiners\":[]}]}` (OR between groups, pairwise AND/OR inside each). Current: `{\"ver\":2,\"root\":{\"items\":[{\"kind\":\"rule\",...}|{\"kind\":\"group\",\"block\":{...}}],\"combiners\":[\"and\",\"or\"]}}` — at each nesting level pairwise combiners join siblings; subgroup is a nested `block` (named “Filter”: rules +optional subgroups). Field names match schema; ops: eq, neq, gt, gte, lt, lte, in, is_null; max 12 predicates total; nesting depth capped. Keyset `cursor` ignored when filters or `q` are set.","schema":{"type":"string"}},{"name":"parent_id","in":"query","description":"When this collection belongs to a parent (`parent_collection_id` set), filter rows whose `parent_id` equals this UUID. Invalid with collections that are not children.","schema":{"type":"string","format":"uuid"}}],"description":"Response includes `searchActive`, `filtersActive`, `total` (when not using keyset cursor with `q`/filters), `nextCursor` when applicable; `nextCursor` is omitted while searching or filtering (use offset for paging). Includes `parentRef` map `{ [parentUuid]: label }` for child collections when rows have `parent_id`.","summary":"List records (offset or keyset cursor)"},"post":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"collectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Create record"}},"/collections/{collectionId}/record-options":{"get":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"collectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"q","in":"query","description":"Full-text + fuzzy search (same as list records).","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":25,"minimum":1,"maximum":50}}],"summary":"Record picker options (id + display label)","description":"Returns `{ rows: [{ id, label }] }` for compact pickers; uses display name template and fallbacks."}},"/collections/{collectionId}/records/{recordId}":{"get":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"include_deleted","in":"query","schema":{"type":"string","enum":["true","1"]},"description":"Include soft-deleted row in result for detail views"}],"summary":"Get one record"},"patch":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Update record"},"delete":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Soft-delete record"}},"/collections/{collectionId}/records/{recordId}/hard":{"delete":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Permanently delete record row (destructive)"}},"/collections/{collectionId}/records/{recordId}/restore":{"post":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Restore soft-deleted record"}},"/collections/{collectionId}/records/{recordId}/print":{"get":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Printable HTML for one record (uses pdfTemplateConfig when set; values escaped)","description":"Returns `text/html; charset=utf-8`. Use a client page with Bearer auth to fetch; do not `window.open` the API origin without passing credentials/headers unless cookies apply.","responses":{"200":{"description":"HTML document","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/collections/{collectionId}/fields":{"post":{"tags":["Collections"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Add field (schema evolution + collection_migrations)"}},"/collections/{collectionId}/fields/{fieldId}":{"patch":{"tags":["Collections"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Update field metadata, optional rename, optional whitelisted type change","description":"Body may include metadata fields and/or `name` (renames physical column when needed) and/or `type` (whitelisted transitions: same physical type = metadata only; integer↔decimal; date↔datetime). Logged in collection_migrations."},"delete":{"tags":["Collections"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean"},"description":"Drop column even when data exists (use with care)"}],"summary":"Delete field (DROP COLUMN and remove fields row; form mappings cascade)"}},"/collections/{collectionId}/import":{"post":{"tags":["Records"],"security":[{"bearerAuth":[]},{"apiToken":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"deprecated":true,"description":"Removed — returns **410**. Use JWT-only `POST /import/files` staging (upload → validate → process). Legacy multipart CSV + mapping is no longer supported on this route.","summary":"DEPRECATED CSV import — use POST /import/files","responses":{"410":{"description":"Gone — see body `migrateTo`"}}}},"/import/files":{"post":{"tags":["Import"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Stage bulk import upload (JWT, org Owner/Admin only)","description":"Multipart `file` field. Allowed: csv, pdf, docx (~50 MB max). Returns `fileId` and preview metadata. Larger uploads may persist to object storage (`storageBackend: true`) while retaining the same `fileId`."}},"/import/files/{fileId}/validate":{"post":{"tags":["Import"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"fileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Validate staged file (optional collectionId + fieldMappings + excludeColumns)"}},"/import/files/{fileId}/process":{"post":{"tags":["Import"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"fileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Run import — body XOR `collectionId` or `autoCreateCollection`; optional `fieldMappings`, `excludeColumns`. Returns 202 when worker processes staged blob."}},"/import/files/{fileId}":{"delete":{"tags":["Import"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"fileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Discard staged upload"}},"/api-tokens":{"get":{"tags":["API tokens"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"includeRevoked","in":"query","required":false,"schema":{"type":"string","enum":["1","true"]},"description":"When set, includes revoked tokens for this user in the org."}],"summary":"List tokens"},"post":{"tags":["API tokens"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Create token"}},"/api-tokens/{id}/usage":{"get":{"tags":["API tokens"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Token usage history","description":"Daily aggregates per endpoint (authenticated route label). Capped at 500 rows."}},"/api-tokens/{id}/revoke":{"post":{"tags":["API tokens"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Revoke token","description":"Sets revokedAt; token stops working immediately."}},"/api-tokens/{id}":{"delete":{"tags":["API tokens"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"summary":"Delete token","description":"Hard-deletes the token row and usage history. Prefer POST …/revoke to disable without removing history."}},"/api/ai/conversations":{"get":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"AI conversation history","description":"Session JWT only (not API tokens). When `sessionId` query is set, returns messages for that thread; otherwise returns recent messages for session grouping. Requires `ai_mcp` feature and `X-Organization-Id`.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"sessionId","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":30,"minimum":1,"maximum":500}}]}},"/api/ai/mcp/chat":{"post":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"MCP-style chat (non-streaming)","description":"Session JWT only. Optional `modeId` selects contextual tool allowlist and system instructions; optional `pageContext` adds UI-supplied grounding (capped). Omit `modeId` for dedicated/full tool mode.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string"},"sessionId":{"type":"string"},"conversationId":{"type":"string"},"modeId":{"type":"string","enum":["dedicated","collection_admin","collection_data","import_wizard","builder","automation_editor","analytics_surface"]},"pageContext":{"type":"string","maxLength":16384}}}}}}}},"/api/ai/mcp/chat/stream":{"post":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"MCP-style chat (SSE stream)","description":"Same body as `/api/ai/mcp/chat`; response is `text/event-stream` with JSON lines and `[DONE]`.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string"},"sessionId":{"type":"string"},"conversationId":{"type":"string"},"modeId":{"type":"string","enum":["dedicated","collection_admin","collection_data","import_wizard","builder","automation_editor","analytics_surface"]},"pageContext":{"type":"string","maxLength":16384}}}}}}}},"/api/agent/capabilities":{"get":{"tags":["Agent"],"security":[{"bearerAuth":[]}],"summary":"Agent capabilities (analytics + chat policy)","description":"Session JWT only (API tokens rejected). Requires `X-Organization-Id`.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/agent/sessions":{"get":{"tags":["Agent"],"security":[{"bearerAuth":[]}],"summary":"List unified agent sessions","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"collectionId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":100}}]},"post":{"tags":["Agent"],"security":[{"bearerAuth":[]}],"summary":"Create agent session","description":"Body optional `{ title }`.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/agent/sessions/{id}/messages":{"get":{"tags":["Agent"],"security":[{"bearerAuth":[]}],"summary":"Messages for agent session","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500}}]}},"/api/agent/sessions/{id}":{"delete":{"tags":["Agent"],"security":[{"bearerAuth":[]}],"summary":"Delete agent session","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/agent/reports/pin":{"post":{"tags":["Agent"],"security":[{"bearerAuth":[]}],"summary":"Pin validated SQL widget to org scratch report","description":"Session JWT only. Requires `analytics_widgets` feature and org admin policy. Body matches dashboard widget suggestion shape + `collectionId`; widget is persisted on the org `agent_scratch` report.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/dashboards/{dashboardId}/render":{"get":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Authenticated dashboard composer render bundle","description":"Requires `analytics_widgets`. Returns `{ dashboard, slots, reportsById, widgetsByReportId, previewRowsByWidgetId }` — analogous to JWT print snapshot payloads but aggregates every slotted report on the composer.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"dashboardId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/ai/reports/generate":{"post":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Gemini — mint a linked report plus widgets transactionally","description":"Org admin + collection read gate. Body: `collectionId` (UUID), `prompt`. Uses Gemini blueprint JSON → validated SQL → transactional `reports` insert + stacked `report_widgets` rows (`source: ai`). Mirrors widget-suggestion guardrails; partial validation errors may still return `201` when at least one widget passes.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/agent/health":{"get":{"tags":["Agent"],"security":[{"bearerAuth":[]}],"summary":"Agent / analytics subsystem health","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/mcp/analytics/health":{"get":{"tags":["AI"],"summary":"MCP analytics health","description":"Unauthenticated. Gemini availability, in-memory cache stats, timestamp."}},"/api/mcp/analytics/generate":{"post":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"NL analytics — generate SQL or multi-step analysis","description":"Session JWT only (API tokens rejected). Requires `X-Organization-Id`. Body: `question`, `collectionIds` (UUIDs), optional `sessionId`, `agentSessionId` (unified agent session UUID), `visualGenerationEnabled`, `includeSummary`, `page`, `pageSize` (≤500), `multiStep` (org admins only). Returns SQL + rows, conversational answer, or multi-step narrative; `429` when rate limit applies.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/mcp/analytics/sessions":{"get":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"List MCP analytics chat sessions","description":"Session marker threads; optional `collectionId`, `limit`, `offset`.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"collectionId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","schema":{"type":"integer","default":30,"minimum":1,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0}}]}},"/api/mcp/analytics/sessions/{id}":{"get":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Load MCP analytics session messages","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]},"delete":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Delete MCP analytics session","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/api/mcp/analytics/re-execute-sql":{"post":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Re-run guarded SELECT with pagination","description":"Body: `sql`, `collectionIds` (all collections referenced in the query), optional `page`, `pageSize`. SELECT-only; same allowlist as analytics tools.","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/mcp/analytics/export/csv":{"post":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Export row array as CSV attachment","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/mcp/analytics/export/json":{"post":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Export row array as JSON attachment","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/mcp/analytics/insights/{id}":{"get":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Collection analytics insights (aggregates)","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/mcp/analytics/saved-queries":{"get":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"List saved MCP analytics queries","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]},"post":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Save an analytics query","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/mcp/analytics/saved-queries/{id}":{"patch":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Rename saved query","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]},"delete":{"tags":["AI"],"security":[{"bearerAuth":[]}],"summary":"Delete saved query","parameters":[{"name":"X-Organization-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/auth/sessions":{"get":{"tags":["Auth"],"security":[{"bearerAuth":[]}],"summary":"List active sessions"}},"/auth/sessions/revoke-all":{"post":{"tags":["Auth"],"security":[{"bearerAuth":[]}],"summary":"Revoke all other sessions"}},"/auth/sessions/{id}/revoke":{"post":{"tags":["Auth"],"security":[{"bearerAuth":[]}],"summary":"Revoke one session"}}}}