openapi: 3.1.0 info: title: OmniRoute API version: 3.8.40 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-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: oneOf: - type: string - type: array items: type: string model: type: string 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/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/{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 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: 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