Help Categories
The five endpoints that open, read, update and remove help categories.
Overview
Categories group the help articles and build a tree. Every category can hang from another, and the ones at the root carry a parent of zero.
They follow the same contract as the articles. A title is wanted in every live language and a slug is optional, unique per language. An update writes the whole record.
One thing differs: a category's search engine fields are kept while indexing is on. Fields filled in while it is off are never saved.
Reference
Listing the Categories
Returns the help categories.
curl 'https://panel.example.com/api/v1/admin/knowledgebase/categories' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/knowledgebase/categories', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const { data } = await res.json();
const byId = Object.fromEntries(data.map((c) => [c.id, c.title]));$ch = curl_init('https://panel.example.com/api/v1/admin/knowledgebase/categories');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The listing holds NO parent id: building the tree wants the detail of every category.
$rows = Api::Knowledgebase()->GetKnowledgebaseCategories()['data'];
foreach ($rows as $c)
$parent[$c['id']] = Api::Knowledgebase()->GetKnowledgebaseCategory(['cid' => $c['id']])['data']['parent_id'];Opening a Category
Opens a new help category.
curl -X POST 'https://panel.example.com/api/v1/admin/knowledgebase/categories' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"parent_id":0,"icon":"bi bi-book","translations":{"en":{"title":"Billing"}}}'const res = await fetch('https://panel.example.com/api/v1/admin/knowledgebase/categories', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
parent_id: 0,
icon: 'bi bi-book',
seo_index: true,
translations: { en: { title: 'Billing', sub_title: 'Invoices and payments' } },
}),
});
const { data, meta } = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/knowledgebase/categories');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'parent_id' => 0, 'translations' => ['en' => ['title' => 'Billing']],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The search engine fields are not kept while indexing is OFF: filling them in loses them.
Api::Knowledgebase()->CreateKnowledgebaseCategory([
'seo_index' => true,
'translations' => ['en' => ['title' => 'Billing', 'seo_title' => 'Billing help']],
]);Reading a Category
Returns a category with all of its languages.
curl 'https://panel.example.com/api/v1/admin/knowledgebase/categories/3' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/knowledgebase/categories/${cid}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const { data } = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/knowledgebase/categories/' . $cid);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The parent id comes HERE alone; call this for every category while building the tree.
$c = Api::Knowledgebase()->GetKnowledgebaseCategory(['cid' => $cid])['data'];
$isRoot = (int) $c['parent_id'] === 0;Updating a Category
Rewrites the category in full.
curl -X PATCH 'https://panel.example.com/api/v1/admin/knowledgebase/categories/3' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"status":"inactive","translations":{"en":{"title":"Billing"}}}'const cur = await fetch(`https://panel.example.com/api/v1/admin/knowledgebase/categories/${cid}`, {
headers: { Authorization: `Bearer ${apiKey}` },
}).then((r) => r.json());
const res = await fetch(`https://panel.example.com/api/v1/admin/knowledgebase/categories/${cid}`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ ...cur.data, rank: 2 }),
});$ch = curl_init('https://panel.example.com/api/v1/admin/knowledgebase/categories/' . $cid);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($category),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Closing a category DOES NOT remove its articles, and a client can no longer reach them through it.
$c = Api::Knowledgebase()->GetKnowledgebaseCategory(['cid' => $cid])['data'];
$c['status'] = 'inactive';
Api::Knowledgebase()->UpdateKnowledgebaseCategory($c + ['cid' => $cid]);Removing a Category
Removes a category and every translation of it.
curl -X DELETE 'https://panel.example.com/api/v1/admin/knowledgebase/categories/3' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/knowledgebase/categories/${cid}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/knowledgebase/categories/' . $cid);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The articles inside STAY and fall out of any category; move them elsewhere first.
$arts = Api::Knowledgebase()->GetKnowledgebaseArticles()['data'];
foreach ($arts as $a) { /* move the ones whose category is $cid */ }
Api::Knowledgebase()->DeleteKnowledgebaseCategory(['cid' => $cid]);Pitfalls
The category listing does not carry the parent id; it gives the id, title, slug, state and icon alone. Building the tree wants each category read on its own, which on a large knowledge base means one call per category.
As with the articles the update body is the whole category. Read the current state first and write over it, even to change the order alone. The languages and fields you leave out go empty.
The search engine title, keywords and description stay only while indexing is on. Filling them in while it is off raises no error and the values are not saved, showing empty on the next read. Turn indexing on first.
Removing a category does not remove the articles inside. They fall out of any category, and a client cannot reach them from the category listing. The articles are still found by address and by search while the navigation breaks. Move them first.
A category cannot be its own parent and that is checked. Longer loops carry no such guard: A under B with B under A passes. Take care not to build a cycle while rearranging the tree.
Related Articles
Vielen Dank für Ihre Rückmeldung!
Unser Support-Team ist rund um die Uhr für Sie da, wenn Sie oben nicht fündig werden.