> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plungeai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Route map — the planes that are not bots, one line per operation

> The One API 2.3.0 has 114 operations.


<!-- sources-of-truth: orchestration/api-gateway/openapi.ts, orchestration/api-gateway/routes/discovery.ts, orchestration/api-gateway/routes/tools.ts, orchestration/api-gateway/routes/agents.ts, orchestration/api-gateway/routes/workflows.ts, orchestration/api-gateway/routes/mcp.ts, orchestration/api-gateway/routes/traces.ts, orchestration/api-gateway/routes/models-proxy.ts | last-synced: 2026-10-05 (One API 2.3.0, 114 operations, each field and status read from GET /v1/openapi.json) -->
The One API 2.3.0 has 114 operations. Bots, executions, schedules, triggers, connections, memory,
skills, templates and the Agent Call door are in `bots-and-door.md`; this file holds the rest, so every
operation is named in this skill. Every route takes `Authorization: Bearer ozk_YOUR_KEY` except the
three marked "no auth". Statuses below are the ones the spec lists per operation; `401 unauthorized` is
on every authenticated route. Regenerate a client from `GET /v1/openapi.json` rather than copying this.

## Service

| Route | Does |
|---|---|
| `GET /health` (no auth) | liveness `{status, service, version}` |
| `GET /v1/openapi.json` (no auth) | this contract, OpenAPI 3.1 |
| `GET /v1/whoami` | `{user_id, via: key\|internal, tier, key_label}` |

## Discovery (`plungeai-discovery`)

| Route | Does |
|---|---|
| `GET /v1/discovery/search` | query `q`, `kind` (`agents`, `skills`, `digital-twins`, `personas`, `experts`, `backgrounds`, `workflows`, `models`, `providers`, `connectors`, `plugins`, `mcp-servers`), `type`, `category`, `status` (default `active`), `tier`, `limit`, `offset`, `mode` (`hybrid`, `keyword`, `vector`), `fields` (`list`, `summary`, `full`) → `{cards, count, total, searchMethod}` |
| `POST /v1/discovery/recommend` | `{type, task}` → `{recommended, card, score}`; `400 invalid_json` / `invalid_request`, `429` |
| `POST /v1/discovery/resolve` | `{task, kinds?, category?, status?}` → `{outcome: match\|uncertain\|none, tool, operation, call: {required_params, example_cnl}, confidence, alternatives, mode: shadow\|act}`; `400 invalid_json` |
| `GET /v1/discovery/cards/{type}/{id}` | the card as markdown; `type` is singular (`agent`, `skill`, `digital_twin`, `expert`, `background`, `workflow`, `model`, `provider`, `connector`, `plugin`, `mcp_server`); `400 invalid_request`, `404 not_found` |

## Tools (`plungeai-tools-connectors`)

| Route | Does |
|---|---|
| `GET /v1/tools` | active tool agents, `limit` ≤ 100 (default 50), `offset` → `{tools, count}` |
| `GET /v1/tools/{id}` | the contract `{agent_id, credential, name, description, operations, inputSchema, examples, output_type}`; `404 unknown_tool` |
| `POST /v1/tools/{id}/execute` | `{operation, params, prompt, format}` → `{ok, content, outcome, request_id}`; `403 refused`, `409 approval_required` or `duplicate_execution_id`, `413`, `422 invalid_params` (echoes the contract), `424` (with `connect`), `429`, `502 execution_failed`, `503 agent_unavailable` |

## Agents (`plungeai-agents`)

| Route | Does |
|---|---|
| `GET /v1/agents` | active agents, `limit` ≤ 100 (default 50), `offset` → `{agents, count}` |
| `GET /v1/agents/categories` | `{categories, count}` |
| `POST /v1/agents/{id}/execute` | `prompt` (or `input`), `persona`, `provider`, `model`, `maxTokens` or `max_tokens`, `temperature`, `top_p`, `reasoning_effort`, `thinking_level`, `system`, `messages`, `sync` (default `true`), `stream` (default `false`: OpenAI-shaped SSE chunks, then `data: [DONE]`), `user_context`, `format`. `200 {content, workflow_id, task_id, request_id}`; `sync: false` is `202 {workflow_id, task_id, request_id}`. Errors: `400 missing_prompt`, `403 agent_not_active`, `404 unknown_agent`, `409 duplicate_execution_id`, `413`, `422 invalid_params` / `unknown_model` / `empty_completion` (raise `max_tokens` to 64 or more), `424`, `429`, `502 engine_error` / `result_unavailable`, `503 agent_unavailable` |
| `GET /v1/agents/results/{workflowId}/{taskId}` | redeem an async result `{content, content_type, workflow_id, task_id}`; `404 not_ready` (poll, 2 s or more), `409 execution_failed`, `422 empty_completion` |

## Workflow execution (`plungeai-workflows` → `references/api.md`)

`POST /v1/workflows/execute` (inline YAML or JSON), `POST /v1/workflows/{id}/execute` (saved),
`POST /v1/workflows/execute-stream` and `POST /v1/workflows/{id}/execute-stream` (SSE),
`GET /v1/workflows/results/{workflowId}/{taskId}` (redeem), `POST /v1/workflows/executions/{id}/cancel`
(the same operation as `POST /v1/executions/{id}/cancel`). Bodies, events and errors are in that file; the saved-workflow CRUD and
versions are in `bots-and-door.md`.

## MCP pass-through and outbound runs (`plungeai-mcp-setup`, `plungeai-results-traces`)

| Route | Does |
|---|---|
| `GET /v1/mcp/tools` | the platform's MCP tool list (JSON-RPC `tools/list` result) |
| `POST /v1/mcp` | Streamable-HTTP MCP pass-through: any MCP client with an `ozk_` key; JSON or SSE; a body that is not JSON is a JSON-RPC `-32700` error, not the router envelope |
| `POST /v1/mcp/runs` | `{server_ids}` (non-empty string array) → `201 {run_id, tools, connected, failed, warnings}`; `502 no_servers_connected` |
| `GET /v1/mcp/runs/{id}/tools` | `{tools, count}`; `404 run_not_found` once the run is closed or 30 minutes idle: open a new one |
| `POST /v1/mcp/runs/{id}/call` | `{name, args?, timeout_ms?}` → `{content}`; `502 tool_call_failed` |
| `DELETE /v1/mcp/runs/{id}` | close the run (idempotent) → `{success}` |

## Traces

| Route | Does |
|---|---|
| `GET /v1/traces/{id}` | `{trace_id, spans, gateway_requests}` for the `x-trace-id` you sent; `404 not_found` for an unknown id or another key's (spans land asynchronously: retry in a few seconds) |

## Models plane (`plungeai-models`)

Same `ozk_` key, `Authorization: Bearer` only.

| Route | Does |
|---|---|
| `POST /v1/chat/completions` | `model`, `models[]` (ordered fallback), `sort` (`price`, `latency`, `throughput`), `messages`, `stream`, `temperature`, `max_tokens`, `top_p`; `@preset/<slug>` is a model name. `402 byok_required`, `403 model_not_allowed` / `content_blocked`, `404 preset_not_found` / `model_not_found`, `405 method_not_allowed`, `429 rate_limit_exceeded` / `spend_cap_exceeded`, `503 money_plane_unavailable` |
| `POST /v1/embeddings` | `{model, input}` |
| `POST /v1/completions` | legacy `{model, prompt (one string), max_tokens?, stream?}`, answered as `text_completion` |
| `GET /v1/models` | the priced catalog |
| `GET /v1/models/{author}/{slug}/endpoints` | the endpoint that serves one model, with per-token pricing |
| `GET /v1/generation?id=` | usage and cost of one completion (`gen-…` id or `x-request-id`) |
| `GET /v1/credits` | `{data: {total_credits, total_usage}}` in USD |
| `GET /v1/key` | the calling key: label, monthly limit, usage, rate limit |

The OpenRouter drop-in base `/api/v1` serves the same eight operations (`POST /api/v1/chat/completions`,
`/embeddings`, `/completions`; `GET /api/v1/models`, `/generation`, `/credits`, `/key`,
`/models/{author}/{slug}/endpoints`) with OpenRouter-shaped errors
(`{"error":{"code": <number>, "message", "metadata"}}`). Point an OpenRouter client's base URL there; new code uses `/v1`.
