Authentication

How to authenticate against the Agora Public API.

The Agora Public API uses a two-step authentication model: a long-lived API key issued to your organization, exchanged at request time for a short-lived session JWT that you attach to every subsequent call.

Public endpoints (metrics) remain unauthenticated; everything else requires a valid session JWT.

Authentication and all authenticated endpoints are in Beta. Access is gated: API keys are issued by Agora on request. To inquire about getting a key, reach out to the Agora team. The public metrics endpoints stay open and need no key.

Exchange the API key for a session JWT

Send a POST /v0/auth/token request with your API key in the Authorization header. No request body is needed.

$curl -X POST https://api.agora.finance/v0/auth/token \
> -H "Authorization: Bearer <YOUR_API_KEY>"

The response returns a sessionJwt:

1{
2 "sessionJwt": "eyJhbGciOiJSUzI1NiIsImtpZCI6IlBfMlhSWENMIn0.eyJzdWIiOiJvcmdfa2V5XzhmMmMzZDRlIiwiaXNzIjoiaHR0cHM6Ly9hcGkuYWdvcmEuZmluYW5jZSIsImV4cCI6MTc0ODQ4NDgwMH0.signature"
3}

The JWT is valid for 15 minutes. The TTL is fixed and not echoed in the response, so your client should track expiry locally (or just re-exchange on any 401 with reason: "token_expired").

Make authenticated requests

Attach the session JWT as a bearer token on every authenticated endpoint:

$curl https://api.agora.finance/v0/accounts \
> -H "Authorization: Bearer <SESSION_JWT>"

A single JWT can be used across multiple requests until it expires. Re-exchanging on every request is unnecessary and will consume your exchange quota faster than intended.

Refresh before expiry

There is no refresh-token endpoint. To extend a session, call POST /v0/auth/token again with the same API key — the previous JWT remains valid until its own expiry, so you can roll over without dropping in-flight requests.

A reasonable client pattern: exchange once at startup, cache the JWT, refresh ~60 seconds before the 15-minute expiry, and retry once on a 401 if the cached JWT was used past its lifetime.

Error responses

Authentication failures return 401 unauthorized with a context.reason naming the specific cause, so you can branch without parsing message:

reasonWhen it happens
missing_headerNo Authorization: Bearer header on the request.
invalid_tokenThe token is malformed or failed validation (signature, audience, or issuer). Re-exchange your API key.
token_expiredThe session JWT is past its 15-minute lifetime. Exchange again.
token_revokedThe API key behind this session has been revoked. Request a new key.
unknown_tenantThe token does not resolve to a known organization. Re-exchange; if it persists, contact support.
missing_claimThe token verified but is missing a required claim. Should not occur with tokens from /v0/auth/token; treat as a bug and capture the Request-Id.

Authorization failures return 403 forbidden when the JWT is valid but your organization doesn’t have permission for the requested action. Contact the Agora team if you believe your account should have access. See the Error Reference for the full code and reason list.

Operational notes

  • Public endpoints stay unauthenticated. /v0/metrics, /v0/metrics/total-supply, and /v0/metrics/circulating-supply continue to work without a JWT. The CORS policy on those endpoints also remains permissive.
  • Every response carries a Request-Id header. Capture it; it’s how Agora support traces a specific request end-to-end, including auth failures.
  • Rate limits are enforced at the Cloudflare edge and apply equally to authenticated and unauthenticated requests. Triggered limits return 429 rate_limit_exceeded with a Retry-After header. See the Error Reference for the full code list.