Skip to main content

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:

FormatWhere it is usedPatternLength
Workspace keyServer-to-server SDK calls; the canonical ingestion pathadj_live_ + 64 hex characters72 chars
Agent keyPer-agent ingestion when you want one key per AI agentadj_agent_ + 48 hex characters58 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 — Authorization header
curl https://api.adjudon.com/api/v1/hash-chain/status \
-H "Authorization: Bearer adj_live_<your-64-hex-key>"
curl — X-API-Key header
curl https://api.adjudon.com/api/v1/hash-chain/status \
-H "X-API-Key: adj_live_<your-64-hex-key>"
Python
from adjudon import Adjudon
client = Adjudon(api_key=os.environ["ADJUDON_API_KEY"])
r = client.hash_chain.status()
Node
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 Unauthorizedwho 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 Forbiddenwe 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.

.env.example
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:

  1. Mint a new key in the dashboard. The raw value is shown once.
  2. Roll clients to the new key — restart the SDK with the new env-var, redeploy services, update CI secrets.
  3. Verify that traffic is hitting the new key on the dashboard's API-key activity panel.
  4. Revoke the old key from the dashboard. Old key returns 401 INVALID_API_KEY immediately.

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

  1. Revoke immediately from the dashboard. The old key starts returning 401 INVALID_API_KEY on the next request.
  2. Mint a replacement and redeploy the consuming services.
  3. Audit the chain. Run POST /api/v1/hash-chain/verify to 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.
  4. 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