# Authentication and API keys

> Create, scope, send, rotate, and revoke Anectico credentials safely.

Canonical page: https://anectico.com/docs/reference/authentication/


Human dashboard sessions and programmatic API keys are separate credentials. Use API keys for SDKs,
collectors, CI, CLI automation, and MCP clients.

## Create a key

Open **Settings → Access**, create an API key, select a project when appropriate, add only the
required scopes, and choose how long the key should remain valid. **Never** is the default; fixed
choices from one day through one year create a short-lived key whose expiry is shown with its
metadata. Expiry cannot be extended after creation, so replace the key if a workload needs more
time. The key is shown once.

The account API accepts the same optional expiry as an RFC3339 timestamp, plus an optional
request-rate figure:

```json
{
  "name": "One-day CI key",
  "scopes": ["traces:read"],
  "expires_at": "2026-08-04T12:00:00Z",
  "rate_limit": 5000
}
```

Omit `expires_at` for a key that never expires. A supplied timestamp must be in the future and no
more than 365 days from creation. An expired key is rejected on its next use; revocation remains
immediate and permanent.

`rate_limit` is the key's expected request volume in **requests per hour**. It is optional; omit it
or send `0` to record the platform default. A supplied value must be a whole number between `0` and
`1000000` — negative values and values above that maximum return `400 invalid_request` naming
`rate_limit`, without creating a key. The figure is stored with the key and returned with its
metadata; it does not on its own change how your requests are throttled, and plan limits apply
regardless of what a key records.

Anectico keys begin with `an_`. Treat the rest as opaque; do not parse meaning from it.

## Send an API key

The public REST API accepts:

```http
X-Anectico-API-Key: an_...
```

It also accepts the generic `X-API-Key` header and `Authorization: ApiKey an_...`. MCP clients
normally use:

```http
Authorization: Bearer an_...
```

Use the header documented by the SDK or client you are configuring rather than sending multiple
credential headers.

## Common key recipes

Scopes use `resource:action` names.

| Purpose | Required starting scopes |
| --- | --- |
| OTLP traces, logs, metrics, and captured errors | `ingest:write` |
| SDK identity, group, and diagnostic events | `analytics:write` in addition to `ingest:write` |
| Browser session replay | `replay:write` |
| Evaluate feature flags and record exposures | `flags:read` plus `analytics:write` |
| Upload source maps, ProGuard mappings, or dSYM binaries | `errors:write` |
| Register a release in CI | `releases:write` |
| Read through MCP | `mcp:read` |
| Allow MCP writes | `mcp:write` plus domain-specific scopes |
| Search logs | `logs:read` |
| Read traces | `traces:read` |
| Read or triage Issues | `errors:read` or the required error write scope |
| List the organization's API keys | `api_key:read` |
| Create, rename, revoke, or re-scope API keys | `api_key:write` |

Most application SDK integrations therefore use a project-scoped custom key with `ingest:write`
and `analytics:write`. Add `replay:write` only to a browser key that records replay. The
**Read & ingest** preset includes every available read scope plus `ingest:write` and
`analytics:write`. The narrower **Ingest only** preset covers OTLP and error ingestion; it does not
authorize identity/events or replay. **Full access** is derived from the complete server scope
catalog; for evaluation it includes both `evals:read` and `evals:write`, so a key can
read the configuration it is allowed to change.

Client-side feature flags are the narrow exception to the usual no-read-scope rule. A browser flag
key requires `flags:read`, which also makes the project's flag configuration readable to that
client. Keep flag targeting and payloads free of secrets.

The Access screen is the current source for the complete scope catalog. See the
[permission scope reference](/docs/reference/permissions) for the selectable groups and safe key
patterns.

## Project scope

A project-scoped key may omit a query-string `project_id` or repeat its exact signed project. A
different non-empty value returns `403 permission_denied` before product logic runs; Anectico never
silently substitutes the signed project for an explicitly conflicting selection. Organization-level
keys retain request-time project selection, and many REST reads accept `project_id` as a query
parameter.

A key created without a project selection is bound to the organization's default project. Creating
an organization-level key is an explicit choice: send `"org_wide": true` in the create-key request
(the CLI's `anectico agent bootstrap --org-wide` does this), and the key is minted with no project
binding at all.

The project binding is fixed for the life of a key. To move a workload to another project, create a
replacement key for that project, deploy it, verify traffic, and revoke the old key.

That binding is also an authority floor when one API key creates another. A project-scoped key with
`api_key:write` can create a successor only in its own project; requesting `org_wide` or naming a
sibling project returns `403 forbidden`. Omitting the project keeps the creator's project —
it never widens the successor because the default project cannot be resolved.

Scope edits, expiry, project changes, and revocation take effect on the next request because the
API key's authorization is resolved server-side for every request, whether it arrives as telemetry
or as an API call; successful checks are not cached. If that authorization check is unavailable,
API-key OTLP and Capture requests fail closed with a retryable service-unavailable response. Removing `traces:read`, `logs:read`,
`metrics:read`, `errors:read`, `search:read`, `persons:read`, or `groups:read` immediately makes the
corresponding Query API return `403`; ingestion continues when `ingest:write` remains present.

## Rotate and revoke

Create the replacement key, deploy it, confirm traffic uses it, then revoke the old key. Revoke
immediately if a key is committed, logged, included in a screenshot, or exposed to an untrusted
client.
