Getting started

Authentication

The agent API is authenticated by per-user bearer tokens with scoped capabilities. There is no session — every request stands alone.

Key format

Every key looks like ac_live_ followed by 64 lowercase hex characters (256 bits of entropy from the OS RNG). Mint at /agent in the AC app — plaintext is shown exactly once.

text
ac_live_4f9c6e8a2b3d1e7f0c5a9b8d2e6f4a3c7b1d8e5f0a9c2b6e4d7a3f8c5b9e2d6a

Sending the token

Pass the token in the Authorization header on every request:

http
Authorization: Bearer ac_live_4f9c6e8a2b3d1e7f0c5a9b8d2e6f4a3c7b1d8e5f0a9c2b6e4d7a3f8c5b9e2d6a

Requests without a valid header return 401 immediately. Requests with a valid key whose scope set doesn’t cover the endpoint return 401 with a Missing scope: <name> message.

Scopes

Scopes are additive. Every key carries one or more from the set below.

FieldTypeDescription
read
scope
Read state: whoami, get_mandate, get_holdings, get_audit.
validate
scope
Dry-run a trade against the IPS without creating an attestation request. Audit-logged.
propose
scope
Submit a proposed trade for human attestation. Implies validation; never executes.

Rotation

  • Mint the replacement key alongside the old one.
  • Hot-swap your agent config (the old key still works while you flip).
  • Revoke the old key from /agent — the next call from it returns 401 immediately.

We recommend rotating every 90 days. Expirations are enforced server-side: a key with expiresAt in the past returns 401 even if it hasn’t been revoked.

Revocation

Revocation is instant. The next call from the key returns 401 Unauthorized — Invalid or revoked key. The row stays in the database so historic audit records remain attributable to a specific key.

How verification works server-side

  • Hashing. We SHA-256 the presented bearer token and look it up by hashedKey — no plaintext comparison happens.
  • Replay. Tokens are stateless. Two parallel calls with the same key are both valid.
  • Last-used. Every successful auth bumps lastUsedAt so you can see staleness in the UI.

Example: failed auth

401 Unauthorized
HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "statusCode": 401,
  "message": "Invalid or revoked key",
  "error": "Unauthorized"
}
Last updated 2026-06-15