---
title: "Token scopes and what each one permits"
description: "The four token scopes, what each unlocks, and why export is gated three separate ways."
---

> Documentation Index
> Fetch the complete documentation index at: https://tee.hypetrade.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Token scopes and what each one permits

Every workspace token carries a set of scopes, fixed at mint time. A call
outside them returns `403` with code `scope_denied` — the token is valid, it
just is not allowed.

## The four scopes

| Scope | Unlocks |
|---|---|
| `read` | Workspace info, account and wallet listing, addresses, assets, network list |
| `write` | Creating and deleting accounts, deriving and importing wallets, tags, setting RPC URLs |
| `sign` | Message signing, typed-data signing, and all transaction routes |
| `export` | The two sealed key-export routes, and nothing else |

Request them at mint time:

```json
{
  "workspace": "demo",
  "password": "…",
  "scopes": ["read", "sign"]
}
```

Omit `scopes` entirely and you get `["read", "write", "sign"]` — the default
grant. **`export` is never included by default**; it must always be asked for
by name.

> **Ask for less**
>
> Scopes cannot be narrowed after minting, but they are cheap to re-mint. A
> service that only reads balances and signs should hold a `["read","sign"]`
> token, so a leaked token cannot create or delete anything.

An unrecognised scope name is rejected outright with `400` and
`invalid_body` — unknown scopes are never silently dropped.

## Why export is different

A leaked signing token moves funds within whatever policy you have set, and
leaves a trace. A leaked export hands over permanent, offline, irrevocable
control of the key itself. So export is gated three independent ways, and all
three must hold:

1. **Step 1**

### A distinct scope

   `export` must be named explicitly in the mint request. No default grant
   includes it.

2. **Step 2**

### A tenant-level enable

   Your operator must have registered an `exportPublicKey` for the tenant. If they
   have not, the mint itself fails with `403` and `export_disabled` — you cannot
   even hold an export-scoped token.

3. **Step 3**

### Encryption to an operator-held key

   The response never contains plaintext key material. It contains a **sealed
   blob** encrypted to the registered X25519 public key, so a stolen token yields
   something the thief cannot open.

Every export attempt is audited — attempt, success, and failure alike — because
"when did this key leave" has to be answerable after the fact.

## Four scope-free routes

Four workspace-token routes accept any scope:

- `POST /v1/accounts/{slug}/unlock` and `POST /v1/accounts/{slug}/lock`.
  Unlocking is a precondition for work you are already authorised to do, not a
  privilege of its own — the scope check still applies to whatever you do next.
- `POST /v1/auth/token/refresh` and `DELETE /v1/auth/token`. Extending or
  ending your own session is not an operation on the workspace's contents, so
  no scope gates it. A token can always refresh and revoke itself, whatever it
  was minted to do.

## Related

- [Export key material](/guides/export-key-material/) — the full sealed-export flow
- [Auth endpoints](/api/auth/) — minting with explicit scopes
- [Errors](/errors/) — `scope_denied`, `export_disabled`, and neighbours

Source: https://tee.hypetrade.xyz/concepts/scopes/index.mdx
