> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bkmark.it/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth2 Scopes — Permissions Reference — Bkmark API

> Every Bkmark OAuth2 scope, the endpoints each one unlocks, and recommended scope sets for read-only, bookmark manager, and full-access integration types.

Scopes define exactly what your application can do on behalf of a user. When you redirect a user to the Bkmark authorization endpoint, you specify the scopes you need in the `scope` query parameter. The user sees a plain-language description of each permission on the consent screen and can approve or deny the request.

Bkmark enforces scopes on every API request. If your token doesn't carry the right scope for an endpoint, the API returns `403 Forbidden` — even if the token is otherwise valid. This means you must request all the scopes you need upfront; you cannot silently expand them later without sending the user through the authorization flow again.

<Note>
  Request only the scopes your integration genuinely needs. Requesting excessive permissions makes the consent screen more alarming to users, reduces the likelihood they'll approve, and increases your blast radius if a token is ever compromised. Follow the principle of least privilege.
</Note>

***

## Available Scopes

| Scope             | What it allows                             | Endpoints unlocked                                                                                                                                                                                            |
| ----------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bookmarks:read`  | View, search, and export bookmarks         | `GET /bookmarks`, `GET /bookmarks/:id`, `GET /bookmarks/export`, `GET /bookmarks/trash`, `GET /search`                                                                                                        |
| `bookmarks:write` | Create, edit, delete, and import bookmarks | `POST /bookmarks`, `PATCH /bookmarks/:id`, `DELETE /bookmarks/:id`, `POST /bookmarks/:id/tags`, `POST /bookmarks/:id/groups`, `POST /bookmarks/bulk`, `POST /bookmarks/import`, `POST /bookmarks/:id/restore` |
| `tags:read`       | View tags                                  | `GET /tags`                                                                                                                                                                                                   |
| `tags:write`      | Create, rename, and delete tags            | `POST /tags`, `PATCH /tags/:id`, `DELETE /tags/:id`                                                                                                                                                           |
| `groups:read`     | View groups                                | `GET /groups`, `GET /groups/:id`                                                                                                                                                                              |
| `groups:write`    | Create, rename, and delete groups          | `POST /groups`, `PATCH /groups/:id`, `DELETE /groups/:id`                                                                                                                                                     |
| `search:read`     | Full-text search across bookmarks          | `GET /search`                                                                                                                                                                                                 |

<Note>
  `search:read` is a subset of what `bookmarks:read` already covers — `GET /search` is accessible with either scope. Request `search:read` alone when your integration only needs search and should not be able to enumerate a user's full bookmark list.
</Note>

***

## Scope Details

### `bookmarks:read`

Grants read access to a user's bookmarks, including the ability to export them and query trash.

**Endpoints:**

<ResponseField name="GET /bookmarks" type="endpoint">
  List all bookmarks. Supports filtering by `since`, `updatedSince`, tags, and groups.
</ResponseField>

<ResponseField name="GET /bookmarks/:id" type="endpoint">
  Fetch a single bookmark by ID.
</ResponseField>

<ResponseField name="GET /bookmarks/export" type="endpoint">
  Export all bookmarks as JSON.
</ResponseField>

<ResponseField name="GET /bookmarks/trash" type="endpoint">
  List soft-deleted bookmarks pending permanent deletion.
</ResponseField>

<ResponseField name="GET /search" type="endpoint">
  Full-text search across bookmark titles, descriptions, and URLs.
</ResponseField>

***

### `bookmarks:write`

Grants write access to create, modify, and delete bookmarks, plus bulk operations and import.

<Note>
  `bookmarks:write` does **not** imply `bookmarks:read`. If your app needs to read bookmarks it just created, request both scopes.
</Note>

**Endpoints:**

<ResponseField name="POST /bookmarks" type="endpoint">
  Save a new bookmark.
</ResponseField>

<ResponseField name="PATCH /bookmarks/:id" type="endpoint">
  Update a bookmark's title, description, tags, groups, favorite status, or archived status.
</ResponseField>

<ResponseField name="DELETE /bookmarks/:id" type="endpoint">
  Soft-delete a bookmark (moves to trash).
</ResponseField>

<ResponseField name="POST /bookmarks/:id/tags" type="endpoint">
  Replace all tags on a bookmark.
</ResponseField>

<ResponseField name="POST /bookmarks/:id/groups" type="endpoint">
  Replace all group assignments for a bookmark.
</ResponseField>

<ResponseField name="POST /bookmarks/bulk" type="endpoint">
  Apply a single action (tag, move, archive, favorite, delete, or export) to up to 500 bookmarks at once.
</ResponseField>

<ResponseField name="POST /bookmarks/import" type="endpoint">
  Import bookmarks from a browser HTML export, Pocket, Raindrop, or a Bkmark JSON export.
</ResponseField>

<ResponseField name="POST /bookmarks/:id/restore" type="endpoint">
  Restore a soft-deleted bookmark from trash.
</ResponseField>

***

### `tags:read`

Grants read access to the user's tag list.

<ResponseField name="GET /tags" type="endpoint">
  List all tags, including name, color, and bookmark count.
</ResponseField>

***

### `tags:write`

Grants write access to create, rename, and delete tags.

<Note>
  `tags:write` does **not** imply `tags:read`. Request both if you need to read existing tags before creating new ones.
</Note>

<ResponseField name="POST /tags" type="endpoint">
  Create a new tag.
</ResponseField>

<ResponseField name="PATCH /tags/:id" type="endpoint">
  Rename a tag or change its color.
</ResponseField>

<ResponseField name="DELETE /tags/:id" type="endpoint">
  Delete a tag (removes it from all bookmarks).
</ResponseField>

***

### `groups:read`

Grants read access to the user's groups (collections of bookmarks).

<ResponseField name="GET /groups" type="endpoint">
  List all groups.
</ResponseField>

<ResponseField name="GET /groups/:id" type="endpoint">
  Fetch a single group and its metadata.
</ResponseField>

***

### `groups:write`

Grants write access to create, rename, and delete groups.

<ResponseField name="POST /groups" type="endpoint">
  Create a new group.
</ResponseField>

<ResponseField name="PATCH /groups/:id" type="endpoint">
  Rename a group or change its color.
</ResponseField>

<ResponseField name="DELETE /groups/:id" type="endpoint">
  Delete a group (bookmarks inside are not deleted).
</ResponseField>

***

### `search:read`

Grants access to full-text search without exposing the full bookmark list. Use this when your integration only needs to let the user find bookmarks by keyword.

<ResponseField name="GET /search" type="endpoint">
  Full-text search across bookmark titles, descriptions, and URLs.
</ResponseField>

***

## Recommended Scope Sets

Choose the combination that matches your integration type. Copy the scope string directly into your authorization URL.

### Read-only

```text theme={null}
bookmarks:read tags:read groups:read
```

Use for dashboards, analytics, bookmark viewers, and audit tools that only display data and never write anything back.

### Bookmark manager

```text theme={null}
bookmarks:read bookmarks:write tags:read tags:write groups:read
```

Use for browser extensions, import/export tools, Zapier or Make actions that save new bookmarks, and apps that organize bookmarks with tags. Includes full bookmark read/write and tag read/write, but does not allow creating or deleting groups.

### Full access

```text theme={null}
bookmarks:read bookmarks:write tags:read tags:write groups:read groups:write search:read
```

Use for fully-featured clients, backup and sync tools, and power-user automations that need complete control over a user's Bkmark account.

***

## Scope Enforcement

When your application makes an API request:

1. Bkmark validates the `Authorization: Bearer` token.
2. Bkmark checks whether the token's granted scopes include the scope required by the endpoint being called.
3. If the required scope is missing, Bkmark returns `403 Forbidden` with an error body indicating which scope is needed.

```json theme={null}
{
  "error": "insufficient_scope",
  "error_description": "This endpoint requires the bookmarks:write scope.",
  "required_scope": "bookmarks:write"
}
```

Scopes are fixed at authorization time. If a user approved `bookmarks:read` but your app later needs `bookmarks:write`, you must send the user through the authorization flow again with the full set of scopes you need. You cannot silently add scopes to an existing token.

<Tip>
  Check the `scope` field in the token exchange response (or call `GET /oauth/token-info`) to confirm which scopes were actually granted before making write calls. Users can grant a subset of what you requested.
</Tip>
