Read articles, collections, and changelog entries with the Notiondesk API

Read Notiondesk help center articles and collections as markdown, in any language, with sync state, and list changelog entries via the REST API.

7 min read

The Notiondesk API reads everything your help center publishes: every article and collection in any language, with its content as markdown, its publication status and its sync state, plus your published changelog entries. Use it to back up your help center, feed your content to another tool, or check which articles failed to sync.

The API reads content but never writes it. Your articles and collections stay in Notion: to change one, edit it in Notion and trigger a sync.

In the Notiondesk API, a collection is called a category.

MethodPathScopeDoes
GET/sites/{site_id}/articlesreadLists articles in one language
GET/sites/{site_id}/articles/{article_id}readReads one article with its markdown content
GET/sites/{site_id}/categoriesreadLists collections in one language, with their hierarchy
GET/sites/{site_id}/categories/{category_id}readReads one collection with its markdown content
GET/sites/{site_id}/changelogreadLists published changelog entries, newest first

Choose the language

Every route on this page takes an optional locale query parameter, such as ?locale=fr. Without it, the response uses the help center's default language. On the list routes, locale must be one of the languages the help center serves: the supported_locales of the help center. Read Support multiple languages in your Help Center to add languages.

List articles

curl "https://api.notiondesk.so/sites/c74781f6-1aea-4e17-ab23-bbb8b4d174b6/articles?page_size=100&locale=en" \
  -H "Authorization: Bearer $NOTIONDESK_API_KEY" \
  -H "nd-version: 2026-10-16"

The list includes every article in every status, drafts and archived articles too, in the order they were created. Page through it with page_size and cursor, as described in Paginate and version Notiondesk API requests.

{
  "object": "list",
  "data": [
    {
      "id": "1761580412",
      "title": "Connect your Notion workspace",
      "slug": "connect-your-notion-workspace",
      "status": "published",
      "categories": [
        {"id": "910000002", "name": "Connecting Notion", "slug": "connecting-notion", "locale": "en", "status": "published"}
      ],
      "tags": [{"name": "Setup", "slug": "setup"}],
      "locales_count": 2,
      "updated_at": "2026-10-18T14:39:03+00:00",
      "published_at": "2026-10-05T04:39:04+00:00",
      "locale": "en",
      "reading_time": 3,
      "views_count": 42,
      "reactions_percent": {"smiley": 50, "neutral_face": 25, "disappointed": 25},
      "source_notion_page_id": "3d5001d0-2470-8122-a1b2-c3d4e5f60789",
      "notion_article_page_url": "https://www.notion.so/3d5001d024708122a1b2c3d4e5f60789",
      "sync_in_progress": false,
      "sync_timeout": false,
      "sync_failed": false,
      "sync_error_code": null,
      "auto_translated": false
    }
  ],
  "has_more": true,
  "next_cursor": "OPAQUE_CURSOR"
}
FieldMeaning
idThe article identifier, used as article_id to read the article
title, slugThe article title and its path segment on the help center
statusdraft, published, review or archived. See How to control article visibility
categoriesThe collections the article belongs to, each with id, name, slug, locale and status
tagsThe article's tags, each with name and slug
locales_countHow many languages the article exists in
updated_at, published_atWhen the article last changed and when it was published
localeThe language of this item
reading_timeEstimated reading time, in minutes
views_countHow many times readers opened the article
reactions_percentEach reader reaction with its share of all reactions, in percent. The reaction names depend on your feedback style
source_notion_page_id, notion_article_page_urlThe Notion page the article syncs from, and the URL of this language's Notion page (null for an automatic translation)
sync_in_progress, sync_timeout, sync_failed, sync_error_codeWhether a sync of the article is running, and whether the last one timed out or failed, and why
auto_translatedWhether this language was produced by automatic translation
Note: Filter the results in your code on sync_failed: true to find every article whose last sync failed, then fix it in Notion and sync it again.

Read an article as markdown

curl "https://api.notiondesk.so/sites/c74781f6-1aea-4e17-ab23-bbb8b4d174b6/articles/1761580412?locale=en" \
  -H "Authorization: Bearer $NOTIONDESK_API_KEY" \
  -H "nd-version: 2026-10-16"
{
  "id": "1761580412",
  "type": "article",
  "title": "Connect your Notion workspace",
  "slug": "connect-your-notion-workspace",
  "text": "# Connect your Notion workspace\n\nOpen **Settings**, then **Notion**...",
  "url": "https://help.example.com/en/articles/connect-your-notion-workspace",
  "locale": "en",
  "last_updated": "2026-10-18T14:39:03+00:00",
  "category": {"id": "910000002", "title": "Connecting Notion", "slug": "connecting-notion"},
  "tags": ["setup"],
  "truncated": false,
  "author": {"name": "Ada Lovelace"},
  "status": "published",
  "content_available": true,
  "sync_in_progress": false,
  "sync_timeout": false,
  "sync_failed": false,
  "sync_error_code": null
}
FieldMeaning
typeAlways article
textThe article content as markdown. Empty when no content is stored yet
truncatedtrue when text was cut at 200,000 bytes. The cut always falls on a whole character
content_availableWhether Notiondesk holds content for this language yet
urlThe article's public address
categoryThe article's main collection: id, title and slug
tagsThe slugs of the article's tags
authorThe article author: name

Every status is readable, so you can read a draft before you publish it. An article with no translation in the requested locale answers 404 not_found.

List collections

curl "https://api.notiondesk.so/sites/c74781f6-1aea-4e17-ab23-bbb8b4d174b6/categories?page_size=100" \
  -H "Authorization: Bearer $NOTIONDESK_API_KEY" \
  -H "nd-version: 2026-10-16"

Each item is a collection in the requested language, in the order collections were created:

{
  "id": "910000001",
  "name": "Getting Started",
  "slug": "getting-started",
  "updated_at": "2026-10-18T14:39:12+00:00",
  "locale": "en",
  "is_parent": true,
  "source_notion_page_id": "5d5001d0-2470-8122-a1b2-c3d4e5f60789",
  "notion_category_page_url": "https://www.notion.so/5d5001d024708122a1b2c3d4e5f60789",
  "sync_in_progress": false,
  "sync_timeout": false,
  "sync_failed": false,
  "sync_error_code": null,
  "parent_ids": [],
  "children_ids": ["910000002"],
  "locales_count": 2,
  "status": "published",
  "auto_translated": false
}

Rebuild your collection tree with three fields:

FieldMeaning
is_parenttrue for a collection at the top of the hierarchy
parent_idsThe collections directly above this one
children_idsThe collections directly below this one

The list carries no article counts. To count a collection's articles, list the articles and group them by categories. Learn how collections organize your help center in Use collections to organize your articles.

Read a collection

curl "https://api.notiondesk.so/sites/c74781f6-1aea-4e17-ab23-bbb8b4d174b6/categories/910000001?locale=en" \
  -H "Authorization: Bearer $NOTIONDESK_API_KEY" \
  -H "nd-version: 2026-10-16"

The response has the same shape as an article: type is category, title, slug, url, status, the sync fields, and text with the collection's own content as markdown, empty when it has none.

List changelog entries

curl "https://api.notiondesk.so/sites/c74781f6-1aea-4e17-ab23-bbb8b4d174b6/changelog?page_size=50&locale=en" \
  -H "Authorization: Bearer $NOTIONDESK_API_KEY" \
  -H "nd-version: 2026-10-16"

The changelog lists the published articles filed under your changelog collections, newest first. Set it up with Setting up changelogs on your help center.

{
  "object": "list",
  "data": [
    {
      "id": "article:1761497350",
      "title": "Multilingual sync is now available",
      "slug": "multilingual-sync-is-now-available",
      "text": "Help centers on the Enterprise plan can now sync every configured locale in a single run instead of one language at a time.",
      "published_at": "2026-10-13T09:12:44+00:00",
      "last_updated": "2026-10-18T14:39:03+00:00",
      "tags": [],
      "url": "https://help.example.com/en/changelogs",
      "locale": "en"
    }
  ],
  "has_more": true,
  "next_cursor": "OPAQUE_CURSOR"
}
FieldMeaning
idarticle: followed by the entry's article id. Remove the prefix to read the full entry with the article route
textThe entry's plain text, usually an excerpt of about 30 words
published_at, last_updatedWhen the entry was published and when it last changed
tagsThe slugs of the entry's tags
urlYour changelog page in this language

Good to know:

  • An entry appears only when its changelog collection is published in the requested language.
  • On a help center that uses guest accounts, the list shows only the entries every reader can see.
  • The list reaches at most the 1,000 newest entries. Past that, has_more is false even when older entries exist.
  • Rarely, during a temporary service issue, a list read can skip or repeat an entry. Read it again later for a complete list.

Errors

StatuscodeWhen
400validation_errorpage_size is outside 1 to 100, the cursor is invalid, locale is not a language the help center serves (lists) or is not 2 to 10 characters (single reads), or the query has an unknown parameter
403insufficient_scopeThe key lacks the read scope
403permission_deniedChangelog only: the changelog is turned off or not included in your plan, or the help center's analytics are turned off
404not_foundThe help center, article or collection does not exist in your workspace, it has no translation in locale, or the changelog is on but has no changelog collection

Every route can also answer invalid_version, authentication_error, rate_limited and internal_error. See Handle Notiondesk API errors, rate limits, and retries.

Common questions

Can I create or edit articles with the Notiondesk API?

No. Notion is the source of truth for your content. Edit the article in Notion, then trigger a sync with the API or wait for scheduled sync.

Does the article list include drafts?

Yes. The list and the read route include every status: draft, published, review and archived. Filter the results in your code on status to keep only published articles.

How do I export every article as markdown?

List the articles, then read each one by its id. The examples article has a complete backup script.

What does truncated: true mean?

The article's markdown is longer than 200,000 bytes, so text holds the first 200,000 bytes, cut on a whole character.

Why is notion_article_page_url empty for some languages?

That language was produced by automatic translation, so it has no Notion page of its own.

What's next

Related articles

Was this page helpful?

Still need help? Ask us