Authentication

API keys, scopes, and what each scope can reach.
View as Markdown

Every request to /api/* is authenticated with a workspace API key sent as a Bearer token:

GET /api/agents HTTP/1.1
Host: api.jelliu.co
Authorization: Bearer jl_0f9e8d7c6b5a4938271605f4e3d2c1b0a998877665544332211ff00ee00dd00

A key belongs to exactly one workspace. Every request made with it acts on that workspace, and rate limits are counted per workspace, not per key.

Key format

PartValue
Prefixjl_
Secret64 lowercase hexadecimal characters (32 random bytes)
Public prefix shown in the dashboardjl_ plus the first 8 hex characters

The header must match Bearer jl_ followed by exactly 64 characters from 0-9a-f. Jelliu stores only a SHA-256 hash of the key, so the full value is shown once, when it is created, and cannot be retrieved later.

Creating and revoking keys

Keys are managed in the dashboard under Settings → API Keys. Creating, listing and revoking keys is restricted to the workspace owner.

  • Expiry is optional. A key created without an expiry date never expires. If you set one, it is honored exactly; it must be in the future.
  • Limit: a workspace can hold up to 25 active keys. Creating one more fails with 409 and code PLAN_LIMIT_EXCEEDED: Maximum 25 active API keys per tenant. Revoke old keys before creating new ones.
  • Revocation takes effect right away on the instance that handles it. Validation results are cached for a few seconds, so allow up to about 10 seconds for a revoked key to be refused everywhere.
  • Keys also stop working when they expire or when their workspace is deleted.

API keys cannot manage credentials. Minting or revoking API keys, and rotating a webhook signing secret, require a signed-in human in the dashboard, even with a full key. An API key attempting it receives 403 FORBIDDEN: This action requires a signed-in admin session — API keys cannot perform credential-management operations.

Scopes

Each key carries one or more scopes: read, write or full.

ScopeRead requests (GET, HEAD, OPTIONS)Mutations (POST, PUT, PATCH, DELETE)Admin-only routes
readYesNoNo
writeYesYesNo
fullYesYesYes

write implies read access. Scopes are enforced on every /api request by HTTP method, and again on routes that are restricted to particular workspace roles.

What full means

A full key stands in for a workspace administrator. On routes that only admins, owners or billing users may call, Jelliu does not look up a role for API keys: a full key passes and any other key is refused. That includes, for example:

  • creating, updating, deleting, activating and pausing campaigns;
  • creating, updating and deleting outbound webhooks;
  • deleting agents;
  • the owner-only surfaces such as listing API keys, the audit log and plan changes.

Routes that members can use, such as creating and updating agents or adding contacts, accept a write key.

Use the least privilege that does the job. A reporting integration only needs read; an integration that adds contacts needs write. Reserve full for automations that manage campaigns or webhooks, and store those keys like an admin password.

Error responses

401 Unauthorized

A key with the right shape that is unknown, revoked or expired:

{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or revoked API key"
}
}

A missing Authorization header, or a bearer value that is not a well-formed jl_ key:

{
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required — sign in with Clerk or provide a Bearer API key"
}
}

403 Forbidden

A key whose scope does not cover the request:

{
"error": {
"code": "FORBIDDEN",
"message": "API key lacks the 'write' scope required for this operation"
}
}

A read or write key calling an admin-only route:

{
"error": {
"code": "FORBIDDEN",
"message": "This operation requires an API key with the 'full' scope"
}
}

A suspended workspace receives 403 with code TENANT_SUSPENDED on every request.

See Errors for the full error envelope.