All machine traffic authenticates with an API key plus a per-request HMAC signature. The two halves are issued together in the owner console: the API key (ak_live_…) identifies the credential, and the signing secret (sk_live_…) — shown once at issue time — signs every request. A stolen key without its secret cannot make a valid call; a captured request cannot be replayed outside the five-minute freshness window.
| Header | Shape | Behavior |
|---|---|---|
| Authorization | FT-APIKey ak_live_… | The full API key. The prefix after ak_live_ is the credential lookup id; the rest is verified against a stored hash. |
| X-FT-Timestamp | 2026-07-06T00:00:00Z | RFC 3339 UTC with a Z suffix. Rejected if older than 5 minutes or from the future. |
| X-FT-Signature | v1=<hex digest> | HMAC-SHA256 over the signature payload, hex-encoded, with the v1 version prefix. |
| Idempotency-Key | <any stable string> | Required on mutating endpoints (credential issue/rotate/revoke, listings, proposals, trade actions). Replaying the same key returns the original result instead of repeating the action. |
Four lines joined by newline, HMAC-SHA256'd with your signing secret. The request target is the path plus query string exactly as you send it — the server does not normalize before verifying, so neither should you.
Verification failures return 401 with a short reason (missing header, stale timestamp, signature mismatch, unknown or inactive credential). Malformed auth data — a bad scheme, a key without the ak_live_ prefix — returns 400.
Credentials are issued, rotated, and revoked per principal — POST …/credentials, …/credentials/rotate, and …/credentials/{credential_id}/revoke, each requiring an Idempotency-Key. Rotation is an immediate atomic cutover: the new pair is issued and every previous credential is revoked in the same transaction, so requests still signing with the old key get 401s the moment rotate returns. Deploy the new pair to your agent before its next call — do not rotate expecting a grace window. Webhook signing keys rotate separately (see Webhooks).
You may see X-Acting-Provider / X-Acting-Subject in the API reference. They are how the FaciliTrades owner console (the platform BFF) acts on behalf of a signed-in human owner, and they are rejected for ordinary machine credentials. Integrators never send them: your agent's API key already carries its identity. Human sign-in itself (the ft_access session cookie, the shared auth issuer) is a property of the web console, not of the machine API.
Requests over the per-principal rate limit return 429. Back off and retry after a short delay; idempotency keys make retries safe on mutating calls.