API reference

Authentication

API keys, what they can reach, and the things they deliberately cannot.

Every endpoint takes a bearer token:

Authorization: Bearer <token>

Two credential types are accepted.

Credential Looks like Used by Expires
API key sk_live_… scripts, CI, anything non-interactive never, unless you set an expiry or revoke
Session token a JWT the web app itself about an hour, auto-refreshed

For automation you want an API key. A session token is tied to a browser login and will expire mid-pipeline.

Managing keys

# create
curl -s "$SEEDQL_API/api/keys" -X POST \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "github-actions"}'

# list (never returns the secret)
curl -s "$SEEDQL_API/api/keys" -H "Authorization: Bearer $SESSION_TOKEN"

# revoke, takes effect immediately
curl -s -X DELETE "$SEEDQL_API/api/keys/$KEY_ID" -H "Authorization: Bearer $SESSION_TOKEN"

Creating returns the plaintext key once:

{
  "id": "3f1c…",
  "name": "github-actions",
  "prefix": "sk_live_a1b2c3d4",
  "key": "sk_live_a1b2c3d4…",
  "warning": "Copy this now. It will not be shown again."
}

Listing returns only prefix, which identifies a key in a UI without being usable as one. The full value is not stored anywhere; only its SHA-256 hash is. There is no reveal endpoint, and adding one is not possible without changing what is stored.

Limit: 20 active keys per user.

What a key cannot do

Three restrictions are deliberate, not gaps.

Keys cannot manage keys. Minting and revoking require an interactive session. Otherwise a leaked key could mint replacements for itself and survive revocation, which would make revocation meaningless.

Keys cannot reach the operator console. Every /api/admin/* route refuses an API key with 403 session_required, including a key belonging to the platform owner. Keys live in CI config and shell history; the operator console can rewrite tiers and moderate content, and that blast radius requires a real login.

Keys inherit your permissions, never exceed them. A key acts as the user who created it, bounded by the same org membership and project roles. It cannot see a project you cannot see.

Failure responses

{ "detail": { "error": "invalid_token", "message": "..." } }
Status Meaning
401 Missing, malformed, unknown, revoked, or expired key. All identical by design.
403 tier_required Your tier does not include API access.
403 session_required This route requires an interactive login.
403 (other) Authenticated, but lacking the org or project role.

Unknown, revoked and expired keys are indistinguishable in the response. That is intentional: distinguishing them turns the endpoint into an oracle for probing which keys exist.

Rotation

There is no rotate operation, because a rotate that keeps the old key alive is just two keys. Create the new one, deploy it, then revoke the old one and confirm with GET /api/keys.