Authentication

API keys, rotation cadence, and storage best practices.

Every request to the scoring API is authenticated with a single header: X-API-Key.

What this is

COHESION issues organization-scoped API keys. Every v1 endpoint except GET / and GET /v1 requires a key. Keys are stored as peppered SHA-256 hashes with a 7-day dual-read plaintext window post-cutover. Plaintext never touches D1 after that window.

When to use

On every request to the scoring API, and whenever you rotate or revoke a key.

Key format

Send the key

curl https://api.cohesionauth.com/v1/score \
  -H "X-API-Key: $COHESION_API_KEY" \
  -H "Content-Type: application/json" \
  -d @payload.json

Python and TypeScript SDKs accept api_key at client construction and set the header automatically.

The legacy api_key body field is deprecated as of 2026-04-17 and sunsets on 2026-07-15. The API emits Deprecation and Sunset headers while still accepting it.

Rotate a key

Self-serve rotation returns a new key exactly once.

curl -X POST https://api.cohesionauth.com/v1/admin/key/rotate \
  -H "X-API-Key: $OLD_COHESION_API_KEY"

Store the new key immediately. The old key stops working on the next request.

Detailed endpoint shape: POST /v1/admin/key/rotate.

Revoke a key

curl -X POST https://api.cohesionauth.com/v1/admin/key/revoke \
  -H "X-API-Key: $COMPROMISED_COHESION_API_KEY"

Revocation is terminal until support reactivates the org. Every future request returns 401.

See POST /v1/admin/key/revoke.

Audit log

Every auth event writes to audit_log. Read your org’s events with GET /v1/admin/audit-log.

Best practices

  1. Store keys in environment variables or a managed secret store. Never in source control.
  2. Rotate keys every 90 days, or immediately on any suspicion of compromise.
  3. Use one key per deployment environment (prod, staging, dev). Limits blast radius.
  4. Do not log the plaintext key. Log the 8-char prefix if you need traceability.
  5. Scan commits for leaks. gitleaks protect --staged --redact -v catches accidental paste.

Errors you might see

StatusMeaningFix
401 UNAUTHORIZEDMissing, unknown, inactive, expired, or wrong-hash keyRotate or re-create the key in dashboard
429Per-IP or per-key rate limitBack off per rate limits

The API returns a uniform UNAUTHORIZED envelope with an 80 ms floor across all auth failures. The real reason is written to audit_log and never returned to the client.

Next step

Ready to score? Go to the quickstart or the track AI decisions guide.