Getting started
Authentication & keys
The three key prefixes, which routes accept which, and how to keep keys safe.
Every route except GET /health and GET /v1/openapi.json needs a key. Each of the three prefixes opens a different set of routes, and sending the wrong prefix is a 401, never a silent fallback.
These docs use PLUNGE_API_KEY; the PlungeAI skills, the Claude Code plugin and the install page use PLUNGEAI_API_KEY; any name works if your config and shell agree.
The three prefixes
| Prefix | Opens | Variable in these docs |
|---|---|---|
ozk_ | The six execution planes (tools, agents, workflows, MCP, discovery, traces) and the MCP server https://mcp.plungeai.com/v1 | $PLUNGE_API_KEY |
sk-ocean- | The models plane only: /v1/chat/completions, /v1/embeddings, /v1/models | $PLUNGE_MODEL_KEY |
sk-conn- | The connector proxy on gateway.plungeai.com | $PLUNGE_CONNECTOR_KEY |
Which routes accept which key
The execution planes (/v1/discovery, /v1/tools, /v1/agents, /v1/workflows, /v1/mcp, /v1/traces) accept only a bearer that starts with ozk_. The models plane accepts only sk-ocean-. Both mistakes answer 401:
# ozk_ key on the models plane → 401
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://api.plungeai.com/v1/chat/completions \
-H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: application/json' \
-d '{"model":"anthropic/claude-haiku-4-5","messages":[{"role":"user","content":"hi"}],"max_tokens":1}'The 401 body is the standard error envelope, and X-Error-Code: unauthorized carries the same code as a header.
Header forms
| Header | Accepted on |
|---|---|
Authorization: Bearer <key> | Every plane and the MCP server |
X-API-Key: <key> | The execution planes and the MCP server (ozk_ keys) |
curl -s "https://api.plungeai.com/v1/tools?limit=1" -H "Authorization: Bearer $PLUNGE_API_KEY"curl -s "https://api.plungeai.com/v1/tools?limit=1" -H "X-API-Key: $PLUNGE_API_KEY"How to obtain each key
All three are self-service at Dashboard → One API → Keys (https://dashboard.plungeai.com/one-api?tab=keys (opens in a new tab)). Name the key, pick an expiry (never, or 7, 30, 90, 180 or 365 days) and copy it: it is shown exactly once and stored hashed. A new key takes your account's tier.
Expiry, revocation and rotation
- Expiry is checked on every request; an expired key answers
401from that moment. - Revoke a key from the same Keys list. Keys are cached briefly, so a revoked key can keep working for about two minutes before it answers
401. If a key leaked, revoke it first and allow for that window. - Rotate without downtime: create the new key, update every client, confirm it with
plungeai_whoami, then revoke the old key. - A lost key cannot be recovered, because only its hash is stored: create a replacement and revoke the old one.
Key fences
Key fences are set by PlungeAI on request. Keys you create in the Dashboard carry no fence: every tool, from any address. On https://mcp.plungeai.com/v1, a key fenced to some tools does not see the others in tools/list, and a call to one answers JSON-RPC -32602; a key fenced to some addresses answers 401 from anywhere else.
Checking yourself: plungeai_whoami
Ask your MCP client to "use plungeai_whoami", or call it directly. It returns the user, the auth type and tier, the key label and the current rate-limit window:
curl -s https://mcp.plungeai.com/v1 \
-H "Authorization: Bearer $PLUNGE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_whoami","arguments":{"user_request":"who am I?"}}}'The fields are on Who am I.
CORS
The One API answers browser requests from any origin, and the models plane exposes x-request-id. Browser code works, but a key in client-side code is a key anyone can read: call PlungeAI from your server.
Keeping the key safe
Treat the key like a password: whoever holds it acts as your account. If a key may have leaked, rotate it now.
- Keep the literal key in a user-level client config or an environment variable. A config file inside a repository only references a variable.
- Before the first commit in a repository you configured, both commands must print nothing:
git grep -n "ozk_"
grep -rn "ozk_" . --exclude-dir=.git --exclude-dir=node_modules- Never put a key in browser code or a client bundle.