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:

bash
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.