Authentication
The Adjudon API authenticates every request. There is no anonymous
endpoint that returns customer data — including /health, which
returns only liveness, no organisation context. Production traffic
goes to https://api.adjudon.com (Frankfurt eu-central-1). Tested
against API version v1.
API keys
Adjudon supports two key formats, neither of which is interchangeable:
| Format | Where it is used | Pattern | Length |
|---|---|---|---|
| Workspace key | Server-to-server SDK calls; the canonical ingestion path | adj_live_ + 64 hex characters | 72 chars |
| Agent key | Per-agent ingestion when you want one key per AI agent | adj_agent_ + 48 hex characters | 58 chars |
The prefix is intentional. GitHub's secret-scanner, GitGuardian, and
most IDE plugins recognise vendor prefixes; an adj_live_ or
adj_agent_ token committed to a public repo is detected and
rotated within minutes. Treat every API key as a production
secret. A workspace key carries the same authority as a logged-in
operator on the issuing organisation; an agent key carries
single-agent ingestion privilege only.
Adjudon stores only the SHA-256 hash of the raw key
(backend/models/ApiKey.js). The raw value is shown exactly once at
creation, in the dashboard. We cannot recover a lost key —
rotate it.
Authenticating requests
Pass the key on every request, either via the X-API-Key header or
as a Bearer token on Authorization:
curl https://api.adjudon.com/api/v1/hash-chain/status \
-H "Authorization: Bearer adj_live_<your-64-hex-key>"
curl https://api.adjudon.com/api/v1/hash-chain/status \
-H "X-API-Key: adj_live_<your-64-hex-key>"
from adjudon import Adjudon
client = Adjudon(api_key=os.environ["ADJUDON_API_KEY"])
r = client.hash_chain.status()
import { Adjudon } from "@adjudon/node";
const client = new Adjudon({ apiKey: process.env.ADJUDON_API_KEY });
const r = await client.hashChain.status();
The dashboard also accepts a JWT for browser sessions
(Authorization: Bearer <jwt>). The JWT is short-lived; for
server-to-server integration use an API key, not a JWT.
401 vs. 403
Both are authentication errors but they answer different questions:
401 Unauthorized— who are you? The key is missing, malformed, hashed-and-not-found, or revoked. Codes:NO_API_KEY,NO_TOKEN,INVALID_API_KEY_FORMAT,INVALID_API_KEY,TOKEN_REVOKED,TOKEN_VERIFICATION_FAILED.403 Forbidden— we know you, you cannot do this. The caller is authenticated but lacks the role, plan, or scope. Codes:FORBIDDEN,UPGRADE_REQUIRED,ADJ_BLOCKED_BY_POLICY.
A 429 Too Many Requests may fire before authentication if the
client is hitting the per-IP outer rate limit; treat the 429 as a
back-off signal and inspect the RATE_LIMIT_EXCEEDED data block. See
Error Codes for the full taxonomy.
Storing keys
Always read the key from an environment variable, a secret manager
(Vault, AWS Secrets Manager, GCP Secret Manager), or a CI-injected
secret — never from a checked-in file. The SDK reads
ADJUDON_API_KEY automatically; the env-var name is conventional
and worth keeping consistent across services.
ADJUDON_API_KEY=adj_live_<rotate-on-team-change>
ADJUDON_BASE_URL=https://api.adjudon.com
Add .env and .env.local to .gitignore. CI secret-scanners that
recognise the adj_live_ prefix will flag accidental commits.
Rotating keys
There is no expiry on Adjudon API keys today. Rotate them on a schedule you set, and on demand whenever a key is suspected leaked. The procedure is dashboard-driven and overlap-tolerant by design:
- Mint a new key in the dashboard. The raw value is shown once.
- Roll clients to the new key — restart the SDK with the new env-var, redeploy services, update CI secrets.
- Verify that traffic is hitting the new key on the dashboard's API-key activity panel.
- Revoke the old key from the dashboard. Old key returns
401 INVALID_API_KEYimmediately.
Two keys can be active for the same workspace simultaneously, so you control the cut-over window. We do not auto-rotate keys for you and we do not enforce a maximum key age — key lifecycle is your operational choice.
If your key leaks
- Revoke immediately from the dashboard. The old key starts
returning
401 INVALID_API_KEYon the next request. - Mint a replacement and redeploy the consuming services.
- Audit the chain. Run
POST /api/v1/hash-chain/verifyto confirm no anomalous traces were ingested between the suspected leak time and the revocation. The chain is tamper-evident; any write that occurred under the leaked key is permanently anchored and visible. - Disclose externally if customer data was exposed; see Responsible Disclosure.
We do not offer mTLS or IP-allowlist enforcement on the public API today. If your environment requires either, we document this honestly on the procurement-question track at Sub-Processors.
See also
- Error Codes — the full 401 / 403 / 429 taxonomy
- Quickstart — record your first trace in under 60 seconds
- Hash Chain API — the audit surface every key write hits
- Responsible Disclosure — what to do if a key is exposed in research