This module (forked from EcomGraduates and @jtorvald) adds a public REST API for the FreeScout knowledge base with nested category support, analytics, custom URL templates, and a built-in testing interface.
- FreeScout installed
- FreeScout Knowledge Base module
- Download the latest module zip file via the releases card on the right.
- Transfer the zip file to the server in the
Modulesfolder of FreeScout. - Unpack the zip file and remove the zip.
- Activate the module via the Modules page in FreeScout.
- Go to Settings → Knowledge Base API and enter or generate a token, then save.
- Run migrations:
php artisan module:migrate KnowledgeBaseApiModule
- Download the latest zip file.
- Transfer it to the
Modulesfolder on your server. - Delete the existing
KnowledgeBaseApiModulefolder. - Unpack the new zip and remove the zip file.
- Nested categories — flat list with
parent_idby default; pass?nested=truefor a recursive tree - Token authentication — all endpoints protected by a configurable API token
- Custom URL templates — control how
urlandclient_urlare built in every response - Multi-locale support —
?locale=/?lang=parameters on all endpoints - Analytics dashboard — view, category, and search tracking with Chart.js visualisations
- Built-in test interface — try every endpoint directly from the settings page
All endpoints require ?token=YOUR_TOKEN.
GET /api/knowledgebase/{mailboxId}/categories
Returns a flat list of all visible categories. Each item includes a parent_id field (null for root categories) so you can build the tree client-side.
Response:
{
"mailbox_id": 1,
"name": "My Mailbox",
"categories": [
{
"id": 3,
"parent_id": null,
"name": "Getting Started",
"description": "...",
"url": "https://example.com/kb/category/3",
"client_url": null,
"article_count": 4
},
{
"id": 7,
"parent_id": 3,
"name": "Installation",
"description": "...",
"url": "https://example.com/kb/category/7",
"client_url": null,
"article_count": 2
}
]
}Pass ?nested=true to receive a recursive tree instead:
GET /api/knowledgebase/{mailboxId}/categories?nested=true
{
"mailbox_id": 1,
"name": "My Mailbox",
"categories": [
{
"id": 3,
"name": "Getting Started",
"description": "...",
"url": "https://example.com/kb/category/3",
"client_url": null,
"article_count": 4,
"children": [
{
"id": 7,
"name": "Installation",
"description": "...",
"url": "https://example.com/kb/category/7",
"client_url": null,
"article_count": 2,
"children": []
}
]
}
]
}GET /api/knowledgebase/{mailboxId}/categories/{categoryId}
Returns the category, its direct subcategories, and all its published articles. Tracks a category view for analytics.
Response:
{
"mailbox_id": 1,
"name": "My Mailbox",
"category": {
"id": 3,
"name": "Getting Started",
"description": "...",
"url": "https://example.com/kb/category/3",
"client_url": null,
"subcategories": [
{
"id": 7,
"name": "Installation",
"description": "...",
"url": "https://example.com/kb/category/7",
"client_url": null,
"article_count": 2
}
]
},
"articles": [
{
"id": 12,
"title": "Quick start guide",
"text": "...",
"url": "https://example.com/kb/article/12",
"client_url": null
}
]
}GET /api/knowledgebase/{mailboxId}/categories/{categoryId}/articles/{articleId}
Returns a single published article. Tracks an article view for analytics.
Response:
{
"mailbox_id": 1,
"mailbox_name": "My Mailbox",
"category": {
"id": 3,
"name": "Getting Started",
"url": "https://example.com/kb/category/3",
"client_url": null
},
"article": {
"id": 12,
"title": "Quick start guide",
"text": "...",
"url": "https://example.com/kb/article/12",
"client_url": null
}
}GET /api/knowledgebase/{mailboxId}/search?q=keyword
Case-insensitive full-text search across published article titles and body text. Tracks the search query for analytics.
Response:
{
"mailbox_id": 1,
"keyword": "installation",
"count": 2,
"results": [
{
"id": 12,
"title": "Quick start guide",
"text": "...",
"categories": [
{ "id": 3, "name": "Getting Started" }
],
"url": "https://example.com/kb/article/12",
"client_url": null
}
]
}GET /api/knowledgebase/{mailboxId}/popular
Returns most-viewed categories and/or articles ranked by view count.
Response:
{
"mailbox_id": 1,
"name": "My Mailbox",
"popular_categories": [
{
"id": 3,
"name": "Getting Started",
"description": "...",
"view_count": 142,
"url": "...",
"client_url": null
}
],
"popular_articles": [
{
"id": 12,
"title": "Quick start guide",
"view_count": 87,
"url": "...",
"client_url": null,
"category": { "id": 3, "name": "Getting Started" }
}
]
}GET /api/knowledgebase/{mailboxId}/export
Exports all visible categories and their published articles as a flat list (useful for AI training, site search indexing, etc.). Each category includes a parent_id field.
Pass ?nested=true to receive a fully hierarchical structure where each category contains a subcategories array:
GET /api/knowledgebase/{mailboxId}/export?nested=true
Response (nested):
{
"mailbox_id": 1,
"name": "My Mailbox",
"generated_at": "2026-03-17T10:00:00+00:00",
"categories": [
{
"id": 3,
"name": "Getting Started",
"description": "...",
"url": "...",
"client_url": null,
"articles": [
{
"id": 12,
"title": "Quick start guide",
"text": "...",
"status": 1,
"url": "...",
"client_url": null
}
],
"subcategories": [
{
"id": 7,
"name": "Installation",
"articles": [...],
"subcategories": []
}
]
}
]
}| Parameter | Endpoints | Description | Default |
|---|---|---|---|
token |
All | API token — required on every request | — |
locale / lang |
All | Language code for returned content (e.g. en, de). lang takes priority over locale. |
Mailbox default |
nested |
/categories, /export |
true to return a recursive tree; false (default) returns a flat list with parent_id |
false |
q |
/search |
Search keyword — required for this endpoint | — |
limit |
/popular |
Maximum number of results to return | 5 |
type |
/popular |
Filter by content type: all, articles, categories |
all |
include_hidden |
/export |
Include hidden / draft categories and articles | false |
Configure under Settings → Knowledge Base API.
| Placeholder | Replaced with |
|---|---|
[mailbox] |
Mailbox ID |
[category] |
Category ID |
[article] |
Article ID (omitted automatically for category URLs) |
Example — Client URL Template:
https://your-site.com/docs?category=[category]&article=[article]
- Article 10 in category 5 →
client_url: "https://your-site.com/docs?category=5&article=10" - Category 5 →
client_url: "https://your-site.com/docs?category=5"
Leave both templates empty to use the default FreeScout KB URLs.
Flat category list:
curl "https://example.com/api/knowledgebase/1/categories?token=YOUR_TOKEN"Nested category tree:
curl "https://example.com/api/knowledgebase/1/categories?nested=true&token=YOUR_TOKEN"Category with subcategories and articles:
curl "https://example.com/api/knowledgebase/1/categories/5?token=YOUR_TOKEN"Single article:
curl "https://example.com/api/knowledgebase/1/categories/5/articles/10?token=YOUR_TOKEN"Search:
curl "https://example.com/api/knowledgebase/1/search?q=installation&token=YOUR_TOKEN"Popular articles (top 10):
curl "https://example.com/api/knowledgebase/1/popular?type=articles&limit=10&token=YOUR_TOKEN"Flat export with hidden content:
curl "https://example.com/api/knowledgebase/1/export?include_hidden=true&token=YOUR_TOKEN"Nested export:
curl "https://example.com/api/knowledgebase/1/export?nested=true&token=YOUR_TOKEN"Locale / language filter:
curl "https://example.com/api/knowledgebase/1/categories?lang=de&token=YOUR_TOKEN"JavaScript fetch:
fetch("https://example.com/api/knowledgebase/1/categories?nested=true&token=YOUR_TOKEN")
.then(res => res.json())
.then(data => console.log(data));
Originally created by jtorvald and extended by EcomGraduates.
Pull requests are welcome.
- Nested categories — flat list (default) now includes
parent_idon every category; pass?nested=trueon/categoriesor/exportfor a recursive tree response subcategoriesfield added to/categories/{id}response (direct children of the requested category)langparameter — alias forlocale; accepted on all endpoints (langtakes priority)resolveLocale()helper centralises locale resolution across all endpoints- Tree building uses a single
getTree(0, true)call and pure PHP iteration — avoids rawWHERE parent_idSQL queries that fail on older KB module versions
- Added article and category view tracking
- Analytics dashboard with Chart.js visualisations (bar/pie charts, tabbed interface)
- Search query tracking (queries, result counts, success rates)
- New endpoints:
/popularand/export - Custom URL templates (
[mailbox],[category],[article]placeholders) - Built-in API testing interface in the settings page
- Token-based authentication added by EcomGraduates
- Initial release by jtorvald (no authentication)
MIT
