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

# SDK & codegen — typed clients, snippets, and the AGENTS.md block

> The supported integration stance, in order of preference:


<!-- sources-of-truth: orchestration/api-gateway/openapi.ts, orchestration/api-gateway/routes/discovery.ts, orchestration/api-gateway/routes/workflows.ts, orchestration/api-gateway/lib/respond.ts, orchestration/api-gateway/docs/guide-3.0/15-sdks-and-clients.md, sdk/one-api-client/README.md, sdk/one-api-python/README.md, sdk/one-api-go/README.md, sdk/one-api-rust/README.md, docs/ONE-API-DEVELOPER-GUIDE-2.0.md | last-synced: 2026-10-14 (One API 2.5.0, 136 operations; the four SDKs 1.0.0 ship via the `one-api-v1.0.0`, `one-api-python-v1.0.0`, `one-api-go-v1.0.0` and `one-api-rust-v1.0.0` tags) -->
The supported integration stance, in order of preference:

1. **Plain HTTPS** — every plane is JSON over HTTPS; any HTTP client works.
2. **The OpenAI SDK you already use** — for the models plane only
   (`base_url = https://api.plungeai.com/v1`, your `ozk_` key). See the `plungeai-models`
   skill.
3. **The official SDKs** — TypeScript `@plungeai/one-api`, Python `plungeai`, Go
   `github.com/PlungeAI/plungeai-go`, Rust `plungeai`. Setup and first call: the
   `plungeai-sdk-setup` skill.
4. **Generate your own client** from the live OpenAPI 3.1 spec — for any other language, or
   when you want only the types.

The OpenAPI document at `GET /v1/openapi.json` is the contract; the official SDKs' resource
layers are generated from it, so every operation in the spec has a method in each of them.

## Generate your own client (any language)

The spec is OpenAPI 3.1 at `https://api.plungeai.com/v1/openapi.json`. Any 3.1-capable
generator works.

**TypeScript**:

```bash
npx openapi-typescript https://api.plungeai.com/v1/openapi.json -o src/plungeai-schema.d.ts
npm install openapi-fetch
```

```ts
import createClient from 'openapi-fetch'
import type { paths } from './plungeai-schema'

export const plungeai = createClient<paths>({
  baseUrl: 'https://api.plungeai.com',
  headers: { Authorization: `Bearer ${process.env.PLUNGEAI_API_KEY}` },
})
```

Re-run the generator when the API changes shape — never patch generated types by hand. Every operation carries a
stable `operationId` (`post-v1-workflows-id-execute`, `get-v1-schedules-id-runs`, …) for generators that name
methods from it. One thing to know: `/v1/discovery/recommend` and `/v1/discovery/cards/{type}/{id}` normalize the
registry's own flat `{"error":"<string>"}` rejections into the standard envelope
(`{"error":{"code","message"}}`, `code` is `not_found` on a 404, `invalid_request` otherwise)
before you ever see them — a generated client's error type for these two routes is accurate
as-is, no special-casing needed.

**Python** (prefer the official `plungeai` package) — for a generated client: `openapi-python-client generate
--url https://api.plungeai.com/v1/openapi.json`.

## Official SDKs

Four packages, one shape: the client reads `PLUNGEAI_API_KEY`, one method per operation
(`client.agents.execute(…)`), typed errors by status (424 carries `connect.link`), 2 retries
with backoff on connection errors, 408, 429 and ≥ 500 — never on 409 or 424 — a 10-minute
timeout, SSE streams, auto-iterating pages, raw-response access, and an idempotency key sent
as `x-trace-id`. All target One API 2.5.0, package version 1.0.0.

| Language | Package | Install | Until published, build from |
|---|---|---|---|
| TypeScript | `@plungeai/one-api` (npm) | `npm install @plungeai/one-api` | `sdk/one-api-client/` (tag `one-api-v1.0.0`) |
| Python | `plungeai` (PyPI) | `pip install plungeai` | `sdk/one-api-python/` (tag `one-api-python-v1.0.0`) |
| Go | `github.com/PlungeAI/plungeai-go` | `go get github.com/PlungeAI/plungeai-go` | `sdk/one-api-go/` (tag `one-api-go-v1.0.0`) |
| Rust | `plungeai` (crates.io) | `cargo add plungeai` | `sdk/one-api-rust/` (tag `one-api-rust-v1.0.0`) |

None is on its registry yet: until its tag is published, build from the `sdk/` directory in the
platform repository. First call in each language, discovery, and the per-language detail: the
`plungeai-sdk-setup` skill.

## curl cookbook

Agent/tool ids below (`brave-agent`, `one-agent`) are illustrative — take real ids from the
discovery call two lines up, never from memory.

```bash
BASE=https://api.plungeai.com
AUTH='Authorization: Bearer ozk_YOUR_KEY'

curl -s $BASE/health                                            # liveness, no auth
curl -s $BASE/v1/openapi.json | head -50                        # live contract, no auth
curl -s "$BASE/v1/discovery/search?q=web%20search&limit=3" -H "$AUTH"
curl -s "$BASE/v1/tools?limit=5" -H "$AUTH"
curl -s $BASE/v1/tools/brave-agent -H "$AUTH"                   # contract (id from discovery)
curl -s -X POST $BASE/v1/agents/one-agent/execute -H "$AUTH" \
  -H 'Content-Type: application/json' -d '{"prompt":"Say: ok"}'
curl -s $BASE/v1/traces/REQUEST_ID_FROM_ABOVE -H "$AUTH"
curl -s "$BASE/v1/workflows?kind=bot&limit=5" -H "$AUTH"          # your saved bots
curl -s -X POST $BASE/v1/execute -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"agent":"<bot id>@1","input":"hi","dry_run":true}'        # the Agent Call door, planned not run
curl -s "$BASE/v1/executions?limit=3" -H "$AUTH"
```

## Self-documenting endpoints

The API teaches itself from the domain — useful for onboarding a coding agent with zero
prior context:

- `GET https://api.plungeai.com/llms.txt` — index (llmstxt.org format)
- `GET https://api.plungeai.com/llms-full.txt` — the full developer guide + route reference
  as one markdown payload
- `GET https://api.plungeai.com/v1/openapi.json` — the machine contract
- `GET https://api.plungeai.com/docs` — human-readable docs page

AI agents at **runtime** can skip HTTP clients entirely: connect an MCP client to
`https://mcp.plungeai.com/v1` with an `ozk_` key (see the `plungeai-mcp-setup` skill).

## AGENTS.md block for generated apps

When you generate an app that calls PlungeAI, drop this block into the app's `AGENTS.md`
(or `CLAUDE.md`) so future coding agents in that repo handle the API correctly. Paste-ready:

```markdown
## PlungeAI One API

This app calls the PlungeAI One API at https://api.plungeai.com.
Official SDKs (env `PLUNGEAI_API_KEY`): `@plungeai/one-api`, `plungeai` (PyPI), `github.com/PlungeAI/plungeai-go`, `plungeai` (crates.io).

- Auth: `Authorization: Bearer $PLUNGEAI_API_KEY` (an `ozk_` platform key) for
  /v1/discovery, /v1/tools, /v1/agents, /v1/workflows, /v1/executions, /v1/schedules,
  /v1/triggers, /v1/bot-groups, /v1/channels, /v1/connections, /v1/memory, /v1/skills,
  /v1/templates, /v1/execute, /v1/mcp, /v1/traces.
  The OpenAI-compatible models plane (/v1/chat/completions, /v1/embeddings,
  /v1/models) takes the same key, as `Authorization: Bearer` only.
  Keys live in env vars only — never commit or log them.
- Live contract: `GET /v1/openapi.json`. Live catalog: `GET /v1/agents`,
  `GET /v1/discovery/search?q=...`. Never hardcode agent/tool/model ids or
  counts — discover them, and re-discover on 404 `unknown_tool` /
  `workflow_not_found`.
- Sync vs async: agent execute defaults to sync; `sync:false` returns 202 +
  `{workflow_id, task_id}` — poll `GET /v1/agents/results/:wf/:task`
  (404 `not_ready` is normal in-flight, back off 2s+).
- HARD RULE — trust fences: `403 refused` (a gated/money verb refused
  outright) and `409 approval_required` (a human must approve before the
  action runs — this is implemented and produced today, not a placeholder)
  are both final for now — surface them to the user; never retry, rephrase,
  or route around a `403 refused`. For `409`, a human approves, by shape:
  a 409 from a tool call → Ocean Studio, then re-issue the identical request;
  a paused agent turn → re-send with `approved: true` + its `action_token`;
  a run reading `needs_approval` → `POST /v1/executions/{id}/continue`
  `{"approve": true}` (MCP `plungeai_continue`) — the held action runs inside
  that call, so do NOT re-issue the original request afterwards.
  A separate, unrelated `403 agent_not_active` (a parked/inactive agent id)
  is a lifecycle state, not a fence — re-discover a fresh id and retry with
  that instead.
- `422 invalid_params` echoes the tool contract — self-correct once, then stop.
- Errors carry `X-Error-Code`; branch on it. Send a fresh UUID as `x-trace-id` (a reused one is
  `409 duplicate_execution_id`). Bots, schedules, executions and the `POST /v1/execute` door:
  `GET /llms-full.txt` §16.
- Rate limits: execution-plane `429 rate_limited` carries `Retry-After` —
  honour it. The models plane's separate `429 rate_limit_exceeded` has no
  Retry-After — use a fixed ~1s backoff there instead.
- 502 `upstream_error` / 500 `internal_error` can come from any route —
  retry once with backoff.
- Correlation: send `x-trace-id` on writes; debug via `GET /v1/traces/:id`.
- Full docs for agents: `GET https://api.plungeai.com/llms-full.txt`.
```

Keep the block verbatim except the env-var names, which should match the app's conventions.
