Authentication

Scopes

A scope is a permission that a credential holds. REST API endpoints each require a scope, and API keys and OAuth access tokens are checked against the same list: a request that needs content.write fails the same way for a Read only key as for a token without that scope.

{
  "status": "error",
  "code": "insufficient_scope",
  "message": "This action requires the content.write scope."
}

The scopes

The third column is what the consent screen shows a person when an OAuth app asks for the scope.

Scope

Allows

Consent screen text

content.read

Reading the help center: sites, articles, categories, images, comments, staged changes and versions, change sets, FAQ sections, the widget's install details, interface translations and exports.

Read your help-center categories and articles.

content.write

Every change to content: creating, updating and deleting articles and categories, uploading and deleting images, replying to, moderating and deleting comments, staging and publishing changes, restoring versions, change sets, FAQ sections, interface translations and relaying reader feedback.

Create and update your help-center articles.

analytics.read

The analytics reports, and reader feedback: the votes and messages readers leave on articles.

Read your help-center analytics reports.

webhooks.manage

Listing, creating and deleting webhooks.

Register webhooks that notify it when your content changes.

notes.read

Reading the private notes your team leaves on articles.

Read the private notes your team leaves on drafts. Readers never see these.

notes.write

Starting notes on passages, and replying to and resolving notes.

Reply to and resolve the private notes your team leaves on drafts.

design.read

Reading the help center's design: the draft, the customization guide, the themes and the published versions.

See your help center's design: its theme, page layouts, components, custom CSS and scripts.

design.write

Every change to the design: editing the draft, applying themes, discarding the draft, restoring versions into it, and publishing it. That includes the custom CSS and scripts every visitor's browser runs once the design is published.

Change your help center's design — theme, layouts, components, custom CSS and scripts — and publish it.

domain.manage

Reading, setting and removing the help center's custom domain.

Connect your help center to your own domain, check its DNS and certificate, and remove the domain.

embed.manage

Changing which websites may embed the help center and run its widget: its embedding origins.

Choose which websites may embed your help center and run its widget. This changes your help center's security headers.

content.write covers every change to content, including deleting articles and categories, deleting images and moderating comments. If your app asks for it, tell your users what the app will do with it.

design.read and design.write aren't part of content.read and content.write: a credential needs them to read or change the design, whatever content scopes it holds. See Design API.

Endpoints by scope

Each endpoint requires exactly one scope, with three kinds of exception: two endpoints any valid credential may call, the single-use image upload URL, which is its own credential, and the requests an AI agent makes before it has a key. Creating a help center and filing a migration request take no credential, and a migration request's status takes the status token that filing it returned (see Migrate a knowledge base as an AI agent).

Scope

Endpoints

None (any valid credential)

GET /v1, GET /v1/account

None (no credential)

POST /v1/agent/help-centers, POST /v1/agent/migration-requests

The request's status token

GET /v1/agent/migration-requests/{id}

content.read

Sites: GET /v1/sites

Articles: GET /v1/articles, GET /v1/articles/{articleId}, GET /v1/articles/{articleId}/staged, GET /v1/articles/{articleId}/versions

Categories: GET /v1/categories

Images: GET /v1/images, GET /v1/images/{imageId}

Comments: GET /v1/comments, GET /v1/articles/{articleId}/comments

Change sets: GET /v1/change-sets, GET /v1/change-sets/{changeSetId}, GET /v1/change-sets/{changeSetId}/status

Widget and FAQ sections: GET /v1/widget, GET /v1/faq-sections, GET /v1/faq-sections/{sectionId}

Redirects (API keys only): GET /v1/redirects

AI agents (the key of the agent that created the help center): GET /v1/agent/help-centers/{id}

Other: GET /v1/translations, GET /v1/export

content.write

Articles: POST /v1/articles, POST /v1/articles/bulk, PATCH /v1/articles/{articleId}, DELETE /v1/articles/{articleId}, POST /v1/articles/{articleId}/feedback

Staged changes and versions: PATCH /v1/articles/{articleId}/staged, DELETE /v1/articles/{articleId}/staged, POST /v1/articles/{articleId}/staged/publish, POST /v1/articles/{articleId}/versions/{versionId}/restore

Categories: POST /v1/categories, PATCH /v1/categories/{categoryId}, DELETE /v1/categories/{categoryId}, PUT /v1/categories/order, PUT /v1/categories/{categoryId}/articles/order

Images: POST /v1/images, POST /v1/images/bulk, POST /v1/images/uploads, DELETE /v1/images/{imageId}

Comments: POST /v1/articles/{articleId}/comments, PATCH /v1/comments/{commentId}, DELETE /v1/comments/{commentId}

Interface translations: POST /v1/translations, POST /v1/translations/{translationKey}

Change sets: POST /v1/change-sets, PATCH /v1/change-sets/{changeSetId}, DELETE /v1/change-sets/{changeSetId}, POST /v1/change-sets/{changeSetId}/items, DELETE /v1/change-sets/{changeSetId}/items/{itemId}, POST /v1/change-sets/{changeSetId}/publish, DELETE /v1/change-sets/{changeSetId}/schedule

FAQ sections: POST /v1/faq-sections, PATCH /v1/faq-sections/{sectionId}, DELETE /v1/faq-sections/{sectionId}, POST /v1/faq-sections/{sectionId}/articles, PUT /v1/faq-sections/{sectionId}/articles/order, DELETE /v1/faq-sections/{sectionId}/articles/{articleId}

Imports, reading included (an OAuth token also needs an Owner or Admin): GET /v1/imports, POST /v1/imports, GET /v1/imports/{importId}, PUT /v1/imports/{importId}, POST /v1/imports/{importId}/run, GET /v1/imports/{importId}/redirect-map, DELETE /v1/imports/{importId}

Redirects (API keys only): POST /v1/redirects, POST /v1/redirects/bulk, DELETE /v1/redirects/{redirectId}

AI agents (the key of the agent that created the help center): DELETE /v1/agent/help-centers/{id}, POST /v1/agent/help-centers/{id}/migration-request

analytics.read

GET /v1/analytics/summary, GET /v1/analytics/content, GET /v1/analytics/searches, GET /v1/feedback

webhooks.manage

GET /v1/webhooks, POST /v1/webhooks, DELETE /v1/webhooks/{webhookId}

notes.read

GET /v1/articles/{articleId}/notes

notes.write

POST /v1/articles/{articleId}/notes, POST /v1/articles/{articleId}/notes/{noteId}/replies, POST /v1/articles/{articleId}/notes/{noteId}/resolve, and the notes and annotate_changes fields of PATCH /v1/articles/{articleId} and PATCH /v1/articles/{articleId}/staged

design.read

GET /v1/template, GET /v1/template/draft, GET /v1/template/schema, GET /v1/template/themes, GET /v1/template/themes/{themeKey}, GET /v1/template/versions

design.write

PATCH /v1/template/draft, POST /v1/template/draft/discard, POST /v1/template/themes/{themeKey}/apply, POST /v1/template/publish, POST /v1/template/versions/{versionId}/restore

domain.manage

GET /v1/custom-domain, PUT /v1/custom-domain, DELETE /v1/custom-domain

embed.manage

PATCH /v1/widget/embedding-origins

None (the URL is the credential)

POST /v1/images/uploads/{intent}, the upload URL that POST /v1/images/uploads returns

Redirects accept only API keys: an OAuth token gets 403 with the code api_key_required. See Redirects. Imports and the custom domain accept OAuth tokens whose person is an Owner or Admin.

How API keys map to scopes

An API key doesn't list scopes itself. Its scope in the dashboard, and its Team notes, Design and Custom domain settings, give it these. A fourth setting, Redirects, adds no scope: it lets the key's redirects lead to other sites (see Redirects).

API key

Scopes it holds

Read only

content.read, analytics.read

Read & write

content.read, content.write, analytics.read, webhooks.manage, embed.manage

Read only with Team notes

The read-only scopes, plus notes.read

Read & write with Team notes

The read and write scopes, plus notes.read and notes.write

Read only with Design

The read-only scopes, plus design.read

Read & write with Design

The read and write scopes, plus design.read and design.write

Read & write with Custom domain

The read and write scopes, plus domain.manage

An AI agent's key (named AI agent, or AI agent (setup) once its user keeps it)

The read and write scopes, plus design.read, design.write and domain.manage

An AI agent's key is the one POST /v1/agent/help-centers returns. It expires, and until someone claims its help center it reaches only that help center's content and design. A key its user lets the agent keep after the claim reaches the help center's content, design, redirects and custom domain; every other endpoint answers 403 with agent_not_allowed. See Migrate a knowledge base as an AI agent.

A Read only key never holds notes.write, design.write, domain.manage or embed.manage. A key holds the design scopes only when Allow access to the help center design is ticked for it, and domain.manage only when Allow managing the custom domain is ticked for a Read & write key. An Owner or Admin sets these when they create the key, or later with Edit access on it in Settings; the change applies from the key's next request. To see what a credential can do, call GET /v1/account: kb.capabilities.read and kb.capabilities.write tell you whether it holds content.read and content.write. See API keys.

How OAuth tokens get scopes

An OAuth app asks for scopes in the scope parameter of the authorization request, separated by spaces:

scope=openid email content.read content.write
  • All or nothing. The consent screen lists every requested scope with its description. The person approves the whole list or denies it; they can't pick some scopes and leave others.

  • A token holds what its request asked for. The granted scopes are in the access token's scopes claim, an array. The token response has no scope field.

  • Unknown scopes fail. A scope that isn't on this page ends the authorization with the error invalid_scope.

  • No scope, no content. An authorization request without scope gives a token with no scopes. It can call GET /v1 and GET /v1/account; everything else answers 403 with insufficient_scope.

  • Asking for more later. Send the person through authorization again with the longer list. The consent screen appears whenever you ask for a scope they haven't approved for your app; when every scope was approved before, the browser returns to your app without it. What a person approves adds up: a later approval doesn't take back scopes they approved earlier.

  • Refreshing can narrow, not widen. A refresh request can pass scope with fewer scopes than the original token. Asking for one the original didn't have fails with invalid_scope.

The full flow is in OAuth 2.1 for apps and AI clients.

OpenID Connect scopes

These identify the person who approved your app. None of them opens a REST API endpoint.

Scope

What you get

Consent screen text

openid

An id_token in the token response.

Authenticate you and confirm your identity.

profile

The claims name, given_name, family_name and picture in the id_token and from userinfo.

Access your basic profile information (name, picture).

email

The claims email and email_verified.

Access your email address.

offline_access

Nothing extra. Every app gets a refresh token whether or not it asks for this scope; it's accepted for clients that always request it.

Stay connected, so you are not asked to sign in again each time its short-lived access expires.

Team notes need scope and access

Holding notes.read or notes.write isn't enough on its own. On every notes request, the person behind the credential (the creator of the API key, or the person who approved the OAuth app) must be an Owner, Admin, Editor or Translator of the help center. If they aren't, the request fails with 403, the code notes_forbidden and this message: "Editorial notes are visible only to team members who can access team comments in the dashboard. The account this credential authenticates as no longer has that access on this help center."

The design needs scope and access

Holding design.read or design.write isn't enough on its own either. On every design request, the person behind the credential must be able to edit the help center's design in the dashboard: an Owner, Admin or Editor. If they can't, the request fails with 403, the code design_forbidden and this message: "Only team members who can edit this help center's design in the dashboard (editors, admins and owners) can read or change it through the API. The account this credential authenticates as no longer has that access on this help center."

The custom domain and the embedding list need scope and role

Holding domain.manage or embed.manage isn't enough either. The person behind the credential must be an Owner or Admin of the help center, as in the dashboard, where only they can change its domain and which websites may embed it. An API key's creator always is: their keys stop working when they aren't. An OAuth token whose person is, for example, an Editor gets 403 with the code role_forbidden and their role.

When a scope is missing

A credential without the scope an endpoint needs gets 403 Forbidden with the body at the top of this page. The message always names the missing scope, for API keys and OAuth tokens alike. Retrying won't help:

  • With an API key, an Owner or Admin can add a setting the key lacks: Edit access on the key in Settings, under API keys, then Team notes, Design or Custom domain. A key's Read only or Read & write scope can't change, so a Read only key that needs a write scope is replaced by a new Read & write key. For domain.manage, a key's message goes on to name the setting: This action requires the domain.manage scope. An API key holds it only when it is a Read & write key and one of the help center's Owners or Admins has ticked "Allow managing the custom domain" for it in Settings > API keys.

  • With an OAuth token, send the person through authorization again with the scope added.

Two other errors look similar. 401 means the credential itself isn't valid. 403 with site_forbidden means the token doesn't reach the help center you named (see Choose which help center a request acts on). Every code is listed in Errors.

AI assistants and their first connection

When an AI assistant connects to the HelpCenter.io MCP server without credentials, the server's sign-in challenge asks for every scope one of its tools uses, and its metadata lists those and webhooks.manage, which no tool uses. An assistant that asks for fewer scopes than the challenge gets a token without the rest. The tools that need them are then refused with an error that names the missing permission, until the person connects the assistant again and approves it. Which scopes an assistant asks for is up to the assistant. See Connect an AI assistant to your help center.

Was this article helpful?