Skip to content

REST API Knowledge

Ed Mozley edited this page Jul 3, 2026 · 1 revision

πŸ“š REST API: Knowledge

The complete usage guide for the Knowledge Base module of the REST API β€” every URL, method, parameter and response shape. Mirrors the interactive documentation at System β†’ API β†’ Documentation (with its live "Try it" tester).

Note

New to the API? The basics table on REST API: Tickets covers base URL, authentication, the response envelope, error codes, rate limits and PATCH semantics β€” identical across all modules.

What's distinctive about Knowledge:

🌍 Install-wide The knowledge base has no company concept β€” a key's company scope does not restrict it (matches the UI).
🏷️ Tags, not categories The module's only taxonomy is free-text tags β€” send them as an array of names and they're created on the fly.
♻️ Recycle bin, not trash-forever DELETE archives; articles restore from the bin; permanent deletion only works from the bin and the bin auto-purges on the module's retention setting β€” all exactly like the UI.
🧠 Embeddings stay warm If the module's OpenAI key is configured, creating or updating an article via the API regenerates its search embedding (best-effort, like the UI) β€” so the AI chat and vector search find API-written articles too.
πŸ‘€ View counts are opt-in Reading an article via the API does not bump view_count unless you pass ?count_view=true β€” a deliberate divergence so sync jobs and chatbots don't inflate the stats the review screens use.

Warning

Article bodies are TinyMCE-style HTML stored verbatim β€” the product performs no server-side sanitisation (the UI behaves identically). Only send trusted HTML, and sanitise on render if you display articles outside FreeITSM.


πŸš€ Quick start

Sync a runbook from your docs pipeline into the KB:

B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_…"

curl -X POST "$B/knowledge/articles" -H "$K" -H "Content-Type: application/json" -d '{
  "title": "How to reset your VPN token",
  "body_html": "<h2>Steps</h2><ol><li>Open the portal</li><li>Click reset</li></ol>",
  "tags": ["vpn", "how-to"],
  "next_review_date": "2026-12-01"
}'

Published immediately, tagged, embedded for AI search, and on the review calendar. πŸ“–


πŸ“š Articles

🟒 GET /knowledge/articles β€” list / search Β  πŸ”‘ knowledge.read

Published articles (or the recycle bin with archived=true). Each list item carries a 300-character plain-text preview instead of the full body.

Parameter Description
q πŸ” Keyword search across title and body (the module's own search β€” no AI required)
tag Only articles carrying this tag (exact name)
author_id / owner_id Filter by author or owning analyst
review overdue Β· upcoming (next 30 days) Β· none β€” the review screen's exact windows
modified_since ISO 8601 β€” the sync-job filter
archived true lists the recycle bin (and runs the same retention auto-purge the UI runs on opening it)
sort modified_at (default, desc), created_at, title, view_count, next_review_date, id β€” prefix - for descending
page / per_page Pagination β€” default 1 / 25, max 100

πŸ”΅ POST /knowledge/articles β€” create Β  πŸ”‘ knowledge.create

Articles are created published immediately β€” the product has no draft workflow. Returns 201 with the full article.

Field Required Description
title βœ… Max 255 characters
body_html The article content (HTML)
tags Array of tag names β€” created on the fly, e.g. ["vpn", "how-to"]
owner_id Owning analyst (drives the review cycle)
next_review_date YYYY-MM-DD

🟒 GET /knowledge/articles/{id} β€” get one Β  πŸ”‘ knowledge.read

The full article with body_html, tags, version number and a has_embedding flag. Add ?count_view=true to count the read as a view (UI parity β€” otherwise machine reads leave the stats alone).

{ "data": { "id": 26, "title": "How to reset your VPN token",
    "tags": ["how-to", "vpn"],
    "author": { "id": 1, "name": "Administrator" }, "owner": null,
    "version": 2, "view_count": 41, "next_review_date": "2026-12-01",
    "is_archived": false,
    "created_at": "2026-07-03T12:18:31Z", "modified_at": "2026-07-03T12:19:07Z",
    "body_html": "<h2>Steps</h2><ol>…</ol>", "has_embedding": true } }

🟠 PATCH /knowledge/articles/{id} β€” update Β  πŸ”‘ knowledge.update

Field Notes
title / body_html New content
tags Replaces the article's tag set
owner_id / next_review_date Review-cycle fields (null clears)
save_as_version true = snapshot the current content into the version history first, then bump the version number β€” exactly the UI's "Save as new version"

The search embedding is refreshed automatically after every create/update (when the OpenAI key is configured). An archived article answers 409 β€” restore it first.

πŸ”΄ DELETE /knowledge/articles/{id} β€” move to the recycle bin Β  πŸ”‘ knowledge.delete

Soft-archives the article. It stays restorable until the module's retention window (knowledge_recycle_bin_days, default 30; 0 = keep forever) purges it.

πŸ”΅ POST /knowledge/articles/{id}/restore β€” restore Β  πŸ”‘ knowledge.restore

Brings an archived article back, exactly as it was.

πŸ”΄ DELETE /knowledge/articles/{id}/permanent β€” permanently delete Β  πŸ”‘ knowledge.purge

Warning

Hard-deletes the article, its version history and its tag links (orphaned tags are cleaned up). Only allowed once the article is already in the recycle bin β€” same guard as the UI. 409 otherwise.


πŸ• Version history

Snapshots are only created when a save says so (save_as_version here, "Save as new version" in the UI) β€” routine edits update in place.

🟒 GET /knowledge/articles/{id}/versions Β  πŸ”‘ knowledge_versions.read

The saved snapshots β€” version number, title at the time, who saved it, when β€” newest first.

🟒 GET /knowledge/articles/{id}/versions/{version} Β  πŸ”‘ knowledge_versions.read

One snapshot including its full body_html β€” everything needed to diff or roll back (roll back by PATCHing the old body onto the article).


🏷️ Tags

🟒 GET /knowledge/tags Β  πŸ”‘ reference.read

Every tag with its published-article count:

{ "data": [ { "id": 3, "name": "how-to", "article_count": 12 },
            { "id": 7, "name": "vpn", "article_count": 4 } ] }

πŸ§ͺ Worked example: docs-pipeline sync

A CI job that keeps the KB in step with a docs repo (knowledge: read, create, update + reference: read):

B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_…"

# Upsert-by-title: find the article, PATCH it (with a version snapshot) or create it
ID=$(curl -s -H "$K" "$B/knowledge/articles?q=$(python3 -c 'import urllib.parse;print(urllib.parse.quote("How to reset your VPN token"))')" | jq -r '.data[0].id // empty')
if [ -n "$ID" ]; then
  curl -s -X PATCH "$B/knowledge/articles/$ID" -H "$K" -H "Content-Type: application/json" \
    -d "{\"body_html\": $(jq -Rs . < rendered.html), \"save_as_version\": true}"
else
  curl -s -X POST "$B/knowledge/articles" -H "$K" -H "Content-Type: application/json" \
    -d "{\"title\": \"How to reset your VPN token\", \"body_html\": $(jq -Rs . < rendered.html), \"tags\": [\"vpn\"]}"
fi

And the review-cycle report β€” what's overdue for review, and who owns it?

curl -s -H "$K" "$B/knowledge/articles?review=overdue&sort=next_review_date&per_page=100" \
  | jq -r '.data[] | [.title, .next_review_date, (.owner.name // "unowned")] | @tsv'

Under the hood: REST API β€” How It Works Β· Other modules: Tickets Β· Assets Β· Problems Β· Changes Β· Keys & permissions: System β†’ API (System module) Β· Module docs: Knowledge.

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally