Authentication
Exchange an API key for a short-lived Bearer access token
Authenticating to the Voodoo Center API is a two-credential flow:
- A long-lived API key (
ak_...) that you create and manage in the dashboard. - A short-lived access token (a Bearer JWT) that you obtain by exchanging the API key, and send on every API request.
You never send the raw API key to the API endpoints — you exchange it for a token first, then authenticate with the token.
1. Create an API key
In the dashboard, open the API page and create a key.
- A key belongs to your account, not to the person who created it: it keeps working when that person leaves the team, is deactivated or changes their password, and stops only when it is revoked or the account is disabled. The API page lists every key of the account, with who created it.
- Creating and revoking keys (and editing the account’s IP allowlist) takes the Manage API keys & IP allowlist permission; the account owner always has it. Using a key takes no permission at all.
- The raw key is shown once, at creation, in the format
ak_.... Copy it immediately and store it somewhere secret — it is hashed server-side and can never be recovered. - You can create, list and revoke keys from the same page. Revoking a key
immediately blocks any new token exchanges with it, and the tokens it has
already issued stop working too (within seconds, with
401token_revoked).
Treat an ak_ key like a password. If it leaks, revoke it in the dashboard and
create a new one.
2. Exchange the key for an access token
POST your key to the token endpoint. The response contains an
access_token valid for 15 minutes (expires_in, in seconds).
cURL
Python
If the key is unknown or revoked you get 401 with
{"detail": "Invalid credentials", "code": "invalid_credentials"} (plus a
legacy error key carrying the same text) — the same answer whether the key
never existed, was revoked, or belongs to a disabled account. Branch on
code, never on the text.
Rate limit
The exchange accepts 20 requests per minute from one IP address, counted
over every request to it — valid key or not. The 21st within the minute gets
429 with a Retry-After header (in seconds) and code throttled:
Wait Retry-After seconds, then exchange again. A cached token (below) keeps
you far from the limit: one exchange per 15 minutes is all a server needs.
3. Call the API with the token
Send the token in the Authorization header as a Bearer credential on every
request:
cURL
Python
Token lifetime and refresh
Access tokens expire 15 minutes after they are issued. There is no refresh
token — when a token expires (a 401 with code: "invalid_token"), simply
exchange your API key again for a fresh token.
A common pattern is to cache one token in memory and re-exchange when it is
close to expiry (or lazily, on the first 401).
A single API key can be exchanged as often as you need, within the rate limit of 20 exchanges a minute per IP address. Keep the key secret and the tokens short-lived — don’t persist tokens longer than their 15-minute window.
Authenticating the API Explorer
You don’t have to run this two-step flow by hand to try the API. The interactive API Explorer in the API Reference does the token exchange for you:
- Enter only your
ak_API key in the Explorer’s authorization panel. - When you run any endpoint, the Explorer calls
POST /v1/auth/token/clientwith your key, reads back theaccess_token, and sends it asAuthorization: Bearer <token>automatically. - You never paste a JWT, and you don’t authorize the token endpoint itself (it’s public).
Transport
All access is over https://api.voodoo.center. Always use HTTPS; plain-HTTP
requests are not supported.