Docs / Getting started

Authentication & scopes

How you authenticate, what a key is allowed to do, and the cross-cutting conventions — errors, idempotency, rate limits, and pagination — that every endpoint follows.

Credentials

Send a bearer credential on every request: a vbk_ API key (Argon2id-verified, created in the dashboard) or a session token from login. Both go in Authorization: Bearer …; the x-api-key header is also accepted. API keys show their secret only once at creation — only a hash and a 16-char prefix are stored.

curl
# either header works; a bearer key or a dashboard session token
curl https://api.ollanode.com/v1/whoami -H "Authorization: Bearer vbk_..."
curl https://api.ollanode.com/v1/whoami -H "x-api-key: vbk_..."

API keys

Key management requires the coarse admin scope and is human-only — agent keys can never manage keys.

POST /v1/api-keys admin

Create a key. Role presets: owner[admin]; agent[read,write] (actor_type=agent, and forbidden from holding admin); viewer[read]; default → [read,write]. Add least-privilege grants with extra_scopes, and constrain with expires_in_secs, allowed_ip, and daily_request_limit. The secret is shown once.

curl
curl -X POST https://api.ollanode.com/v1/api-keys \
  -H "Authorization: Bearer $SESSION" \
  -H "Content-Type: application/json" \
  -d '{"name":"ci-agent","role":"agent",
       "extra_scopes":["videos:read","zones:purge"],
       "expires_in_secs":86400,"allowed_ip":"203.0.113.7",
       "daily_request_limit":5000}'
201 (secret shown once)
{ "id":"key_...", "name":"ci-agent", "prefix":"vbk_1234abcd...",
  "scopes":["read","write"], "extra_scopes":["videos:read","zones:purge"],
  "actor_type":"agent", "expires_at":"...", "daily_request_limit":5000,
  "key":"vbk_<48 hex — shown once>" }
Use cases
  • Mint a short-lived, IP-pinned, quota-capped key for an AI agent or CI job.
  • Issue a read-only key (role:"viewer") for a reporting dashboard.
GET /v1/api-keys admin

List keys for the project. Secrets are never returned — only the id, name, prefix, scopes, and lifecycle fields.

curl
curl https://api.ollanode.com/v1/api-keys -H "Authorization: Bearer $SESSION"
DELETE /v1/api-keys/{id} admin

Revoke a key. Revocation is immediate — the per-request prefix lookup filters revoked keys on the very next call.

curl
curl -X DELETE https://api.ollanode.com/v1/api-keys/key_abc -H "Authorization: Bearer $SESSION"
Use cases
  • Rotate a key by creating a new one, then revoking the old — there is no dedicated rotate endpoint for API keys.

Roles

Human users hold one org role, which derives their coarse scopes. Owner-only powers (delete org, transfer ownership) key off the project's owner marker, so owner and admin share scopes.

RoleCoarse scopesNotes
ownerread, write, adminPlus org delete & ownership transfer
adminread, write, adminTeam, keys, approvals decisions
memberread, writeProduct work, no admin
viewerreadRead-only

Scopes: coarse and fine-grained

A call is authorized if the key has the coarse admin scope, or the exact fine-grained resource:action grant (or a resource:* wildcard), or the matching coarse preset — read satisfies any read/list/get; write satisfies every other action. So document the fine-grained scope as the least-privilege grant; a broad write/read key also passes.

ResourceFine-grained scopes
Videos & librariesvideos:read · videos:write · videos:delete · libraries:write · libraries:delete
CDN zoneszones:write · zones:purge · zones:rotate · zones:delete
Storagestorage:read · storage:write · storage:delete
DNSdns:read · dns:write · dns:delete
Edge functionsfunctions:read · functions:write · functions:delete
KV storekv:read · kv:write
Webhooks / analytics / logswebhooks:read · webhooks:write · analytics:read · logs:read
Governanceapprovals:create · approvals:read
Human-only pseudo-scopes — team:write, keys:write, org:delete — appear in the capability map but can never be granted to an agent key. See AI agents & governance.

Errors

Every error is a stable JSON body — { "error": { "code", "message" } } — with a conventional status. Internal errors never leak detail.

StatusMeaning
400Validation — malformed or invalid input
401Unauthorized — missing/invalid/expired credential
403Forbidden — authenticated but not allowed (or human-only)
404Not found (also cross-tenant isolation)
409Conflict — e.g. owner can't self-delete before handling the org
429Rate limited — see Retry-After
202Approval pending — an agent action is queued for a human

Idempotency

Send an Idempotency-Key header on any POST/PATCH/PUT/DELETE. It's DB-backed and keyed by caller + method + path + query + body digest: a retry replays the original 2xx (response carries idempotency-replayed: true), a concurrent duplicate gets 409, and the same key with a different body gets 422.

curl
curl -X POST https://api.ollanode.com/v1/videos \
  -H "Authorization: Bearer $OLLANODE_API_KEY" \
  -H "Idempotency-Key: 3f9c-launch-video" \
  -H "Content-Type: application/json" \
  -d '{"title":"Launch"}'

Rate limits

Requests are token-bucketed per key (or per IP for unauthenticated calls). Every response carries X-RateLimit-Limit and X-RateLimit-Remaining; a 429 also sets Retry-After and X-RateLimit-Reset (seconds). Per-key daily caps surface as 429 too.

Request IDs

Pass X-Request-Id to correlate a call across logs and audit, or read the one the API mints back on every response (including errors). Audit entries store it.

Pagination

Collection GETs take ?limit= (default 25, max 100) and ?offset=, and return { items, total, limit, offset }. Storage file listing is the one cursor-based exception (?cursor=next_cursor).

curl
curl "https://api.ollanode.com/v1/videos?limit=25&offset=50" \
  -H "Authorization: Bearer $OLLANODE_API_KEY"