Skip to main content
Every article returned by the API conforms to the shape below. List endpoints return a lightweight projection — content is omitted and tag_names is added — so list payloads stay compact.

Identifiers

object
string
required
Always "article".
id
uuid
required
Server-generated identifier. Stable for the lifetime of the article.
slug
string
required
URL-safe handle. Lowercase letters, numbers, and dashes only (/^[a-z0-9-]+$/), maximum 200 characters. Unique per organization (and per-language for translations) — reusing a slug already taken by another article in your org is rejected. You set this on create; you can change it via PATCH, but inbound deep links to the old slug will 404.

Content

title
string
required
Human title. Indexed for search.
content
string
required
The source body — markdown is the canonical input. External image URLs are rehosted on write (see overview). Omitted from list payloads.
content_plain
string | null
Plain-text mirror of content used for retrieval, embeddings, and previews. Derived server-side from the markdown you send — you don’t supply it, and any value sent in the request body is ignored.
language
string
required
ISO 639-1 two-letter language code for the primary body. Translations carry their own language on the satellite resource.
Supported codes: en, ja, de, fr, ko, zh, nl, sv, es, it, no. Sending any other value returns invalid_payload. Defaults to en when omitted on create.

Status & visibility

status
enum
required
Lifecycle state. One of:
  • draft — not indexed, not visible
  • published — indexed and surfaced according to visibility
  • unpublished — taken down from public surfaces; embeddings removed
  • archived — soft-deleted; not indexed, hidden from UI
See Publishing & indexing for transition semantics.
visibility
enum
required
Who can see the article when status === "published". One of:
  • public — KB site visitors and chatbots
  • internal — authenticated org agents only
  • chatbot_only — surfaced to chatbots; not rendered in the KB UI
published_at
datetime | null
ISO-8601 timestamp of the first transition to published. Auto-set by the server on that first publish and sticky thereafter — it is not re-stamped on later re-publishes, and stays set even after the article is unpublished or archived. null until the article has been published at least once.

Indexing

indexing_status
enum
required
State of the embedding pipeline for this article. One of:
  • not_started — never enqueued
  • pending — queued, not yet picked up
  • processing — embedding in flight
  • indexed — embeddings written; article searchable
  • failed — pipeline error; the article is not searchable
Poll this field or subscribe to the article.indexed / article.indexing_failed webhooks to detect completion. The underlying error string is not surfaced via the API.
indexed_at
datetime | null
ISO-8601 timestamp of the most recent successful index write. null until the first index completes.

Categorization

knowledge_base_id
uuid | null
The knowledge base this article belongs to. Required on create — every new article must be scoped to a knowledge base. The id must belong to your organization; a foreign or nonexistent knowledge_base_id is rejected. May be null on older articles created before this was enforced.
category_id
uuid | null
The category (folder) this article sits inside. null for articles that live at the root of a knowledge base. The id must belong to your organization; a foreign or nonexistent category_id is rejected. See Article Categories.

Timestamps

created_at
datetime
required
ISO-8601 timestamp of insertion.
updated_at
datetime
required
ISO-8601 timestamp of the most recent write.

List projection

List endpoints (GET /articles) drop content and add tag_names — the resolved tag names attached to the article. Use the detail endpoint to fetch the full body.
tag_names
string[]
Resolved names of every tag assigned to the article. Only present on list responses.
Relations are returned by GET /articles/{id}/relations. Each entry carries the related article’s id and resolved title — slugs aren’t included; use GET /articles/{relatedId} if you need the full record.
{
  "object": "article_relation",
  "article_id": "8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e",
  "related_article_id": "5d694e14-5440-4f5d-9e8a-7c3b2a1d0f9e",
  "related_title": "How exchanges work"
}

Example

{
  "object": "article",
  "id": "8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e",
  "knowledge_base_id": "2c1b4a9f-7e8d-4a3c-9b1f-6e5d4c3b2a1f",
  "category_id": "5d694e14-5440-4f5d-9e8a-7c3b2a1d0f9e",
  "title": "Returns & refunds",
  "slug": "returns-and-refunds",
  "content": "## Our policy\n\nReturns are accepted within 30 days of delivery, no questions asked. Use the returns portal to start the process.\n\n<img data-asset-id=\"a7f3c2e1-9b4d-4e8a-bc15-2d6f8a0e3c91\" alt=\"Returns portal screenshot\">",
  "content_plain": "Our policy Returns are accepted within 30 days of delivery, no questions asked. Use the returns portal to start the process. Returns portal screenshot",
  "status": "published",
  "visibility": "public",
  "language": "en",
  "indexing_status": "indexed",
  "indexed_at": "2026-05-22T14:02:11+00:00",
  "published_at": "2026-05-22T14:01:58+00:00",
  "created_at": "2026-05-22T13:59:01+00:00",
  "updated_at": "2026-05-22T14:01:58+00:00"
}

List example

{
  "object": "list",
  "data": [
    {
      "object": "article",
      "id": "8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e",
      "knowledge_base_id": "2c1b4a9f-7e8d-4a3c-9b1f-6e5d4c3b2a1f",
      "category_id": "5d694e14-5440-4f5d-9e8a-7c3b2a1d0f9e",
      "title": "Returns & refunds",
      "slug": "returns-and-refunds",
      "content_plain": "Our policy Returns are accepted within 30 days...",
      "status": "published",
      "visibility": "public",
      "language": "en",
      "indexing_status": "indexed",
      "indexed_at": "2026-05-22T14:02:11+00:00",
      "published_at": "2026-05-22T14:01:58+00:00",
      "created_at": "2026-05-22T13:59:01+00:00",
      "updated_at": "2026-05-22T14:01:58+00:00",
      "tag_names": ["policy", "customer-facing"]
    }
  ]
}