# Authentication

Every request to the AgentSky API must include a bearer token. Tokens are scoped — the scope you need depends on what the call does.

## Getting a token

**From the browser:** Developer → API keys → New key. Copy the token immediately; it is shown only once.

**From the CLI:**

```bash
sky auth login          # opens a browser tab; pastes the token automatically
sky auth login --no-browser   # prints a URL; paste the code manually (CI)
```

Successful login stores a credential in `~/.config/sky/credentials.json` and sets the `SKY_API_TOKEN` environment variable for the current shell. Use `sky auth status` to inspect the current session.

**In CI / server environments:** Set the `SKY_API_TOKEN` environment variable or pass the token in every request.

## Using a token

Pass the token as a bearer in the `Authorization` header:

```bash
curl https://api.agentsky.dev/v1/agents \
  -H "Authorization: Bearer ast_..."
```

The AgentSky SDK picks up `SKY_API_TOKEN` automatically if the header is not set explicitly.

## Scopes

Tokens have one of three scopes. Higher scopes include all permissions of lower scopes.

| Scope | Grants |
|---|---|
| `read` | GET any resource you own |
| `write` | read + create and update agents, sessions, routines, webhooks, policies, files |
| `admin` | write + manage workspace members, billing, and universe-level settings |

`read ⊂ write ⊂ admin`. Most integration scenarios need only `write`. Use `read` for monitoring dashboards or tooling that only fetches data. Never generate an `admin` token for a service that doesn't need billing access.

## Personal vs. scoped tokens

**Personal tokens** act on all universes (workspaces) your account belongs to. This is the default.

**Universe-scoped tokens** are tied to a single universe and cannot act outside it — safer for multi-tenant setups where each customer has its own universe.

Create a scoped token by selecting a universe when you create the key in Developer → API keys.

## The X-Universe header

When you hold a personal token and want to act inside a specific universe, pass the universe's slug in `X-Universe`:

```bash
curl -X POST https://api.agentsky.dev/v1/sessions \
  -H "Authorization: Bearer ast_..." \
  -H "X-Universe: acme" \
  -H "Content-Type: application/json" \
  -d '{ "agent": "agent_cmtb2f0a8m9k7x51q4ez6r0d" }'
```

Every resource created in that call belongs to the `acme` universe. Without the header, the call acts on your personal workspace.

Universe-scoped tokens imply a universe; you do not need to repeat the header on every call.

## Revoking a token

Browser: Developer → API keys → revoke. CLI: `sky auth logout` (revokes the stored token and clears the local credential).

## See also

- [Concepts](https://agentsky.dev/docs/concepts.md) — agents, sessions, universes
- [Agent API guide](https://agentsky.dev/docs/agent-api.md) — end-to-end integration with auth examples
- [API reference](https://agentsky.dev/docs/api.md) — full error catalog, including 401/403 shapes
