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

# Authentication

> One header, three kinds of credential.

Everything goes in `Authorization`.

| Credential      | Header                                | Who uses it                                        |
| --------------- | ------------------------------------- | -------------------------------------------------- |
| API key         | `Authorization: Bearer klk_...`       | Programmatic callers                               |
| Session token   | `Authorization: Bearer <clerk jwt>`   | The dashboard                                      |
| Machine payment | `Authorization: Payment <credential>` | Agents — see [Paying as an agent](/agent-payments) |

An API key and a session token resolve to the same account and behave
identically. Nothing you can do with one is unavailable through the other.

## API keys

Mint one with `POST /api/billing/claim`. The raw key is returned exactly once and
stored only as a hash, so we cannot show it to you again or recover it — which is
also why the endpoint refuses if your account already has a live key. Silently
minting a second would leave you holding a credential you had no way to tell
apart from the first, or to revoke with confidence.

```bash theme={null}
curl -X POST https://api.kealinks.com/api/billing/claim \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

<Warning>
  A key can repoint every code on the account, including ones already printed on
  physical material. Treat it like a production database credential, not like an
  analytics token.
</Warning>

## Workspaces

An account **is** a workspace. Members you invite create links that belong to the
workspace, not to themselves — being invited is delegation of the owner's
account, never a free account of your own.

A session token that can reach several workspaces selects one with
`X-Workspace-Id`. An API key belongs to exactly one workspace and ignores the
header; `GET /api/workspaces` reports the one it is scoped to.

```bash theme={null}
curl https://api.kealinks.com/api/links \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "X-Workspace-Id: acct_2YgQk1p8fT3mN7wCxRvBdLsHjZa"
```

Asking for a workspace you are not a member of is a `401`, decided before
anything else about the request is considered.

## What authentication does not decide

Authentication answers "who are you". It never answers "may you". Those are
separate on purpose, and the gap is where the product promise lives: a cancelled
customer signs in normally, lists their links, downloads artwork for codes they
printed years ago, and reaches the billing portal. What they cannot do is create
or edit. See [Errors](/errors) for how that is reported, and
[Permanence](/permanence) for why.
