* fix(gemini): preserve structured tool calls for antigravity * fix(gemini): parse prefixed textual tool calls * fix(antigravity): preserve textual SSE tool calls * fix(stream): normalize textual passthrough tool calls * fix(stream): normalize split textual tool calls * fix(stream): suppress malformed textual tool calls * fix(stream): suppress compact malformed tool calls * fix(stream): emit structured textual tool calls * fix(stream): suppress unknown textual tool calls * fix(stream): normalize responses textual tool calls * chore: ignore .claude/settings.local.json (per-user Claude Code permissions) * fix(opencode-go): route qwen3.x via claude messages + repair fixMissingToolResponses for Claude-shape upstreams (#2791) Integrated into release/v3.8.6 * fix: resolve npm install warnings — remove dead deps, relax engine constraint (#2792) Integrated into release/v3.8.6 * fix: register missing web-cookie validators (claude-web, gemini-web, copilot-web, t3-web) (#2793) Integrated into release/v3.8.6 * fix: Error: Unable to inspect existing database #2771 (#2795) Integrated into release/v3.8.6 * fix(oauth): repair Google loopback callback flow (#2796) Integrated into release/v3.8.6 * feat(logs): add clean history button (#2799) Integrated into release/v3.8.6 * [codex] home: restore settings-driven home layout and quota auto-refresh (#2800) Integrated into release/v3.8.6 * fix(gemini): emit signaturelessToolCallMode:text for GEMINI format models (#2801) Integrated into release/v3.8.6 * feat(modelSpecs): align opencode-go family with upstream provider limits (#2802) Integrated into release/v3.8.6 * chore: apply unit test fixes, polyfills, and environment precedence fixes * docs(agents): atualiza fluxos de release e triagem Expande os workflows de release para incluir auditoria de segurança, CHANGELOG completo por commits, quality gate obrigatório, homologação em VPS local, publicação oficial, deploy em Akamai e validação de artefatos. Reorganiza a triagem de features com arquivos permanentes por bucket, suporte a itens em andamento, regra de reclaim após 15 dias e novo tratamento para ideias viáveis catalogadas. Corrige a orientação de revisão de discussões para usar a ordem cronológica real dos comentários e respostas ao identificar a última atividade. * fix(lockout): classify Gemini Antigravity resource exhaustion as quota_exhausted * fix(reasoning): gate replay by interleaved field * docs(rule-16): permit human Co-authored-by, restrict only AI/bot trailers Rule #16 previously banned all `Co-Authored-By` trailers absolutely. That blocked the upstream-port workflows (`/port-upstream-features` and `/port-upstream-issues`), which must credit human upstream PR authors and issue reporters in OmniRoute commits. Refine the rule to ban only AI/bot-attributed trailers (Claude, GPT, Copilot, Bot; anthropic.com / openai.com / bot-owned noreply.github.com emails) while allowing standard human `Co-authored-by: Name <email>` attribution. Sync the rule across the source CLAUDE.md, the E2E shakedown doc note, and 41 i18n translations. * fix(gitlawb): add specialty validators for connection test — bypass /models probe GitLawB OpenGateway API (xiaomi-mimo compatible) does not expose a /models endpoint, causing validateOpenAILikeProvider to 404 on the initial probe and report 'Provider validation endpoint not supported'. Add specialty validators for both gitlawb and gitlawb-gmi that follow the same pattern as the existing xiaomi-mimo validator: skip GET /models, validate directly via POST /chat/completions with a minimal test message. Any 401/403 response means an invalid key; all other responses mean auth is OK. Fixes test-connection returning 404 for GitLawB providers. * test(gitlawb): add 12 unit tests for gitlawb and gitlawb-gmi specialty validators Covers success, auth failure (401/403), non-auth acceptance (400/422/429), network errors, and custom baseUrl overrides for both providers. * feat(gitlawb): serve models from static registry without API-unavailable warning GitLawB's OpenGateway API does not expose a /models endpoint per provider-path. Previously the models route fell through to the generic fallback which returned static catalog models with the misleading 'API unavailable — using local catalog' warning. Now gitlawb and gitlawb-gmi are handled as static model providers (same pattern as reka and qwen OAuth) — models are served from the provider registry without any warning, since all registered models are functional via POST /chat/completions. * refactor(gitlawb): extract shared opengateway validator factory, fix docs path in test - Extract gitlawb/gitlawb-gmi validators into buildOpengatewayValidator factory - Fix dockerignore-docs-coverage test: update stale docs/AUTO-COMBO.md -> docs/routing/AUTO-COMBO.md * fix(reasoning): guard interleaved capability lookup * feat(gitlawb): dynamic model fetch with gmi-cloud fallback Hybrid approach: - gitlawb (xiaomi-mimo): dynamic /models endpoint → 356 models - gitlawb-gmi (gmi-cloud): 404 fallback → local catalog gracefully Mimics Gitlawb/openclaude's model-routing pattern * i18n(pt-BR): complete missing translations and sync with en.json * feat(build): nix multi-OS package manager install (#2806) Integrated into release/v3.8.6 * fix(i18n): translate 144 new __MISSING__ pt-BR strings (#2816) Integrated into release/v3.8.6 * chore(docs): set coverage gate to 40/40/40/40 in CLAUDE.md Aligns the documented coverage gate with the v3.8.6 release decision (lowered from 75/75/75/70). Matches the threshold already set in package.json by the large feature PRs (planos 11-22). * fix(cli): respect PORT env var in serve command (#2845) Integrated into release/v3.8.6. * fix(deepseek-web): return 400 when client sends tools[] - chat.deepseek.com has no tool support (#2854) Integrated into release/v3.8.6. * fix(qoder): reject invalid/expired PATs returning Cosy 500 error (#2860) Integrated into release/v3.8.6. * fix(cli): register openclaw in tool-detector (#2833) (#2850) Integrated into release/v3.8.6. * fix(api): include noAuth providers in /v1/models catalog (#2798) (#2814) Integrated into release/v3.8.6. * fix(combo): resolve custom provider targets via combo name (#2778) (#2812) Integrated into release/v3.8.6. * fix(translator): strip safety_identifier in openai-responses cleanup (#2770) (#2809) Integrated into release/v3.8.6. * fix(quota): honor explicit per-connection preflight opt-out (#2831) (#2844) Integrated into release/v3.8.6. * fix(usage): un-invert GitHub Copilot Free/limited quota — limited_user_quotas is remaining (#2876) (#2881) Integrated into release/v3.8.6. * fix(nous-research): correct baseUrl to include /chat/completions (#2826) (#2835) Integrated into release/v3.8.6. * fix(opencode): qwen3.x max/plus models lack vision support (#2822) (#2836) Integrated into release/v3.8.6. * fix(translator): pass-through tool_search built-in tool type (#2766) (#2811) Integrated into release/v3.8.6. * fix(github): route claude-opus-4.6 via chat completions (#2821) Integrated into release/v3.8.6. * docs(oauth): add Windsurf login fix design (Phase 1 hotfix + Phase 2 Firebase OAuth) Two-phase plan to fix the broken Windsurf OAuth flow: - Phase 1: drop the dead app.devin.ai/editor/signin PKCE path, promote import-token from windsurf.com/show-auth-token as the primary path - Phase 2: port Firebase OAuth + RegisterUser flow from fendoushaonian/WindSurf-gRPC-API for full browser-based automation Spec only - no code changes yet. * docs(plan): Phase 1 windsurf login hotfix implementation plan 10 tasks covering: - TDD assertions for flowType + 410 Gone responses - Provider switch to import_token - Route handler retiring authorize/start-callback-server/poll-callback - OAuthModal UI override - i18n sync - Verification + PR steps * fix(cli): replace cli-table3 with hand-rolled formatter (#2752) (#2813) Integrated into release/v3.8.6. * fix(skills): skip interception for unregistered client-native tools (#2815) (#2817) Integrated into release/v3.8.6. * feat(sse): add RTK filters for kubectl, docker-build, composer, gh (#2824) Integrated into release/v3.8.6. * fix(geminiHelper): support rec.image content shape + warn on dropped remote URLs (refs #2807) (#2855) Integrated into release/v3.8.6. * fix(cli): allow nullable/optional apiKey in cliMitmStartSchema (#2857) Integrated into release/v3.8.6. * fix(combo): preserve system messages during context handoff summary generation (#2865) Integrated into release/v3.8.6. * fix: wire CLIProxyAPI fallback settings into chatCore routing engine (#2866) Integrated into release/v3.8.6. * fix(usage): add opencode quota fetcher (#2852) (#2867) Integrated into release/v3.8.6. * feat(claude): default xhigh support for newer Opus models (#2874) Integrated into release/v3.8.6. * fix(cli): restore omniroute logs command stream (#2756) (#2810) Integrated into release/v3.8.6. * fix(combo): normalize upstream Headers for Node 24 undici interop (#2751) (#2823) Integrated into release/v3.8.6. * Rename proxy log Public IP to Client IP (#2880) Integrated into release/v3.8.6. * fix(claude): preserve max effort for supported models (#2875) Integrated into release/v3.8.6. * fix(oauth): switch windsurf provider to import_token flow The PKCE auth URL targeting app.devin.ai/editor/signin returns 404 post-rebrand. Until Phase 2 ports Firebase OAuth + RegisterUser, the only supported path is import-token via windsurf.com/show-auth-token. - windsurf.ts: drop buildAuthUrl, set flowType=import_token - generateAuthData returns supported:false + helpful error for windsurf/devin-cli - tests: assert flowType + disabled stub * fix(oauth): return 410 Gone for retired windsurf/devin-cli PKCE actions start-callback-server, authorize, and poll-callback (GET + POST) now return 410 Gone with a pointer to /import-token. The 410 short-circuit runs before auth so the response is honest about the action being permanently gone, not gated. Codex PKCE flow unchanged. Tests: 5 new assertions cover GET + POST 410 paths and a Codex regression check. * refactor(oauth): annotate retired PKCE fields in WINDSURF_CONFIG No behaviour change - comment-only update documenting that authorizeUrl, codeChallengeMethod, callbackPort, callbackPath, apiServerUrl, and exchangePath are no longer consumed. Active fields (inferenceUrl, showAuthTokenUrl, firebaseApiKey, ideName) called out separately. * fix(cli,docs): use requireCliToolsAuth in logs route + document OPENCODE quota env Post-merge contract fixes for v3.8.6: - src/app/api/cli-tools/logs/route.ts (#2810) now uses the shared requireCliToolsAuth guard (param renamed req->request) to satisfy the cli-tools-auth-hardening contract test. - Document OMNIROUTE_OPENCODE_QUOTA_URL (#2867) in docs/reference/ENVIRONMENT.md to satisfy the env/docs sync contract. * fix(dashboard): force import-token panel for windsurf/devin-cli Phase 1 hotfix: hide the 'Browser Login' tab and start in Paste API Key mode. Removes windsurf/devin-cli from PKCE_CALLBACK_SERVER_PROVIDERS so no callback server is started for them. Codex still uses the PKCE flow. The 'Get token' link continues to point at windsurf.com/show-auth-token via the existing supportsTokenPaste form copy. * fix(oauth): windsurf import-token mapTokens signature mismatch The route at `src/app/api/oauth/[provider]/[action]/route.ts` invokes `providerData.mapTokens({ accessToken: token })` (object), matching the cursor/kiro signature. The windsurf provider was declared with `mapTokens(token: string)` instead, so the entire object was stored as `accessToken`. When the connection record reached the SQLite layer it crashed with: SQLite3 can only bind numbers, strings, bigints, buffers, and null Fix by aligning windsurf's `mapTokens` signature with the route caller and the cursor/kiro convention. Also dedupe a copy-pasted second `if (action === "import-token")` block in the route handler — the second block was unreachable but identical to the first. Adds two regression tests asserting that `provider.mapTokens({ accessToken })` returns a string `accessToken` for both windsurf and devin-cli, so a future signature drift trips the gate instead of the SQLite bind error in production. * feat(compression): expand pt-BR pack with troglodita rules (15 → 49) (#2818) Integrated into release/v3.8.6 * fix(sse): repair RTK engine defaults so dedup and direct calls work (#2825) Integrated into release/v3.8.6 * fix(mcp): redirect console.log/warn to stderr in --mcp stdio mode (#2840) Integrated into release/v3.8.6 * fix(gemini-cli): prefer real project IDs over default-project (#2841) Integrated into release/v3.8.6 * fix(opencode-go): add provider limits quota fetcher (#2861) Integrated into release/v3.8.6 * Audit & add web cookie providers: fix 4 missing registry entries + DuckDuckGo (#2862) Integrated into release/v3.8.6 * fix(antigravity): harden signatureless tool history (#2878) Integrated into release/v3.8.6 * fix: provider model sync pruning and dynamic antigravity MITM proxy mappings (#2886) Integrated into release/v3.8.6 * feat(usage): per-API-key token limits scoped to model/provider/global (#2888) Integrated into release/v3.8.6 * fix(audio): build multipart body manually to preserve Content-Type (#2842) Integrated into release/v3.8.6 * refactor: remove agent skill documentation files and streamline maintenance workflows * test(stabilization): resolve unit test failures in blackbox-web, schema-coercion, translator-helper-branches, usage-service-hardening, and audio-transcription * fix(security): mitigate Socket.dev supply-chain findings + secrets opt-in + minimal build profile (#2863) (#2871) Two real security gaps closed and four cosmetic Socket.dev fingerprints removed. See docs/security/SOCKET_DEV_FINDINGS.md for the per-finding maintainer attestation. Real bugs fixed: - cloudSync: HMAC verification of `X-Cloud-Sig` + opt-in `OMNIROUTE_CLOUD_SYNC_SECRETS=true` before overwriting `accessToken` / `refreshToken` / `providerSpecificData` from a remote response. Closes the silent-credential-swap surface (a misconfigured or hostile CLOUD_URL could previously replace local tokens unverified). - Zed import: split into 2-step `/discover` + `/import` flow. `/import` now requires `confirmedAccounts: [{ service, account, fingerprint }]` and re-reads the keychain server-side to filter by fingerprint, so a tampered discover response cannot trick the endpoint into saving an unrelated token. Cosmetic Socket.dev mitigations: - runElevatedPowerShell writes the elevated payload to a per-call temp `.ps1` file (mode 0o600) and references it via `-File`. Removes the textbook `-EncodedCommand <base64utf16le>` pattern flagged as malware by Socket's AI classifier. - Maintainer attestation `SECURITY-AUDITOR-NOTE:` blocks added at every flagged call site pointing to `docs/security/SOCKET_DEV_FINDINGS.md`. Build-time hardening: - `OMNIROUTE_BUILD_PROFILE=minimal` (`npm run build:secure`) physically removes the four sensitive modules from the standalone bundle via webpack `NormalModuleReplacementPlugin`. Stubs throw `FeatureDisabledError` at runtime. Intended for the `omniroute-secure` artifact. Tests: - 24 new unit tests in `tests/unit/security/` covering the wrapper builder, HMAC verification (4 cases), credential fingerprint determinism (5 cases), confirmedAccounts validation + fingerprint filtering (6 cases), and the minimal-build stubs (5 cases). Docs: - New `docs/security/SOCKET_DEV_FINDINGS.md` — per-finding attestation. - New `socket.yml` — Socket.dev v2 config pointing at the attestation. - Updated `SECURITY.md` — supply-chain scanner section. - Updated `.env.example` — three new env vars documented. Backwards compatibility: - Cloud sync token overwrite is OFF by default. Users who relied on it must set `OMNIROUTE_CLOUD_SYNC_SECRETS=true`. Breaking change documented in CHANGELOG. - Zed import 2-step is the new default; legacy 1-step preserved behind `OMNIROUTE_ZED_IMPORT_LEGACY_ONE_STEP=true` and will be removed in v3.9. Closes #2863 * fix(security): redact public Firebase Web key from windsurf spec; doc SHA-256 cache-key rationale (#2894) Two security-scanning findings on release/v3.8.6: - Secret-scanning alert 7 (google_api_key): the windsurf login-fix design spec embedded the literal public Firebase Web API key on two lines. Firebase Web API keys are non-sensitive by design (they identify the project; access is gated by Firebase Security Rules + key restrictions), but the literal trips secret scanning. Redacted to a placeholder; the embedded default still goes through resolvePublicCred per rule #11. - Code-scanning alert 261 (js/insufficient-password-hash): tokenCacheKey() uses SHA-256 to derive an in-memory cache key from the session token, not for password-at-rest storage. Added a comment documenting why CWE-916 KDFs do not apply (false positive). * fix(ci): resolve release/v3.8.6 gate failures (docs-sync, any-budget, pack-artifact) (#2895) * fix(ci): resolve release/v3.8.6 gate failures (docs-sync, any-budget, pack-artifact) Three CI gates failed on release/v3.8.6 (run 26630300877): - docs-sync: CHANGELOG had a spurious "## [3.8.6-patch]" section above "## [3.8.6]", so the latest release no longer matched package.json (3.8.6) and the 41 i18n CHANGELOG mirrors were flagged as missing that section. Fold the lone #2752 entry into [3.8.6] and drop the patch heading. - any-budget:t11: open-sse/handlers/chatCore.ts regressed to 1 explicit `any` (budget 0). Type the persist callback arg as Record<string, unknown>, which matches runWithOnPersist's RefreshPersistFn contract exactly. - pack-artifact: open-sse/utils/setupPolyfill.ts ships via package.json "files" (bin/omniroute.mjs imports it at startup) but was missing from the pack policy allowlist. Allow it and add a regression test. * fix(security): redact public Firebase Web key from windsurf spec Redact the literal public Firebase Web API key (secret-scanning #7) to a placeholder, mirroring the redaction on release/v3.8.6 (PR #2894) and the windsurf fix branch. Non-sensitive public Web key; trips secret scanning. * feat(combo): Zero-Latency Combos (Hedging, Proactive Compression, Predictive TTFT) (#2868) * feat(combo): implement zero-latency combo optimizations (hedging, proactive compression, predictive TTFT) * fix(combo): fix predictive TTFT skip logic and unhandled promise rejections --------- Co-authored-by: Automation <automation@omniroute> * feat: implement automated skill workflows and update system configuration and validation schemas * test: eliminate dynamic cast warnings in cloud-sync unit test * test: isolate services-branch-hardening database directory to avoid concurrency issues * feat(providers): add 7 new web-cookie providers + research catalog + discovery tool New providers: - huggingchat: free LLM chat via huggingface.co/chat (no subscription) - phind: free dev-focused AI chat via phind.com/api/agent - poe-web: multi-model chat via poe.com GraphQL (p-b cookie) - venice-web: privacy-focused AI chat via venice.ai (session cookie) - v0-vercel-web: Vercel v0 code gen via v0.dev (session cookie) - kimi-web: Moonshot Kimi chat via kimi.moonshot.cn (session cookie) - doubao-web: ByteDance Doubao chat via doubao.com (session cookie) Additional: - Research catalog: docs/research/UNLIMITED_LLM_ACCESS.md - Discovery tool design + stub: src/lib/discovery/ + migration 073 - Unit tests: 33 tests for all 7 providers - Shared helpers consolidated in error.ts (slop cleanup) - All registered in WEB_COOKIE_PROVIDERS + providerRegistry + webSessionCredentials Closes #2885 * fix(typecheck): resolve typecheck errors in combo spec and compression modules * feat(api,oauth): add `agy` (Antigravity CLI) standalone provider with CLI token import (#2899) Add a standalone OAuth provider `agy` (Antigravity CLI) next to gemini-cli/antigravity. It reuses the antigravity inference backend (identical Google client_id + daily-cloudcode-pa.googleapis.com endpoint, executor and token-refresh) but ships its own model catalog — including the Claude models the backend exposes (claude-opus-4-6-thinking, claude-sonnet-4-6) — its own account pool, and four ways to connect: - token-file import (paste/upload the agy oauth token JSON) - auto-detect a local CLI login (~/.gemini/antigravity-cli/antigravity-oauth-token) - browser OAuth (via the shared OAuthModal Google loopback flow) - bulk / ZIP import New routes: POST /api/providers/agy-auth/{import,import-bulk,zip-extract,apply-local}. Catalog pinned from the live :fetchAvailableModels endpoint. Docs (openapi.yaml, ENVIRONMENT.md, .env.example, CHANGELOG) updated; new unit tests for registration, the token parser, and route auth-hardening. * fix(security): redact public Firebase Web key from windsurf spec (#2896) Redact the literal public Firebase Web API key (secret-scanning #7) to a placeholder. Firebase Web API keys are non-sensitive by design but the literal trips GitHub secret scanning. Mirrors the redaction landed on release/v3.8.6 (PR #2894). Embedded default still flows through resolvePublicCred (rule #11). * Pr 2871 (#2897) * fix(security): mitigate Socket.dev supply-chain findings + secrets opt-in + minimal build profile (#2863) Two real security gaps closed and four cosmetic Socket.dev fingerprints removed. See docs/security/SOCKET_DEV_FINDINGS.md for the per-finding maintainer attestation. Real bugs fixed: - cloudSync: HMAC verification of `X-Cloud-Sig` + opt-in `OMNIROUTE_CLOUD_SYNC_SECRETS=true` before overwriting `accessToken` / `refreshToken` / `providerSpecificData` from a remote response. Closes the silent-credential-swap surface (a misconfigured or hostile CLOUD_URL could previously replace local tokens unverified). - Zed import: split into 2-step `/discover` + `/import` flow. `/import` now requires `confirmedAccounts: [{ service, account, fingerprint }]` and re-reads the keychain server-side to filter by fingerprint, so a tampered discover response cannot trick the endpoint into saving an unrelated token. Cosmetic Socket.dev mitigations: - runElevatedPowerShell writes the elevated payload to a per-call temp `.ps1` file (mode 0o600) and references it via `-File`. Removes the textbook `-EncodedCommand <base64utf16le>` pattern flagged as malware by Socket's AI classifier. - Maintainer attestation `SECURITY-AUDITOR-NOTE:` blocks added at every flagged call site pointing to `docs/security/SOCKET_DEV_FINDINGS.md`. Build-time hardening: - `OMNIROUTE_BUILD_PROFILE=minimal` (`npm run build:secure`) physically removes the four sensitive modules from the standalone bundle via webpack `NormalModuleReplacementPlugin`. Stubs throw `FeatureDisabledError` at runtime. Intended for the `omniroute-secure` artifact. Tests: - 24 new unit tests in `tests/unit/security/` covering the wrapper builder, HMAC verification (4 cases), credential fingerprint determinism (5 cases), confirmedAccounts validation + fingerprint filtering (6 cases), and the minimal-build stubs (5 cases). Docs: - New `docs/security/SOCKET_DEV_FINDINGS.md` — per-finding attestation. - New `socket.yml` — Socket.dev v2 config pointing at the attestation. - Updated `SECURITY.md` — supply-chain scanner section. - Updated `.env.example` — three new env vars documented. Backwards compatibility: - Cloud sync token overwrite is OFF by default. Users who relied on it must set `OMNIROUTE_CLOUD_SYNC_SECRETS=true`. Breaking change documented in CHANGELOG. - Zed import 2-step is the new default; legacy 1-step preserved behind `OMNIROUTE_ZED_IMPORT_LEGACY_ONE_STEP=true` and will be removed in v3.9. Closes #2863 * feat: implement automated skill workflows and update system configuration and validation schemas * test: eliminate dynamic cast warnings in cloud-sync unit test * test: isolate services-branch-hardening database directory to avoid concurrency issues * chore(docs): refresh generated docs collection index Update the generated Fumadocs browser collection mapping to keep documentation imports in sync with the current docs structure. * docs: update generated browser docs collection manifest Refresh the generated Fumadocs browser collection mapping so the docs site can resolve the current documentation files correctly. --------- Co-authored-by: OpenClaw <openclaw@kuzhomesrv.local> Co-authored-by: Dmitry Kuznetsov <139351986+dmitry@users.noreply.local> Co-authored-by: KuzyaBot <kuzya@local> Co-authored-by: JeferssonLemes <jeferssondev@gmail.com> Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com> Co-authored-by: Markus Hartung <mail@hartmark.se> Co-authored-by: akarray <akarray@users.noreply.github.com> Co-authored-by: Apostol Apostolov <theapoapostolov@gmail.com> Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com> Co-authored-by: Dmitry Kuznetsov <dmitry@kuznetsov.me> Co-authored-by: Nikolay Alafuzov <alafuzov_nn@rusklimat.ru> Co-authored-by: oyi77 <oyi77@users.noreply.github.com> Co-authored-by: Ronaldo Davi <alltomatos@users.noreply.github.com> Co-authored-by: levonk <277861+levonk@users.noreply.github.com> Co-authored-by: Lenine Júnior <lenine@engrene.com.br> Co-authored-by: Annas Alghoffar <aag.annas@gmail.com> Co-authored-by: Tushar Agarwal <76201310+Tushar49@users.noreply.github.com> Co-authored-by: GreatLiu <eurasiaxz@qq.com> Co-authored-by: yuna amelia <230527278+yunaamelia@users.noreply.github.com> Co-authored-by: Randi <55005611+rdself@users.noreply.github.com> Co-authored-by: Container <78986709+disonjer@users.noreply.github.com> Co-authored-by: nickwizard <35692452+nickwizard@users.noreply.github.com> Co-authored-by: Rajvardhan Patil <rajvardhanpatil7890@gmail.com> Co-authored-by: Raxxoor <manker_lol@hotmail.com> Co-authored-by: Muhammad Mugni Hadi <mugnimaestra3@gmail.com> Co-authored-by: mi <123757457+soyelmismo@users.noreply.github.com> Co-authored-by: Automation <automation@omniroute>
50 KiB
title, version, lastUpdated
| title | version | lastUpdated |
|---|---|---|
| API Reference | 3.8.2 | 2026-05-13 |
API Reference
🌐 Languages: 🇺🇸 English | 🇧🇷 Português (Brasil) | 🇪🇸 Español | 🇫🇷 Français | 🇮🇹 Italiano | 🇷🇺 Русский | 🇨🇳 中文 (简体) | 🇩🇪 Deutsch | 🇮🇳 हिन्दी | 🇹🇭 ไทย | 🇺🇦 Українська | 🇸🇦 العربية | 🇯🇵 日本語 | 🇻🇳 Tiếng Việt | 🇧🇬 Български | 🇩🇰 Dansk | 🇫🇮 Suomi | 🇮🇱 עברית | 🇭🇺 Magyar | 🇮🇩 Bahasa Indonesia | 🇰🇷 한국어 | 🇲🇾 Bahasa Melayu | 🇳🇱 Nederlands | 🇳🇴 Norsk | 🇵🇹 Português (Portugal) | 🇷🇴 Română | 🇵🇱 Polski | 🇸🇰 Slovenčina | 🇸🇪 Svenska | 🇵🇭 Filipino | 🇨🇿 Čeština
Complete reference for all OmniRoute API endpoints.
Table of Contents
- Chat Completions
- Embeddings
- Image Generation
- List Models
- Compatibility Endpoints
- Files API
- Batches API
- Search API
- WebSocket Streaming
- Quotas & Issues Reporting
- Semantic Cache
- Dashboard & Management
- Combo Management
- Webhooks
- Registered Keys (Auto-Management)
- Agents Protocol
- Management Proxies
- Resilience (extended)
- Skills
- Memory
- MCP Server
- A2A Server
- Cloud, Evals & Assess
- Request Processing
- Authentication
Chat Completions
POST /v1/chat/completions
Authorization: Bearer your-api-key
Content-Type: application/json
{
"model": "cc/claude-opus-4-6",
"messages": [
{"role": "user", "content": "Write a function to..."}
],
"stream": true
}
Custom Headers
| Header | Direction | Description |
|---|---|---|
X-OmniRoute-No-Cache |
Request | Set to true to bypass cache |
X-OmniRoute-Progress |
Request | Set to true for progress events |
X-Session-Id |
Request | Sticky session key for external session affinity |
x_session_id |
Request | Underscore variant also accepted (direct HTTP) |
Idempotency-Key |
Request | Dedup key (5s window) |
X-Request-Id |
Request | Alternative dedup key |
X-OmniRoute-Cache |
Response | HIT or MISS (non-streaming) |
X-OmniRoute-Idempotent |
Response | true if deduplicated |
X-OmniRoute-Progress |
Response | enabled if progress tracking on |
X-OmniRoute-Session-Id |
Response | Effective session ID used by OmniRoute |
Nginx note: if you rely on underscore headers (for example
x_session_id), enableunderscores_in_headers on;.
Embeddings
POST /v1/embeddings
Authorization: Bearer your-api-key
Content-Type: application/json
{
"model": "nebius/Qwen/Qwen3-Embedding-8B",
"input": "The food was delicious"
}
Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA, OpenRouter, GitHub Models.
# List all embedding models
GET /v1/embeddings
Image Generation
POST /v1/images/generations
Authorization: Bearer your-api-key
Content-Type: application/json
{
"model": "openai/gpt-image-2",
"prompt": "A beautiful sunset over mountains",
"size": "1024x1024"
}
Available providers: OpenAI (GPT Image 2), xAI (Grok Image), Together AI (FLUX), Fireworks AI, Nebius (FLUX), Hyperbolic, NanoBanana, OpenRouter, SD WebUI (local), ComfyUI (local).
# List all image models
GET /v1/images/generations
List Models
GET /v1/models
Authorization: Bearer your-api-key
→ Returns all chat, embedding, and image models + combos in OpenAI format
Compatibility Endpoints
| Method | Path | Format |
|---|---|---|
| POST | /v1/chat/completions |
OpenAI |
| POST | /v1/messages |
Anthropic |
| POST | /v1/responses |
OpenAI Responses |
| POST | /v1/embeddings |
OpenAI |
| POST | /v1/images/generations |
OpenAI Images |
| POST | /v1/images/edits |
OpenAI Images (edit/inpaint) |
| POST | /v1/videos/generations |
OpenAI-style video generation |
| POST | /v1/music/generations |
OpenAI-style music generation |
| POST | /v1/audio/transcriptions |
OpenAI Audio (STT) |
| POST | /v1/audio/speech |
OpenAI TTS (returns audio body) |
| POST | /v1/rerank |
Cohere/Voyage-style rerank |
| POST | /v1/moderations |
OpenAI Moderations |
| GET | /v1/models |
OpenAI |
| POST | /v1/messages/count_tokens |
Anthropic |
| GET | /v1beta/models |
Gemini |
| POST | /v1beta/models/{...path} |
Gemini generateContent |
| POST | /v1/api/chat |
Ollama |
All POST routes follow the same shape: Bearer your-api-key + Zod-validated JSON body (v1RerankSchema, v1ModerationSchema, v1AudioSpeechSchema, etc., see src/shared/validation/schemas.ts). 4xx is returned on schema failure.
# Rerank
POST /v1/rerank { "model": "cohere/rerank-3", "query": "...", "documents": ["..."] }
# Moderations
POST /v1/moderations { "model": "omni-moderation-latest", "input": "..." }
# TTS — returns audio/mpeg (or requested format) body
POST /v1/audio/speech { "model": "openai/tts-1", "input": "Hello", "voice": "alloy" }
# Image edit (multipart)
POST /v1/images/edits -F image=@input.png -F prompt="..." -F mask=@mask.png
# Video / music generation (provider-prefixed model id)
POST /v1/videos/generations { "model": "runway/gen-3", "prompt": "..." }
POST /v1/music/generations { "model": "suno/v3.5", "prompt": "..." }
Dedicated Provider Routes
POST /v1/providers/{provider}/chat/completions
POST /v1/providers/{provider}/embeddings
POST /v1/providers/{provider}/images/generations
The provider prefix is auto-added if missing. Mismatched models return 400.
Files API
OpenAI-compatible files endpoint for batch input/output and file-purpose uploads.
| Method | Path | Description |
|---|---|---|
| POST | /v1/files |
Upload a file (multipart: file, purpose, expires_after[anchor], expires_after[seconds]) — 512 MiB max |
| GET | /v1/files |
List files for the authenticated API key |
| GET | /v1/files/[id] |
Retrieve a file's metadata |
| DELETE | /v1/files/[id] |
Delete a file |
| GET | /v1/files/[id]/content |
Stream the raw file body back |
Auth: Bearer API key — files are scoped per-API-key via getApiKeyRequestScope.
Batches API
OpenAI-compatible batch processing.
| Method | Path | Description |
|---|---|---|
| POST | /v1/batches |
Create batch — body validated by v1BatchCreateSchema (input_file_id, endpoint, completion_window) |
| GET | /v1/batches |
List batches |
| GET | /v1/batches/[id] |
Retrieve batch status + request_counts |
| DELETE | /v1/batches/[id] |
Delete a finished/failed batch |
| POST | /v1/batches/[id]/cancel |
Cancel an in-progress batch |
Auth: Bearer API key. Batches are scoped per-API-key.
Search API
Web/search provider abstraction (Tavily, Brave, Exa, Serper, etc.).
| Method | Path | Description |
|---|---|---|
| GET | /v1/search |
List configured search providers + capabilities |
| POST | /v1/search |
Run a search query — body validated by v1SearchSchema, supports caching/coalescing |
| GET | /v1/search/analytics |
Per-provider hit/latency/cache stats |
Auth: Bearer API key (extractApiKey + isValidApiKey). Search policy enforced via enforceApiKeyPolicy.
WebSocket Streaming
GET /v1/ws?handshake=1
Validates a WebSocket upgrade handshake and returns the wire protocol example messages (request, cancel). Actual WS frames are handled by the bundled WS server outside the Next.js route table.
Auth: Bearer API key during handshake.
Quotas & Issues Reporting
| Method | Path | Description |
|---|---|---|
| GET | /v1/quotas/check |
Pre-validate quota for a provider + accountId before issuing a registered key |
| POST | /v1/issues/report |
Report a quota/key issuance failure to GitHub (requires GITHUB_ISSUES_REPO + token) |
Auth: Bearer API key (isAuthenticated).
Semantic Cache
# Get cache stats
GET /api/cache/stats
# Clear all caches
DELETE /api/cache/stats
Response example:
{
"semanticCache": {
"memorySize": 42,
"memoryMaxSize": 500,
"dbSize": 128,
"hitRate": 0.65
},
"idempotency": {
"activeKeys": 3,
"windowMs": 5000
}
}
Dashboard & Management
Authentication
| Endpoint | Method | Description |
|---|---|---|
/api/auth/login |
POST | Login |
/api/auth/logout |
POST | Logout |
/api/settings/require-login |
GET/PUT | Toggle login required |
Provider Management
| Endpoint | Method | Description |
|---|---|---|
/api/providers |
GET/POST | List / create providers |
/api/providers/[id] |
GET/PUT/DELETE | Manage a provider |
/api/providers/[id]/test |
POST | Test provider connection |
/api/providers/[id]/models |
GET | List provider models |
/api/providers/validate |
POST | Validate provider config |
/api/provider-nodes* |
Various | Provider node management |
/api/provider-models |
GET/POST/PATCH/DELETE | Custom models (add, update, hide/show, delete) |
OAuth Flows
| Endpoint | Method | Description |
|---|---|---|
/api/oauth/[provider]/[action] |
Various | Provider-specific OAuth |
Routing & Config
| Endpoint | Method | Description |
|---|---|---|
/api/models/alias |
GET/POST | Model aliases |
/api/models/catalog |
GET | All models by provider + type |
/api/combos* |
Various | Combo management |
/api/keys* |
Various | API key management |
/api/pricing |
GET | Model pricing |
Usage & Analytics
| Endpoint | Method | Description |
|---|---|---|
/api/usage/history |
GET | Usage history |
/api/usage/logs |
GET | Usage logs |
/api/usage/request-logs |
GET | Request-level logs |
/api/usage/[connectionId] |
GET | Per-connection usage |
/api/usage/token-limits |
GET/POST/DELETE | Per-API-key token-limit budgets |
Settings
| Endpoint | Method | Description |
|---|---|---|
/api/settings |
GET/PUT/PATCH | General settings |
/api/settings/proxy |
GET/PUT | Network proxy config |
/api/settings/proxy/test |
POST | Test proxy connection |
/api/settings/ip-filter |
GET/PUT | IP allowlist/blocklist |
/api/settings/thinking-budget |
GET/PUT | Reasoning token budget |
/api/settings/system-prompt |
GET/PUT | Global system prompt |
/api/settings/compression |
GET/PUT | Global compression config |
Context & Compression
| Endpoint | Method | Description |
|---|---|---|
/api/compression/preview |
POST | Preview off/lite/standard/aggressive/ultra/RTK/stacked compression |
/api/compression/language-packs |
GET | List available Caveman language packs |
/api/compression/rules |
GET | List Caveman rule metadata |
/api/context/caveman/config |
GET/PUT | Caveman-specific settings alias |
/api/context/rtk/config |
GET/PUT | RTK-specific settings, including custom filters and raw-output retention |
/api/context/rtk/filters |
GET | RTK filter catalog and custom-filter diagnostics |
/api/context/rtk/test |
POST | Run RTK preview/test against a text payload |
/api/context/rtk/raw-output/[id] |
GET | Read retained redacted raw output by pointer id |
/api/context/combos |
GET/POST | Compression combo list/create |
/api/context/combos/[id] |
GET/PUT/DELETE | Compression combo detail/update/delete |
/api/context/combos/[id]/assignments |
GET/PUT | Assign compression combos to routing combos |
/api/context/analytics |
GET | Compression analytics alias |
Monitoring
| Endpoint | Method | Description |
|---|---|---|
/api/sessions |
GET | Active session tracking |
/api/rate-limits |
GET | Per-account rate limits |
/api/monitoring/health |
GET | Health check + provider summary (catalogCount, configuredCount, activeCount, monitoredCount) |
/api/cache/stats |
GET/DELETE | Cache stats / clear |
Backup & Export/Import
| Endpoint | Method | Description |
|---|---|---|
/api/db-backups |
GET | List available backups |
/api/db-backups |
PUT | Create a manual backup |
/api/db-backups |
POST | Restore from a specific backup |
/api/db-backups/export |
GET | Download database as .sqlite file |
/api/db-backups/import |
POST | Upload .sqlite file to replace database |
/api/db-backups/exportAll |
GET | Download full backup as .tar.gz archive |
Cloud Sync
| Endpoint | Method | Description |
|---|---|---|
/api/sync/cloud |
Various | Cloud sync operations |
/api/sync/initialize |
POST | Initialize sync |
/api/cloud/* |
Various | Cloud management |
Tunnels
| Endpoint | Method | Description |
|---|---|---|
/api/tunnels/cloudflared |
GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
/api/tunnels/cloudflared |
POST | Enable or disable the Cloudflare Quick Tunnel (action=enable/disable) |
/api/tunnels/ngrok |
GET | Read ngrok Tunnel runtime status for the dashboard |
/api/tunnels/ngrok |
POST | Enable or disable the ngrok Tunnel (action=enable/disable) |
CLI Tools
| Endpoint | Method | Description |
|---|---|---|
/api/cli-tools/claude-settings |
GET | Claude CLI status |
/api/cli-tools/codex-settings |
GET | Codex CLI status |
/api/cli-tools/droid-settings |
GET | Droid CLI status |
/api/cli-tools/openclaw-settings |
GET | OpenClaw CLI status |
/api/cli-tools/runtime/[toolId] |
GET | Generic CLI runtime |
CLI responses include: installed, runnable, command, commandPath, runtimeMode, reason.
ACP Agents
| Endpoint | Method | Description |
|---|---|---|
/api/acp/agents |
GET | List all detected agents (built-in + custom) with status |
/api/acp/agents |
POST | Add custom agent or refresh detection cache |
/api/acp/agents |
DELETE | Remove a custom agent by id query param |
GET response includes agents[] (id, name, binary, version, installed, protocol, isCustom) and summary (total, installed, notFound, builtIn, custom).
Resilience & Rate Limits
| Endpoint | Method | Description |
|---|---|---|
/api/resilience |
GET/PATCH | Get/update request queue, connection cooldown, provider breaker, and wait settings |
/api/resilience/reset |
POST | Reset provider circuit breakers |
/api/resilience/model-cooldowns |
GET | List active per-(provider, connection, model) lockouts, sorted by remaining time |
/api/resilience/model-cooldowns |
DELETE | Clear a model lockout — body {provider, model} or {all: true} to wipe everything |
/api/rate-limits |
GET | Per-account rate limit status |
/api/rate-limit |
GET | Global rate limit configuration |
All four
/api/resilience/*routes require management auth (requireManagementAuth). See Resilience (extended) for a full breakdown of provider breaker vs connection cooldown vs model lockout.
Evals
| Endpoint | Method | Description |
|---|---|---|
/api/evals |
GET/POST | List eval suites / run evaluation |
Policies
| Endpoint | Method | Description |
|---|---|---|
/api/policies |
GET/POST/DELETE | Manage routing policies |
Compliance
| Endpoint | Method | Description |
|---|---|---|
/api/compliance/audit-log |
GET | Compliance audit log (last N) |
v1beta (Gemini-Compatible)
| Endpoint | Method | Description |
|---|---|---|
/v1beta/models |
GET | List models in Gemini format |
/v1beta/models/{...path} |
POST | Gemini generateContent endpoint |
These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
Internal / System APIs
| Endpoint | Method | Description |
|---|---|---|
/api/init |
GET | Application initialization check (used on first run) |
/api/tags |
GET | Ollama-compatible model tags (for Ollama clients) |
/api/restart |
POST | Trigger graceful server restart |
/api/shutdown |
POST | Trigger graceful server shutdown |
/api/system/env/repair |
POST | Repair OAuth provider environment variables |
/api/system-info |
GET | Generate system diagnostics report |
Note: These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
OAuth Environment Repair (v3.6.1+)
POST /api/system/env/repair
Content-Type: application/json
{
"provider": "claude-code"
}
Repairs missing or corrupted OAuth environment variables for a specific provider. Returns:
{
"success": true,
"repaired": ["CLAUDE_CODE_OAUTH_CLIENT_ID", "CLAUDE_CODE_OAUTH_CLIENT_SECRET"],
"backupPath": "/home/user/.omniroute/backups/env-repair-2026-04-11.bak"
}
Audio Transcription
POST /v1/audio/transcriptions
Authorization: Bearer your-api-key
Content-Type: multipart/form-data
Transcribe audio files using Deepgram or AssemblyAI.
Request:
curl -X POST http://localhost:20128/v1/audio/transcriptions \
-H "Authorization: Bearer your-api-key" \
-F "file=@recording.mp3" \
-F "model=deepgram/nova-3"
Response:
{
"text": "Hello, this is the transcribed audio content.",
"task": "transcribe",
"language": "en",
"duration": 12.5
}
Supported providers: deepgram/nova-3, assemblyai/best.
Supported formats: mp3, wav, m4a, flac, ogg, webm.
Ollama Compatibility
For clients that use Ollama's API format:
# Chat endpoint (Ollama format)
POST /v1/api/chat
# Model listing (Ollama format)
GET /api/tags
Requests are automatically translated between Ollama and internal formats.
Telemetry
# Get latency telemetry summary (p50/p95/p99 per provider)
GET /api/telemetry/summary
Response:
{
"providers": {
"claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
"github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
}
}
Budget
# Get budget status for all API keys
GET /api/usage/budget
# Set or update a budget
POST /api/usage/budget
Content-Type: application/json
{
"apiKeyId": "key-123",
"dailyLimitUsd": 5.00,
"weeklyLimitUsd": 30.00,
"monthlyLimitUsd": 100.00,
"warningThreshold": 0.8,
"resetInterval": "monthly"
}
Schema notes (
setBudgetSchema):apiKeyIdis required; at least one ofdailyLimitUsd,weeklyLimitUsd, ormonthlyLimitUsdmust be greater than zero. Optional fields:warningThreshold(0–1),resetInterval(daily|weekly|monthly),resetTime(HH:MM). The legacy{keyId, limit, period}shape returns400 Bad Request.
Token Limits
Per-API-key token budgets (distinct from the USD-based Budget above). Enforced inline on the request path: when a key's current window usage reaches its limit, requests are rejected with 429 Too Many Requests. Limits can be scoped to a specific model, a provider, or applied globally across the key; when several limits match a request, the most restrictive one wins.
# List a key's token limits (includes live window usage)
GET /api/usage/token-limits?apiKeyId=key-123
# Create or update a token limit
POST /api/usage/token-limits
Content-Type: application/json
{
"apiKeyId": "key-123",
"scopeType": "model",
"scopeValue": "openai/gpt-4o",
"tokenLimit": 1000000,
"resetInterval": "monthly",
"enabled": true
}
# Delete a token limit by id
DELETE /api/usage/token-limits?id=tl-abc
Schema notes (
setTokenLimitSchema):apiKeyIdandscopeType(model|provider|global) are required.scopeValueis required unlessscopeTypeisglobal(e.g. a model id formodelscope, a provider id forproviderscope).tokenLimitmust be a positive integer (coerced from string). Optional:id(omit to create, supply to update),resetInterval(daily|weekly|monthly, defaultmonthly),resetTime(HH:MM),enabled(defaulttrue).GETresponses enrich each limit withtokensUsed,remaining,windowStart,periodStartAt, andnextResetAt. This is a management-class endpoint (auth enforced centrally by the authz pipeline).
Request Processing
- Client sends request to
/v1/* - Route handler calls
handleChat,handleEmbedding,handleAudioTranscription, orhandleImageGeneration - Model is resolved (direct provider/model or alias/combo)
- Credentials selected from local DB with account availability filtering
- For chat:
handleChatCorechecks semantic/signature cache and resolves combo compression settings - Proactive compression runs before provider translation when enabled (
lite, Caveman, RTK, or stacked) - Provider executor sends upstream request
- Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
- Usage, compression analytics, and request logs are recorded
- Fallback applies on errors according to combo rules
Full architecture reference: ARCHITECTURE.md
Combo Management
Higher-level routing combos (already summarized under /api/combos*) can also be mapped 1:1 from a model id pattern, allowing transparent redirection of an OpenAI-style model id to a combo.
| Method | Path | Description |
|---|---|---|
| GET | /api/model-combo-mappings |
List all model→combo mappings |
| POST | /api/model-combo-mappings |
Create mapping — body: {pattern, comboId, priority?, enabled?, description?} |
| GET | /api/model-combo-mappings/[id] |
Retrieve a single mapping |
| PUT | /api/model-combo-mappings/[id] |
Update fields of an existing mapping |
| DELETE | /api/model-combo-mappings/[id] |
Remove a mapping |
Auth: management session/API key (requireManagementAuth).
Webhooks
Outbound webhook subscriptions for OmniRoute events (request completion, quota exhaustion, key rotation, etc.).
| Method | Path | Description |
|---|---|---|
| GET | /api/webhooks |
List webhooks (secrets are masked to <prefix>...) |
| POST | /api/webhooks |
Create webhook — body: {url, events?: ["*"], secret?, description?} |
| GET | /api/webhooks/[id] |
Retrieve a webhook |
| PUT | /api/webhooks/[id] |
Update url/events/secret/description |
| DELETE | /api/webhooks/[id] |
Remove a webhook |
| POST | /api/webhooks/[id]/test |
Send a test payload to the webhook URL and return delivery status |
Auth: management session/API key (requireManagementAuth).
Registered Keys (Auto-Management)
Used by the auto-key management subsystem to issue and rotate API keys against a backing provider/account, with daily/hourly quotas.
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/registered-keys |
List registered keys (masked prefix only) |
| POST | /api/v1/registered-keys |
Issue a new registered key — body: {name, provider?, accountId?, idempotencyKey?, expiresAt?, dailyBudget?, hourlyBudget?}. Returns the raw key once. Returns 429 on quota refusal. |
| GET | /api/v1/registered-keys/[id] |
Retrieve a registered key's metadata (no raw material) |
| DELETE | /api/v1/registered-keys/[id] |
Revoke a registered key |
| POST | /api/v1/registered-keys/[id]/revoke |
Explicit revoke endpoint (same effect as DELETE) |
Auth: Bearer API key (isAuthenticated). See also /v1/quotas/check and /v1/issues/report.
Agents Protocol
Cloud agent tasks (Claude Code, Codex Cloud, OpenHands, etc.) executed remotely on behalf of OmniRoute users.
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/agents/tasks |
List tasks — optional ?provider=, ?status=, ?limit= (1–500, default 50) |
| POST | /api/v1/agents/tasks |
Create task — body validated by CreateCloudAgentTaskSchema (providerId, prompt, source, options?). Returns 201 with task envelope |
| DELETE | /api/v1/agents/tasks?id=... |
Delete a task |
| GET | /api/v1/agents/tasks/[id] |
Read task — synchronously refreshes status from the upstream cloud agent when an external_id is set |
| POST | /api/v1/agents/tasks/[id] |
Discriminated action: {action: "approve"}, {action: "message", message}, or {action: "cancel"} |
| DELETE | /api/v1/agents/tasks/[id] |
Delete a specific task by id |
Auth: management auth required on every method (
requireCloudAgentManagementAuth). Prior to v3.8.0 these were unauthenticated — see commit588a0333for the breaking change.
# Create a Claude Code cloud task
curl -X POST http://localhost:20128/api/v1/agents/tasks \
-H "Authorization: Bearer your-management-key" \
-H "Content-Type: application/json" \
-d '{"providerId":"claude-code-cloud","prompt":"Fix the failing test","source":{"repo":"...","branch":"..."}}'
Management Proxies
Outbound HTTP(S)/SOCKS proxies that can be assigned to providers, accounts, or globally.
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/management/proxies |
List proxies (with ?id= returns one; with ?id=&where_used=1 returns the assignment graph) |
| POST | /api/v1/management/proxies |
Create proxy — body validated by createProxyRegistrySchema |
| PATCH | /api/v1/management/proxies |
Update proxy — body validated by updateProxyRegistrySchema (requires id) |
| DELETE | /api/v1/management/proxies?id=...&force=1 |
Delete proxy (use force=1 to detach assignments) |
| GET | /api/v1/management/proxies/assignments |
List assignments — filterable by proxy_id, scope, scope_id; pass resolve_connection_id=<id> to resolve the active proxy for a connection |
| PUT | /api/v1/management/proxies/assignments |
Assign — body validated by proxyAssignmentSchema ({scope, scopeId?, proxyId?}). Clears dispatcher cache |
| PUT | /api/v1/management/proxies/bulk-assign |
Bulk-assign — body validated by bulkProxyAssignmentSchema ({scope, scopeIds[], proxyId?}) |
| GET | /api/v1/management/proxies/health?hours=24 |
Aggregate proxy health (success/fail counts, latency) over a window |
Auth: management session/API key on every route (requireManagementAuth).
The task description's
POST /api/v1/management/proxies/[id]/assignmentsandPOST /api/v1/management/proxies/[id]/healthare served by the flat/assignmentsand/healthroutes shown above — there are no per-id subroutes in the codebase.
Resilience (extended)
OmniRoute exposes three independent temporary-failure mechanisms; the management endpoints below let operators read and override them:
| Scope | State storage | Read | Reset / clear |
|---|---|---|---|
| Provider breaker | domain_circuit_breakers + in-memory |
/api/monitoring/health |
POST /api/resilience/reset |
| Connection cooldown | rateLimitedUntil on provider connections |
/api/rate-limits, /api/providers/[id] |
(re-enables lazily; clear via provider PUT) |
| Model lockout | In-memory model-availability registry | GET /api/resilience/model-cooldowns |
DELETE /api/resilience/model-cooldowns |
# Clear a single model lockout
curl -X DELETE http://localhost:20128/api/resilience/model-cooldowns \
-H "Cookie: auth_token=..." \
-H "Content-Type: application/json" \
-d '{"provider":"openai","model":"gpt-4o-mini"}'
# Wipe every lockout
curl -X DELETE http://localhost:20128/api/resilience/model-cooldowns \
-H "Cookie: auth_token=..." \
-d '{"all":true}'
Full conceptual reference and breaker defaults: see CLAUDE.md → "Resilience Runtime State".
Skills
Skill framework for extending OmniRoute with custom executable handlers, plus marketplace integrations.
| Method | Path | Description |
|---|---|---|
| GET | /api/skills |
List installed skills — filterable by ?q=, ?mode=on|off|auto, ?source=skillsmp|skillssh|local, paginated |
| GET | /api/skills/[id] |
Retrieve one skill |
| PUT | /api/skills/[id] |
Update skill (name, description, mode, schema, handler, tags) |
| DELETE | /api/skills/[id] |
Uninstall a skill |
| POST | /api/skills/install |
Install a skill from a raw manifest — body: {name, version, description, schema:{input, output}, handlerCode, apiKeyId?} |
| GET | /api/skills/executions |
List recent skill executions (audit trail with inputs/outputs/duration) |
| GET | /api/skills/marketplace?q=... |
Search/popular list from the SkillsMP marketplace (requires skillsmpApiKey setting) |
| POST | /api/skills/marketplace/install |
Install a skill by id from SkillsMP |
| GET | /api/skills/skillssh?q=&limit= |
Search the skills.sh registry |
| POST | /api/skills/skillssh/install |
Install a skill by id from skills.sh |
Auth: management session/API key. Marketplace search routes accept either management auth or a Bearer API key (isAuthenticated).
Memory
Persistent conversational/factual memory store, scoped per API key / session.
| Method | Path | Description |
|---|---|---|
| GET | /api/memory |
List memories — ?apiKeyId=, ?type=, ?sessionId=, ?q=, with offset/limit or page/limit pagination |
| POST | /api/memory |
Create memory — body validated by Zod: {content, key, type?, sessionId?, apiKeyId?, metadata?, expiresAt?} |
| GET | /api/memory/[id] |
Retrieve one memory |
| DELETE | /api/memory/[id] |
Delete a memory |
| GET | /api/memory/health |
Memory subsystem health (DB connectivity, embeddings backend, vector index status) |
Auth: management session/API key (requireManagementAuth). type enum: FACTUAL, EPISODIC, SEMANTIC, PROCEDURAL (see MemoryType in src/lib/memory/types.ts).
MCP Server
OmniRoute ships an embedded Model Context Protocol server with 3 transports (stdio, SSE, streamable-http) and scoped tools. The dashboard endpoints below read status/audit data and proxy the HTTP transports.
| Method | Path | Description | |
|---|---|---|---|
| GET | /api/mcp/status |
Heartbeat, transport, online state, last call, top tools, 24h success rate | |
| GET | /api/mcp/tools |
List of MCP tools with name, description, scopes, phase, auditLevel, sourceEndpoints |
|
| GET | /api/mcp/sse |
Open SSE stream for the SSE transport (returns 503 if MCP disabled or transport mismatch) |
|
| POST | /api/mcp/sse |
Send JSON-RPC frame on the SSE transport | |
| GET | /api/mcp/stream |
Open SSE side of the Streamable HTTP transport (server-initiated messages) | |
| POST | /api/mcp/stream |
Send JSON-RPC frame on the Streamable HTTP transport | |
| DELETE | /api/mcp/stream |
End a Streamable HTTP session | |
| GET | /api/mcp/audit |
Query audit log — ?limit=, ?offset=, ?tool=, `?success=true |
false, ?apiKeyId=` |
| GET | /api/mcp/audit/stats |
Aggregate audit stats (totals, success rate, avg duration, top tools) |
Auth: the sse/stream transports honor the MCP-specific auth surface (Bearer API key with mcp scope); the status/tools/audit* routes are readable from the dashboard (no extra auth required beyond reaching the dashboard host).
Both HTTP transports are gated by
settings.mcpEnabledandsettings.mcpTransport— a transport mismatch returns400, an MCP disabled state returns503.
A2A Server
OmniRoute exposes an A2A (Agent-to-Agent) JSON-RPC 2.0 endpoint plus a REST wrapper for inspection/dashboard use.
JSON-RPC
POST /a2a
Authorization: Bearer your-api-key # optional unless OMNIROUTE_API_KEY is set
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "message/send",
"params": {
"skill": "smart-routing",
"messages": [{"role": "user", "content": "Route this coding task"}]
}
}
Supported methods (all gated on settings.a2aEnabled):
| Method | Description |
|---|---|
message/send |
Synchronous skill execution; returns {task, artifacts, metadata} |
message/stream |
Streaming SSE execution of the same skill set |
tasks/get |
Fetch a task by taskId |
tasks/cancel |
Cancel a task by taskId |
Built-in skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report.
Agent Card
GET /.well-known/agent.json
Returns the public A2A agent card (name, description, capabilities, skill catalog, auth scheme) — cached publicly for 1h. No auth required.
REST helpers
| Method | Path | Description |
|---|---|---|
| GET | /api/a2a/status |
A2A enabled + task stats + cached agent card summary |
| GET | /api/a2a/tasks |
List tasks — ?state=submitted|working|completed|failed|cancelled, ?skill=, ?limit= (≤200), ?offset= |
| POST | /api/a2a/tasks |
(Not implemented as a REST helper — create via JSON-RPC message/send) |
| GET | /api/a2a/tasks/[id] |
Retrieve one task |
| POST | /api/a2a/tasks/[id]/cancel |
Cancel a task |
Auth: the REST helpers run without management auth (dashboard-readable); the JSON-RPC /a2a route uses Bearer OMNIROUTE_API_KEY if configured.
Cloud, Evals & Assess
| Method | Path | Description | ||
|---|---|---|---|---|
| POST | /api/cloud/auth |
Verify a Bearer key and return masked provider connections + model aliases for cloud sync clients | ||
| POST | /api/cloud/credentials/update |
Update encrypted credentials for a cloud-synced provider | ||
| POST | /api/cloud/model/resolve |
Resolve a logical model id to a concrete provider/model using the local routing table | ||
| GET | /api/cloud/models/alias |
List model aliases as exposed to cloud sync | ||
| GET | /api/assess |
Read latest assessment categorizations (per-provider/model) | ||
| POST | /api/assess |
Run an assessment — body: `{scope: {type:"all"} | {type:"provider", providerId} | {type:"model", modelId}, trigger?}` |
| GET | /api/evals |
List built-in eval suites + most recent runs | ||
| POST | /api/evals |
Trigger an eval run | ||
| POST | /api/evals/suites |
Create a custom eval suite — body validated by evalSuiteSaveSchema |
||
| GET | /api/evals/suites/[id] |
Retrieve a custom eval suite |
Auth: /api/cloud/auth validates a Bearer key directly; the other /api/cloud/*, /api/evals/*, and /api/assess routes require management session/API key. /api/assess POST uses validateBody with a discriminated-union scope schema.
Authentication
- Dashboard routes (
/dashboard/*) useauth_tokencookie - Login uses saved password hash; fallback to
INITIAL_PASSWORD requireLogintoggleable via/api/settings/require-login/v1/*routes optionally require Bearer API key whenREQUIRE_API_KEY=true
Breaking change (v3.8.0) —
/api/v1/agents/tasks/*and the cooldown management endpoints now require management auth (dashboardauth_tokencookie or a management-scoped API key). Clients that previously called these routes unauthenticated will receive401 Unauthorized. See commit588a0333(fix(auth): require management auth for agent and cooldown APIs).