API keys and authentication.
Anoman keys are bearer tokens passed in the Authorization header. They are scoped per customer, tied to a tier, and rotatable from the dashboard.
Key format
Anoman API keys
Every key starts with the prefix anm-sk- followed by 40+ characters of base64-encoded random bytes.
Example key
anm-sk-Mh4uZf2W8Rk1JtX9...- The raw key is shown exactly once at creation — copy it immediately.
- We store only a bcrypt hash. Lost keys cannot be recovered — issue a new one.
- Keys are scoped per API key row, not per customer. One customer can have many keys with different tiers, budgets, and policies.
- Keys live in app.anoman.io/dashboard/keys.
Header format
Authorization: Bearer
Pass the key in the standard OAuth 2.0 bearer header. The OpenAI and Anthropic SDKs do this automatically when you set their api_key parameter.
curl https://api.anoman.io/v1/chat/completions \
-H "Authorization: Bearer anm-sk-..." \
-H "Content-Type: application/json" \
-d '{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Hi"}]}'x-api-key header too (for Anthropic SDK compatibility on the /anthropic/ endpoint). Bearer is preferred everywhere else.Authentication errors
When auth fails
All authentication failures return HTTP 401 or 403 with a JSON body matching the shape below. The code field distinguishes the failure type so you can branch your client-side handling.
{
"error": {
"type": "invalid_request_error",
"code": "auth_invalid",
"message": "Invalid API key. Get one at https://app.anoman.io/dashboard/keys"
}
}| HTTP | Code | Cause |
|---|---|---|
| 401 | auth_missing | No Authorization header sent |
| 401 | auth_invalid | Key is malformed or unknown |
| 403 | auth_revoked | Key was revoked from the dashboard |
| 402 | budget_exceeded | Monthly budget hit. Top up or wait for cycle reset. |
See the full error code reference for non-auth failure modes.
Best practices
Storing and rotating keys
Treat your Anoman key like an OAuth bearer — anyone with the key can spend your budget. Load from a secret manager or environment variable; never commit to source control.
import os
from openai import OpenAI
# Read from env at startup. Fail fast if absent.
api_key = os.environ.get("ANOMAN_API_KEY")
if not api_key:
raise RuntimeError("ANOMAN_API_KEY must be set")
client = OpenAI(base_url="https://api.anoman.io/v1", api_key=api_key)Recommended scoping pattern
- One key per environment — separate
development,staging,productionkeys so you can revoke a leaked dev key without impacting prod. - One key per service if your stack has multiple call sites (web backend, batch worker, etc.). Lets you attribute usage in traces and revoke surgically.
- Per-key budget — set a monthly USD cap on each key in the dashboard. A runaway script then hits 402 instead of draining your account.
Rotation
- Create a new key in the dashboard (existing keys stay live).
- Deploy the new key to your service env var.
- Revoke the old key once you confirm zero traffic on it (visible in
last_used_at).
Leak response
If a key is exposed (committed to GitHub, posted in a screenshot, etc.):
- Revoke immediately via the dashboard — takes effect within 60 seconds.
- Issue a replacement key.
- Audit the trace log for unexpected usage in the window between leak and revocation.
- Reach out at [email protected] if you suspect abuse — we can correlate with our internal logs.