> Every Sentinel doc, as Markdown: https://runsentinel.app/llms.txt

# Authentication

Three kinds of credential, one header: <code>Authorization: Bearer &lt;token&gt;</code>.

| Credential | Looks like | Made by | Reach |
|---|---|---|---|
| Login session | `ss-sl_…` | `sentinel login` | Your whole account, minus the web-only actions |
| API key | `sk-snt_…` | Web app (Settings → API keys) or `sentinel keys create` | Only the areas you give it |
| OAuth app | `oat-snt_…` | Signing in from an MCP client (hosted `/mcp`) | Only the areas you allowed, only on `/mcp`. Listed and revoked with your keys |

A secondlayer API key won't work here; Sentinel keys start `sk-snt_`.

The login session is your secondlayer session. `sentinel login` and `secondlayer login --credits` share one file, so either serves both.

`sentinel login` prints a link and a code: open the link, check the code matches and approve. Only approve a code you started. Without a terminal (an agent's shell) it saves the attempt for 15 minutes, 0600, and `sentinel login --wait` finishes it (exit `3` while you haven't approved yet). `sentinel login --email` uses an emailed 6-digit code instead.

## Which credential wins

The CLI and the local MCP server pick the first that exists:

1. `--token <key>` (CLI only)
2. `SENTINEL_API_KEY` in the environment
3. The key saved by `sentinel login --with-token`, in `~/.secondlayer/sentinel.json`
4. The secondlayer session from `sentinel login`

`sentinel whoami` shows who you are and where the credential came from. `sentinel logout` revokes the session on secondlayer, forgets both saved credentials, and signs the secondlayer CLI out too.

## In CI

Make a key on the account page (`/account`), then either set it:

```sh
export SENTINEL_API_KEY=sk-snt_…
```

or save it once. The key is checked before it is stored:

```sh
$ echo "$KEY" | sentinel login --with-token
```

## Key areas

A key gets none, read or write on each of three areas. Write includes read.

Each verb needs one area (the [API](/docs/api#key-policy) lists the routes):

{/* key-areas:start */}
| Area | Read | Write |
|---|---|---|
| Plans | `contracts` | `show`, `update`, `auto-plan`, `link`, `plan-linked`, `rename`, `remove`, `import` |
| Monitoring | `list`, `show`, `logs`, `destinations` | `status watch`, `on`, `test-alert`, `retry-history`, `off`, `when`, `describe`, `mute`, `group`, `backtest`, `every`, `at`, `destinations add`, `destinations default`, `destinations remove`, `connect slack` |
| Alerts | `alerts`, `show` | `read`, `redeliver`, `mute` |

Any key, whatever its areas: `ask`, `show`, `whoami`, `upgrade`, `status`.
{/* key-areas:end */}

Give an agent only what it needs. "Tune alerts" is Monitoring write and nothing else.

> **Spends money**
>
> Monitoring write turns monitoring on, which counts against your tier, and sets checks that are charged per run. Hand it only to something you would hand a card to.

## Keys from your login

Your own sign-in manages keys: the account page (`/account`) or `sentinel login`. A key or an OAuth app never can (`403 Use the web app or sentinel login for this.`).

```sh
$ sentinel keys create ci --monitoring write
$ sentinel keys
$ sentinel keys revoke <id> --yes
```

Areas left out are read (alerts: write). The key prints once. A key made outside the account page emails your account its name, areas and where it came from.

## Stays on the account page

Sign-in, choosing a tier and opening the billing portal. A key that tries gets `403 Use the web app for this.`

## Errors and limits

| Status | Means |
|---|---|
| `401` | No token, or a bad one |
| `403` | The key lacks an area (`This key needs Monitoring: write.`), the action is web-only, or your secondlayer account hasn't approved Sentinel yet (`Approve Sentinel on this secondlayer account: run sentinel login --force`; turning a watch on: `Allow Sentinel to use your secondlayer account first: …`) |
| `404` | Not there, or not yours to see |
| `429` | Over 120 requests a minute for this key |
| `503` | Sign-in is unavailable. Try again. Never anonymous access |

Next: [CLI](/docs/cli), [MCP server](/docs/mcp).
