> ## Documentation Index
> Fetch the complete documentation index at: https://docs.burthq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Authenticate requests to the Burt public analytics API

The public API uses organization-scoped API keys with the HTTP bearer scheme.

## Base URL

Send server-to-server requests directly to:

```text theme={null}
https://api.burthq.com
```

Only the documented `/api/v1` routes are a supported public contract. Other
backend routes on the same host are internal and may change without notice.
The API does not currently provide a browser CORS contract, so keep API keys
in server-side integrations.

```text theme={null}
Authorization: Bearer $BURT_API_KEY
```

Create a key in **Settings → API Keys** in the Burt dashboard. The key is
scoped to one organization and must include `analytics:read`. The secret is
shown once when it is created; store it in a secret manager and export it for
local commands:

```bash theme={null}
export BURT_API_KEY='burt_sk_...'
```

The documentation uses `$BURT_API_KEY` so a secret never needs to appear in a
script, ticket, or source file.

## Limits

Each key may make 60 requests per minute. Two further admission limits protect
the service as a whole:

* Verification of credentials without a successful verification in the last
  seven days is limited globally. During a sustained flood of invented keys,
  the first request with a brand-new key can be deferred; established keys are
  unaffected, including integrations that call only hourly or nightly.
* Concurrent `POST /api/v1/analytics/query` executions are capped per
  organization and across the API.

A response over any of these limits is `429` with the `rate_limited` error
code and a `Retry-After` header containing the number of seconds to wait
before retrying.

## Authentication failures

* A missing `Authorization` header or a malformed credential returns `401`
  `unauthorized`. These requests spend no limits.
* A well-formed key that is unknown or revoked returns the identical `401`
  `unauthorized` envelope, so the response does not distinguish an unknown key
  from a revoked one. While the global credential-verification limit is
  exhausted, these requests return `429` `rate_limited` instead. Retry after
  `Retry-After`.
* A valid key without `analytics:read` returns `403` `insufficient_scope`. The
  per-key rate check runs before the scope check, so an over-limit key
  receives `429` before `403`.

For query requests, HTTP body parsing happens before bearer authentication.
Malformed JSON, an unsupported content type, or an oversized body therefore
returns `400 invalid_query` before authentication or custom rate limiting.

Every response from an analytics endpoint includes `x-request-id`. The same
value appears as `error.request_id` when the response is an error.
