REST API Knowledge - edmozley/freeitsm GitHub Wiki
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.
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. ๐
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 |
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 |
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 } }| 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.
Soft-archives the article. It stays restorable until the module's retention window (knowledge_recycle_bin_days, default 30; 0 = keep forever) purges it.
Brings an archived article back, exactly as it was.
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.
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.
The saved snapshots โ version number, title at the time, who saved it, when โ newest first.
One snapshot including its full body_html โ everything needed to diff or roll back (roll back by PATCHing the old body onto the article).
Every tag with its published-article count:
{ "data": [ { "id": 3, "name": "how-to", "article_count": 12 },
{ "id": 7, "name": "vpn", "article_count": 4 } ] }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\"]}"
fiAnd 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.