# Authentication

> Bearer tokens minted from the dashboard, scoped to what they need.

Every request to `/api/v1` carries a bearer token:

```bash
curl https://lunary.cloud/api/v1/instances \
  -H "Authorization: Bearer lc_your_token_here"
```

## Minting a token

Tokens are minted in the dashboard under **Access → API tokens**. A token belongs to your organization, carries an explicit set of scopes, and can have an expiry. The token value starts with `lc_` and is shown once; we store only a hash.

Mint narrow tokens for narrow jobs: a read-only token for a status page, a `write_plugs` token for a CI job that triggers backups.

## Scopes

| Scope | Grants |
| --- | --- |
| `read_instances` | List and read your instances and their health. |
| `write_instances` | Provision and tear down instances. |
| `read_plugs` | Read plugs, runs, routines, and artifact download URLs. |
| `write_plugs` | Trigger plugs; create, update, delete, and run routines. |
| `read_agent_sessions` | Read delegated agent sessions. |
| `write_agent_sessions` | Register and transition agent sessions. |
| `read_billing` | Read subscription, payment method, and invoices. |

## Errors

- **401 `unauthorized`** — the token is missing, malformed, expired, or revoked.
- **403 `insufficient_scope`** — the token is valid but lacks the scope the endpoint requires; `details.required` names it.
- **429 `rate_limited`** — over budget for this class of request (reads and writes are metered separately). `Retry-After` gives the wait in seconds; every response carries `X-RateLimit-Limit` and `X-RateLimit-Remaining`.

Each endpoint's required scope is listed in the [API reference](/api), which is generated from the same OpenAPI document the server enforces.

## OAuth for MCP clients

The [MCP endpoint](/api/mcp) also accepts OAuth access tokens issued by our sign-in provider, so an MCP client can log in through the browser instead of pasting a token. REST endpoints accept `lc_` tokens only.
