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

# Authenticating REST API requests

> Send a workspace-scoped API key as a bearer token. The key names the workspace, so no request can be pointed at someone else's.

Every REST API request except `/healthz` needs a workspace-scoped API key, sent as a bearer token.

```bash Shell theme={null}
curl https://api.attensira.com/v1/analytics/visibility \
  -H "Authorization: Bearer atn_live_<your key>"
```

It is the same key and the same header as the [MCP server](/mcp/connect). One key reaches both surfaces; you do not need a second credential to add the other.

## The key

Mint a key at [app.attensira.com/settings/developer](https://app.attensira.com/settings/developer). See [API keys](/account/api-keys) for minting, scopes and revocation.

The format is `atn_live_` followed by 32 hexadecimal characters:

```text Key format theme={null}
atn_live_0123456789abcdef0123456789abcdef
```

<Warning>
  The key is displayed exactly once, because only a hash is stored. Attensira cannot re-display it — a lost key is replaced, not recovered.
</Warning>

## The key names the workspace

No endpoint takes a workspace or project id. There is no path segment, query parameter or body field anywhere in `/v1` that identifies a workspace, because the key already does.

That is a security property, not a convenience: a URL that cannot express a workspace cannot be pointed at someone else's. To work across two workspaces, mint two keys.

## What a 401 means

A request with a missing, malformed or unusable key gets:

```json 401 response theme={null}
{
  "error": {
    "type": "unauthorized",
    "message": "missing or malformed Authorization header. Send: Authorization: Bearer atn_live_<32 hex>",
    "status": 401
  }
}
```

The response carries `WWW-Authenticate: Bearer`, so a client knows which scheme to retry with.

A `401` covers four different situations deliberately, and the message does not distinguish them: the header was absent or the wrong shape, the key does not exist, the key was revoked, or the key expired. Telling an unauthenticated caller *which* of those is true would confirm that a particular key once existed. Check the key at [app.attensira.com/settings/developer](https://app.attensira.com/settings/developer) rather than inferring from the response.

<Note>
  A key that is real but lacks the scope an endpoint needs gets `403` with `type: "forbidden"`, not `401`. `GET /v1/account` returns the key's `scopes`, so that is where to look when a write fails and a read succeeds.
</Note>

## How the token travels

The API service checks only the *shape* of the key at the door — the `atn_live_` prefix and 32 hex characters — and rejects anything else before it can become a round trip, so a typo never reaches the backend or its logs. That check is not authentication.

The token itself is forwarded verbatim to the Attensira backend, which owns the real validation: hash lookup, revocation, expiry, scopes and per-key rate limiting. Two consequences worth knowing:

* **Redirects are never followed.** A `3xx` is treated as the response rather than chased, because following one could re-send a live key to another host.
* **A key is never cached or mirrored.** Revoking a key at the dashboard takes effect on the next request; there is no copy of it in the API layer to go stale.

## Keeping a key safe

Send it from a server, never from a browser or a mobile app — anything shipped to a client device is public, and this key can delete prompts and spend credits.

Store it in your platform's secret store and read it from an environment variable. A key in a committed `.env`, a CI log or a screenshot should be revoked and replaced rather than reasoned about.

Mint one key per integration. Keys carry `last_used_at`, so a per-integration key is the difference between revoking one job and breaking every job you have.
