REST API Knowledge - edmozley/freeitsm GitHub Wiki

๐Ÿ“š 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.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ