Getting started
Authentication
Your servers call the API with an API key. People can also sign in to the optional dashboard. Both reach the same tenant: your workspace and everything in it.
API keys
Send your key as a bearer token on every request:
Authorization: Bearer vk_prod_3f9a1c2b7d4e_…
A key looks like vk_<env>_<prefix>_<secret>, where
env is dev or prod. Each key belongs to one
tenant, and everything you create or read with it belongs to that tenant. The full
key is shown once, when you create it, so store it somewhere safe.
Your first key
Creating a key through the API needs a key, so the first one comes from the admin
command line: python -m app.admin create-tenant on a deployment, or
seed-dev locally. See Deploying.
Create a key
/v1/api-keys Body parameters
| Field | Type | Description |
|---|---|---|
nameoptional | string | A label so you can recognise the key later. |
expires_in_daysoptional | int | The key stops working after this many days (1 to 3650). Leave it out for a key that never expires. |
curl -X POST http://localhost:8000/v1/api-keys \
-H "Authorization: Bearer $OFFHOOK_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "production backend" }'{
"id": "5e2a9c41-7b3d-4f1e-a8c6-2d9b4e7f1a03",
"prefix": "3f9a1c2b7d4e",
"key": "vk_prod_3f9a1c2b7d4e_…",
"expires_at": null,
"created_at": "2026-10-15T10:00:00Z"
} List keys
/v1/api-keys Returns each key's prefix, name, last use, expiry and revocation time. Never the key itself.
Revoke a key
/v1/api-keys/{id} Revocation takes effect immediately. The next request with that key gets 401.
Dashboard sign-in
If you run the optional dashboard, people sign in with Clerk. A person's first sign-in creates a tenant for them, and they can create API keys from there. See Configuration for the Clerk settings.
Errors
401: the key is missing, malformed, wrong, expired or revoked.403: the key's tenant has been deactivated.