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

# Authentication

> Sessions versus API tokens, the token format, all 14 scopes and what each one grants, expiry, revoking, and which endpoints accept a token at all.

Every authenticated request carries a bearer credential:

```bash theme={null}
curl https://my.server.express/api/v1/cloud \
  -H "Authorization: Bearer $SE_TOKEN"
```

That credential is one of two things, and they don't behave the same way.

## Sessions and API tokens

| | Session | API token |
| - | - | - |
| Where it comes from | Signing in to the client area | **Settings → API tokens** |
| Lifetime | Minutes, renewed by the browser | Until it expires or you revoke it |
| Scopes | None. A session can do anything you can. | Only the scopes you picked |
| Reaches | The whole customer API | Only endpoints that opted in to tokens |

A session is what the client area uses. It's short-lived and tied to a browser, so it isn't something you should script against. **Use an API token for anything automated.** The rest of this page is about tokens.

## Creating a token

In the client area, open **Settings → API tokens** and create one. You choose:

* **A name.** It's for you, so you can tell which one to revoke later. Up to 80 characters.
* **Scopes.** What the token may do. Pick the narrowest set that works.
* **An expiry**, if you want one, anywhere from 1 to 3650 days. With no expiry, the token lives until you revoke it.

You can hold up to 20 active tokens at once. Revoke one to make room for another.

The token is shown **once**, at creation. We store a SHA-256 hash and the public prefix, never the token itself. If you lose it, revoke it and make a new one. We can't recover it for you.

## Token format

```text theme={null}
se_live_AbCdEfGhIjKl_<43 characters of secret>
```

A token is 64 characters long and made of two fixed-width halves. The first 20 characters (`se_live_` plus a 12-character prefix) are public. That's what the token list in the client area shows you, and it's how we find the right record without touching the secret. The rest is the secret.

> [!WARNING]
>
> Don't split a token on `_` to parse it. The alphabet is base64url, which uses `_` as an ordinary character, so about half of all secrets contain one. Split by position, or better, don't split at all.

## Scopes

There are 14 scopes, and they're deliberately coarse. A scope nobody understands is a scope nobody sets correctly.

| Scope | Grants |
| - | - |
| `services:read` | List servers and view specs, status and network details. |
| `services:stats` | Bandwidth, CPU and memory graphs. |
| `services:power` | Boot, shut down and reboot servers. |
| `services:rescue` | Toggle rescue mode and read rescue credentials. |
| `services:reinstall` | **Destructive.** Wipe a server and reinstall the OS. Destroys all data on the machine. |
| `services:cancel` | **Destructive.** Schedule or issue cancellation of a paid service. |
| `snapshots:read` | List the snapshots on your servers and when they were taken. |
| `snapshots:write` | **Destructive.** Take, delete and roll back to snapshots. A rollback discards everything written since. |
| `catalogue:read` | Live dedicated and cloud stock, specs, and your own pricing. |
| `orders:place` | **Spends money.** Order servers. Creates a real service and a real invoice you owe. |
| `invoices:read` | List invoices, line items and payment status. |
| `invoices:pay` | **Spends money.** Settle an invoice using account credit or a saved card. |
| `tickets:read` | List support tickets and their replies. |
| `tickets:write` | Open tickets and post replies. |

The five marked scopes are never granted by default, and the client area makes you confirm twice before it'll create a token that holds any of them. A CI job that reads server status has no business being able to [reinstall the box](https://docs.server.express/guides/servers.md), or to [order another one](https://docs.server.express/guides/reselling.md).

Snapshots have their own pair on purpose. Listing them is harmless. Rolling back throws away every write since the snapshot was taken. A token that can list your servers shouldn't be able to do that by accident.

### Checking a token's scopes

`GET /v1/auth/whoami` accepts any valid token and returns its name and scope list. That makes it a good first call in any script. Fail early with a clear message instead of halfway through a job:

```bash theme={null}
curl -s https://my.server.express/api/v1/auth/whoami \
  -H "Authorization: Bearer $SE_TOKEN" | jq '.data.scopes'
```

### Missing a scope

If you call an endpoint your token isn't scoped for, you get a `403` that names the scope it's missing:

```json theme={null}
{
  "success": false,
  "error": "This token is missing the \"services:power\" scope."
}
```

Scopes are fixed at creation. To widen one, make a new token. A token can't grant itself more power, and that's the point.

## Which endpoints accept tokens

Most of the customer API doesn't accept tokens at all. That's the default, not an oversight. An endpoint stays closed to tokens until someone deliberately opts it in and names a scope, so new routes always ship closed.

In the [API reference](https://docs.server.express/api-reference/introduction.md), every endpoint that takes a token shows the scope it needs, taken from the spec's `x-required-scope` field. If an endpoint doesn't list a scope, it needs a browser session.

If you send a token to one of those endpoints, you get a `401` that says so, rather than a confusing "invalid token":

```json theme={null}
{
  "success": false,
  "error": "This endpoint does not accept API tokens. Sign in from the client area."
}
```

## Expiry and revoking

Revoke a token from the same settings page. It takes effect on the next request, with no cache to wait out.

Revoked and expired tokens each fail with a `401` that tells you which:

| Message | What happened |
| - | - |
| `This API token has been revoked` | Someone revoked it. Make a new one. |
| `This API token has expired` | It hit its expiry date. Make a new one. |
| `Invalid API token` | The prefix or secret doesn't match any token. |
| `Malformed API token` | It starts with `se_live_` but isn't the right shape, usually from a truncated copy and paste. |

The first two are nearly always your own stale config, so they don't count against you. The last two look like guessing, and they count toward an [automatic IP block](https://docs.server.express/errors-and-rate-limits.md#failed-authentication-and-ip-blocks).

Banning an account revokes every token it holds.

## Keeping tokens safe

* Keep them in environment variables or a secrets manager, never in the repo.
* Use one token per system, so revoking one doesn't break five others.
* Set an expiry on anything that isn't permanent infrastructure.
* The token list shows when and from which IP each token was last used. Check it now and then. If a token hasn't been used in six months, revoke it.

Tokens carry your account's authority. Anyone who holds one can do everything its scopes allow.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.