Kerabie
API Reference

Knowledge Base

Manage articles via the authenticated API, and read published articles from the public widget-facing endpoints.

Kerabie exposes two separate knowledge base surfaces:

  • /v1/kb/*: authenticated CRUD for your own articles, using an API key (see Authentication). Available on every plan.
  • /public/kb/*: read-only, published-only articles for embeddable consumers (the chat widget, the React Native helpdesk package). No API key; scoped by the widget key your embed already uses.

Every published article is also fed automatically into the AI chatbot as answer context, so anything you publish here can be used to answer visitor questions without extra setup.

Authenticated API (/v1/kb)

List articles

GET /v1/kb/articles
Authorization: Bearer ker_live_abc123...

Query params

ParamTypeDescription
searchstringFull-text search across title and content
categorystringFilter by category
pagenumberPage number (default: 1)
limitnumberResults per page (default 20)

Response

{
  "data": [
    {
      "id": 12,
      "title": "How to reset your password",
      "content": "<p>Go to the login page and click Forgot Password...</p>",
      "type": "faq",
      "category": "Account",
      "status": "published",
      "imageUrl": "https://cdn.kerabie.com/knowledge-base/42/12-1234.jpg",
      "views": 245,
      "helpfulPct": 92,
      "votes": 30,
      "aiCitations": 88,
      "createdAt": "2026-03-15T10:00:00Z",
      "updatedAt": "2026-03-15T10:00:00Z"
    }
  ],
  "meta": { "total": 43, "page": 1, "limit": 20, "hasMore": true }
}

content is HTML: the dashboard editor, the chat widget and the apps all store and show it that way. Plain text sent through the API or a CSV import is shown as-is, so send HTML (<p>…</p>) for paragraphs and formatting.

helpfulPct is the share of widget visitors who answered "Was this helpful?" with yes, and stays null until at least 3 have voted. aiCitations counts the AI chatbot answers that cited the article.


Stats

GET /v1/kb/stats
{ "total": 43, "published": 38, "drafts": 5, "views": 12840, "top": { "title": "How to reset your password", "views": 1240 }, "categories": ["Account", "Billing"] }

Insights: what to write or fix next

GET /v1/kb/insights
{
  "mostViewed": [{ "id": 12, "title": "How to reset your password", "views": 1240, "pct": 100 }],
  "gaps": [{ "question": "okta sso", "count": 23 }],
  "lowestRated": [{ "id": 7, "title": "Do you offer refunds?", "helpfulPct": 74, "votes": 12 }],
  "stale": [{ "id": 9, "title": "Connect WhatsApp", "age": "4 months" }]
}

gaps are customer questions in the last 30 days that the AI had no article to answer from. lowestRated needs at least 3 votes per article. stale lists published articles not updated in 90 days. Cached for a few minutes.


Get an article

GET /v1/kb/articles/:id

Create an article

POST /v1/kb/articles
{
  "title": "How to reset your password",
  "content": "<p>Go to the login page...</p>",
  "category": "Account",
  "type": "faq",
  "status": "published"
}

type is one of faq | article | news | information (default article). status is one of draft | published | archived (default published).


Update an article

PATCH /v1/kb/articles/:id

Accepts the same fields as create; only send what's changing.


Delete an article

DELETE /v1/kb/articles/:id

Public, widget-facing API (/public/kb)

No API key. Authenticate with your widget key, either as an x-widget-key header or a widgetKey query param, the same key your chat widget embed already uses.

List published articles

GET /public/kb/articles?widgetKey=wk_yourorg_abc123&search=refund

Query params

ParamTypeDescription
searchstringFull-text search
categorystringFilter by category
typestringFilter by faq | article | news | information
page / limitnumberPagination

Returns only status: "published" articles, the same { data, meta } shape as the authenticated list.

Get a published article

GET /public/kb/articles/:id?widgetKey=wk_yourorg_abc123

Increments the article's view count.

Rate an article

POST /public/kb/articles/:id/feedback?widgetKey=wk_yourorg_abc123
{ "helpful": true }

The "Was this helpful?" vote from the widget and the React Native package. A visitor can vote up to 3 times per article per day (429 after that); 404 for a draft or unknown article. Votes feed the helpfulness shown in the dashboard.

The chat widget's built-in search screen calls a simpler variant of this, GET /public/knowledge-base?widgetKey=...&q=..., returning { items: [...] }; that's what actually powers the widget UI. The /public/kb/* endpoints above exist for consumers that need pagination or a single-article lookup, like the React Native helpdesk package.

Importing content

Import, crawl, and refine are dashboard actions, authenticated with your logged-in session (not an API key); they live under /knowledge-base/*, not /v1/kb/*. They're documented here because they're part of the same feature, not because they're callable with a ker_live_ key.

Three ways to get content into the knowledge base beyond typing it manually; all AI-assisted and gated by plan (see below).

Upload a document

POST /knowledge-base/import/document
Content-Type: multipart/form-data

Upload a file (max 5MB). Everything becomes drafts for you to review.

  • .csv: one article per row, no AI step and no AI quota used. Use a header row with title (or question) and content (or answer); category and type are optional. Up to 500 rows; rows that can't be used are returned in skipped with their row number.
  • .docx, .md, .txt, .pdf, .json: AI structures the text into one or more draft articles.

Crawl a website

A two-step flow: you pick which pages get imported before anything runs:

POST /knowledge-base/crawl/discover
{ "url": "https://docs.yoursite.com" }

Returns candidate pages found on that domain (from on-page links and, when present, sitemap.xml):

{ "pages": [{ "url": "https://docs.yoursite.com/faq", "title": "FAQ" }] }
POST /knowledge-base/crawl/import
{ "urls": ["https://docs.yoursite.com/faq"] }

Runs as a background job (crawling and AI structuring can take a while for several pages) and responds immediately with a job ID:

{ "jobId": "42" }

Poll for completion:

GET /knowledge-base/jobs/:jobId
{ "status": "succeeded", "result": { "imported": 4, "items": [...] } }

Refine an article with AI

POST /knowledge-base/:id/refine

Streams the refined content back as Server-Sent Events (data: { "delta": "..." } chunks, ending with data: { "done": true }) and saves the result once the stream completes. AI-generated text never uses em dashes.

Plan limits

Import, crawl, and refine share one monthly AI-operations budget per organisation, plus crawl has its own per-run page cap:

PlanAI ops / monthPages per crawl
FreeNot availableNot available
Basic1020
Pro50100
EnterpriseUnlimitedUnlimited

Exceeding either limit returns a 403 with a message naming the limit.