External KB API

Atender exposes a stable v1 API at /api/v1/kb/* for managing your Knowledge Base from outside the in-app editor. Use it for doc-as-code pipelines, automated content imports, or sync with another system.

5 min read

External KB API

Most of Atender’s Knowledge Base is managed in the in-app editor. But for teams that prefer doc-as-code workflows — the same way they manage application code — Atender exposes a stable, scope-gated v1 API at /api/v1/kb/*. You authenticate with a tenant API key, you call the endpoints, and your KB stays in sync with whatever upstream source of truth you keep.

This is how Atender keeps its own help center current. Articles live as markdown in a vault, a small Python script reads them on every change, and /api/v1/kb/* creates or updates them in the live KB. Embeddings rebuild server-side automatically.

When to use the API

Reach for the API when:

  • Your articles are authored elsewhere — in a Git repo, a CMS, a spreadsheet, another help center. You want a sync, not a copy-paste.
  • You want articles versioned and reviewed in pull requests. Markdown in a Git repo gives you diff, branch, review, merge — the same review discipline as code.
  • You’re migrating from another help center. A one-time bulk import via the API is faster than recreating articles in the UI.
  • You’re building a content pipeline. Generate articles from product specs, sync from a spec repository, regenerate when source data changes.

If your team writes content in the in-app editor and that flow is working, you don’t need the API.

What the API can do

The v1 surface covers the operations a content pipeline needs:

  • Articles — List, get, create, update, delete, publish, mark-reviewed
  • Categories — List, get, create, update, delete
  • Subcategories — List, create, update, delete
  • Tags — List, create, update, delete
  • Search — Run a keyword query against article titles, content, summaries and keywords

The endpoints accept JSON. Articles can be created or updated with full content, summaries, keywords, custom metadata (uxPath, videoUrl, etc.), and category assignments.

Public article listings include categorySlug and publicUrl for each article. publicUrl respects your custom Knowledge Base domain when one is configured; otherwise, it falls back to the Atender /knowledge/<tenant>/<category>/<article> path.

What the API can’t do (yet)

  • Creating roles — role tagging itself is on the v1 surface: GET /api/v1/kb/roles lists the roles, and roleIds on article create/update accepts role UUIDs or role slugs. What isn’t exposed is creating, renaming or deleting the roles themselves — do that in the in-app editor.
  • Sections — managing sections via API isn’t supported on v1 yet. Use the in-app editor.
  • Knowledge Base settings — branding, layout, theme — aren’t on the v1 API. Configure them in the in-app editor.
  • Translations — translation syncs are started manually in the in-app editor, not automatically when you publish. There’s no v1 API to trigger them, and direct write of translated content isn’t supported on v1 yet.
  • Handbook procedures — Handbook is exposed through its own supported /api/v1/handbook* endpoints for procedures, categories, and access rules. KB article endpoints remain under /api/v1/kb/*. If a tenant has multiple Handbooks, callers must pass and use the correct handbook partition for the procedures they are managing.

Authentication

Every v1 KB call is authenticated with a tenant API key. Generate one in Settings → API & MCP:

  1. Click Create Key.
  2. Pick scopes: knowledge:read (for read-only access) and/or knowledge:write (for create/update/delete).
  3. Optionally set an end date if the key should stop working automatically.
  4. Name the key something obvious — “doc-as-code pipeline”, “migration script”, “github-actions-sync”.
  5. Click Create key. Copy the key — it’s shown once, then hidden.
  6. Set it as Authorization: Bearer <key> on each request.

API keys come in two prefixes:

  • sa_live_* — Production keys. Make real changes to the live KB.
  • sa_test_* — Sandbox keys. For development and testing.

API keys work until you revoke them, unless you set an end date. When a key reaches its end date, it stops authenticating, but the rest of the workspace keeps running. Settings → API & MCP shows each key’s stop date under the key name. Rotate or revoke keys there when team members leave or you suspect compromise.

The shape of an article

An article in the API has these fields:

{
  "title": "How to update your payment method",
  "slug": "update-payment-method",
  "summary": "Open your account settings, go to Billing, click Change.",
  "content": "...full markdown body...",
  "categoryId": "cat_abc123",
  "subcategoryId": null,
  "status": "published",
  "difficulty": "beginner",
  "estimatedMinutes": 2,
  "keywords": ["payment", "credit card", "billing"],
  "customMetadata": {
    "uxPath": "Account → Billing → Payment methods"
  }
}

The customMetadata field is an open jsonb bucket — you can stash any structured data your downstream consumers need. Atender’s own pipeline puts uxPath, type, related[], and sourcePath here. The public read API exposes customMetadata so the Agent Stack and other downstream consumers can read it.

How idempotency works

The v1 endpoints do not upsert. POST /api/v1/kb/articles always creates: the slug is generated from the title, and if that slug is already taken the new article gets a numeric suffix (update-payment-method-1) — so sending the same article twice leaves you with two. Categories (slug from name), subcategories (slug scoped to categoryId) and tags behave the same way. A pipeline that re-runs has to do the “is this a create or an update?” branching itself: look the article up with GET /api/v1/kb/articles/by-slug/{slug} and PATCH /api/v1/kb/articles/{id} when it already exists.

Rate limits

The API has standard rate limits — generous for normal use, reasonable for bulk imports. If you’re bulk-importing a few thousand articles, expect to add backoff between calls. The error response includes a Retry-After header when limits are hit.

A doc-as-code pattern

The pattern Atender’s own help center uses:

  1. Articles are markdown files in a Git repo, with frontmatter for metadata.
  2. A small Python script reads each file, calls /api/v1/kb/categories to ensure the category exists, then creates the article with POST /api/v1/kb/articles — or PATCHes the existing one when the slug is already taken.
  3. Embeddings rebuild server-side when the article is created or its content changes.
  4. Translations are synced separately, from the in-app editor.

If that’s the shape you want, see Push articles via API for a working example.

Where to go next

Tags

Ai FeaturesAdvancedConcept