openapi: 3.1.0 info: title: OmniRoute API version: 3.8.49 description: | OmniRoute is a local-first AI API proxy router. It provides an OpenAI-compatible endpoint that routes requests to multiple AI providers with load balancing, failover, and usage tracking. ## Base URLs - **Local**: `http://localhost:20128` ## Authentication All proxy endpoints require a Bearer token (API key managed via the dashboard). Management endpoints are protected when `requireLogin` is enabled. contact: name: OmniRoute license: name: MIT servers: - url: http://localhost:20128 description: Local development tags: - name: Playground description: Playground Studio — preset management and prompt improvement - name: Memory description: Conversational memory management — CRUD, engine status, playground preview, summarization, reindex, and Qdrant settings (plan 21 — v3.8.6). All routes require management auth. - name: Chat description: OpenAI-compatible chat completions - name: Messages description: Anthropic-compatible messages - name: Responses description: OpenAI Responses API - name: Embeddings description: Text embedding generation - name: Images description: Image generation - name: Audio description: Audio speech and transcription - name: Moderations description: Content moderation - name: Rerank description: Document reranking - name: Models description: Available model listing - name: Providers description: Provider connection management - name: Provider Nodes description: Provider node configuration - name: API Keys description: API key management - name: Combos description: Routing combo management - name: Settings description: Application settings - name: Compression description: Prompt compression, RTK filters, Caveman rules, and compression combos - name: Usage description: Usage analytics and logs - name: Translator description: Format translation debug & testing - name: CLI Tools description: CLI tool configuration management - name: Embedded Services description: >- Install, start, stop, and monitor locally-running embedded services (9Router, CLIProxyAPI). All routes are LOCAL_ONLY — accessible from loopback only (hard rule #17). - name: OAuth description: OAuth flows for provider authentication - name: System description: System management (restart, shutdown, backup) - name: Pricing description: Model pricing configuration - name: Cloud description: Cloud worker authentication and sync - name: Fallback description: Fallback chain management - name: Telemetry description: Telemetry and token health monitoring - name: Agent Skills description: >- Agent Skills catalog — 42 SKILL.md files (22 REST API + 20 CLI) for external agents, MCP clients, and A2A orchestrators to discover OmniRoute capabilities. - name: AgentBridge description: >- MITM proxy manager for 9 IDE agents (Antigravity, Kiro, Copilot, Codex, Cursor, Zed, Claude Code, Open Code, Trae). Controls server lifecycle, DNS/model mappings, bypass list, and cert management. All routes are LOCAL_ONLY + SPAWN_CAPABLE (hard rules #15, #17). See docs/frameworks/AGENTBRIDGE.md. - name: Traffic Inspector description: >- LLM-aware HTTPS traffic debugger with 4 capture modes (AgentBridge, Custom Hosts, HTTP_PROXY :8080, System-wide). Provides real-time WebSocket stream, session recording, HAR export, SSE merge, and conversation normalization. All routes are LOCAL_ONLY + SPAWN_CAPABLE (hard rules #15, #17). See docs/frameworks/TRAFFIC_INSPECTOR.md. paths: # --- Playground + Search Tools (plans 17+18) --- /api/playground/improve-prompt: post: tags: - Playground summary: Improve prompt via LLM description: | Rewrites the supplied system prompt and/or user prompt using a meta-prompt (inspired by Anthropic Console Prompt Improver). Internally calls `/v1/chat/completions` with the model specified in the request body. Quota is consumed from the caller's account. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - model properties: system: type: string maxLength: 50000 description: System prompt to improve (at least one of system/prompt required) prompt: type: string maxLength: 50000 description: User prompt to improve model: type: string description: Model to use for the improvement call (e.g. openai/gpt-4o) tone: type: string enum: - concise - detailed default: concise responses: "200": description: Improved prompt(s) content: application/json: schema: type: object properties: improvedSystem: type: string improvedPrompt: type: string tokensIn: type: integer tokensOut: type: integer "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" /api/playground/presets: get: tags: - Playground summary: List playground presets description: Returns all saved playground presets ordered by creation date (newest first). security: - BearerAuth: [] responses: "200": description: Preset list content: application/json: schema: type: object properties: presets: type: array items: $ref: "#/components/schemas/PlaygroundPreset" "401": $ref: "#/components/responses/Unauthorized" post: tags: - Playground summary: Create playground preset description: Saves the current playground configuration as a named preset in the database. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PlaygroundPresetCreate" responses: "201": description: Created preset content: application/json: schema: $ref: "#/components/schemas/PlaygroundPreset" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" /api/playground/presets/{id}: parameters: - name: id in: path required: true schema: type: string format: uuid get: tags: - Playground summary: Get playground preset security: - BearerAuth: [] responses: "200": description: Preset found content: application/json: schema: $ref: "#/components/schemas/PlaygroundPreset" "401": $ref: "#/components/responses/Unauthorized" "404": description: Preset not found put: tags: - Playground summary: Update playground preset security: - BearerAuth: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PlaygroundPresetCreate" responses: "200": description: Updated preset content: application/json: schema: $ref: "#/components/schemas/PlaygroundPreset" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "404": description: Preset not found delete: tags: - Playground summary: Delete playground preset security: - BearerAuth: [] responses: "204": description: Deleted "401": $ref: "#/components/responses/Unauthorized" "404": description: Preset not found # --- Memory Engine (plan 21) --- /api/memory: get: tags: - Memory summary: List memory entries security: - ManagementSessionAuth: [] parameters: - name: apiKeyId in: query schema: type: string - name: type in: query schema: type: string enum: - factual - episodic - procedural - semantic - name: sessionId in: query schema: type: string - name: q in: query schema: type: string - name: limit in: query schema: type: integer minimum: 1 maximum: 200 default: 50 - name: page in: query schema: type: integer minimum: 1 default: 1 - name: offset in: query schema: type: integer minimum: 0 responses: "200": description: Paginated list of memories with stats content: application/json: schema: type: object properties: data: type: array items: $ref: "#/components/schemas/MemoryEntry" total: type: integer totalPages: type: integer stats: type: object properties: total: type: integer tokensUsed: type: integer hitRate: type: number cacheStats: type: object properties: hits: type: integer misses: type: integer "401": $ref: "#/components/responses/Unauthorized" post: tags: - Memory summary: Create a memory entry security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object required: - content - key properties: content: type: string minLength: 1 key: type: string minLength: 1 type: type: string enum: - factual - episodic - procedural - semantic default: factual sessionId: type: string nullable: true apiKeyId: type: string metadata: type: object additionalProperties: true expiresAt: type: string format: date-time nullable: true responses: "201": description: Created memory entry content: application/json: schema: $ref: "#/components/schemas/MemoryEntry" "400": description: Validation error "401": $ref: "#/components/responses/Unauthorized" /api/memory/{id}: parameters: - name: id in: path required: true schema: type: string description: Memory UUID get: tags: - Memory summary: Get a single memory entry security: - ManagementSessionAuth: [] responses: "200": description: Memory entry content: application/json: schema: $ref: "#/components/schemas/MemoryEntry" "401": $ref: "#/components/responses/Unauthorized" "404": description: Memory not found put: tags: - Memory summary: Update a memory entry description: Update `type`, `key`, `content`, and/or `metadata` of an existing memory. If an embedding source is available, the vector in `vec_memories` is also regenerated. Corresponds to `MemoryUpdatePutSchema`. security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object properties: type: type: string enum: - factual - episodic - procedural - semantic key: type: string minLength: 1 content: type: string minLength: 1 metadata: type: object additionalProperties: true additionalProperties: false responses: "200": description: Updated memory entry content: application/json: schema: $ref: "#/components/schemas/MemoryEntry" "400": description: Validation error "401": $ref: "#/components/responses/Unauthorized" "404": description: Memory not found delete: tags: - Memory summary: Delete a memory entry description: Deletes the SQLite row, removes the vector from `vec_memories`, and best-effort deletes the point from Qdrant. security: - ManagementSessionAuth: [] responses: "200": description: Deleted content: application/json: schema: type: object properties: success: type: boolean "401": $ref: "#/components/responses/Unauthorized" "404": description: Memory not found /api/memory/health: get: tags: - Memory summary: Memory store health check description: Round-trip create→list→delete to verify the store is alive. security: - ManagementSessionAuth: [] responses: "200": description: Health result content: application/json: schema: type: object properties: working: type: boolean latencyMs: type: number error: type: string nullable: true "401": $ref: "#/components/responses/Unauthorized" /api/memory/retrieve-preview: post: tags: - Memory summary: Dry-run memory retrieval (Playground) description: Simulates `retrieveMemories()` for a given query and returns the ranked results with score, tier, and token count. Does NOT modify any memory. Corresponds to `RetrievePreviewSchema`. security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object required: - query properties: query: type: string minLength: 1 strategy: type: string enum: - exact - semantic - hybrid default: hybrid maxTokens: type: integer minimum: 1 maximum: 16000 default: 2000 apiKeyId: type: string description: Optional — tests global pool when omitted limit: type: integer minimum: 1 maximum: 100 default: 20 additionalProperties: false responses: "200": description: Preview results content: application/json: schema: type: object properties: memories: type: array items: type: object properties: id: type: string type: type: string enum: - factual - episodic - procedural - semantic key: type: string content: type: string score: type: number tokens: type: integer tier: type: string enum: - fts5 - vector - hybrid-rrf - qdrant vecScore: type: number nullable: true ftsScore: type: number nullable: true resolution: type: object properties: embeddingSource: type: string enum: - remote - static - transformers nullable: true embeddingModel: type: string nullable: true vectorStore: type: string enum: - sqlite-vec - qdrant - none strategyUsed: type: string enum: - exact - semantic - hybrid rerankApplied: type: boolean fallbackReason: type: string nullable: true totalTokensUsed: type: integer budgetMaxTokens: type: integer "400": description: Validation error "401": $ref: "#/components/responses/Unauthorized" /api/memory/embedding-providers: get: tags: - Memory summary: List embedding providers description: Returns all providers that have embedding-capable models, indicating which have an active API key configured. security: - ManagementSessionAuth: [] responses: "200": description: Provider list content: application/json: schema: type: object properties: providers: type: array items: type: object properties: provider: type: string hasKey: type: boolean models: type: array items: type: object properties: id: type: string description: "Format: provider/model" name: type: string dimensions: type: integer nullable: true "401": $ref: "#/components/responses/Unauthorized" /api/memory/engine-status: get: tags: - Memory summary: Memory engine status description: Returns the full engine status including keyword tier availability, embedding resolution, vector store statistics (sqlite-vec), Qdrant health, and rerank configuration. Corresponds to `MemoryEngineStatusSchema`. security: - ManagementSessionAuth: [] responses: "200": description: Engine status content: application/json: schema: type: object properties: keyword: type: object properties: available: type: boolean backend: type: string enum: - FTS5 embedding: type: object properties: source: type: string enum: - remote - static - transformers nullable: true model: type: string nullable: true dimensions: type: integer nullable: true available: type: boolean reason: type: string cacheStats: type: object properties: hits: type: integer misses: type: integer size: type: integer vectorStore: type: object properties: backend: type: string enum: - sqlite-vec - qdrant - none available: type: boolean rowCount: type: integer needsReindex: type: integer reason: type: string qdrant: type: object properties: enabled: type: boolean healthy: type: boolean nullable: true latencyMs: type: number nullable: true error: type: string nullable: true rerank: type: object properties: enabled: type: boolean provider: type: string nullable: true model: type: string nullable: true available: type: boolean reason: type: string "401": $ref: "#/components/responses/Unauthorized" /api/memory/summarize: post: tags: - Memory summary: Compact old memories description: "Manually triggers memory compaction for memories older than `olderThanDays`. Use `dryRun: true` to preview candidates. Corresponds to `MemorySummarizeSchema`." security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object properties: olderThanDays: type: integer minimum: 1 maximum: 365 default: 30 apiKeyId: type: string description: Optional — compacts all keys when omitted dryRun: type: boolean default: false additionalProperties: false responses: "200": description: Summarization result content: application/json: schema: type: object properties: candidates: type: integer tokensSaved: type: integer dryRun: type: boolean "400": description: Validation error "401": $ref: "#/components/responses/Unauthorized" /api/memory/reindex: post: tags: - Memory summary: Trigger vector reindex description: "Starts background reindexing of memories with `needs_reindex = 1`. Use `force: true` to regenerate ALL vectors regardless of index status. Corresponds to `MemoryReindexSchema`." security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object properties: force: type: boolean default: false description: When true, marks all memories needs_reindex=1 before running. additionalProperties: false responses: "200": description: Reindex started content: application/json: schema: type: object properties: started: type: boolean pending: type: integer description: Memories still pending after this batch "400": description: Validation error "401": $ref: "#/components/responses/Unauthorized" /api/settings/memory: get: tags: - Memory - Settings summary: Get memory settings description: Returns the extended memory settings including 7 new fields added in plan 21 (embeddingSource, embeddingProviderModel, transformersEnabled, staticEnabled, rerankEnabled, rerankProviderModel, vectorStore). security: - ManagementSessionAuth: [] responses: "200": description: Extended memory settings content: application/json: schema: $ref: "#/components/schemas/MemorySettingsExtended" "401": $ref: "#/components/responses/Unauthorized" put: tags: - Memory - Settings summary: Update memory settings description: "Update any subset of the extended memory settings. All fields are optional; only provided fields are updated. Schema: `MemorySettingsExtendedSchema`." security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/MemorySettingsExtended" responses: "200": description: Updated memory settings content: application/json: schema: $ref: "#/components/schemas/MemorySettingsExtended" "400": description: Validation error "401": $ref: "#/components/responses/Unauthorized" /api/settings/qdrant: get: tags: - Memory - Settings summary: Get Qdrant settings description: Returns current Qdrant configuration. The `apiKey` field is never returned raw — use `hasApiKey` / `apiKeyMasked` instead. security: - ManagementSessionAuth: [] responses: "200": description: Qdrant settings content: application/json: schema: $ref: "#/components/schemas/QdrantSettings" "401": $ref: "#/components/responses/Unauthorized" put: tags: - Memory - Settings summary: Update Qdrant settings description: 'Update Qdrant configuration. Pass `apiKey: ""` to remove the stored key. Schema: `QdrantSettingsUpdateSchema`.' security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object properties: enabled: type: boolean host: type: string port: type: integer minimum: 1 maximum: 65535 collection: type: string minLength: 1 embeddingModel: type: string minLength: 1 apiKey: type: string description: Empty string removes the key additionalProperties: false responses: "200": description: Updated Qdrant settings content: application/json: schema: $ref: "#/components/schemas/QdrantSettings" "400": description: Validation error "401": $ref: "#/components/responses/Unauthorized" /api/settings/qdrant/health: get: tags: - Memory summary: Qdrant health probe description: Performs a liveness check against the configured Qdrant instance. Returns latency and any connection error (sanitized — no stack traces). security: - ManagementSessionAuth: [] responses: "200": description: Health result content: application/json: schema: $ref: "#/components/schemas/QdrantHealthResult" "401": $ref: "#/components/responses/Unauthorized" /api/settings/qdrant/search: post: tags: - Memory summary: Qdrant semantic search test description: "Performs a test semantic search against the Qdrant collection. Useful for validating that the integration works end-to-end. Schema: `QdrantSearchSchema`." security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object required: - query properties: query: type: string minLength: 1 topK: type: integer minimum: 1 maximum: 50 default: 5 additionalProperties: false responses: "200": description: Search results content: application/json: schema: type: object properties: results: type: array items: type: object "400": description: Validation error "401": $ref: "#/components/responses/Unauthorized" "503": description: Qdrant unavailable (structured error, no stack trace) /api/settings/qdrant/cleanup: post: tags: - Memory summary: Clean up expired Qdrant points description: Removes Qdrant points for memories that have expired or exceeded the configured retention window. security: - ManagementSessionAuth: [] responses: "200": description: Cleanup result content: application/json: schema: type: object properties: deleted: type: integer checked: type: integer "401": $ref: "#/components/responses/Unauthorized" "503": description: Qdrant unavailable (structured error, no stack trace) /api/settings/qdrant/embedding-models: get: tags: - Memory summary: List Qdrant embedding models description: Returns the list of embedding models available for use with Qdrant. security: - ManagementSessionAuth: [] responses: "200": description: Embedding models list content: application/json: schema: type: object properties: models: type: array items: type: string "401": $ref: "#/components/responses/Unauthorized" # ─── Proxy Endpoints ────────────────────────────────────────── /api/v1/chat/completions: post: tags: [Chat] summary: Create chat completion description: OpenAI-compatible chat completions endpoint. Routes to configured providers. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ChatCompletionRequest" responses: "200": description: Chat completion response (or SSE stream) headers: X-OmniRoute-Response-Cost: schema: type: string description: Request cost in USD, fixed 10 decimals (e.g. `0.0001234500`; `0.0000000000` for free/unpriced). X-OmniRoute-Tokens-In: schema: type: string description: Input (prompt) token count. X-OmniRoute-Tokens-Out: schema: type: string description: Output (completion) token count. X-OmniRoute-Model: schema: type: string description: Resolved model. X-OmniRoute-Provider: schema: type: string description: Resolved provider alias. X-OmniRoute-Latency-Ms: schema: type: string description: Handler latency in milliseconds. X-OmniRoute-Cache-Hit: schema: type: string enum: ["true", "false"] description: Whether the response was served from cache. X-OmniRoute-Fallback-Attempts: schema: type: string description: Number of fallback attempts (only present when > 0). X-OmniRoute-Decision: schema: type: string description: >- Routing decision trace: `strategy=; provider=; latency_ms=`. `` is the combo strategy (e.g. `priority`, `weighted`, `fusion`) or `single` for a non-combo request. Emitted on every completion response. X-OmniRoute-Request-Id: schema: type: string description: Request correlation id (present when known). X-OmniRoute-Version: schema: type: string description: OmniRoute build version (always present). X-OmniRoute-Cost-Saved: schema: type: string description: >- On a semantic-cache HIT, the original (would-have-been) cost in USD that the cache avoided (fixed 10 decimals). Present only on cache hits; X-OmniRoute-Response-Cost is 0 for the same response (incremental cost). content: application/json: schema: $ref: "#/components/schemas/ChatCompletionResponse" text/event-stream: schema: type: string "401": $ref: "#/components/responses/Unauthorized" "502": description: All upstream providers failed /api/v1/ws: get: tags: [Chat] summary: Chat completion over WebSocket (handshake + upgrade) description: >- OpenAI-compatible chat over a WebSocket connection. `GET` with `?handshake=1` returns the connection descriptor (auth path, message protocol and live-event channels) as JSON; a plain `GET` without an Upgrade returns `426 Upgrade Required`. After upgrading, the client exchanges JSON frames — `{type:"request", id, payload:{model, messages}}` to start a completion and `{type:"cancel", id}` to abort it. A separate live channel (default port `LIVE_WS_PORT=20129`, path `/live`) streams dashboard events on the `requests`, `combo` and `credentials` topics with a 15s heartbeat. Requires an API key. security: - BearerAuth: [] parameters: - name: handshake in: query description: Set to `1` to receive the JSON connection descriptor instead of upgrading. required: false schema: type: string enum: ["1"] responses: "101": description: WebSocket upgrade successful "200": description: Handshake descriptor (auth path, message protocol, live channels) "401": description: WebSocket auth required (no credential supplied) "403": description: Invalid WebSocket credential "426": description: Upgrade Required — connect via WebSocket or use `?handshake=1` /api/v1/providers/{provider}/chat/completions: post: tags: [Chat] summary: Create chat completion (provider-specific) description: Routes to a specific provider by name. security: - BearerAuth: [] parameters: - name: provider in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ChatCompletionRequest" responses: "200": description: Chat completion response "401": $ref: "#/components/responses/Unauthorized" /api/v1/api/chat: post: tags: [Chat] summary: Ollama-compatible chat endpoint description: Provides compatibility with Ollama's /api/chat format. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object responses: "200": description: Chat response (JSON or streaming) /api/v1/messages: post: tags: [Messages] summary: Create message (Anthropic-compatible) description: Anthropic Messages API endpoint. Routes to Claude providers. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/MessagesRequest" responses: "200": description: >- Message response (or SSE stream). Non-streaming success responses carry the `X-OmniRoute-*` cost-telemetry headers (see `POST /api/v1/chat/completions`), including `X-OmniRoute-Request-Id` and `X-OmniRoute-Version`. "401": $ref: "#/components/responses/Unauthorized" /api/v1/messages/count_tokens: post: tags: [Messages] summary: Count tokens for a message security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object responses: "200": description: Token count /api/v1/responses: post: tags: [Responses] summary: Create response (OpenAI Responses API) description: OpenAI Responses API endpoint. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object responses: "200": description: >- Response object or SSE stream. Non-streaming success responses carry the `X-OmniRoute-*` cost-telemetry headers (see `POST /api/v1/chat/completions`), including `X-OmniRoute-Request-Id` and `X-OmniRoute-Version`. "401": $ref: "#/components/responses/Unauthorized" /api/v1/embeddings: post: tags: [Embeddings] summary: Create embeddings security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [input, model] properties: input: description: >- Text, token IDs, or up to 32 canonical multimodal items. Structured media input is accepted only when the resolved registry model advertises the requested modalities. URL sources must be public HTTPS and are fetched server-side into bounded inline media (redirect revalidation, timeout, size limits, public DNS checks, and connection pinning) before provider submission. Inline media is limited to 8 MiB decoded per item and 16 MiB decoded per request. Canonical items are translated to provider-native request shapes (Jina modality-keyed objects / Gemini embedContent parts) rather than forwarded unchanged. oneOf: - type: string - type: array minItems: 1 items: type: string - type: array minItems: 1 items: type: integer minimum: 0 - type: array minItems: 1 items: type: array minItems: 1 items: type: integer minimum: 0 - type: array minItems: 1 maxItems: 32 items: $ref: "#/components/schemas/EmbeddingMultimodalItem" model: type: string dimensions: type: integer minimum: 1 encoding_format: type: string enum: [float, base64] additionalProperties: true responses: "200": description: >- Embedding vectors. Success responses carry the `X-OmniRoute-*` cost-telemetry headers (see `POST /api/v1/chat/completions`); media cost is computed per modality when pricing is available, otherwise `0` (fail-open). /api/v1/providers/{provider}/embeddings: post: tags: [Embeddings] summary: Create embeddings (provider-specific) security: - BearerAuth: [] parameters: - name: provider in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object responses: "200": description: Embedding vectors /api/v1/images/generations: post: tags: [Images] summary: Generate images security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [prompt] properties: prompt: type: string model: type: string n: type: integer default: 1 size: type: string default: 1024x1024 responses: "200": description: >- Generated images. Success responses carry the `X-OmniRoute-*` cost-telemetry headers (see `POST /api/v1/chat/completions`); image cost is computed per image when pricing is available, otherwise `0` (fail-open). /api/v1/providers/{provider}/images/generations: post: tags: [Images] summary: Generate images (provider-specific) security: - BearerAuth: [] parameters: - name: provider in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object responses: "200": description: Generated images /api/v1/audio/speech: post: tags: [Audio] summary: Generate speech audio description: Text-to-speech endpoint. Routes to configured TTS providers. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [input] properties: input: type: string model: type: string voice: type: string responses: "200": description: >- Audio data. Success responses carry the `X-OmniRoute-*` cost-telemetry headers (see `POST /api/v1/chat/completions`); speech cost is computed per character when pricing is available, otherwise `0` (fail-open). /api/v1/audio/transcriptions: post: tags: [Audio] summary: Transcribe audio description: Audio-to-text transcription endpoint. security: - BearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary model: type: string responses: "200": description: >- Transcription result. Success responses carry the `X-OmniRoute-*` cost-telemetry headers (see `POST /api/v1/chat/completions`); transcription cost is computed per second when pricing is available, otherwise `0` (fail-open). /api/v1/moderations: post: tags: [Moderations] summary: Create moderation description: Content moderation endpoint. Routes to configured moderation providers. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [input] properties: input: oneOf: - type: string - type: array items: type: string responses: "200": description: >- Moderation result. Success responses carry the `X-OmniRoute-*` cost-telemetry headers (see `POST /api/v1/chat/completions`); moderations are always cost `0` (free). /api/v1/rerank: post: tags: [Rerank] summary: Rerank documents description: Document reranking endpoint. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [query, documents] properties: query: type: string documents: type: array items: type: string model: type: string responses: "200": description: >- Reranked documents. Success responses carry the `X-OmniRoute-*` cost-telemetry headers (see `POST /api/v1/chat/completions`); rerank cost is computed per search-unit when pricing is available, otherwise `0` (fail-open). /api/v1: get: tags: [System] summary: API v1 root endpoint description: Returns basic API info and status. security: - BearerAuth: [] responses: "200": description: API info /api/v1/models: get: tags: [Models] summary: List available models description: Returns all models available across configured providers. security: - BearerAuth: [] responses: "200": description: Model list content: application/json: schema: type: object properties: object: type: string example: list data: type: array items: $ref: "#/components/schemas/Model" /api/v1/providers/{provider}/models: get: tags: [Models] summary: List models for a specific provider description: Returns only models for the selected provider with provider prefix removed from each model id. security: - BearerAuth: [] parameters: - in: path name: provider required: true schema: type: string description: Provider id or alias (for example `openai`, `claude`, `cc`). responses: "200": description: Provider-scoped model list content: application/json: schema: type: object properties: object: type: string example: list data: type: array items: $ref: "#/components/schemas/Model" "400": description: Unknown provider /api/models: get: tags: [Models] summary: List models (management) responses: "200": description: Internal model list with aliases /api/models/alias: post: tags: [Models] summary: Create or update a model alias requestBody: required: true content: application/json: schema: type: object responses: "200": description: Alias created/updated /api/models/catalog: get: tags: [Models] summary: Get full model catalog responses: "200": description: Complete catalog with all providers # ─── Management Endpoints ────────────────────────────────────── /api/providers: get: tags: [Providers] summary: List provider connections responses: "200": description: Provider connection list content: application/json: schema: type: object properties: connections: type: array items: $ref: "#/components/schemas/ProviderConnection" post: tags: [Providers] summary: Create provider connection requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ProviderConnectionCreate" responses: "201": description: Created provider connection /api/providers/{id}: get: tags: [Providers] summary: Get provider connection parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Provider connection details "404": description: Provider not found patch: tags: [Providers] summary: Update provider connection parameters: - $ref: "#/components/parameters/ResourceId" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ProviderConnectionCreate" responses: "200": description: Updated provider delete: tags: [Providers] summary: Delete provider connection parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Provider deleted /api/providers/{id}/test: post: tags: [Providers] summary: Test provider connection parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Test result /api/providers/{id}/models: get: tags: [Providers] summary: List models for a provider parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Provider model list /api/providers/test-batch: post: tags: [Providers] summary: Test multiple providers at once responses: "200": description: Batch test results /api/providers/validate: post: tags: [Providers] summary: Validate provider credentials responses: "200": description: Validation result /api/providers/client: get: tags: [Providers] summary: Get client-side provider info responses: "200": description: Provider info for frontend /api/providers/agy-auth/import: post: tags: [Providers] summary: Import an Antigravity CLI (agy) token file as an `agy` connection responses: "200": description: Created or updated provider connection /api/providers/agy-auth/import-bulk: post: tags: [Providers] summary: Bulk-import multiple Antigravity CLI (agy) token files (up to 50) responses: "200": description: Per-entry import results (success/failed counts) /api/providers/agy-auth/zip-extract: post: tags: [Providers] summary: Extract `.json` token files from an uploaded ZIP for agy bulk import responses: "200": description: Extracted token-file entries /api/providers/agy-auth/apply-local: post: tags: [Providers] summary: Auto-detect and import the local Antigravity CLI (agy) login from disk responses: "200": description: Created or updated provider connection "404": description: No local agy login found /api/provider-nodes: get: tags: [Provider Nodes] summary: List provider nodes responses: "200": description: Provider node list post: tags: [Provider Nodes] summary: Create provider node responses: "201": description: Created node /api/provider-nodes/{id}: patch: tags: [Provider Nodes] summary: Update provider node parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Updated node delete: tags: [Provider Nodes] summary: Delete provider node parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Node deleted /api/provider-nodes/validate: post: tags: [Provider Nodes] summary: Validate a provider node responses: "200": description: Validation result /api/provider-models: get: tags: [Provider Nodes] summary: List provider models responses: "200": description: Provider model list /api/keys: get: tags: [API Keys] summary: List API keys responses: "200": description: API key list content: application/json: schema: type: object properties: keys: type: array items: $ref: "#/components/schemas/ApiKey" "401": description: Authentication required post: tags: [API Keys] summary: Create API key requestBody: required: true content: application/json: schema: type: object required: [label] properties: label: type: string responses: "201": description: Created API key (includes full key value) "401": description: Authentication required /api/keys/{id}: get: tags: [API Keys] summary: Get API key parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: API key metadata "401": description: Authentication required "404": description: Key not found patch: tags: [API Keys] summary: Update API key parameters: - $ref: "#/components/parameters/ResourceId" requestBody: required: true content: application/json: schema: type: object additionalProperties: true responses: "200": description: API key settings updated "400": description: Invalid update request "401": description: Authentication required "404": description: Key not found delete: tags: [API Keys] summary: Delete API key parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Key deleted "401": description: Authentication required "404": description: Key not found /api/combos: get: tags: [Combos] summary: List routing combos responses: "200": description: Combo list post: tags: [Combos] summary: Create routing combo requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ComboCreate" responses: "201": description: Created combo /api/combos/{id}: patch: tags: [Combos] summary: Update combo parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Updated combo delete: tags: [Combos] summary: Delete combo parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Combo deleted /api/combos/metrics: get: tags: [Combos] summary: Get combo metrics responses: "200": description: Metrics for combos /api/combos/test: post: tags: [Combos] summary: Test a combo configuration responses: "200": description: Test result /api/settings: get: tags: [Settings] summary: Get application settings responses: "200": description: Current settings patch: tags: [Settings] summary: Update settings requestBody: required: true content: application/json: schema: type: object responses: "200": description: Updated settings /api/settings/purge-request-history: post: tags: [Settings] summary: Clear request log history description: Deletes `call_logs`, legacy `request_detail_logs`, and local request artifact files under `DATA_DIR/call_logs`. security: - ManagementSessionAuth: [] responses: "200": description: Request history cleared content: application/json: schema: type: object properties: deleted: type: integer deletedArtifacts: type: integer deletedDetailedLogs: type: integer errors: type: integer "401": description: Unauthorized "500": description: Cleanup failed or reported errors content: application/json: schema: type: object properties: deleted: type: integer deletedArtifacts: type: integer deletedDetailedLogs: type: integer errors: type: integer error: type: object /api/settings/compression: get: tags: [Compression] summary: Get global compression settings security: - ManagementSessionAuth: [] responses: "200": description: Current compression settings put: tags: [Compression] summary: Update global compression settings security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object properties: enabled: type: boolean defaultMode: type: string enum: [off, lite, standard, aggressive, ultra, rtk, stacked] autoTriggerMode: type: string enum: [off, lite, standard, aggressive, ultra, rtk, stacked] autoTriggerTokens: type: integer minimum: 0 rtkConfig: type: object additionalProperties: true stackedPipeline: type: array items: type: object responses: "200": description: Updated compression settings /api/settings/compression/mcp-accessibility: get: tags: [Compression] summary: Get the MCP tool-output accessibility (trimming) config security: - ManagementSessionAuth: [] responses: "200": description: Current mcpAccessibility config put: tags: [Compression] summary: Update the MCP tool-output accessibility (trimming) config description: >- Partial-merge update. Numeric floors (e.g. a maxTextChars below the truncation-tail reserve) are folded back to the safe defaults server-side, so the response reflects the effective config. security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object properties: enabled: type: boolean maxTextChars: type: integer minimum: 1 collapseThreshold: type: integer minimum: 1 collapseKeepHead: type: integer minimum: 0 collapseKeepTail: type: integer minimum: 0 minLengthToProcess: type: integer minimum: 1 responses: "200": description: Updated mcpAccessibility config (numeric floors applied) /api/compression/preview: post: tags: [Compression] summary: Preview compression for a message payload security: - BearerAuth: [] - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object required: [messages, mode] properties: mode: type: string enum: [off, lite, standard, aggressive, ultra, rtk, stacked] messages: type: array items: type: object required: [role, content] properties: role: type: string content: oneOf: - type: string - type: array items: {} config: type: object additionalProperties: true responses: "200": description: Compression preview with diff, validation, and stats /api/compression/language-packs: get: tags: [Compression] summary: List Caveman compression language packs security: - BearerAuth: [] - ManagementSessionAuth: [] responses: "200": description: Available languages and rule-pack metadata /api/compression/rules: get: tags: [Compression] summary: List Caveman compression rule metadata security: - BearerAuth: [] - ManagementSessionAuth: [] responses: "200": description: Caveman rule metadata /api/context/rtk/config: get: tags: [Compression] summary: Get RTK compression settings security: - ManagementSessionAuth: [] responses: "200": description: Current RTK config put: tags: [Compression] summary: Update RTK compression settings security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object properties: enabled: type: boolean intensity: type: string enum: [minimal, standard, aggressive] customFiltersEnabled: type: boolean trustProjectFilters: type: boolean rawOutputRetention: type: string enum: [never, failures, always] rawOutputMaxBytes: type: integer responses: "200": description: Updated RTK config /api/context/rtk/filters: get: tags: [Compression] summary: List RTK filters and load diagnostics security: - ManagementSessionAuth: [] responses: "200": description: RTK filter catalog and diagnostics /api/context/rtk/import: post: tags: [Compression] summary: Validate or install an RTK TOML schema v1 filter file security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object required: [action, content] additionalProperties: false properties: action: type: string enum: [validate, install] content: type: string maxLength: 1048576 overwrite: type: boolean description: Replace an existing global file and create a backup responses: "200": description: Filter metadata, inline-test outcomes, warnings, and installation status "400": description: Invalid TOML, schema, regular expression, inline test, or install request /api/context/rtk/test: post: tags: [Compression] summary: Run RTK compression preview for text security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: type: object required: [text] properties: text: type: string command: type: string config: type: object additionalProperties: true responses: "200": description: Detection and RTK compression result /api/context/rtk/raw-output/{id}: get: tags: [Compression] summary: Read retained redacted RTK raw output security: - ManagementSessionAuth: [] parameters: - in: path name: id required: true schema: type: string pattern: "^[a-f0-9]{24}$" responses: "200": description: Raw output text "404": description: Raw output not found /api/settings/payload-rules: get: tags: [Settings] summary: Get payload rules configuration description: | Returns the current payload rules used to mutate outgoing request payloads before they are sent upstream. Requires a dashboard management session cookie when management auth is enabled. security: - ManagementSessionAuth: [] responses: "200": description: Current payload rules configuration content: application/json: schema: $ref: "#/components/schemas/PayloadRulesConfig" "401": $ref: "#/components/responses/ManagementAuthenticationRequired" "403": $ref: "#/components/responses/ManagementInvalidToken" "500": description: Failed to read payload rules configuration content: application/json: schema: $ref: "#/components/schemas/ApiErrorResponse" put: tags: [Settings] summary: Update payload rules configuration description: | Persists and hot reloads payload rules. The legacy input field `default-raw` is accepted on writes and normalized to `defaultRaw` in responses/runtime state. Requires a dashboard management session cookie when management auth is enabled. security: - ManagementSessionAuth: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdatePayloadRulesRequest" responses: "200": description: Updated payload rules configuration content: application/json: schema: $ref: "#/components/schemas/PayloadRulesConfig" "400": $ref: "#/components/responses/ValidationError" "401": $ref: "#/components/responses/ManagementAuthenticationRequired" "403": $ref: "#/components/responses/ManagementInvalidToken" "500": description: Failed to update payload rules configuration content: application/json: schema: $ref: "#/components/schemas/ApiErrorResponse" /api/settings/combo-defaults: get: tags: [Settings] summary: Get combo default settings responses: "200": description: Default combo settings /api/settings/proxy: get: tags: [Settings] summary: Get proxy settings responses: "200": description: Current proxy settings patch: tags: [Settings] summary: Update proxy settings responses: "200": description: Updated proxy settings /api/settings/proxy/test: post: tags: [Settings] summary: Test proxy connection responses: "200": description: Test result /api/settings/require-login: post: tags: [Settings] summary: Toggle login requirement responses: "200": description: Updated /api/settings/ip-filter: get: tags: [Settings] summary: Get IP filter configuration description: Returns the current IP filter settings including blacklist, whitelist, and temp bans. responses: "200": description: IP filter configuration put: tags: [Settings] summary: Update IP filter configuration description: | Configure IP filtering with blacklist/whitelist modes, add/remove individual IPs, and manage temp bans. requestBody: required: true content: application/json: schema: type: object properties: enabled: type: boolean mode: type: string enum: [blacklist, whitelist] blacklist: type: array items: type: string whitelist: type: array items: type: string addBlacklist: type: string removeBlacklist: type: string addWhitelist: type: string removeWhitelist: type: string tempBan: type: object properties: ip: type: string durationMs: type: integer reason: type: string removeBan: type: string responses: "200": description: Updated IP filter configuration /api/settings/system-prompt: get: tags: [Settings] summary: Get system prompt configuration description: Returns the current system prompt injection settings. responses: "200": description: System prompt configuration put: tags: [Settings] summary: Update system prompt configuration requestBody: required: true content: application/json: schema: type: object properties: prompt: type: string enabled: type: boolean responses: "200": description: Updated system prompt configuration /api/settings/thinking-budget: get: tags: [Settings] summary: Get thinking budget configuration description: Returns the current thinking/reasoning budget settings for AI models. responses: "200": description: Thinking budget configuration put: tags: [Settings] summary: Update thinking budget configuration requestBody: required: true content: application/json: schema: type: object properties: mode: type: string description: Thinking mode (e.g., auto, manual, disabled) customBudget: type: integer minimum: 0 maximum: 131072 effortLevel: type: string enum: [none, low, medium, high] responses: "200": description: Updated thinking budget configuration /api/rate-limit: get: tags: [Settings] summary: Get rate limit configuration responses: "200": description: Rate limit settings post: tags: [Settings] summary: Update rate limit configuration requestBody: required: true content: application/json: schema: type: object responses: "200": description: Updated rate limit settings /api/tags: get: tags: [System] summary: List Ollama-compatible model tags description: Returns models in Ollama /api/tags format for Ollama client compatibility responses: "200": description: Ollama model tags # ─── Usage & Analytics ───────────────────────────────────────── /api/usage/analytics: get: tags: [Usage] summary: Get usage analytics parameters: - name: period in: query schema: type: string enum: [day, week, month] default: day responses: "200": description: Usage analytics data /api/usage/call-logs: get: tags: [Usage] summary: Get call logs parameters: - name: limit in: query schema: type: integer default: 50 - name: offset in: query schema: type: integer default: 0 responses: "200": description: Paginated call logs /api/usage/call-logs/{id}: get: tags: [Usage] summary: Get a specific call log parameters: - $ref: "#/components/parameters/ResourceId" responses: "200": description: Call log detail /api/usage/{connectionId}: get: tags: [Usage] summary: Get usage for a specific connection parameters: - name: connectionId in: path required: true schema: type: string responses: "200": description: Connection usage data /api/usage/history: get: tags: [Usage] summary: Get usage history responses: "200": description: Historical usage data /api/usage/logs: get: tags: [Usage] summary: Get usage logs responses: "200": description: Usage log entries /api/usage/proxy-logs: get: tags: [Usage] summary: Get proxy logs responses: "200": description: Proxy log entries /api/usage/request-logs: get: tags: [Usage] summary: Get request logs responses: "200": description: Request log entries /api/usage/budget: get: tags: [Usage] summary: Get usage budget status description: Returns current budget limits and consumption. responses: "200": description: Budget status post: tags: [Usage] summary: Configure usage budget description: Set or update budget limits for usage tracking. requestBody: required: true content: application/json: schema: type: object responses: "200": description: Updated budget configuration # ─── Pricing ─────────────────────────────────────────────────── /api/pricing: get: tags: [Pricing] summary: Get model pricing responses: "200": description: Current pricing configuration post: tags: [Pricing] summary: Set model pricing responses: "200": description: Updated pricing /api/pricing/defaults: get: tags: [Pricing] summary: Get default pricing responses: "200": description: Default pricing data /api/pricing/models: get: tags: [Pricing] summary: Get pricing per model description: Returns pricing information organized by model. responses: "200": description: Per-model pricing data # ─── Translator ──────────────────────────────────────────────── /api/translator/detect: post: tags: [Translator] summary: Detect request format description: Detects the API format of a request body (OpenAI, Claude, Gemini, etc.) requestBody: required: true content: application/json: schema: type: object required: [body] properties: body: type: object responses: "200": description: Detected format /api/translator/translate: post: tags: [Translator] summary: Translate between formats description: Converts a request between API formats (e.g. Claude → OpenAI) requestBody: required: true content: application/json: schema: type: object required: [sourceFormat, targetFormat, body] properties: step: type: string sourceFormat: type: string targetFormat: type: string provider: type: string body: type: object responses: "200": description: Translated request /api/translator/send: post: tags: [Translator] summary: Send translated request to provider requestBody: required: true content: application/json: schema: type: object required: [provider, body] properties: provider: type: string body: type: object responses: "200": description: Provider response (may be SSE stream) /api/translator/history: get: tags: [Translator] summary: Get translation history description: Returns recent translation events for the Live Monitor responses: "200": description: Translation history entries # ─── CLI Remote Mode ─────────────────────────────────────────── /api/cli/connect: post: tags: [CLI Remote Mode] summary: Exchange the management password for a scoped CLI access token description: > Remote-mode bootstrap. Public (password-gated) route: verifies the management password with brute-force lockout, then mints an `oma_` access token. The plaintext token is returned once. requestBody: required: true content: application/json: schema: type: object required: [password] properties: password: { type: string } name: { type: string } scope: { type: string, enum: [read, write, admin] } expiresInDays: { type: integer, minimum: 1, maximum: 3650 } responses: "200": description: Token minted (token returned once) "401": description: Invalid password "429": description: Too many failed attempts /api/cli/whoami: get: tags: [CLI Remote Mode] summary: Report the current credential (scope, name, expiry) responses: "200": description: Authenticated; access-token details when applicable "401": description: Authentication required /api/cli/tokens: get: tags: [CLI Remote Mode] summary: List access tokens (masked) — admin scope responses: "200": description: Masked token list "403": description: Insufficient scope post: tags: [CLI Remote Mode] summary: Create a scoped access token — admin scope requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: { type: string } scope: { type: string, enum: [read, write, admin] } expiresInDays: { type: integer, minimum: 1, maximum: 3650 } responses: "200": description: Token created (token returned once) "403": description: Insufficient scope /api/cli/tokens/{id}: delete: tags: [CLI Remote Mode] summary: Revoke an access token by id or display prefix — admin scope parameters: - name: id in: path required: true schema: { type: string } responses: "200": description: Token revoked "403": description: Insufficient scope "404": description: Token not found or already revoked # ─── CLI Tools ───────────────────────────────────────────────── /api/cli-tools/backups: get: tags: [CLI Tools] summary: List CLI tool backups responses: "200": description: Backup list post: tags: [CLI Tools] summary: Create CLI tool backup responses: "200": description: Backup created /api/cli-tools/runtime/{toolId}: get: tags: [CLI Tools] summary: Get runtime status for a CLI tool parameters: - name: toolId in: path required: true schema: type: string responses: "200": description: Runtime status /api/cli-tools/guide-settings/{toolId}: get: tags: [CLI Tools] summary: Get guide settings for a tool parameters: - name: toolId in: path required: true schema: type: string responses: "200": description: Guide settings /api/cli-tools/antigravity-mitm: get: tags: [CLI Tools] summary: Get Antigravity MITM proxy settings responses: "200": description: MITM proxy configuration post: tags: [CLI Tools] summary: Update Antigravity MITM proxy settings requestBody: required: true content: application/json: schema: type: object responses: "200": description: Updated MITM proxy configuration delete: tags: [CLI Tools] summary: Reset Antigravity MITM proxy settings responses: "200": description: MITM proxy settings reset /api/cli-tools/antigravity-mitm/alias: get: tags: [CLI Tools] summary: Get Antigravity MITM alias configuration responses: "200": description: Alias configuration put: tags: [CLI Tools] summary: Update Antigravity MITM alias configuration requestBody: required: true content: application/json: schema: type: object responses: "200": description: Updated alias configuration /api/cli-tools/claude-settings: get: tags: [CLI Tools] summary: Get Claude CLI settings responses: "200": description: Claude CLI configuration post: tags: [CLI Tools] summary: Apply Claude CLI settings requestBody: required: true content: application/json: schema: type: object responses: "200": description: Claude CLI settings applied delete: tags: [CLI Tools] summary: Reset Claude CLI settings responses: "200": description: Claude CLI settings reset /api/cli-tools/cline-settings: get: tags: [CLI Tools] summary: Get Cline CLI settings responses: "200": description: Cline CLI configuration post: tags: [CLI Tools] summary: Apply Cline CLI settings requestBody: required: true content: application/json: schema: type: object responses: "200": description: Cline CLI settings applied delete: tags: [CLI Tools] summary: Reset Cline CLI settings responses: "200": description: Cline CLI settings reset /api/cli-tools/codex-profiles: get: tags: [CLI Tools] summary: Get Codex profiles responses: "200": description: Codex profile list post: tags: [CLI Tools] summary: Create Codex profile requestBody: required: true content: application/json: schema: type: object responses: "200": description: Profile created put: tags: [CLI Tools] summary: Update Codex profile requestBody: required: true content: application/json: schema: type: object responses: "200": description: Profile updated delete: tags: [CLI Tools] summary: Delete Codex profile responses: "200": description: Profile deleted /api/cli-tools/codex-settings: get: tags: [CLI Tools] summary: Get Codex CLI settings responses: "200": description: Codex CLI configuration post: tags: [CLI Tools] summary: Apply Codex CLI settings requestBody: required: true content: application/json: schema: type: object responses: "200": description: Codex CLI settings applied delete: tags: [CLI Tools] summary: Reset Codex CLI settings responses: "200": description: Codex CLI settings reset /api/cli-tools/droid-settings: get: tags: [CLI Tools] summary: Get Droid CLI settings responses: "200": description: Droid CLI configuration post: tags: [CLI Tools] summary: Apply Droid CLI settings requestBody: required: true content: application/json: schema: type: object responses: "200": description: Droid CLI settings applied delete: tags: [CLI Tools] summary: Reset Droid CLI settings responses: "200": description: Droid CLI settings reset /api/cli-tools/kilo-settings: get: tags: [CLI Tools] summary: Get Kilo CLI settings responses: "200": description: Kilo CLI configuration post: tags: [CLI Tools] summary: Apply Kilo CLI settings requestBody: required: true content: application/json: schema: type: object responses: "200": description: Kilo CLI settings applied delete: tags: [CLI Tools] summary: Reset Kilo CLI settings responses: "200": description: Kilo CLI settings reset /api/cli-tools/openclaw-settings: get: tags: [CLI Tools] summary: Get OpenClaw CLI settings responses: "200": description: OpenClaw CLI configuration post: tags: [CLI Tools] summary: Apply OpenClaw CLI settings requestBody: required: true content: application/json: schema: type: object responses: "200": description: OpenClaw CLI settings applied delete: tags: [CLI Tools] summary: Reset OpenClaw CLI settings responses: "200": description: OpenClaw CLI settings reset # ─── Embedded Services ───────────────────────────────────────── # All routes LOCAL_ONLY (loopback only) — hard rule #17. # See docs/frameworks/EMBEDDED-SERVICES.md for full reference. /api/services/9router/install: post: tags: [Embedded Services] summary: Install 9Router from npm description: >- Installs the `9router` npm package under DATA_DIR/services/9router/. Uses execFile (no shell interpolation — hard rule #13). **LOCAL_ONLY** — loopback only. requestBody: required: false content: application/json: schema: type: object properties: version: type: string default: latest description: npm version tag or semver to install responses: "200": description: Install succeeded content: application/json: schema: type: object properties: ok: type: boolean installedVersion: type: string path: type: string "400": description: Invalid request body "500": description: npm install failed /api/services/9router/start: post: tags: [Embedded Services] summary: Start 9Router description: >- Spawns the 9Router process. Idempotent if already running. **LOCAL_ONLY** — loopback only. responses: "200": description: Service started (or already running) content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" "409": description: 9Router is not installed "503": description: Start failed /api/services/9router/stop: post: tags: [Embedded Services] summary: Stop 9Router description: >- Gracefully stops 9Router (SIGTERM → 15 s → SIGKILL). Idempotent. **LOCAL_ONLY** — loopback only. responses: "200": description: Service stopped content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" "503": description: Stop failed /api/services/9router/restart: post: tags: [Embedded Services] summary: Restart 9Router description: >- Equivalent to stop() then start() under the operation lock. **LOCAL_ONLY** — loopback only. responses: "200": description: Service restarted content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" /api/services/9router/update: post: tags: [Embedded Services] summary: Update 9Router to a newer npm version description: >- Stops the service (if running), installs the newer npm version, then restarts. **LOCAL_ONLY** — loopback only. requestBody: required: false content: application/json: schema: type: object properties: version: type: string default: latest responses: "200": description: Update succeeded content: application/json: schema: type: object properties: ok: type: boolean previousVersion: type: string installedVersion: type: string "400": description: Invalid request body "500": description: Update failed /api/services/9router/rotate-key: post: tags: [Embedded Services] summary: Rotate the 9Router API key description: >- Generates a new API key, encrypts it at-rest, and restarts the service to apply it. The plaintext key is never returned. **LOCAL_ONLY** — loopback only. responses: "200": description: Key rotated content: application/json: schema: type: object properties: keyRotated: type: boolean restarted: type: boolean "500": description: Rotation failed /api/services/9router/status: get: tags: [Embedded Services] summary: Get 9Router status description: >- Returns combined live supervisor state and DB metadata. **LOCAL_ONLY** — loopback only. responses: "200": description: Status response content: application/json: schema: $ref: "#/components/schemas/ServiceStatusExtended" "500": description: Status read failed /api/services/9router/auto-start: post: tags: [Embedded Services] summary: Toggle 9Router auto-start description: >- When enabled, 9Router starts automatically on the next OmniRoute boot. **LOCAL_ONLY** — loopback only. requestBody: required: true content: application/json: schema: type: object required: [enabled] properties: enabled: type: boolean responses: "200": description: Auto-start flag updated content: application/json: schema: type: object properties: autoStart: type: boolean "400": description: Invalid request body /api/services/cliproxy/install: post: tags: [Embedded Services] summary: Install CLIProxyAPI from npm description: >- Installs the CLIProxyAPI package under DATA_DIR/services/cliproxy/. **LOCAL_ONLY** — loopback only. requestBody: required: false content: application/json: schema: type: object properties: version: type: string default: latest responses: "200": description: Install succeeded content: application/json: schema: type: object properties: ok: type: boolean installedVersion: type: string "400": description: Invalid request body "500": description: npm install failed /api/services/cliproxy/start: post: tags: [Embedded Services] summary: Start CLIProxyAPI description: >- Spawns the CLIProxyAPI process. Idempotent if already running. **LOCAL_ONLY** — loopback only. responses: "200": description: Service started content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" "409": description: CLIProxyAPI is not installed "503": description: Start failed /api/services/cliproxy/stop: post: tags: [Embedded Services] summary: Stop CLIProxyAPI description: >- Gracefully stops CLIProxyAPI. Idempotent. **LOCAL_ONLY** — loopback only. responses: "200": description: Service stopped content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" /api/services/cliproxy/restart: post: tags: [Embedded Services] summary: Restart CLIProxyAPI description: >- stop() then start() under the operation lock. **LOCAL_ONLY** — loopback only. responses: "200": description: Service restarted content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" /api/services/cliproxy/update: post: tags: [Embedded Services] summary: Update CLIProxyAPI to a newer npm version description: >- Stops, installs newer version, restarts. **LOCAL_ONLY** — loopback only. requestBody: required: false content: application/json: schema: type: object properties: version: type: string default: latest responses: "200": description: Update succeeded content: application/json: schema: type: object properties: ok: type: boolean installedVersion: type: string "500": description: Update failed /api/services/cliproxy/status: get: tags: [Embedded Services] summary: Get CLIProxyAPI status description: >- Returns live supervisor state and DB metadata (no apiKeyMasked — CLIProxyAPI does not use an injected API key). **LOCAL_ONLY** — loopback only. responses: "200": description: Status response content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" /api/services/cliproxy/auto-start: post: tags: [Embedded Services] summary: Toggle CLIProxyAPI auto-start description: >- When enabled, CLIProxyAPI starts automatically on the next OmniRoute boot. **LOCAL_ONLY** — loopback only. requestBody: required: true content: application/json: schema: type: object required: [enabled] properties: enabled: type: boolean responses: "200": description: Auto-start flag updated content: application/json: schema: type: object properties: autoStart: type: boolean "400": description: Invalid request body /api/services/mux/install: post: tags: [Embedded Services] summary: Install Mux from npm description: >- Installs the `mux` npm package (coder/mux — local agent-orchestration daemon) under DATA_DIR/services/mux/. **LOCAL_ONLY** — loopback only. requestBody: required: false content: application/json: schema: type: object properties: version: type: string default: latest responses: "200": description: Install succeeded content: application/json: schema: type: object properties: ok: type: boolean installedVersion: type: string "400": description: Invalid request body "500": description: npm install failed /api/services/mux/start: post: tags: [Embedded Services] summary: Start Mux description: >- Spawns `mux server --host 127.0.0.1 --port `. Idempotent if already running. **LOCAL_ONLY** — loopback only. responses: "200": description: Service started content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" "409": description: Mux is not installed "503": description: Start failed /api/services/mux/stop: post: tags: [Embedded Services] summary: Stop Mux description: >- Gracefully stops Mux. Idempotent. **LOCAL_ONLY** — loopback only. responses: "200": description: Service stopped content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" /api/services/mux/restart: post: tags: [Embedded Services] summary: Restart Mux description: >- stop() then start() under the operation lock. **LOCAL_ONLY** — loopback only. responses: "200": description: Service restarted content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" /api/services/mux/update: post: tags: [Embedded Services] summary: Update Mux to a newer npm version description: >- Stops, installs newer version, restarts. **LOCAL_ONLY** — loopback only. requestBody: required: false content: application/json: schema: type: object properties: version: type: string default: latest responses: "200": description: Update succeeded content: application/json: schema: type: object properties: ok: type: boolean installedVersion: type: string "500": description: Update failed /api/services/mux/status: get: tags: [Embedded Services] summary: Get Mux status description: >- Returns live supervisor state and DB metadata. **LOCAL_ONLY** — loopback only. responses: "200": description: Status response content: application/json: schema: $ref: "#/components/schemas/ServiceStatus" /api/services/mux/auto-start: post: tags: [Embedded Services] summary: Toggle Mux auto-start description: >- When enabled, Mux starts automatically on the next OmniRoute boot. **LOCAL_ONLY** — loopback only. requestBody: required: true content: application/json: schema: type: object required: [enabled] properties: enabled: type: boolean responses: "200": description: Auto-start flag updated content: application/json: schema: type: object properties: autoStart: type: boolean "400": description: Invalid request body /api/services/bifrost/install: post: tags: [Embedded Services] summary: Install Bifrost description: >- Installs the `@maximhq/bifrost` npm package under DATA_DIR/services/bifrost/. The package downloads the Go binary on first run. Accepts an optional `version` field (semver or `latest`). **LOCAL_ONLY** — loopback only. requestBody: required: false content: application/json: schema: type: object properties: version: type: string default: latest responses: "200": description: Installation result content: application/json: schema: type: object properties: ok: type: boolean installedVersion: type: string installPath: type: string durationMs: type: number /api/services/bifrost/start: post: tags: [Embedded Services] summary: Start Bifrost description: Starts the supervised Bifrost process. **LOCAL_ONLY** — loopback only. responses: "200": description: Service status after start "409": description: Bifrost is not installed /api/services/bifrost/stop: post: tags: [Embedded Services] summary: Stop Bifrost description: Stops the supervised Bifrost process. **LOCAL_ONLY** — loopback only. responses: "200": description: Service status after stop /api/services/bifrost/restart: post: tags: [Embedded Services] summary: Restart Bifrost description: Restarts the supervised Bifrost process. **LOCAL_ONLY** — loopback only. responses: "200": description: Service status after restart "409": description: Bifrost is not installed /api/services/bifrost/update: post: tags: [Embedded Services] summary: Update Bifrost description: >- Updates Bifrost to the latest npm version. Stops the running process, installs the new version, and restarts if it was previously running. **LOCAL_ONLY** — loopback only. responses: "200": description: Update result /api/services/bifrost/status: get: tags: [Embedded Services] summary: Get Bifrost status description: Returns live and DB status for the supervised Bifrost service. **LOCAL_ONLY** — loopback only. responses: "200": description: Bifrost service status /api/services/bifrost/auto-start: post: tags: [Embedded Services] summary: Toggle Bifrost auto-start description: >- When enabled, Bifrost starts automatically on the next OmniRoute boot. **LOCAL_ONLY** — loopback only. requestBody: required: true content: application/json: schema: type: object required: [enabled] properties: enabled: type: boolean responses: "204": description: Auto-start flag updated "400": description: Invalid request body /api/services/{name}/logs: get: tags: [Embedded Services] summary: Stream service logs via SSE description: >- Returns a Server-Sent Events stream from the service's in-memory ring buffer (5 MB, circular). Sends a `snapshot` event with historical lines first, then live `log` events, plus a `heartbeat` every 15 s. **LOCAL_ONLY** — loopback only. parameters: - name: name in: path required: true schema: type: string enum: [9router, cliproxy] - name: tail in: query schema: type: integer default: 200 maximum: 1000 description: Number of historical lines to include in the initial snapshot - name: filter in: query schema: type: string maxLength: 200 description: >- Case-insensitive substring filter applied to log lines. No regex — ReDoS-safe by design. responses: "200": description: SSE log stream content: text/event-stream: schema: type: string description: >- Events: `snapshot` (LogLine[]), `log` (LogLine), `heartbeat` ({}) "400": description: filter parameter exceeds maximum length "404": description: Service not found # ─── OAuth ───────────────────────────────────────────────────── /api/oauth/{provider}/{action}: get: tags: [OAuth] summary: OAuth flow handler description: Handles OAuth authorization and callback for providers parameters: - name: provider in: path required: true schema: type: string - name: action in: path required: true schema: type: string enum: [authorize, callback, refresh, status] responses: "200": description: OAuth flow response "302": description: Redirect to provider auth page /api/oauth/cursor/auto-import: get: tags: [OAuth] summary: Auto-import Cursor OAuth credentials description: Automatically detects and imports Cursor credentials from local config. responses: "200": description: Import result /api/oauth/cursor/import: get: tags: [OAuth] summary: Get Cursor import status responses: "200": description: Current import status post: tags: [OAuth] summary: Import Cursor OAuth credentials requestBody: required: true content: application/json: schema: type: object responses: "200": description: Credentials imported /api/oauth/kiro/auto-import: get: tags: [OAuth] summary: Auto-import Kiro OAuth credentials description: Automatically detects and imports Kiro credentials from local config. responses: "200": description: Import result /api/oauth/kiro/import: get: tags: [OAuth] summary: Get Kiro import status responses: "200": description: Current import status post: tags: [OAuth] summary: Import Kiro OAuth credentials requestBody: required: true content: application/json: schema: type: object responses: "200": description: Credentials imported /api/oauth/kiro/social-authorize: get: tags: [OAuth] summary: Initiate Kiro social OAuth authorization description: Starts the social OAuth flow for Kiro. responses: "302": description: Redirect to OAuth provider /api/oauth/kiro/social-exchange: post: tags: [OAuth] summary: Exchange Kiro social OAuth token description: Exchanges the authorization code for access tokens. requestBody: required: true content: application/json: schema: type: object responses: "200": description: Token exchange result # ─── Cloud ───────────────────────────────────────────────────── /api/cloud/auth: post: tags: [Cloud] summary: Authenticate with cloud worker description: Authenticates with the OmniRoute cloud worker for remote access. requestBody: required: true content: application/json: schema: type: object responses: "200": description: Authentication result /api/cloud/credentials/update: put: tags: [Cloud] summary: Update cloud worker credentials requestBody: required: true content: application/json: schema: type: object responses: "200": description: Credentials updated /api/cloud/model/resolve: post: tags: [Cloud] summary: Resolve model via cloud description: Resolves a model request through the cloud worker. requestBody: required: true content: application/json: schema: type: object responses: "200": description: Resolved model info /api/cloud/models/alias: get: tags: [Cloud] summary: Get cloud model aliases responses: "200": description: Cloud model alias list put: tags: [Cloud] summary: Update cloud model alias requestBody: required: true content: application/json: schema: type: object responses: "200": description: Alias updated # ─── Fallback ────────────────────────────────────────────────── /api/fallback/chains: get: tags: [Fallback] summary: List fallback chains description: Returns all registered fallback chains for model routing. responses: "200": description: Fallback chain list post: tags: [Fallback] summary: Create fallback chain description: Registers a fallback routing chain for a model. requestBody: required: true content: application/json: schema: type: object required: [model, chain] properties: model: type: string chain: type: array items: type: object properties: provider: type: string priority: type: integer enabled: type: boolean responses: "200": description: Fallback chain created delete: tags: [Fallback] summary: Delete fallback chain requestBody: required: true content: application/json: schema: type: object required: [model] properties: model: type: string responses: "200": description: Fallback chain deleted # ─── System ──────────────────────────────────────────────────── /api/auth/login: post: tags: [System] summary: Authenticate user requestBody: required: true content: application/json: schema: type: object required: [password] properties: password: type: string minLength: 1 responses: "200": description: JWT token returned "400": description: Invalid login request "401": description: Invalid password "403": description: Password setup required "429": description: Too many failed attempts /api/auth/logout: post: tags: [System] summary: Log out responses: "200": description: Session cleared /api/init: get: tags: [System] summary: Initialize application responses: "200": description: Init status /api/restart: post: tags: [System] summary: Restart the application responses: "200": description: Restart initiated /api/shutdown: post: tags: [System] summary: Shutdown the application x-always-protected: true responses: "200": description: Shutdown initiated /api/db-backups: get: tags: [System] summary: List database backups responses: "200": description: Backup list post: tags: [System] summary: Create database backup responses: "200": description: Backup created patch: tags: [System] summary: Save database backup retention settings requestBody: required: true content: application/json: schema: type: object properties: keepLatest: type: integer minimum: 1 maximum: 200 retentionDays: type: integer minimum: 0 maximum: 3650 responses: "200": description: Backup retention settings saved /api/storage/health: get: tags: [System] summary: Check storage health responses: "200": description: Storage health status /api/sync/cloud: post: tags: [System] summary: Sync with cloud responses: "200": description: Sync result /api/sync/initialize: post: tags: [System] summary: Initialize cloud sync responses: "200": description: Sync initialized # ─── Resilience & Monitoring ──────────────────────────────────── /api/resilience: get: tags: [System] summary: Get resilience configuration responses: "200": description: Request queue, connection cooldown, provider breaker, and wait settings patch: tags: [System] summary: Update resilience configuration requestBody: required: true content: application/json: schema: type: object responses: "200": description: Updated resilience configuration /api/resilience/reset: post: tags: [System] summary: Reset circuit breakers responses: "200": description: Circuit breakers reset /api/monitoring/health: get: tags: [System] summary: System health check description: Returns system health including uptime, memory, circuit breakers, rate limits responses: "200": description: Health status /api/rate-limits: get: tags: [System] summary: Get per-account rate limit status responses: "200": description: Rate limit status by account /api/sessions: get: tags: [System] summary: Get active sessions responses: "200": description: Active session list /api/cache: get: tags: [System] summary: Get cache statistics responses: "200": description: Semantic cache and idempotency stats delete: tags: [System] summary: Clear all caches responses: "200": description: Caches cleared /api/cache/stats: get: tags: [System] summary: Get detailed cache statistics description: Returns detailed statistics for all cache layers. responses: "200": description: Detailed cache stats delete: tags: [System] summary: Clear cache statistics responses: "200": description: Cache stats cleared # ─── Telemetry & Token Health ─────────────────────────────────── /api/telemetry/summary: get: tags: [Telemetry] summary: Get telemetry summary description: Returns aggregated telemetry data including request metrics and performance stats. responses: "200": description: Telemetry summary data /api/token-health: get: tags: [Telemetry] summary: Get token health status description: Returns health status of OAuth tokens across all providers. responses: "200": description: Token health status # ─── Evals & Policies ────────────────────────────────────────── /api/evals: get: tags: [System] summary: List eval suites responses: "200": description: Eval suite list post: tags: [System] summary: Run evaluation requestBody: required: true content: application/json: schema: type: object responses: "200": description: Eval results /api/evals/{suiteId}: get: tags: [System] summary: Get eval suite details parameters: - name: suiteId in: path required: true schema: type: string responses: "200": description: Eval suite details /api/policies: get: tags: [System] summary: List routing policies responses: "200": description: Policy list post: tags: [System] summary: Create routing policy requestBody: required: true content: application/json: schema: type: object responses: "201": description: Created policy delete: tags: [System] summary: Delete routing policy responses: "200": description: Policy deleted /api/compliance/audit-log: get: tags: [System] summary: Get compliance audit log description: > Returns paginated audit log entries. Use `level=high` to filter to high-level actions only (powers the Activity feed). Use `level=all` (default) for full compliance table. security: - bearerAuth: [] parameters: - name: level in: query schema: type: string enum: [high, all] default: all description: "high = Activity feed events only; all = all audit events" - name: action in: query schema: type: string description: Filter by exact action string (e.g. "provider.added") - name: actor in: query schema: type: string description: Filter by actor identifier - name: limit in: query schema: type: integer default: 50 maximum: 500 - name: offset in: query schema: type: integer default: 0 responses: "200": description: Audit log entries "401": description: Unauthorized "500": description: Internal server error # ─── Quota Sharing (Group B, plan 22) ──────────────────────────── /api/quota/pools: get: tags: [Quota] summary: List quota pools security: - bearerAuth: [] responses: "200": description: Array of QuotaPool objects content: application/json: schema: type: array items: $ref: "#/components/schemas/QuotaPool" "401": description: Unauthorized "500": description: Internal server error post: tags: [Quota] summary: Create quota pool security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PoolCreate" responses: "201": description: Pool created content: application/json: schema: $ref: "#/components/schemas/QuotaPool" "400": description: Validation error (Zod) "401": description: Unauthorized "500": description: Internal server error /api/quota/pools/{id}: get: tags: [Quota] summary: Get quota pool by ID security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: "200": description: QuotaPool object content: application/json: schema: $ref: "#/components/schemas/QuotaPool" "401": description: Unauthorized "404": description: Pool not found "500": description: Internal server error patch: tags: [Quota] summary: Update quota pool (name or allocations) security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PoolUpdate" responses: "200": description: Updated pool "400": description: Validation error "401": description: Unauthorized "404": description: Pool not found "500": description: Internal server error delete: tags: [Quota] summary: Delete quota pool security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: "204": description: Deleted "401": description: Unauthorized "404": description: Pool not found "500": description: Internal server error /api/quota/pools/{id}/usage: get: tags: [Quota] summary: Get pool usage snapshot (per-key consumption + burn rate) security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: "200": description: PoolUsageSnapshot content: application/json: schema: $ref: "#/components/schemas/PoolUsageSnapshot" "401": description: Unauthorized "404": description: Pool not found "500": description: Internal server error /api/quota/plans: get: tags: [Quota] summary: List resolved provider plans (catalog + manual overrides) security: - bearerAuth: [] responses: "200": description: Array of ProviderPlan "401": description: Unauthorized "500": description: Internal server error /api/quota/plans/{connectionId}: get: tags: [Quota] summary: Get resolved plan for a connection security: - bearerAuth: [] parameters: - name: connectionId in: path required: true schema: type: string responses: "200": description: ProviderPlan (source = auto | manual) "401": description: Unauthorized "404": description: Connection not found "500": description: Internal server error put: tags: [Quota] summary: Upsert manual plan override for a connection security: - bearerAuth: [] parameters: - name: connectionId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PlanUpsert" responses: "200": description: Updated plan "400": description: Validation error (Zod) "401": description: Unauthorized "500": description: Internal server error delete: tags: [Quota] summary: Delete manual plan override (reverts to catalog/auto) security: - bearerAuth: [] parameters: - name: connectionId in: path required: true schema: type: string responses: "204": description: Override deleted "401": description: Unauthorized "404": description: Override not found "500": description: Internal server error /api/quota/preview: get: tags: [Quota] summary: Dry-run quota enforcement check (preview only, no consumption recorded) security: - bearerAuth: [] parameters: - name: apiKeyId in: query required: true schema: type: string - name: poolId in: query required: true schema: type: string - name: estimatedTokens in: query schema: type: number - name: estimatedUsd in: query schema: type: number - name: estimatedRequests in: query schema: type: integer responses: "200": description: EnforceDecision (allow/block + reason) "400": description: Validation error (Zod) "401": description: Unauthorized "500": description: Internal server error /api/settings/quota-store: get: tags: [Settings] summary: Get current quota store driver settings description: Redis URL is masked in the response (shows only scheme+host). security: - bearerAuth: [] responses: "200": description: QuotaStoreSettings (driver + masked redisUrl) "401": description: Unauthorized "500": description: Internal server error put: tags: [Settings] summary: Update quota store driver settings security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/QuotaStoreSettings" responses: "200": description: Settings updated "400": description: Validation error (Zod) — e.g. driver=redis without valid URL "401": description: Unauthorized "500": description: Internal server error # ─── v1beta (Gemini-Compatible) ───────────────────────────────── /api/v1beta/models: get: tags: [Models] summary: List models (Gemini format) description: Returns models in Gemini v1beta format for native SDK compatibility security: - BearerAuth: [] responses: "200": description: Model list in Gemini format /api/v1beta/models/{path}: post: tags: [Models] summary: Gemini generateContent description: Gemini-compatible generateContent endpoint security: - BearerAuth: [] parameters: - name: path in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object responses: "200": description: Generated content # ─── AgentBridge ────────────────────────────────────────────── /api/tools/agent-bridge/agents: get: tags: [AgentBridge] summary: List all 9 IDE agents with current state description: >- Returns the state (dns_enabled, cert_trusted, setup_completed, last_started_at, last_error) for all 9 configured IDE agents. LOCAL_ONLY. responses: "200": description: Array of agent state rows content: application/json: schema: type: array items: $ref: "#/components/schemas/AgentBridgeAgentState" "403": description: Loopback-only — request came from a non-loopback address /api/tools/agent-bridge/state: get: tags: [AgentBridge] summary: Get global AgentBridge server state description: Returns running status, port, cert info, and intercepted request count. responses: "200": description: Server state content: application/json: schema: $ref: "#/components/schemas/AgentBridgeServerState" /api/tools/agent-bridge/server: post: tags: [AgentBridge] summary: Control AgentBridge MITM server description: Start, stop, restart, trust-cert, or regenerate-cert. SPAWN_CAPABLE. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AgentBridgeServerAction" responses: "200": description: Action executed "400": description: Invalid action "409": description: Port 443 conflict /api/tools/agent-bridge/agents/{agentId}/dns: post: tags: [AgentBridge] summary: Enable or disable DNS for one agent description: Adds or removes /etc/hosts entries for the agent's host list. SPAWN_CAPABLE. parameters: - name: agentId in: path required: true schema: $ref: "#/components/schemas/AgentId" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AgentBridgeDnsAction" responses: "200": description: DNS updated "400": description: Validation error /api/tools/agent-bridge/agents/{agentId}/mappings: get: tags: [AgentBridge] summary: Get model mappings for one agent parameters: - name: agentId in: path required: true schema: $ref: "#/components/schemas/AgentId" responses: "200": description: Array of source→target model mappings content: application/json: schema: type: array items: $ref: "#/components/schemas/AgentBridgeMappingRow" put: tags: [AgentBridge] summary: Update model mappings for one agent parameters: - name: agentId in: path required: true schema: $ref: "#/components/schemas/AgentId" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AgentBridgeMappingPut" responses: "200": description: Mappings updated /api/tools/agent-bridge/bypass: get: tags: [AgentBridge] summary: List bypass patterns (hosts never decrypted) responses: "200": description: Bypass patterns content: application/json: schema: type: array items: $ref: "#/components/schemas/AgentBridgeBypassRow" put: tags: [AgentBridge] summary: Update user bypass patterns requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AgentBridgeBypassUpsert" responses: "200": description: Patterns updated /api/tools/agent-bridge/cert: post: tags: [AgentBridge] summary: Download or regenerate the AgentBridge CA certificate requestBody: required: true content: application/json: schema: type: object required: [action] properties: action: type: string enum: [download, regenerate] responses: "200": description: CA certificate PEM (download) or regeneration confirmation /api/tools/agent-bridge/upstream-ca: get: tags: [AgentBridge] summary: Get configured upstream CA cert path responses: "200": description: Upstream CA configuration content: application/json: schema: type: object properties: path: type: string nullable: true post: tags: [AgentBridge] summary: Set upstream CA cert path for corporate TLS environments requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AgentBridgeUpstreamCaPost" responses: "200": description: Upstream CA configured "400": description: Path does not exist or is not readable # ─── Traffic Inspector ───────────────────────────────────────── /api/tools/traffic-inspector/requests: get: tags: [Traffic Inspector] summary: List intercepted requests (filterable) parameters: - name: profile in: query schema: type: string enum: [llm, custom, all] - name: host in: query schema: type: string - name: agent in: query schema: $ref: "#/components/schemas/AgentId" - name: status in: query schema: type: string enum: ["2xx", "3xx", "4xx", "5xx", error] - name: source in: query schema: $ref: "#/components/schemas/CaptureSource" - name: sessionId in: query schema: type: string format: uuid responses: "200": description: Array of intercepted requests content: application/json: schema: type: array items: $ref: "#/components/schemas/InterceptedRequest" delete: tags: [Traffic Inspector] summary: Clear the in-memory traffic buffer responses: "204": description: Buffer cleared /api/tools/traffic-inspector/requests/{id}: get: tags: [Traffic Inspector] summary: Get a single intercepted request by ID parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: Intercepted request details content: application/json: schema: $ref: "#/components/schemas/InterceptedRequest" "404": description: Request not found in buffer /api/tools/traffic-inspector/requests/{id}/replay: post: tags: [Traffic Inspector] summary: Replay a captured request through OmniRoute router description: Re-executes the original request body against /v1/chat/completions. Consumes quota. parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: Replay response (streaming or JSON) "404": description: Request not found /api/tools/traffic-inspector/requests/{id}/annotation: put: tags: [Traffic Inspector] summary: Save or update annotation on a request parameters: - name: id in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/InspectorAnnotationPut" responses: "200": description: Annotation saved /api/tools/traffic-inspector/ws: get: tags: [Traffic Inspector] summary: Live WebSocket stream of intercepted requests description: >- Upgrade to WebSocket. On connect, server sends `{type:"snapshot", data:[...]}`. Subsequent events: `{type:"new", data:{...}}`, `{type:"update", data:{...}}`, `{type:"clear"}`. LOCAL_ONLY. responses: "101": description: WebSocket upgrade successful "403": description: Non-loopback origin rejected /api/tools/traffic-inspector/export.har: get: tags: [Traffic Inspector] summary: Export current filtered request list as HAR 1.2 parameters: - name: profile in: query schema: type: string enum: [llm, custom, all] - name: sessionId in: query schema: type: string format: uuid responses: "200": description: HAR file (JSON) content: application/json: schema: type: object description: HAR 1.2 format /api/tools/traffic-inspector/hosts: get: tags: [Traffic Inspector] summary: List custom capture hosts responses: "200": description: Custom hosts list content: application/json: schema: type: array items: $ref: "#/components/schemas/InspectorCustomHost" post: tags: [Traffic Inspector] summary: Add a custom capture host (edits /etc/hosts) requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/InspectorCustomHostCreate" responses: "201": description: Host added "409": description: Host already exists /api/tools/traffic-inspector/hosts/{host}: delete: tags: [Traffic Inspector] summary: Remove a custom capture host parameters: - name: host in: path required: true schema: type: string responses: "204": description: Host removed patch: tags: [Traffic Inspector] summary: Toggle enabled state of a custom host parameters: - name: host in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: [enabled] properties: enabled: type: boolean responses: "200": description: Host updated /api/tools/traffic-inspector/capture-modes: get: tags: [Traffic Inspector] summary: Get state of all 4 capture modes responses: "200": description: Capture modes state content: application/json: schema: $ref: "#/components/schemas/InspectorCaptureModesState" /api/tools/traffic-inspector/capture-modes/http-proxy: post: tags: [Traffic Inspector] summary: Start or stop the HTTP_PROXY listener (port 8080) description: SPAWN_CAPABLE — spawns a net.Server listener. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/InspectorCaptureModeAction" responses: "200": description: Action executed "409": description: Port conflict (EADDRINUSE) when starting /api/tools/traffic-inspector/capture-modes/system-proxy: post: tags: [Traffic Inspector] summary: Apply or revert system-wide proxy settings description: SPAWN_CAPABLE — executes networksetup/gsettings/netsh. Requires admin. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/InspectorSystemProxyAction" responses: "200": description: System proxy updated "500": description: OS command failed (permission error) /api/tools/traffic-inspector/capture-modes/tls-intercept: post: tags: [Traffic Inspector] summary: Toggle TLS body decryption in HTTP_PROXY mode requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/InspectorTlsInterceptToggle" responses: "200": description: TLS intercept mode updated /api/tools/traffic-inspector/sessions: get: tags: [Traffic Inspector] summary: List all saved recording sessions responses: "200": description: Sessions list content: application/json: schema: type: array items: $ref: "#/components/schemas/InspectorSession" post: tags: [Traffic Inspector] summary: Start a new recording session requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/InspectorSessionStart" responses: "201": description: Session started content: application/json: schema: $ref: "#/components/schemas/InspectorSession" /api/tools/traffic-inspector/sessions/{id}: get: tags: [Traffic Inspector] summary: Get session snapshot (all captured requests) parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: Session with embedded requests "404": description: Session not found patch: tags: [Traffic Inspector] summary: Stop or rename a recording session parameters: - name: id in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/InspectorSessionPatch" responses: "200": description: Session updated delete: tags: [Traffic Inspector] summary: Delete a recording session parameters: - name: id in: path required: true schema: type: string format: uuid responses: "204": description: Session deleted /api/tools/traffic-inspector/sessions/{id}/export.har: get: tags: [Traffic Inspector] summary: Export a recorded session as HAR 1.2 parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: HAR file for this session content: application/json: schema: type: object description: HAR 1.2 format "404": description: Session not found /api/tools/traffic-inspector/internal/ingest: post: tags: [Traffic Inspector] summary: Internal ingest endpoint for server.cjs passthrough path description: >- Accepts a serialized InterceptedRequest from the CJS MITM server for requests that do not go through TypeScript handlers (e.g., passthrough hosts). Requires INSPECTOR_INTERNAL_INGEST_TOKEN header. LOCAL_ONLY. security: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/InterceptedRequest" responses: "204": description: Ingested "401": description: Invalid or missing ingest token # ─── OpenAPI Spec ────────────────────────────────────────────── /api/openapi/spec: get: tags: [System] summary: Get OpenAPI specification catalog description: >- Returns a structured JSON catalog parsed from this `openapi.yaml`, including info, servers, tags, schemas, and a flat list of endpoints (method, path, tags, summary, security, parameters, responses). Used by the in-app API explorer. responses: "200": description: Parsed OpenAPI catalog content: application/json: schema: type: object properties: info: type: object servers: type: array items: type: object tags: type: array items: type: object endpoints: type: array items: type: object properties: method: type: string path: type: string tags: type: array items: type: string summary: type: string description: type: string security: type: boolean parameters: type: array items: type: object requestBody: type: boolean responses: type: array items: type: string schemas: type: array items: type: string "404": description: openapi.yaml file not found on disk "500": description: Failed to parse OpenAPI spec # ─── Agent Skills Catalog ──────────────────────────────────────────────────── /api/agent-skills: get: tags: [Agent Skills] summary: List agent skills catalog description: | Returns the full 42-entry Agent Skills catalog with optional filtering. Skills describe how to use OmniRoute's REST API and CLI — they are structured SKILL.md documentation files discoverable by external agents, MCP clients, and A2A orchestrators. No authentication required. parameters: - name: category in: query required: false schema: type: string enum: [api, cli] description: Filter by category (api = REST API skills, cli = CLI skills) - name: area in: query required: false schema: type: string description: Filter by area slug (e.g. "providers", "models", "cli-serve") responses: "200": description: Catalog list content: application/json: schema: type: object required: [skills, count, coverage] properties: skills: type: array items: $ref: "#/components/schemas/AgentSkill" count: type: integer coverage: $ref: "#/components/schemas/SkillCoverage" "400": $ref: "#/components/responses/BadRequest" "500": $ref: "#/components/responses/InternalError" /api/agent-skills/{id}: get: tags: [Agent Skills] summary: Get a single agent skill description: | Returns metadata for a single agent skill by its canonical ID (e.g. `omni-providers`, `cli-serve`). No authentication required. parameters: - name: id in: path required: true schema: type: string pattern: "^[a-z][a-z0-9-]*$" description: Canonical skill ID example: omni-providers responses: "200": description: Agent skill metadata content: application/json: schema: $ref: "#/components/schemas/AgentSkill" "400": $ref: "#/components/responses/BadRequest" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalError" /api/agent-skills/{id}/raw: get: tags: [Agent Skills] summary: Get raw SKILL.md content description: | Returns the SKILL.md content for a skill as `text/markdown`. Resolution order: local filesystem `skills/{id}/SKILL.md` → GitHub raw URL (1-hour cache). No authentication required. parameters: - name: id in: path required: true schema: type: string pattern: "^[a-z][a-z0-9-]*$" description: Canonical skill ID example: omni-providers responses: "200": description: SKILL.md content as Markdown headers: X-Skill-Source: schema: type: string enum: [filesystem, github, generated] description: Where the content was loaded from X-Skill-Fetched-At: schema: type: string format: date-time description: ISO timestamp of when the content was fetched Cache-Control: schema: type: string description: "public, max-age=3600" content: text/markdown: schema: type: string "400": $ref: "#/components/responses/BadRequest" "404": $ref: "#/components/responses/NotFound" "502": description: Upstream GitHub fetch failed content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": $ref: "#/components/responses/InternalError" /api/agent-skills/coverage: get: tags: [Agent Skills] summary: Get SKILL.md coverage stats description: | Returns how many of the 22 API skills and 20 CLI skills have SKILL.md files on the local filesystem vs the catalog totals. No authentication required. responses: "200": description: Coverage stats content: application/json: schema: $ref: "#/components/schemas/SkillCoverage" "500": $ref: "#/components/responses/InternalError" /api/agent-skills/generate: post: tags: [Agent Skills] summary: Trigger SKILL.md generator description: | Runs the Agent Skills generator which writes `skills/{id}/SKILL.md` for all 42 catalog entries (or a subset via `onlyIds`). Preserves ` ... ` blocks. **Requires management authentication.** security: - BearerAuth: [] - ManagementSessionAuth: [] requestBody: required: false content: application/json: schema: type: object properties: dryRun: type: boolean default: true description: "If true, reports what would be generated without writing files" prune: type: boolean default: false description: "If true, deletes skill directories not in the catalog" onlyIds: type: array items: type: string description: "If provided, only regenerate these skill IDs" responses: "200": description: Generator report content: application/json: schema: type: object required: [generated, unchanged, pruned, orphansDetected, errors] properties: generated: type: array items: type: string description: IDs that got new/updated SKILL.md unchanged: type: array items: type: string description: IDs whose content was already up to date pruned: type: array items: type: string description: IDs whose directories were deleted (prune mode) orphansDetected: type: array items: type: string description: Directories found in skills/ not in the catalog errors: type: array items: type: object required: [id, error] properties: id: type: string error: type: string "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalError" "503": description: Generator module not available /api/v1/ocr: post: tags: - Images summary: Document OCR description: >- Mistral OCR–compatible document OCR endpoint. Accepts a JSON body referencing a document/image and returns extracted text. Success responses carry the `X-OmniRoute-*` cost-telemetry headers. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object properties: model: type: string document: type: object responses: "200": description: OCR result with extracted text. "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalError" /api/v1/audio/translations: post: tags: - Audio summary: Translate audio to English description: >- OpenAI Whisper–compatible audio translation (multipart/form-data). Unlike `/api/v1/audio/transcriptions`, output is always English regardless of the source language. Success responses carry the `X-OmniRoute-*` cost-telemetry headers. security: - BearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: - file properties: file: type: string format: binary model: type: string responses: "200": description: English translation of the audio. "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalError" /api/v1/providers/suggested-models: get: tags: - Providers summary: Suggested media models description: >- Read-only server-side proxy to the public HuggingFace Hub models search API, used by the dashboard to suggest models for a media provider kind without exposing an HF token client-side. Never accepts or returns credentials. parameters: - name: type in: query schema: type: string description: Media kind to search for (e.g. `image`, `audio`, `video`). responses: "200": description: List of suggested HuggingFace Hub models. "500": $ref: "#/components/responses/InternalError" /api/v1/provider-plugin-manifest: get: tags: - Providers summary: Provider plugin manifest description: Returns the manifest describing installed provider plugins. responses: "200": description: Provider plugin manifest. "500": $ref: "#/components/responses/InternalError" /api/keys/{id}/devices: get: tags: - API Keys summary: List devices for an API key description: >- Lists the distinct devices (masked IP + User-Agent fingerprints) tracked for an API key by the in-memory device tracker. IPs are masked before storage; the route never sees the raw client IP. x-internal: true parameters: - name: id in: path required: true schema: type: string responses: "200": description: Distinct devices seen for the API key. "401": $ref: "#/components/responses/ManagementAuthenticationRequired" "404": $ref: "#/components/responses/NotFound" /api/settings/purge-usage-history: post: tags: - Settings summary: Purge usage history description: Dashboard-only. Purges stored usage-history records. x-internal: true responses: "200": description: Usage history purged. "401": $ref: "#/components/responses/Unauthorized" /api/oauth/codex/import-token: post: tags: - OAuth summary: Import a Codex connection from a bare access token description: >- Dashboard-only. Creates a Codex (ChatGPT/OpenAI) connection from a raw access token with no refresh token (authType `access_token`). x-internal: true responses: "200": description: Connection imported. "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" /api/cli-tools/crush-settings: get: tags: - CLI Tools summary: Read Crush CLI OmniRoute config description: Local-only. Reads the OmniRoute provider block in Crush's config. x-internal: true responses: "200": description: Current Crush config state. post: tags: - CLI Tools summary: Write Crush CLI OmniRoute config description: Local-only. Registers OmniRoute as an `openai-compat` provider in Crush's config. x-internal: true responses: "200": description: Crush config updated. delete: tags: - CLI Tools summary: Remove OmniRoute from Crush CLI config description: Local-only. Removes the OmniRoute provider block from Crush's config. x-internal: true responses: "200": description: Crush config entry removed. /api/cli-tools/codewhale-settings: get: tags: - CLI Tools summary: Read CodeWhale CLI OmniRoute config description: >- Local-only. Reads the OmniRoute config block from `~/.codewhale/config.toml` (with `~/.deepseek/config.toml` legacy fallback). x-internal: true responses: "200": description: Current CodeWhale config state. post: tags: - CLI Tools summary: Write CodeWhale CLI OmniRoute config description: Local-only. Writes the OmniRoute config block in CodeWhale TOML format. x-internal: true responses: "200": description: CodeWhale config updated. delete: tags: - CLI Tools summary: Remove OmniRoute from CodeWhale CLI config description: Local-only. Removes the OmniRoute config block from CodeWhale's config. x-internal: true responses: "200": description: CodeWhale config entry removed. components: securitySchemes: BearerAuth: type: http scheme: bearer description: API key obtained from the OmniRoute dashboard ManagementSessionAuth: type: apiKey in: cookie name: auth_token description: Dashboard management session cookie for protected management routes parameters: ResourceId: name: id in: path required: true schema: type: string responses: Unauthorized: description: Missing or invalid API key content: application/json: schema: type: object properties: error: type: string example: Unauthorized ManagementAuthenticationRequired: description: Authentication required for management routes content: application/json: schema: $ref: "#/components/schemas/ApiErrorResponse" example: error: message: Authentication required type: invalid_request requestId: 3f9f6f5a-509a-4b35-b0a7-2d2d99d73a01 ManagementInvalidToken: description: Bearer tokens are not accepted for management routes content: application/json: schema: $ref: "#/components/schemas/ApiErrorResponse" example: error: message: Invalid management token type: invalid_request requestId: 1b6a6ff8-d60c-4900-8d0a-25f81749f0a3 ValidationError: description: Request body failed validation content: application/json: schema: $ref: "#/components/schemas/ValidationErrorResponse" BadRequest: description: The request was malformed or failed validation content: application/json: schema: $ref: "#/components/schemas/ApiErrorResponse" example: error: message: Invalid request type: invalid_request_error requestId: 8c2b1d44-7a3e-4c91-9b0f-1e2d3c4b5a60 NotFound: description: The requested resource was not found content: application/json: schema: $ref: "#/components/schemas/ApiErrorResponse" example: error: message: Resource not found type: not_found_error requestId: 4d5e6f70-1a2b-3c4d-5e6f-7a8b9c0d1e2f InternalError: description: An unexpected server error occurred content: application/json: schema: $ref: "#/components/schemas/ApiErrorResponse" example: error: message: Internal server error type: api_error requestId: 0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d schemas: EmbeddingMultimodalItem: oneOf: - type: object required: [type, text] properties: type: type: string const: text text: type: string minLength: 1 - type: object required: [type, source] properties: type: type: string enum: [image, audio, video, document] source: oneOf: - type: object required: [type, url] properties: type: type: string const: url url: type: string format: uri description: Public HTTPS URL. - type: object required: [type, data, media_type] properties: type: type: string const: base64 data: type: string format: byte media_type: type: string description: Provider-neutral structured embedding input item. PlaygroundPreset: type: object required: - id - name - endpoint - model - params - created_at properties: id: type: string format: uuid name: type: string maxLength: 100 endpoint: type: string description: Playground endpoint key (e.g. "chat.completions") model: type: string system: type: string nullable: true params: type: object additionalProperties: true description: Serialized parameter values (temperature, max_tokens, etc.) created_at: type: string format: date-time PlaygroundPresetCreate: type: object required: - name - endpoint - model properties: name: type: string minLength: 1 maxLength: 100 endpoint: type: string minLength: 1 model: type: string minLength: 1 system: type: string nullable: true params: type: object additionalProperties: true default: {} MemoryEntry: type: object description: A single persisted memory entry properties: id: type: string description: UUID apiKeyId: type: string sessionId: type: string nullable: true type: type: string enum: - factual - episodic - procedural - semantic key: type: string description: Stable upsert key (e.g. preference:i_prefer_python) content: type: string metadata: type: object additionalProperties: true createdAt: type: string format: date-time updatedAt: type: string format: date-time expiresAt: type: string format: date-time nullable: true needsReindex: type: integer description: 1 if the vector for this memory is stale or missing MemorySettingsExtended: type: object description: Extended memory settings including 7 new fields from plan 21. All fields are optional for PUT (patch semantics). properties: enabled: type: boolean maxTokens: type: integer minimum: 0 maximum: 16000 retentionDays: type: integer minimum: 1 maximum: 365 strategy: type: string enum: - recent - semantic - hybrid skillsEnabled: type: boolean embeddingSource: type: string enum: - remote - static - transformers - auto description: Which embedding source to use. "auto" = remote > static > transformers. embeddingProviderModel: type: string nullable: true description: Embedding provider/model in "provider/model" format (e.g. openai/text-embedding-3-small). transformersEnabled: type: boolean description: Opt-in for Transformers.js local MiniLM model (~400MB RAM) staticEnabled: type: boolean description: Opt-in for static potion-base-8M local model rerankEnabled: type: boolean description: Enable reranking step (+200-500ms/req) rerankProviderModel: type: string nullable: true description: Rerank provider/model in "provider/model" format vectorStore: type: string enum: - sqlite-vec - qdrant - auto description: Which vector backend to use QdrantSettings: type: object description: Qdrant vector database configuration (read shape — no raw apiKey) properties: enabled: type: boolean host: type: string port: type: integer minimum: 1 maximum: 65535 collection: type: string embeddingModel: type: string hasApiKey: type: boolean apiKeyMasked: type: string nullable: true description: First 4 chars of the configured API key, or null QdrantHealthResult: type: object description: Result of a Qdrant liveness probe properties: ok: type: boolean latencyMs: type: number error: type: string nullable: true description: Sanitized error message (no stack traces) AgentSkill: type: object description: >- Single entry in the Agent Skills catalog. Describes one OmniRoute REST API surface (category: api) or CLI subcommand group (category: cli) with a canonical ID and a link to its SKILL.md documentation file. required: [id, name, description, category, area, rawUrl, githubUrl] properties: id: type: string pattern: "^[a-z][a-z0-9-]*$" description: Canonical skill ID (e.g. "omni-providers", "cli-serve") example: omni-providers name: type: string minLength: 1 maxLength: 100 description: Human-readable skill name example: Provider Management description: type: string minLength: 1 maxLength: 2000 description: One-paragraph description of what the skill covers category: type: string enum: [api, cli] description: "api = REST API skill; cli = CLI subcommand skill" area: type: string minLength: 1 maxLength: 50 description: Functional area slug (e.g. "providers", "combos-routing", "cli-serve") example: providers endpoints: type: array items: type: string description: REST API endpoints (present for api-category skills only) example: ["POST /api/providers", "GET /api/providers/:id"] cliCommands: type: array items: type: string description: CLI subcommand names (present for cli-category skills only) example: ["providers list", "providers test", "providers rotate"] icon: type: string description: Material symbol icon name for dashboard display isEntry: type: boolean description: Whether this is a recommended starting point isNew: type: boolean description: Whether this skill was added in a recent release rawUrl: type: string format: uri description: GitHub raw URL of the SKILL.md file example: "https://raw.githubusercontent.com/diegosouzapw/OmniRoute/refs/heads/main/skills/omni-providers/SKILL.md" githubUrl: type: string format: uri description: GitHub blob URL for viewing the SKILL.md in the browser example: "https://github.com/diegosouzapw/OmniRoute/blob/main/skills/omni-providers/SKILL.md" SkillCoverage: type: object description: >- Coverage statistics for the Agent Skills catalog: how many of the 22 REST API skills and 20 CLI skills have generated SKILL.md files on the local filesystem. required: [api, cli, totalSkills, generatedAt] properties: api: type: object required: [have, total] properties: have: type: integer minimum: 0 maximum: 22 description: Number of API skills with SKILL.md on disk total: type: integer enum: [22] description: Canonical API skill count (always 22) cli: type: object required: [have, total] properties: have: type: integer minimum: 0 maximum: 20 description: Number of CLI skills with SKILL.md on disk total: type: integer enum: [20] description: Canonical CLI skill count (always 20) totalSkills: type: integer minimum: 0 maximum: 42 description: Sum of api.have + cli.have generatedAt: type: string format: date-time description: ISO datetime when coverage was last computed ErrorResponse: type: object description: Standard error response body required: [error] properties: error: type: object required: [message] properties: message: type: string description: Human-readable error message (never includes stack traces) code: type: string description: Machine-readable error code # ─── AgentBridge Schemas ──────────────────────────────────────── AgentId: type: string enum: - antigravity - kiro - copilot - codex - cursor - zed - claude-code - open-code - trae description: One of the 9 supported IDE agents AgentBridgeAgentState: type: object description: Per-agent MITM state properties: agent_id: $ref: "#/components/schemas/AgentId" dns_enabled: type: boolean cert_trusted: type: boolean setup_completed: type: boolean last_started_at: type: string format: date-time nullable: true last_error: type: string nullable: true AgentBridgeServerState: type: object description: Global AgentBridge MITM server state properties: running: type: boolean port: type: integer example: 443 certReady: type: boolean interceptedCount: type: integer activeConnections: type: integer lastStartedAt: type: string format: date-time nullable: true AgentBridgeServerAction: type: object required: [action] properties: action: type: string enum: [start, stop, restart, trust-cert, regenerate-cert] AgentBridgeDnsAction: type: object required: [enabled] properties: enabled: type: boolean AgentBridgeMappingRow: type: object properties: agent_id: $ref: "#/components/schemas/AgentId" source_model: type: string example: gpt-4o target_model: type: string example: claude-sonnet-4.7 updated_at: type: string format: date-time AgentBridgeMappingPut: type: object required: [mappings] properties: mappings: type: array items: type: object required: [source, target] properties: source: type: string example: gpt-4o target: type: string example: claude-sonnet-4.7 AgentBridgeBypassRow: type: object properties: pattern: type: string example: "*.bank.*" source: type: string enum: [default, user] created_at: type: string format: date-time AgentBridgeBypassUpsert: type: object required: [patterns] properties: patterns: type: array items: type: string example: ["*.bank.*", "*.gov.*"] AgentBridgeUpstreamCaPost: type: object required: [path] properties: path: type: string description: Absolute path to a PEM file for corporate upstream CA example: "/etc/ssl/certs/corporate-ca.pem" # ─── Traffic Inspector Schemas ────────────────────────────────── CaptureSource: type: string enum: [agent-bridge, custom-host, http-proxy, system-proxy] DetectedKind: type: string enum: [llm, app, unknown] InterceptedRequest: type: object description: A single intercepted HTTP request captured by the Traffic Inspector required: [ id, source, timestamp, method, host, path, requestHeaders, requestSize, responseHeaders, responseSize, status, ] properties: id: type: string format: uuid source: $ref: "#/components/schemas/CaptureSource" agent: $ref: "#/components/schemas/AgentId" timestamp: type: string format: date-time method: type: string example: POST host: type: string example: api.githubcopilot.com path: type: string example: /v1/chat/completions requestHeaders: type: object additionalProperties: type: string requestBody: type: string nullable: true description: Masked (secrets replaced with ***) requestSize: type: integer responseHeaders: type: object additionalProperties: type: string responseBody: type: string nullable: true responseSize: type: integer status: oneOf: - type: integer - type: string enum: [in-flight, error] proxyLatencyMs: type: number nullable: true upstreamLatencyMs: type: number nullable: true totalLatencyMs: type: number nullable: true error: type: string nullable: true description: Sanitized error message (no stack traces) sourceModel: type: string nullable: true mappedModel: type: string nullable: true detectedKind: $ref: "#/components/schemas/DetectedKind" contextKey: type: string nullable: true description: 12-char SHA-256 hex of the system prompt (for conversation grouping) example: a3f9c2b1d5e4 annotation: type: string nullable: true sessionId: type: string format: uuid nullable: true note: type: string nullable: true description: Informational note (e.g. TLS tunnel metadata) InspectorCustomHost: type: object properties: host: type: string example: api.openai.com enabled: type: boolean label: type: string nullable: true kind: type: string enum: [llm, app, custom] added_at: type: string format: date-time last_seen_at: type: string format: date-time nullable: true InspectorCustomHostCreate: type: object required: [host] properties: host: type: string minLength: 1 example: my-internal-llm.company.com enabled: type: boolean default: true label: type: string nullable: true kind: type: string enum: [llm, app, custom] default: custom InspectorCaptureModesState: type: object properties: agentBridge: type: object properties: active: type: boolean customHosts: type: object properties: active: type: boolean count: type: integer httpProxy: type: object properties: active: type: boolean port: type: integer example: 8080 systemProxy: type: object properties: active: type: boolean guardMinutes: type: integer InspectorCaptureModeAction: type: object required: [action] properties: action: type: string enum: [start, stop] InspectorSystemProxyAction: type: object required: [action] properties: action: type: string enum: [apply, revert] port: type: integer minimum: 1 maximum: 65535 example: 8080 guardMinutes: type: integer minimum: 1 example: 30 InspectorTlsInterceptToggle: type: object required: [enabled] properties: enabled: type: boolean InspectorAnnotationPut: type: object required: [annotation] properties: annotation: type: string maxLength: 10000 InspectorSession: type: object properties: id: type: string format: uuid name: type: string nullable: true started_at: type: string format: date-time ended_at: type: string format: date-time nullable: true request_count: type: integer profile: type: string enum: [llm, custom, all] nullable: true InspectorSessionStart: type: object properties: name: type: string example: "Antigravity test run #1" InspectorSessionPatch: type: object required: [action] properties: action: type: string enum: [stop, rename] name: type: string QuotaPool: type: object description: A quota sharing pool — binds a provider connection to allocation rules. required: [id, connectionId, name, createdAt, allocations] properties: id: type: string connectionId: type: string name: type: string createdAt: type: string format: date-time allocations: type: array items: $ref: "#/components/schemas/PoolAllocation" PoolAllocation: type: object required: [apiKeyId, weight, policy] properties: apiKeyId: type: string weight: type: number minimum: 0 maximum: 100 description: Share percentage (0–100) capValue: type: number nullable: true description: Absolute cap value (optional) capUnit: type: string enum: [percent, requests, tokens, usd] nullable: true policy: type: string enum: [hard, soft, burst] PoolCreate: type: object required: [connectionId, name] properties: connectionId: type: string name: type: string maxLength: 120 allocations: type: array items: $ref: "#/components/schemas/PoolAllocation" default: [] PoolUpdate: type: object properties: name: type: string maxLength: 120 allocations: type: array items: $ref: "#/components/schemas/PoolAllocation" PoolUsageSnapshot: type: object required: [poolId, generatedAt, dimensions] properties: poolId: type: string generatedAt: type: string format: date-time dimensions: type: array items: type: object properties: unit: type: string enum: [percent, requests, tokens, usd] window: type: string enum: ["5h", hourly, daily, weekly, monthly] limit: type: number consumedTotal: type: number perKey: type: array items: type: object properties: apiKeyId: type: string consumed: type: number fairShare: type: number deficit: type: number description: "Negative = surplus; positive = over-allocation" borrowing: type: boolean burnRate: type: object nullable: true properties: tokensPerSecond: type: number timeToExhaustionMs: type: number nullable: true QuotaDimension: type: object required: [unit, window, limit] properties: unit: type: string enum: [percent, requests, tokens, usd] window: type: string enum: ["5h", hourly, daily, weekly, monthly] limit: type: number minimum: 0 PlanUpsert: type: object required: [dimensions] properties: dimensions: type: array minItems: 1 items: $ref: "#/components/schemas/QuotaDimension" QuotaStoreSettings: type: object required: [driver] properties: driver: type: string enum: [sqlite, redis] redisUrl: type: string format: uri nullable: true description: Redis connection URL (write-only; masked in GET responses) ServiceStatus: type: object description: Live supervisor state for an embedded service properties: tool: type: string example: 9router state: type: string enum: [not_installed, stopped, starting, running, stopping, error] pid: type: integer nullable: true port: type: integer example: 20130 health: type: string enum: [unknown, healthy, degraded] startedAt: type: string format: date-time nullable: true lastError: type: string nullable: true ServiceStatusExtended: allOf: - $ref: "#/components/schemas/ServiceStatus" - type: object description: >- Extended status including version metadata and (for 9Router) API key preview. properties: installedVersion: type: string nullable: true latestVersion: type: string nullable: true updateAvailable: type: boolean apiKeyMasked: type: string nullable: true description: >- Masked API key preview (e.g. "nr_****abcd"). Present only for services that use an injected API key (9Router). autoStart: type: boolean providerExpose: type: boolean description: >- Whether models from this service are exposed as a routing provider. 9Router only. ApiErrorResponse: type: object properties: error: type: object properties: message: type: string type: type: string details: description: Optional additional error details requestId: type: string format: uuid ValidationErrorResponse: type: object properties: error: type: object required: [message, details] properties: message: type: string example: Invalid request details: type: array items: type: object required: [field, message] properties: field: type: string message: type: string PayloadRuleModelSpec: type: object additionalProperties: false required: [name] properties: name: type: string minLength: 1 protocol: type: string minLength: 1 PayloadMutationRule: type: object additionalProperties: false required: [models, params] properties: models: type: array minItems: 1 items: $ref: "#/components/schemas/PayloadRuleModelSpec" params: type: object minProperties: 1 additionalProperties: true PayloadFilterRule: type: object additionalProperties: false required: [models, params] properties: models: type: array minItems: 1 items: $ref: "#/components/schemas/PayloadRuleModelSpec" params: type: array minItems: 1 items: type: string minLength: 1 PayloadRulesConfig: type: object additionalProperties: false required: [default, override, filter, defaultRaw] properties: default: type: array items: $ref: "#/components/schemas/PayloadMutationRule" override: type: array items: $ref: "#/components/schemas/PayloadMutationRule" filter: type: array items: $ref: "#/components/schemas/PayloadFilterRule" defaultRaw: type: array items: $ref: "#/components/schemas/PayloadMutationRule" UpdatePayloadRulesRequest: type: object additionalProperties: false description: At least one payload-rules section must be present in the request body. properties: default: type: array items: $ref: "#/components/schemas/PayloadMutationRule" override: type: array items: $ref: "#/components/schemas/PayloadMutationRule" filter: type: array items: $ref: "#/components/schemas/PayloadFilterRule" defaultRaw: type: array items: $ref: "#/components/schemas/PayloadMutationRule" default-raw: type: array items: $ref: "#/components/schemas/PayloadMutationRule" anyOf: - required: [default] - required: [override] - required: [filter] - required: [defaultRaw] - required: [default-raw] ChatCompletionRequest: type: object required: [model, messages] properties: model: type: string example: gpt-4o messages: type: array items: type: object required: [role] properties: role: type: string description: >- Message role. The proxy accepts any non-empty string; common values include system, user, assistant, tool, function, and developer. example: user content: description: >- Message content. May be a plain string, an array of content parts for multimodal inputs (text, image, audio, etc.), or null when the message only carries tool/function calls. oneOf: - type: string - type: array items: type: object - type: "null" name: type: string tool_call_id: type: string tool_calls: type: array items: type: object function_call: type: object stream: type: boolean default: false temperature: type: number minimum: 0 maximum: 2 max_tokens: type: integer top_p: type: number minimum: 0 maximum: 1 n: type: integer minimum: 1 default: 1 stop: description: Up to 4 stop sequences (string or array of strings). oneOf: - type: string - type: array items: type: string maxItems: 4 frequency_penalty: type: number minimum: -2 maximum: 2 presence_penalty: type: number minimum: -2 maximum: 2 seed: type: integer logprobs: type: boolean top_logprobs: type: integer minimum: 0 maximum: 20 response_format: type: object description: Output format constraint (e.g. JSON mode or JSON Schema). properties: type: type: string example: json_object tools: type: array description: Tool definitions available to the model. items: type: object tool_choice: description: Controls which tool (if any) is invoked by the model. oneOf: - type: string example: auto - type: object parallel_tool_calls: type: boolean default: true service_tier: type: string example: auto user: type: string description: Stable end-user identifier for abuse monitoring. ChatCompletionResponse: type: object properties: id: type: string object: type: string example: chat.completion choices: type: array items: type: object properties: index: type: integer message: type: object properties: role: type: string content: type: string finish_reason: type: string usage: type: object properties: prompt_tokens: type: integer completion_tokens: type: integer total_tokens: type: integer MessagesRequest: type: object required: [model, messages, max_tokens] properties: model: type: string example: claude-sonnet-4-5-20250514 messages: type: array items: type: object required: [role, content] properties: role: type: string enum: [user, assistant] content: type: string max_tokens: type: integer stream: type: boolean default: false system: type: string Model: type: object properties: id: type: string object: type: string example: model owned_by: type: string ProviderConnection: type: object properties: id: type: string provider: type: string name: type: string url: type: string isActive: type: boolean maxConcurrent: type: integer nullable: true minimum: 0 priority: type: integer testStatus: type: string enum: [active, error, untested] createdAt: type: string format: date-time ProviderConnectionCreate: type: object required: [provider, url] properties: provider: type: string example: openai name: type: string url: type: string apiKey: type: string isActive: type: boolean default: true maxConcurrent: type: integer nullable: true minimum: 0 ApiKey: type: object properties: id: type: string label: type: string keyPreview: type: string description: Last 4 characters of the key isActive: type: boolean createdAt: type: string format: date-time ComboCreate: type: object required: [name, model] properties: name: type: string model: type: string strategy: type: string enum: - priority - weighted - round-robin - context-relay - fill-first - p2c - random - least-used - cost-optimized - reset-aware - reset-window - headroom - strict-random - auto - lkgp - context-optimized - fusion default: priority nodes: type: array items: type: object properties: connectionId: type: string weight: type: integer priority: type: integer