Need to manage API keys, view logs, or check usage?Open the Developer portal →

Authentication

Circa has two ways to authenticate: an API key for your own data, and an OAuth app for acting on another user's behalf.

Two methods

Which one you want depends on whose data you are reaching for.

  • API key (x-api-key) — the primary method, and the right one for almost every integration. The key acts as you, on your own data, across the teams you belong to. Create one in the portal, put it in your environment, send it as a header. Everything below this section describes it.
  • OAuth app (Authorization: Bearer circa_oat_…) — for building a product that acts on another Circa user's behalf. The user approves your app on a consent screen and picks which of their teams you may access; you receive short-lived tokens scoped to that decision. See OAuth apps.

Both methods hit the same /public/* endpoints and both require the x-team-id header described below. Never ask a customer to paste their API key into your product — that is what OAuth is for.

API keys

Include your key in every request using the x-api-key header.

x-api-key: circa_live_6JeiZORoVyRPqYBuc3ft7kIWjlA7w25h

Key format

Keys are prefixed with either circa_live_ or circa_test_ followed by 32 random characters, e.g. circa_live_6JeiZORoVyRPqYBuc3ft7kIWjlA7w25h.

Live vs. test keys

When you create a key in the Developer portal, you'll choose one of two types:

  • Live (circa_live_…) — for production traffic. Circa stores only a SHA-256 hash and the first 18 characters (the "prefix"); the full value is returned exactly once at creation. Keep these in a secret manager.
  • Test (circa_test_…) — for development. The plain key remains revealable on the API keys page so you can re-copy it any time. Same usage as live keys but billed against a separate sandbox quota.
⚠
If you lose a live key, it can't be recovered. You will have to revoke it and generate a new one. Test keys can be re-revealed in the portal.

Revocation

Revoking a key in the portal takes effect immediately. The next request with that key returns 401 Unauthorized. Revoked keys are soft-deleted so their historical logs remain visible.

Errors

A 401 is returned when the key is missing, unknown, or revoked. The message tells you which.

401Unauthorizedunknown key
{
  "statusCode": 401,
  "message": "Invalid API key"
}
401Unauthorizedrevoked key
{
  "statusCode": 401,
  "message": "API key has been revoked"
}
401Unauthorizedno credentials at all
{
  "statusCode": 401,
  "message": "Authentication is missing. Send an API key in the 'x-api-key' header, or an OAuth access token as 'Authorization: Bearer'."
}

Team scope: x-team-id (required)

Every request must also include an x-team-id header naming which team to operate against. Your API key is tied to the user who created it, so the team ID you pass must be one that user is an active member of.

The same header is required on OAuth-authenticated requests, where it must name one of the teams the user granted — see OAuth apps.

x-api-key: circa_live_6JeiZORoVyRPqYBuc3ft7kIWjlA7w25h
x-team-id: 4b6f9c28-6f4e-4e7f-a36d-2ff989045d10

Where to find your team id

In app.circa.ai, open the team selector in the top-right navbar. Each row has a settings icon — click the one next to the team you want the id for:

Team selector dropdown with the settings icon next to a team highlighted.
Top-right navbar → team selector → settings icon next to the team.

That opens Team Settings → General, where you'll find the team id with a one-click copy button:

Team Settings dialog with the Team ID row and Copy button highlighted.
Team Settings → General → Team ID. Use this value as x-team-id.

If you're a member of multiple teams, switch between them in the same dropdown to grab each id, or call GET /public/teams to enumerate them programmatically (the response includes which one is your most recent).

Omitting the header returns 400 Bad Request. Passing a team the owner is not a member of returns 403 Forbidden.

400Bad Request
{
  "statusCode": 400,
  "message": "Missing required 'x-team-id' header. Pass the id of a team the API key owner belongs to."
}
403Forbidden
{
  "statusCode": 403,
  "message": "The API key owner is not a member of team '...'."
}

Both messages above are the API-key wording. OAuth-authenticated requests get the same status codes with messages that name the app and the grant instead — see the authorization code flow.

Best practices

  • Store keys in a secret manager (AWS Secrets Manager, Doppler, Vercel env vars). Never commit them to source control.
  • Create one key per environment (production, staging, CI) so you can revoke them independently.
  • Rotate keys periodically. Revoke unused keys.
  • Treat keys like passwords — a leaked key gives full access to your data and can debit your credit balance via /materials/:id/properties/pull, /processes/:id/pull, or /processes/:id/impacts/pull.