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

# Authentication

> API keys for the HTS Pilot API - where to create one, how to send it, what a role allows, and what 401 and 403 answers look like.

Every request but `GET /api/health` needs an API key, sent in the `X-API-Key` header:

```bash
curl https://htspilot.com/api/usage/me \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
```

## Creating a key

An administrator creates keys in the application, under Admin, API keys: give the key a name and a role. The key
is shown once, when it is created; only its first characters are kept for display afterwards. A key starts with
`hts_`. It can be revoked at any time on the same page, and a revoked key answers `401` from then on.

Keys are not created through this API: the key management routes belong to the application and are not part of
the customer API.

## Roles

A key has one of three roles, and acts for the account that created it:

| Role | May |
| --- | --- |
| `entry` (shown as "user") | Create and read its own lookups and batches, use the catalog, read tariff data and usage |
| `reviewer` | Everything above for all lookups and batches, plus decisions, deleting a SKU, acknowledging an alert, reports |
| `admin` | Everything above, plus webhooks |

- The role of a key never exceeds the role of the account that created it. If the account is later given a lower
  role, the key is cut to that role too.
- With the `entry` role a key sees only the lookups and batches of its own account; one of another account
  answers `404`. Reviewers and admins see all of them.
- The plan of the account that created the key applies to the key ([Rate limits and quotas](/rate-limits.md)).
- An operation that needs more than the `entry` role says so in its description.

`GET /api/auth/me` returns the account and the effective role behind a key ([System](/system.md)).

## Sessions are not for integrations

The web application signs in with a session token sent as `Authorization: Bearer <token>`. Those sign-in and
account routes are not part of the customer API and are not described here. Integrations use an API key.

## What 401 and 403 look like

No key: `401`.

```json
{ "detail": "Please sign in", "code": "unauthenticated" }
```

A key that does not exist or was revoked: `401`. A key whose owner account was deactivated also answers `401`, with
the message "The API key owner has been disabled".

```json
{ "detail": "Invalid API key", "code": "unauthenticated" }
```

A valid key whose role does not allow the call: `403`.

```json
{ "detail": "Admin role or higher required", "code": "forbidden" }
```

A valid key whose plan does not include the feature, or would exceed a plan limit: `403`, with `details`
([Errors](/errors.md#plan-refusals)).

## Keeping a key safe

- A key is a secret with the rights of its role. Keep it in a secret store or an environment variable, never in
  source code, a URL, a log line or a browser page.
- Call the API from your servers. A key in front-end code is readable by everyone who opens the page.
- Give each integration its own key with the lowest role that works, so one can be revoked without stopping the
  others.
- If a key may have leaked, revoke it and create a new one. There is no way to read a key again after it was
  created.
- The [API explorer](/explorer/) keeps the key you type in memory for that tab only; it is gone when the page is
  reloaded.
