# Team notes

_Category: REST API reference_

Team notes are the private notes your team leaves on an article in the editor: a note on a highlighted passage, and the replies under it. Readers never see them. With the API, an integration or an AI agent can read the open notes on an article, answer them and resolve them, so feedback your team writes on a draft reaches the tool that revises it.

A typical loop: the agent reads the open notes, revises the article without touching the live version (see [Staged changes and versions](https://developers.helpcenter.io/content/staged-changes-api)), replies to each note with what it changed, and resolves the notes it has dealt with. A person still reviews and publishes.

Team notes are available on every plan. To see how your team writes them, see [Leave notes for your team](https://self.helpcenter.io/content/team-notes). Reader comments are a separate resource: see [Comments](https://developers.helpcenter.io/content/comments-api). Internal notes, the blocks your team types into the article text, have no endpoint, and article content you fetch through the API leaves them out.

## Endpoints

| Method and path | What it does | Access |
| --- | --- | --- |
| `GET /v1/articles/{articleId}/notes` | List the notes on an article. | Any API key with Team notes. OAuth: `notes.read` |
| `POST /v1/articles/{articleId}/notes/{noteId}/replies` | Reply to a note. | Read & write key with Team notes. OAuth: `notes.write` |
| `POST /v1/articles/{articleId}/notes/{noteId}/resolve` | Resolve a note. | Read & write key with Team notes. OAuth: `notes.write` |

There is no endpoint to create, edit or delete a note. A note belongs to a passage your team highlights in the editor, so it starts there.

## Get access

Access to team notes is granted separately from access to your content, and checked twice on every request.

- **The key must be created with Team notes.** When you create the key, turn on **Allow access to editorial notes** under **Team notes** (see [Create an API key](https://self.helpcenter.io/content/create-an-api-key)). A **Read only** key can then read notes; a **Read & write** key can also reply and resolve. An existing key can't be given access: create a new one. Without it, the API answers `403 Forbidden` with the code `insufficient_scope`.
- **OAuth apps** get `notes.read` and `notes.write` only when they ask for these scopes and the person connecting the app approves them (see [Scopes](https://developers.helpcenter.io/content/scopes)). `content.read` and `content.write` don't include them.
- **The person behind the credential must still be on the team.** Every request checks that the team member who created the key, or who approved the app, can open team notes on this help center in the dashboard: an Owner, Admin, Editor or Translator. If they left the team or lost that role, the API answers `403` with the code `notes_forbidden`, and a new key from a current team member fixes it.
- **Private articles stay private.** If that person can't open the article in the dashboard, because it is private and not shared with them or it sits in a private category they are not a member of, its notes answer `404 Not Found`. So do articles in the Trash.

## The note object

| Field | Type | Description |
| --- | --- | --- |
| `id` | integer | The note's ID. |
| `article_id` | integer | The article the note is on. |
| `parent_id` | integer or null | `null` for a note, the note's `id` for a reply. |
| `lang` | string | The article language the note was written in, for example `en`. Replies take the note's language. |
| `note` | string | The text, as plain text. |
| `anchor` | object | `quote` is the passage that was highlighted when the note was written, and `mark_id` the highlight's ID in the article. Use `quote` to find the text the note is about. Both are `null` on replies. |
| `author` | object or null | `id`, `name` and `avatar` (a URL, or `null`) of the team member. Never an email address. |
| `resolved` | boolean | `true` once the note is resolved. |
| `created_at`, `updated_at` | string | ISO 8601 in UTC, for example `2026-09-30T08:15:56+00:00`. |
| `replies` | array | On a note: its replies, oldest first, each a note object without `replies`. |
| `_links` | object | `reply` and `resolve`, each with the `method` and `url` to call. |

Replies carry `_links` too, but you reply to and resolve the note, not a reply: use the links of the note at the top of the thread. A reply's own links answer `404`.

## List the notes on an article

GET`/v1/articles/{articleId}/notes`

List the open team notes on an article, oldest first, each with its replies and the passage it is about.

| Parameter | Type | Description |
| --- | --- | --- |
| `include_resolved` | 1 or 0 | Default `0`: open notes only. `1` adds resolved notes, with their replies. `true` and `false` are refused with `422 Unprocessable Entity`. |
| `lang` | string | Only notes in this language. It is matched exactly and not checked against your languages, so a typo returns an empty list. |

Notes come oldest first, with every note on the article in one response. `meta.threads_count` is the number of notes returned, `meta.open_count` how many of them are open, and `meta.includes_resolved` echoes your choice. The top-level `article.title` is an object with every language of the title.

## Reply to a note

POST`/v1/articles/{articleId}/notes/{noteId}/replies`

Reply to a note. The response is the whole thread: the note with all its replies, yours last.

| Field | Type | Description |
| --- | --- | --- |
| `note` | string | Required. Plain text, 1 to 5000 characters. The field is `note`, not `comment`: a body with `comment` is refused with "A note body is required." |

- The reply is signed by the team member who created the key, or who approved the app, and takes the note's language.
- The response is the whole thread: the note, with every reply and yours last.
- Replying sends no email and doesn't change the article.
- Sending the same request twice adds two replies.
- A resolved note answers `404` with "That note is resolved. Re-open it in the dashboard to continue the thread." A resolved note can't be reopened, in the dashboard or over the API, so ask your team to start a new note in the editor.

## Resolve a note

POST`/v1/articles/{articleId}/notes/{noteId}/resolve`

Resolve a note and all its replies. There is no request body, and it cannot be undone.

Resolving closes the note and all its replies. Resolving a note that is already resolved answers `200` with "That note was already resolved.", so a retry is safe. It can't be undone, and resolved notes stay readable only through this API, with `include_resolved=1`.

Resolving through the API doesn't change the article. When your team resolves a note in the editor, the editor also removes the highlight from the text; after an API resolve, the passage stays highlighted and the highlight no longer opens a note.

## Errors

| Status | When |
| --- | --- |
| `401 Unauthorized` | The key or token is missing or not valid: `{"status": "unauthorized"}`. |
| `403 Forbidden` | `insufficient_scope`: the key was created without Team notes, a Read only key tried to reply or resolve, or an OAuth token lacks `notes.read` or `notes.write`. `notes_forbidden`: the person behind the credential can no longer open team notes on this help center. |
| `404 Not Found` | "Article not found." for an article you can't reach, "No such note on this article." for an unknown note or a reply's ID, or "That note is resolved." when you reply to a resolved note. |
| `422 Unprocessable Entity` | A parameter or field is not valid. `errors` names it. |
| `429 Too Many Requests` | Over the rate limit (see [Rate limits](https://developers.helpcenter.io/content/rate-limits)). Wait for the seconds in `Retry-After`. |

## Related

- [Comments](https://developers.helpcenter.io/content/comments-api)
- [API keys](https://developers.helpcenter.io/content/api-keys)
- [Scopes](https://developers.helpcenter.io/content/scopes)
