For AI agents: a documentation index is available at https://www.plungeai.com/docs/llms.txt. Append .md to any page URL, or send Accept: text/markdown, to get markdown. Setup instructions for agents are at https://www.plungeai.com/docs/agents.md. One ozk_ key opens every plane, models included.

Documentation Index: fetch the complete documentation index at /llms.txt. Use this file to discover all available pages before exploring further.

Setup for the PlungeAI One API (https://api.plungeai.com, v2.3.0) — a self-service ozk_ key, the Bearer/X-API-Key header, your first curl call, the live OpenAPI 3.1 contract at /v1/openapi.json, typed-client codegen, the three API levels (compatible wire, standard REST incl. bots, schedules and executions, the Agent Call door POST /v1/execute), and shared error/rate-limit basics. Use whenever writing or GENERATING code that calls PlungeAI, or answering "how do I authenticate", "where's the OpenAPI spec", "how do I generate a typed client" or "can I run a bot over REST". Triggers: "PlungeAI API", "api.plungeai.com", "One API", "call plungeai from code", "plungeai openapi", "plungeai curl", "plungeai SDK". Route detail: the capability skills (plungeai-agents, plungeai-workflows, plungeai-scheduling, plungeai-results-traces, …). MCP → plungeai-mcp-setup; terminal → plungeai-cli-setup; unsure which door → choose-your-plungeai-door.

Download zip (opens in a new tab) · View raw SKILL.md (opens in a new tab)

One base URL for the whole platform: https://api.plungeai.com. Plain JSON over HTTPS — no SDK required. The models ("money") plane is OpenAI-compatible. Machine-readable contract: GET /v1/openapi.json (OpenAPI 3.1). This skill gets you authenticated and making calls; the route-by-route manual for each capability (what params, what the response looks like, error handling per route) lives in that capability's own skill — load it next.

Prerequisites — get a key

Self-service ozk_ key: Dashboard → One API → Keys (https://dashboard.plungeai.com) → create → name it, pick an expiry (never, or 7–365 days) → copy it once, it is shown exactly once and stored hashed thereafter. Ask the account owner only for a shared/team key minted under someone else's account. Keys inherit your account's tier (free by default).

The same ozk_ key opens the models plane too (/v1/chat/completions, /v1/embeddings, /v1/models, see plungeai-models) — one key for every plane. The legacy sk-ocean- / sk-conn- keys are retired: no new ones can be minted, and existing ones sit read-only under Dashboard → One API → Keys → Legacy keys until revoked.

Discovery first — hard rule

The catalog is live. Never hardcode agent ids, tool lists, model slugs, or route shapes from memory:

  • GET /v1/openapi.json — the live route contract, no auth required. This is the one authority for what routes exist; regenerate any typed client from it, never patch by hand.
  • GET /v1/agents / GET /v1/discovery/search?q=<capability> — what's callable right now (full capability detail: plungeai-discovery, plungeai-agents).

Quick start — first call

curl -X POST https://api.plungeai.com/v1/agents/one-agent/execute \
  -H "Authorization: Bearer ozk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Say exactly: hello ocean", "sync": true}'
{
  "content": "hello ocean",
  "workflow_id": "00000000-0000-4000-8000-000000000001",
  "task_id": "t1",
  "request_id": "00000000-0000-4000-8000-000000000004"
}

That is the whole integration pattern: bearer key, JSON body, JSON result. Every other plane (tools, workflows, models, MCP pass-through, discovery, traces) works the same shape — the per-plane request/response detail is in that plane's capability skill.

Three levels — all supported, none deprecated

LevelWhatUse it when
1 Compatible wire/v1/chat/completions, /v1/models, /api/v1/* (models only)an OpenAI or OpenRouter client should just work
2 Standard RESTone route per resource, JSON or YAML in and out: /v1/workflows (saved workflows, agents, bots, campaigns, versions), /v1/executions, /v1/schedules, /v1/triggers, /v1/bot-groups, /v1/channels, /v1/connections, /v1/memory, /v1/skills, /v1/templatesyou manage a resource or call it by id — start here
3 Agent Call doorPOST /v1/execute: the body is the program — a bare task, a workflow:, or agent: <saved id>@3 + inputthe body is the program; it always runs through the engine, so a saved bot keeps its stored policy
# a saved bot, pinned to snapshot 3, planned but not run
curl -s -X POST https://api.plungeai.com/v1/execute \
  -H "Authorization: Bearer ozk_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"agent":"<saved bot id>@3","input":"Check the pricing page","dry_run":true}'

Bots over REST: set a bot's permission classes, locks and spend caps (PUT /v1/workflows/{id}/permissions), read its workspace files and inbox, bind a paired chat (/bindings), group bots (/v1/bot-groups), steer a running execution (POST /v1/executions/{id}/steer), schedule it once (@once + run_at) or wake it, and mint webhook, email or outbound-hook triggers. Connections (/v1/connections, on_behalf_of for your customers) are there too. Every route, body field and status of those: references/bots-and-door.md; every other operation (discovery, tools, agents, MCP, traces, models): references/route-map.md. The saved-bot authoring rules are plungeai-bot-agent's; MCP and CLI spellings are in the verb tables of plungeai-workflows and plungeai-scheduling.

Save a workflow, run it, read the result

A saved workflow is CNL YAML in the yaml field of POST /v1/workflows (kind is workflow, agent, bot or campaign). The smallest valid body, as YAML (a workflow: wrapper, tasks: list, one type: task):

workflow:
  name: Hello
  tasks:
    - type: task
      id: t1
      agent: one-agent
      prompt: "Say exactly: {input}"
KEY=ozk_YOUR_KEY; API=https://api.plungeai.com
# save → 201 {"workflow":{"id":"<id>",…},"warnings":[]}   (a refusal is 422 invalid_workflow with errors[])
curl -s -X POST $API/v1/workflows -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"name":"Hello","kind":"workflow","yaml":"workflow:\n  name: Hello\n  tasks:\n    - type: task\n      id: t1\n      agent: one-agent\n      prompt: \"Say exactly: {input}\"\n"}'
# or save a YAML file as the body (kind and name ride the query; workflow.name is the name when ?name is left out)
curl -s -X POST "$API/v1/workflows?kind=bot&name=Hello" -H "Authorization: Bearer $KEY" -H 'Content-Type: text/yaml' --data-binary @bot.yaml
# run it by id → {"success":true,"workflow_id":"<execution id>","final_task_id":"t1","request_id":"…","content":"…"}
curl -s -X POST $API/v1/workflows/<id>/execute -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" -d '{"input":"hello"}'
# read it back: the execution id is the `workflow_id` of the run answer (not the saved workflow's id)
curl -s $API/v1/executions/<execution id>/output -H "Authorization: Bearer $KEY"

Agent ids in agent: come from discovery, never memory: GET /v1/discovery/search?q=<capability> returns skill and other cards first, so add &kind=agents when you want an agent id (GET /v1/agents lists them too). Other routes you will want next: GET /v1/executions/{id} (poll status), GET /v1/executions/{id}/output, GET /v1/executions/{id}/files, POST /v1/schedules — all in references/bots-and-door.md.

Authentication — header and error basics

KeyPlanesHow to send
ozk_YOUR_KEYExecution planes: /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/tracesAuthorization: Bearer ozk_YOUR_KEY (or X-API-Key: ozk_YOUR_KEY)
ozk_YOUR_KEY (the same key)Models plane: /v1/chat/completions, /v1/embeddings, /v1/modelsAuthorization: Bearer ozk_YOUR_KEY only (no X-API-Key here)
  • Never hardcode keys in generated code — read the one ozk_ key from an env var (PLUNGEAI_API_KEY) for every plane.
  • Execution-plane errors use the envelope {"error":{"code","message",…}} and always carry X-Error-Code: <code> — branch on the header. The body follows the negotiated format (?format= or a body field, Accept: json default, yaml, markdown, text); an unknown value is 400 invalid_format. A 424 adds error.connect ({provider, method, link}); an error on a call that created an execution carries X-Execution-Id. /v1/discovery/recommend and /v1/discovery/cards/:type/:id normalize the registry's own flat {"error":"<string>"} into the envelope (code is not_found on a 404, invalid_request otherwise). The models plane uses the OpenAI error shape ({"error":{"message","type","code","request_id"}}); the /api/v1 drop-in the OpenRouter one.
  • Every response carries a server-minted x-request-id header. To correlate your own calls, send x-trace-id and keep your own copy — it is not echoed back, but it is threaded across every internal hop and queryable at GET /v1/traces/<your id> (plungeai-results-traces).

Error semantics — the ones every caller needs

StatusCodeMeaningWhat your code does
400run_at_required / run_at_pastA @once schedule with no run_at, or one not in the futureSend an ISO-8601 time WITH a UTC offset, in the future
400invalid_json / invalid_yaml / invalid_body / invalid_format / missing_workflow / ambiguous_bodyAn unreadable body, an unknown format, none of workflow / agent / tasks, or agent: next to workflow:Fix the body; the message names the problem
401unauthorizedMissing/invalid key, or the wrong key prefix for this planeFix the key. Never retry in a loop
403refusedTrust fence. The agent/tool refused the action outright — a gated/money verb, unattended surface. A policy verdict, not a lifecycle stateFINAL. Surface verbatim. NEVER retry, rephrase, or route around
403agent_not_activeA named agent (in a workflow or a single-agent execute) is parked/inactive — a lifecycle state, distinct from refused aboveRe-discover a fresh id (GET /v1/discovery/search); don't retry the same id
403lock_admin_requiredA bot's permission locks can be set only by a team admin; nothing in that body was writtenAsk an admin; resend without locks
404unknown_agent / unknown_tool / agent_not_found (the POST /v1/execute door) / <thing>_not_found (workflow, execution, schedule, trigger, group, binding, version, template, skill, memory, connection, …)No such id, or another account's (the two answer alike)Re-discover; don't retry the same id
404not_readyAsync result not landed yetPoll again with backoff (2s+)
409approval_requiredTrust fence. A human must approve before the action runs — implemented and produced today, not a placeholder. Three shapes, three answers (below)Never approve on your own
409duplicate_execution_idThe x-trace-id you sent was already used by an earlier runSend a fresh UUID, or omit it
413payload_too_largeBody over 1 MiBShrink the body
422invalid_workflowA saved workflow, agent or bot fails CNL validation or its kind's lint (errors and warnings listed); nothing is writtenFix exactly the listed fields and resend
422invalid_paramsOutcome needs_input — body fails the tool contract (the response echoes missing and the contract), or a field on a resource route is missing or malformedSelf-correct from the echoed contract or message, then retry once
424connection_required / credential_requiredOutcome needs_connection / needs_api_key — no connected account, or no API key for a connector; error.connect names the provider and where to connect itPOST /v1/connections/{provider} (a key) or …/link (a hosted URL for a customer), or Ocean Studio → Connectors, then retry
429rate_limitedExecution planes — per-tier RPM/RPD cap, or failed-auth meteringHonour the Retry-After header; back off
429rate_limit_exceeded / spend_cap_exceeded / insufficient_quotaModels plane only — separate codes, separate plane; rate, spend-cap, or quota limitBack off; caps/quotas are policy, not transients
5xxengine_error / upstream_error / storage_error / scheduler_error / internal_error (503 agent_unavailable / not_enabled)Upstream or router failure, or a feature not switched on yetOne retry with backoff is reasonable

409 approval_required — pick the row that matches what you hold:

You haveApprove withThen
A 409 from POST /v1/tools/{id}/execute (the dispatch fence; no execution exists to continue)Studio, by a humanre-issue the identical request
A paused agent turn on /v1/agents/{id}/execute (the reply carries an action_token)re-send the same call with approved: true + that action_token (both, or 400 invalid_params)nothing else
A run whose GET /v1/executions/{id} reads needs_approvalPOST /v1/executions/{id}/continue {"approve": true, "allow_scope": "once"|"run"|"always"} (MCP plungeai_continue) — the held action runs inside that calldo NOT re-issue the original request (it would act twice)

Canonical code list (all planes, every status): developer guide §13 at GET /llms-full.txt — §13.2 (execution-plane codes), §13.3 (outcome→HTTP mapping), §13.5 (the two trust-fence statuses). 403 refused and 409 approval_required are the fence; everything else is caller-fixable.

Sync vs async and per-route detail are in each capability's own skill.

Rate limits

Execution-plane tiers: free 30/min · 1,000/day, pro 100/min · 10,000/day, enterprise 300/min · 100,000/day (a key with no tier counts as free; a per-key rate_limit override applies only on https://mcp.plungeai.com/v1, not here). Enforced per-key on POST calls only (GETs are free); a hit answers 429 rate_limited with a Retry-After header — honour it. Failed authentications are metered per client IP. These numbers are the defaults: the operator sets the limits, and when they are switched off there is no 429 except failed-auth metering. The models plane has its own, separate limiter, default 600 req/min per key, answering 429 rate_limit_exceeded with no Retry-After header — back off on a short fixed interval (~1s) instead. Don't hammer result-polling endpoints; use 2s+ intervals.

Self-documenting endpoints (no auth), SDK and codegen

GET /v1/openapi.json (OpenAPI 3.1) · GET /llms.txt (index) · GET /llms-full.txt (full guide and route reference as one markdown payload) · GET /docs (human page) · GET /health. AI agents at runtime can skip HTTP: connect an MCP client to https://mcp.plungeai.com/v1 with an ozk_ key (plungeai-mcp-setup).

Typed clients: four official SDKs, generated from the live spec — TypeScript @plungeai/one-api, Python plungeai, Go github.com/PlungeAI/plungeai-go, Rust plungeai (setup and first call: plungeai-sdk-setup). For any other language, generate a client from GET /v1/openapi.json. Snippets (codegen, the SDK table, the curl cookbook, a paste-ready AGENTS.md block): references/sdk-and-codegen.md.

Verify

# 1. Liveness (no auth) — expect {"status":"ok","service":"one-api-router",...}
curl -s https://api.plungeai.com/health

# 2. Authenticated GET — expect {"tools":[...],"count":N}
curl -s "https://api.plungeai.com/v1/tools?limit=1" \
  -H "Authorization: Bearer ozk_YOUR_KEY"

# 3. A 401 here means the key is wrong; a 200 with cards means you're in:
curl -s "https://api.plungeai.com/v1/discovery/search?q=web%20search&limit=1" \
  -H "Authorization: Bearer ozk_YOUR_KEY"

# 4. Who the key is — expect {"user_id":"…","via":"key","tier":…,"key_label":…}
curl -s https://api.plungeai.com/v1/whoami -H "Authorization: Bearer ozk_YOUR_KEY"

For the models plane, verify with the same ozk_ key: curl -s https://api.plungeai.com/v1/models -H "Authorization: Bearer ozk_YOUR_KEY".

References

  • references/bots-and-door.md — bots, executions, schedules, triggers, connections, memory, skills, templates and the Agent Call door over REST: every route, body field, limit and status (One API 2.3.0).
  • references/route-map.md — every other operation, one line each: service, discovery, tools, agents, workflow execution, MCP, traces, models plane and the /api/v1 drop-in.
  • references/sdk-and-codegen.md — the four official SDKs, typed-client generation for other languages, curl cookbook, self-documenting endpoints, the paste-ready AGENTS.md block for generated apps.
  • plungeai-models — the OpenAI-compatible plane in depth: routing, presets, guardrails, caching, pricing.
  • plungeai-agents, plungeai-tools-connectors — execute a registry agent or a structured tool; contracts, sync/async, 422 handling.
  • plungeai-workflows — CNL YAML authoring and the workflow execution routes (inline + saved, SSE streaming).
  • plungeai-discovery — catalog search, recommendations, cards.
  • plungeai-scheduling — /v1/schedules and /v1/triggers: cron, one-time run_at, wake, webhook/email/hook triggers.
  • plungeai-bot-agent — the saved bot's YAML and keys (what the REST bot routes govern).
  • plungeai-results-traces — /v1/executions (status, output, continue, followup, steer, files), traces, MCP-as-server routes.
  • plungeai-mcp-setup — the same platform over MCP instead of REST.
  • plungeai-sdk-setup — the official TypeScript, Python, Go and Rust SDKs.
  • plungeai-cli-setup — operate PlungeAI from a terminal.

Reference pages

Planned: TI-34

The docs assistant is not available yet. You can hand these docs to your own assistant instead.