Overview
Authentication
One header, one kind of credential, and four refusals that mean different things.
Every call carries an API key as a bearer token:
curl https://api.formalogic.io/v1/oracles \
-H "Authorization: Bearer fk_live_…"There is no other scheme. No query parameter, no cookie, no signed URL — a credential in a URL ends up in a proxy log, a browser history and a bug report, and offering it as an option means it will eventually be used.
Getting a key
Keys are created on the API keys page. The token is shown once, at the moment it is created, and is not recoverable afterwards — we store a hash of it, so there is nowhere to read it back from.
Give each caller its own key. Quota is per organisation, so a second key does not buy a second allowance; what it buys is the ability to revoke one integration without breaking the others, and a usage log that tells you which one is spending.
Two identities, and they never mix
An API key authenticates a machine against the oracle API. It knows nothing about people and has no role. The only thing it can read about your account is which organisation it belongs to — no members, no usage, no billing, and nothing it could change.
A console session authenticates a person against the console — minting keys, changing a plan, reading usage. It cannot call an oracle.
The two run in separate processes with separate credentials against separate database roles. A key that leaks cannot be used to raise your plan or list your team; a console session that leaks cannot be used to spend your credits.
What each refusal means
All four are 401, and the code says which — because the remedies differ and a
client that cannot tell them apart will retry something that is never going to
start working.
| Code | What happened | What to do |
|---|---|---|
KEY_MISSING |
No Authorization header, or not a bearer token |
Send the header |
KEY_UNKNOWN |
The token is not one of ours | Check for a truncated paste |
KEY_REVOKED |
It was valid and someone revoked it | Mint a new one; do not retry |
KEY_EXPIRED |
It carried an expiry and passed it | Mint a new one; do not retry |
KEY_REVOKED and KEY_EXPIRED are permanent. Backing off and retrying will
produce the same answer forever.
One refusal is not about the key at all: 403 ORG_DISABLED means the key is
fine and the organisation it belongs to is not active. Keep the key — minting
another would be refused the same way — and write to [email protected].
The console answers the same code to every member of that organisation.
Note what is not in that list: a spent allowance answers 402 QUOTA_EXCEEDED, not 401. Your credential is fine. See
Limits and credits.
Rotating a key
Mint the replacement first, move traffic to it, then revoke the old one. Revoking takes effect on the next request — there is no cache to wait out and no grace period, which is what makes it useful when a key has leaked.