# Authentication

> Authenticate with API keys, choose their scopes, revoke them, keep them out of browsers, and trace requests with request IDs.

Every API request needs an API key. A key belongs to you and acts on your accounts and copiers. Create and revoke keys under **API keys** in the app at [app.algotradertools.com](https://app.algotradertools.com/api-keys).

## Send your API key [#send-your-api-key]

Pass the key as a bearer token in the `Authorization` header:

```bash
curl https://api.algotradertools.com/v1/accounts \
  -H "Authorization: Bearer $ATT_API_KEY"
```

If a tool can't set the `Authorization` header but can set a custom one, send the key in `X-API-Key` instead:

```bash
curl https://api.algotradertools.com/v1/accounts \
  -H "X-API-Key: $ATT_API_KEY"
```

Only API keys work on `/v1`. Being signed in to the app in your browser doesn't count there, so your app sign-in never works in place of an API key.

| Problem                                  | Error                         |
| ---------------------------------------- | ----------------------------- |
| No key sent                              | `401 authentication_required` |
| Unknown or malformed key                 | `401 invalid_api_key`         |
| Revoked key                              | `401 api_key_revoked`         |
| Key without the scope the endpoint needs | `403 insufficient_scope`      |

## Key format [#key-format]

Keys look like this:

```text
att_<12-character key ID>_<40-character secret>
```

The key ID is made of lowercase letters and digits. The secret is made of letters and digits. A key starts like `att_k3m9x2p7q4vd_…`.

We store only a hash of the secret. The full key is shown once, when you create it. After that, the app shows its prefix (`att_k3m9x2p7q4vd_`) and its last four characters, along with when it was created and last used. If you lose a key, revoke it and create a new one.

You can have up to 20 active keys, for example one per service or environment, so that each can be revoked on its own.

## Scopes [#scopes]

Give each key only the scopes it needs. All four are selected when you create a key; untick the ones it shouldn't have. A request outside the key's scopes fails with `403 insufficient_scope`.

| Scope            | Allows                                                                            |
| ---------------- | --------------------------------------------------------------------------------- |
| `accounts:read`  | Listing and reading accounts: `GET /v1/accounts`, `GET /v1/accounts/{account_id}` |
| `accounts:write` | Connecting, reconnecting and disconnecting accounts. Includes `accounts:read`     |
| `copiers:read`   | Reading copiers, their followers and their copy events                            |
| `copiers:write`  | Creating, changing and deleting copiers and followers. Includes `copiers:read`    |

A dashboard that only shows what is being copied needs `copiers:read`. A script that onboards new followers needs `accounts:write` and `copiers:write`.

## Revoke a key [#revoke-a-key]

Revoke a key under **API keys** in the app. It stops working immediately: the next request with it fails with `401 api_key_revoked`. Revoke a key whenever someone who had access to it leaves, and straight away if it may have leaked.

> **If a key leaks**
>
> Revoke it, create a replacement and deploy that. Then check your copiers and accounts for changes you don't recognise: a key with `copiers:write` can change how your accounts trade.

## Never use keys in browsers [#never-use-keys-in-browsers]

A web page can't call the API from the browser, because the API doesn't allow cross-origin requests. And a key embedded in a web page, a mobile app or a public repository can be copied by anyone who sees it. Call the API from your own server, and keep the key in an environment variable or a secrets manager.

## Request IDs [#request-ids]

Every response has an `X-Request-Id` header with the request's ID. Error responses repeat it in the `request_id` field. Log it with your own request data, and include it when you contact support.

```http
X-Request-Id: b7c1e2d4-5f6a-4b8c-9d0e-1f2a3b4c5d6e
```

Treat the ID as a plain string and don't rely on its format. The API always assigns it. If you send an `X-Request-Id` of your own, it is replaced, so keep your own IDs in your logs next to the one the API returns.

## Rate limits [#rate-limits]

Each key can make 120 requests per minute. Connecting, reconnecting and disconnecting accounts is limited to 5 per minute per user, across all your keys. See [Limits and pagination](/docs/limits#rate-limits) for the headers that tell you where you stand.
