# Scopes

A scope is one named permission on a credential. Every route needs one, and the server checks it on every request.

A write scope implies its read scope. `todos:write` gives you `todos:read`.

## The list

| scope | grants |
|---|---|
| `todos:read` `todos:write` | to-dos |
| `containers:read` `containers:write` | areas, projects, subprojects |
| `inbox:read` `inbox:write` | capture |
| `tags:read` `tags:write` | tags |
| `attachments:read` `attachments:write` | attachments, including file bytes |
| `filters:read` `filters:write` | saved filters |
| `settings:read` `settings:write` | week start |
| `sessions:read` `sessions:write` | keys, grants and sessions |
| `webhooks:write` | webhooks, including reading them |
| `tasks:read` `tasks:write` | umbrellas over the content scopes |

## Two rules that catch people out

**The umbrellas do not imply `sessions:*` or `webhooks:write`.** `tasks:write` is broad access to content. Listing a user's credentials, or wiring a channel that sends their activity to a URL, is a different kind of power, so it is asked for by name.

**`webhooks:write` covers its own reads.** Listing subscriptions reveals every endpoint the user has connected, so there is no read-only half.

## You may get less than you ask for

At approval time the user can grant a subset. Ask for `todos:read todos:write` and they may grant read only.

Read the granted scope from the token response. Do not assume you got what you asked for.

```json
{
  "access_token": "...",
  "token_type": "Bearer",
  "scope": "todos:read",
  "expires_in": 3600
}
```

`GET /v1/me` reports the same list at any time.

## When a scope is missing

The route returns [forbidden_scope](/errors/forbidden_scope). The credential is valid, so refreshing will not help. Send the user through approval again, asking for the scope you need.

## Next

- [Authentication](/authentication) for how a credential is created.
- [Encryption](/encryption) for what a granted scope actually hands over.
