API keys let you call AgentFlow from servers, CI runners, scripts, and webhook integrations without juggling SIWE / Telegram sessions. They sit alongside cookies and JWTs as a third auth path — same routes, same permissions, just a different header. Each key carries its own metering: a requests-per-minute cap, an optional FLOW spend cap per period (day / week / month / forever), and a usage log every call lands in. Think of it as the OpenRouter Activity page — same shape, FLOW instead of USD.Documentation Index
Fetch the complete documentation index at: https://agentflow-fea9d881-feat-republic-narrative.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Wire format
Keys are 72 characters:af_live_ followed by 64 hex chars (32 bytes of CSPRNG randomness, 256 bits of entropy). The server stores only an HMAC-SHA256 hash plus a 12-character display prefix; the raw value is shown to you exactly once.
When to use an API key
- A backend that needs to mint receipts, list marketplace agents, or call
/me/*on behalf of its owner. - A CI pipeline that publishes agents or runs build-stream tests.
- A long-lived bot script where keeping a SIWE session alive is awkward.
af_session cookie issued by POST /auth/verify — it is HttpOnly and rotates automatically.
POST /me/api-keys — mint a key
Auth: cookie / bearer / x-api-key.Human label, 1–64 chars. Surface it in your secret manager so future-you knows what this key is for.
Per-key requests-per-minute cap. Default 60. Set 0 to disable the cap.
Optional FLOW spend cap per period. Decimal string preferred (
"100.5"); numbers are accepted but lose precision past 6 decimals. Omit for no cap.Period bucket —
day, week, month, or forever. Default month.GET /me/api-keys — list active keys
Returns the public shape only — never the hash. Each entry carries its current limits andspend_period_used so you can render budget bars without a second roundtrip.
PATCH /me/api-keys/:id — adjust limits
All fields are optional — pass only what you want to change. Switchingspend_period resets spend_period_used to 0 so the new bucket starts clean.
DELETE /me/api-keys/:id — revoke
Soft-revoke. The row sticks around so audit trails (who created what, when it was last used) stay readable. Subsequentx-api-key calls with the revoked key get 401.
Authentication header
Send the raw key inx-api-key on any request that would otherwise need a session:
x-api-key and Authorization: Bearer … and the key is invalid, you get 401 even though the bearer would have worked.
Rate limits
Every successful response carries:| Header | Meaning |
|---|---|
X-RateLimit-Limit | Configured rate_limit_rpm. |
X-RateLimit-Remaining | Slots left in the current 1-minute window. |
X-RateLimit-Reset | ISO timestamp when the window rolls over. |
Retry-After header (in seconds) and:
api_keys row so it stays consistent across all replicas. Setting rate_limit_rpm to 0 disables the cap entirely.
Spend limits
Each request also gets:| Header | Meaning |
|---|---|
X-FLOW-Cost | FLOW charged for this request (0 for free endpoints). |
X-FLOW-Period-Used | FLOW spent so far in the current period. |
X-FLOW-Period-Limit | Configured cap (omitted if no cap). |
X-FLOW-Period-Reset | ISO timestamp when the period rolls over. |
period_used >= spend_limit_flow the API returns 402 Payment Required:
Usage tracking
Every authenticated request that arrived withx-api-key is logged to api_key_usage (best-effort, non-blocking). Two endpoints expose the data:
GET /me/api-keys/:id/usage?since=day|week|month|all
GET /me/api-keys/:id/recent?limit=50
limit is clamped to 200. Use it for live tail / debug. The cabinet’s API key detail page polls this for the “Recent calls” panel.
Comparison with OpenRouter
If you’re already running on OpenRouter, the model is identical — only the unit changes:| OpenRouter | AgentFlow |
|---|---|
| API key with USD spend cap | API key with FLOW spend cap |
| Activity page (calls + cost) | /me/api-keys/:id/usage + cabinet UI |
X-RateLimit-* headers | X-RateLimit-* headers (same names) |
| Per-model breakdown | by_model in /usage |
Cabinet UI
A self-service “API Keys” tab in the cabinet lets you create, list, and revoke keys; the per-key detail page at/account/api-keys/:id exposes the limits editor + activity surface described above.
Rotation
Keys are immutable from a credential standpoint. To rotate:apiKeys.create({ name: 'ci-runner-v2', … }).- Swap your service config to the new key. Both keys keep working in parallel.
apiKeys.revoke(<old-id>).
last_used_at ticking so you can confirm everything migrated before pulling the plug.
Security checklist
- Store the raw key in env vars, secret managers (1Password, AWS Secrets Manager, doppler), or encrypted CI variables. Never commit it to git.
- Treat the
prefixas the user-facing identifier in audit views — it is safe to share. - Set a
spend_limit_floweven if you trust the consumer — it’s the cheapest blast radius limit you’ll ever set. - Rotate on a schedule (quarterly is a sane default) using the create-then-revoke flow above.
- Revoke immediately on suspected leaks — soft-revoke preserves the audit trail without giving the attacker any wiggle room.