Skip to main content

Authentication

The Expedify API authenticates with scoped API keys. Every request carries one, and the key's scopes decide what it can do.

The key

Authorization: Bearer agx_<your_key>
  • Mint keys: Settings → API Keys (owner/admin). Pick the scopes the key needs in the scope picker → copy the agx_… value.
  • Shown once. Keys are stored hash-only; copy the secret at creation. Lost it? Rotate.
  • Per-organization. A key belongs to exactly one org and carries its tenant binding — it can never read or write another org's data.
  • Rotate / revoke any time (Settings → API Keys). Revoking cuts off every client using that key immediately.
curl https://api.expedify.ai/v1/objects/contacts?limit=1 \
-H "Authorization: Bearer agx_your_key"

Scopes — default-deny

A key holds a set of scopes (contacts:read, deals:write, workflows:run, …). Every operation declares the scope it requires; no scope → 403. write / author / run imply read on the same resource. See the Scopes reference.

Honored only on /v1

API keys are authenticated exclusively on /v1. This is deliberate: /v1 is the one door, and the scope check on it is the one lock. Keys are not accepted on internal application routes.

Rate limits

Requests are rate-limited per key + per org. Responses carry:

HeaderMeaning
X-RateLimit-LimitYour window's ceiling
X-RateLimit-RemainingRequests left in the window
X-RateLimit-ResetWhen the window resets

Over the limit → 429 with a Retry-After header. Back off and retry after it. (The SDKs do this automatically.)

Errors

Auth failures use the standard envelope:

{ "error": { "type": "unauthorized", "message": "Missing or invalid API key", "request_id": "…" } }

401 = missing/bad key · 403 = valid key, missing scope.