---
title: "API token scopes: give a token only the access it needs"
description: "Restrict a Linkbreakers API token to the resources it needs, such as links:read or visitors:write. How scopes work, how to create and change a scoped token, and what an insufficient_scope error means."
canonical: "https://linkbreakers.com/help/article/api-token-scopes"
last-updated: 2026-10-24
---

# API token scopes: give a token only the access it needs

> Restrict a Linkbreakers API token to the resources it needs, such as links:read or visitors:write. How scopes work, how to create and change a scoped token, and what an insufficient_scope error means.

## Short answer

Every Linkbreakers API token has either **full access** or a list of **scopes**, such as `links:read` or `visitors:write`. A scoped token can only call the endpoints its scopes cover, and anything else is refused with a `403` naming the scope that was missing. Give an AI agent, a reporting script or a single-purpose integration only the scopes it needs, so a leaked token cannot do more than its job.

## Quick summary

- A scope is `resource:read` or `resource:write`, for example `links:read`, `analytics:read` or `webhooks:write`
- A write scope also grants the read scope of the same resource: `links:write` can read links too
- Tokens created without scopes have full access, including any scope added later. Every token that existed before scopes keeps full access
- Every API endpoint requires exactly one scope, declared in the [OpenAPI specification](https://api.linkbreakers.com/internal/openapi/api/v1/api.swagger.json)
- The full list of scopes is public at `GET https://api.linkbreakers.com/v1/api-scopes`
- A token can only create or update tokens with scopes it holds itself
- [Publishable keys](/help/article/secret-key-vs-publishable-key) stay limited to visitor identification and take no scopes

## How scopes work

A scope names a resource and an access level. The resources follow the API: links (with tags, folders and link settings), workflows, QR codes, page themes, media, custom domains, visitors, analytics, webhooks, integrations, workspace, members, API tokens, billing and the Assistant.

When a request arrives, Linkbreakers looks up the one scope that endpoint requires and checks it against the token:

- **Full access** passes every check
- **A scoped token** passes when it holds that scope, or the write scope of the same resource
- **Anything else** is refused with `403` and the code `INSUFFICIENT_SCOPE`

Changes to a token's scopes reach every request within 30 seconds.

Signing in to the dashboard is not affected: your own session always has full access.

A token belongs to the workspace that created it and never acts in another one, even when the person who created it belongs to [several workspaces](/help/article/work-across-multiple-workspaces).

## Create a scoped token in the dashboard

1. Go to [**Dashboard → API Tokens**](https://app.linkbreakers.com/workspace/dashboard/api-tokens) and click **Create new token**
2. Name the token after its job, for example "Weekly analytics export"
3. Keep **Secret Key** selected
4. Under **Access**, choose **Restricted**
5. For each resource the token needs, pick **Read** or **Read & write**. Leave the rest on **None**
6. Click **Create token** and copy it. It is shown only once

To change what an existing token can do, open its menu in the token list and choose **Edit access**. You can switch between full access and a restricted set at any time without issuing a new token.

## Create a scoped token with the API

In REST request bodies, scopes use their enum names. Send them in `scopes`; leave `scopes` out for full access.

```bash
curl -X POST https://api.linkbreakers.com/v1/workspace-tokens \
  -H "Authorization: Bearer $LINKBREAKERS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Weekly analytics export",
    "keyType": "WORKSPACE_TOKEN_KEY_TYPE_SECRET",
    "scopes": ["API_SCOPE_ANALYTICS_READ", "API_SCOPE_LINKS_READ"]
  }'
```

The token making this call needs `tokens:write`, and it cannot grant a scope it does not hold. To change scopes later, `PATCH /v1/workspace-tokens/{id}` with new `scopes`, or with `"fullAccess": true` to restore full access.

## Find the scope an endpoint needs

You do not need to guess. The same information is published in three machine-readable places, all generated from one definition in the API:

- **The OpenAPI specification.** Each operation lists its scope under `security` and in `x-required-scope`, and its description ends with "Requires the `links:write` scope." The `oauth2` security scheme lists every scope with a description
- **The scope list.** `GET https://api.linkbreakers.com/v1/api-scopes` returns every scope with its resource, access level and description. It needs no authentication
- **Protected resource metadata.** `https://api.linkbreakers.com/.well-known/oauth-protected-resource` follows RFC 9728 and lists every scope in `scopes_supported`

The SDKs are generated from the OpenAPI specification, so each method's documentation names its scope too.

## Errors

A token without the scope an endpoint needs gets a `403`:

```json
{
  "code": 7,
  "codeType": "INSUFFICIENT_SCOPE",
  "message": "this token is missing the links:write scope this endpoint requires. links:write allows: Create, update and delete links, tags, folders and link settings. Use a token that holds links:write, or one with full access. Learn more: https://linkbreakers.com/help/article/api-token-scopes",
  "details": []
}
```

The response also carries `WWW-Authenticate: Bearer error="insufficient_scope", scope="links:write"`, so a client can tell exactly which scope to ask for.

A request with no token, or a token that is invalid or revoked, gets a `401` with a `WWW-Authenticate` header pointing at the protected resource metadata.

## What a scoped token can never do

Some actions would let a restricted token turn itself into full access, so they need a full-access token or a dashboard session, whatever scopes the token holds:

- Signing in, with or without MFA
- Inviting a member
- Changing a member's sign-in email, or your own email or password. Changing names still only needs `members:write`
- Opening the dashboard's real-time connection, which the Assistant uses

A scoped token that tries gets a `403` with the code `SCOPED_TOKEN_NOT_ALLOWED`.

## Scopes for AI agents and MCP

Scopes are the safest way to let an AI agent work in your workspace. For an agent that calls the REST API, an SDK or the CLI, create a token restricted to what the agent's task needs, for example `links:read` and `analytics:read` for an agent that writes reports, and it cannot delete links, change webhooks or create other tokens even if it is told to.

The [Linkbreakers MCP server](/help/article/how-to-set-up-and-configure-the-linkbreakers-mcp-server) does not accept API tokens, scoped or not: MCP clients connect through OAuth. They can request the same scopes in the `scope` parameter, for example `scope=links:read analytics:read`. The resulting token is limited to those scopes on both the MCP server and the REST API. Requesting `mcp:tools`, or no scope at all, grants full access, which is what existing MCP clients already do.

Scopes Linkbreakers does not issue, such as `offline_access`, `openid` or `profile`, are ignored rather than refused, so clients that always ask for them still connect. If none of the requested scopes are Linkbreakers scopes, the grant is full access, as if no scope had been requested. The `scope` field of the token response says what was granted. Refresh tokens are issued whether or not `offline_access` was requested.

For the other ways an agent can get credentials, including self-registration through auth.md, see [How Linkbreakers works with AI agents](/help/article/linkbreakers-for-ai-agents).

## Frequently asked questions

### Do my existing tokens still work?

Yes. Every token created before scopes existed has full access and keeps it. Nothing changes until you restrict a token yourself.

### Does `links:write` let a token read links?

Yes. A write scope always includes the read scope of the same resource, so you never need to pick both.

### Why can't my scoped token create another token with more access?

A token can only grant scopes it holds itself. A token with `tokens:write` and `links:read` can create a `links:read` token, but not a full-access one. This stops a restricted token from being used to mint a broader one.

### What happens to a full-access token when new endpoints are added?

It can call them. Full access is not a list of today's scopes: it covers every scope, including ones added later. A restricted token only gains new access when you edit it.

### Can publishable keys have scopes?

No. Publishable keys are designed to sit in client-side code and are limited to visitor identification. Use a restricted secret key for anything else.
