Next CapNext Cap

Helpdesk Content API

Pull your help center's collections and articles — every language included — into your own database and build a fully custom help site on your own domain. Enterprise-only.

Overview

The Helpdesk Content API exposes everything your help desk contains — help centers, the collection tree, and every article in every language — as raw JSON. Pull the content into your own database and render a fully custom help site with your own design, on your own domain. Content endpoints are read-only (GET); authoring stays in the dashboard, and the hosted help center keeps working unchanged alongside it.

Enterprise plan only. Keys on any other plan receive 403 on every endpoint on this page. Organizations below Enterprise use the hosted help center.

Authentication

Use your existing Data API key from Settings → API Keys (the same sk_live_ key the External Data API uses), passed in the X-Api-Key header or as a Bearer token.

Authenticationbash
curl -H "X-Api-Key: sk_live_YOUR_KEY" \
https://api.nextcap.ai/api/v1/external/help/centers
The key is org-private and can read drafts as well as published content. Treat it like a database credential: server-side only, never in a browser bundle or mobile app.

Localized Fields

Localized fields (title, summary, description, body) are locale maps like { "en": "…", "fr": "…" } — one response carries every translation, and article body values are Markdown. To match the hosted help center, treat an article as translated into a locale only when both title[locale] and body[locale] are non-empty, and fall back to the center's default_locale otherwise.

Help Centers

GET/external/help/centersAPI Key

List every help center in your organization (an org can run several, e.g. one per widget).

Response — 200 OKjson
{
"data": [
{
"id": "uuid",
"slug": "acme-support",
"name": "Acme Support",
"description": "How to get the most out of Acme",
"scope": "agent",
"default_locale": "en",
"locales": ["en", "fr", "es"],
"primary_widget_id": "uuid",
"custom_domain": "help.acme.com",
"created_at": "2026-05-01T09:00:00.000Z",
"updated_at": "2026-07-01T14:30:00.000Z"
}
]
}
GET/external/help/centers/:centerIdAPI Key

Get a single help center by ID.

Collections & Categories

GET/external/help/centers/:centerId/collectionsAPI Key

The full collection tree as a flat list. Rebuild the hierarchy via parent_id (null = top level) and order siblings by position.

Response — 200 OKjson
{
"data": [
{
"id": "uuid",
"help_center_id": "uuid",
"parent_id": null,
"slug": "billing",
"title": { "en": "Billing", "fr": "Facturation" },
"description": { "en": "Plans, invoices, refunds" },
"icon": "RiBankCardLine",
"position": 0,
"created_at": "2026-05-01T09:00:00.000Z",
"updated_at": "2026-06-20T11:00:00.000Z"
}
]
}
GET/external/help/centers/:centerId/categoriesAPI Key

Legacy second-level grouping under collections. Empty for most organizations — nested sub-collections replaced it.

Articles

GET/external/help/centers/:centerId/articlesAPI Key

Paginated article list, ordered by updated_at ascending for stable sync walks.

statusstring

published (default), draft, archived, or all.

collection_idUUID

Only articles filed under this collection.

category_idUUID

Only articles filed under this category.

updated_afterISO 8601

Incremental sync cursor. Inclusive (updated_at >= cursor), so boundary rows re-deliver instead of skipping — upsert by id.

updated_beforeISO 8601

Upper bound on updated_at.

include_deletedboolean

Include soft-deleted articles (deleted_at set) so you can tombstone local rows. Default false.

pageinteger

Page number (default: 1).

per_pageinteger

Items per page, 1–100 (default: 20).

Response — 200 OKjson
{
"data": [
{
"id": "uuid",
"help_center_id": "uuid",
"collection_id": "uuid",
"category_id": null,
"slug": "getting-started",
"title": { "en": "Getting started", "fr": "Premiers pas" },
"summary": { "en": "Set up your account in five minutes" },
"body": { "en": "## Welcome\n\nFirst, …", "fr": "## Bienvenue\n\n…" },
"cover_image_url": null,
"seo_title": null,
"seo_description": null,
"og_image": null,
"tags": ["onboarding"],
"status": "published",
"visibility": "both",
"position": 0,
"author": { "name": "Jane Doe", "avatar_url": "https://…" },
"published_at": "2026-07-01T10:00:00.000Z",
"created_at": "2026-06-20T09:00:00.000Z",
"updated_at": "2026-07-02T14:30:00.000Z",
"deleted_at": null
}
],
"meta": { "page": 1, "per_page": 20, "total": 58, "total_pages": 3 }
}
GET/external/help/centers/:centerId/articles/:articleIdAPI Key

Get a single article by ID. Soft-deleted articles are returned with deleted_at set, so a webhook consumer reacting to help_article.deleted never hits a 404.

Public visibility on the hosted help center means status = published and visibility of both or helpcenter_only — mirror that filter for parity (widget_only articles belong to the in-chat Help tab, hidden to neither surface).

Keeping Your Copy in Sync

  1. Backfill — page through articles?status=all&per_page=100&page=N until meta.total_pages, plus one call each for collections and categories.
  2. Incremental — remember the newest updated_at you have seen and poll with status=all&include_deleted=true&updated_after=<cursor>. The boundary is inclusive, so upsert by id and repeats are harmless.
  3. Real time — subscribe to the help_* events on the Webhooks page and re-fetch the entity named in the payload. Treat webhooks as the change notification and these GET endpoints as the source of truth.

Webhook Events

Thirteen events cover the content graph: help_center.*, help_collection.*, help_category.* (created / updated / deleted), plus help_article.created / updated / published / deleted. help_article.published fires on the draft → published transition and is the typical "rebuild my public site" trigger. Setup, payload format, signature verification, and retry behavior are on the Webhooks page.

Engagement Beacons (Optional)

The hosted help center records page views and "was this helpful?" votes that power the dashboard's Insights. Your custom frontend can keep that data flowing through the same public, unauthenticated beacons — they are browser-safe and need no API key.

POST/public/help/:centerId/articles/:slug/viewNone

Record one page view. Returns 204.

localestring

Locale the article was read in.

sessionIdstring

Random per-visitor session identifier.

referrerstring

Optional referrer URL.

POST/public/help/:centerId/articles/:articleId/feedbackNone

Record a helpfulness vote.

ratingstringrequired

positive, neutral, or negative.

commentstring

Optional free-text comment.

localestring

Locale the article was read in.

sessionIdstring

Random per-visitor session identifier.