Website Categories
The seven endpoints that create, move and remove blog and reference categories.
Overview
Categories exist for two content types: blog posts and references. Plain pages, contracts and news carry no category, so they never appear at these endpoints.
Categories form a tree. Each record can have a parent, and zero puts it at the root. That information comes back only at the detail endpoint, while the list gives records in a flat order.
The shape matches that of pages: content is kept per language, the type is fixed at creation, and the address is unique within each language. Images are simpler here, as a category has one header image.
Reference
Listing the Categories
Returns the categories of the type you pick.
articles, references. Blog categories by default.curl 'https://panel.example.com/api/v1/admin/website/categories?type=articles' \
-H "Authorization: Bearer $API_KEY"const url = new URL('https://panel.example.com/api/v1/admin/website/categories');
url.searchParams.set('type', 'articles');
const res = await fetch(url, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/website/categories?' . http_build_query(['type' => 'articles']));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The list carries NO PARENT: building the tree means reading each record on its own.
$cats = Api::Website()->GetCategories([], ['type' => 'articles'])['data'];Reading One Category
Returns one category with all its languages.
articles, references.curl 'https://panel.example.com/api/v1/admin/website/categories/3' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/website/categories/${id}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/website/categories/' . $id);
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 back ONLY here; the tree is built from this field.
$cat = Api::Website()->GetCategory(['id' => $id])['data'];
$isRoot = $cat['parent'] === 0;Creating a Category
Opens a new category and writes its languages.
articles, references. It cannot be changed later.curl -X POST 'https://panel.example.com/api/v1/admin/website/categories' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"type":"articles","languages":{"tr":{"title":"Duyurular"}}}'const res = await fetch('https://panel.example.com/api/v1/admin/website/categories', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'articles',
languages: { en: { title: 'Announcements' } },
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/website/categories');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'type' => 'articles',
'languages' => ['en' => ['title' => 'Announcements']],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// To nest a category give the PARENT id; zero puts it at the root.
Api::Website()->CreateCategory([
'type' => 'articles',
'parent' => $parentId,
'languages' => ['en' => ['title' => 'Release notes']],
]);Updating a Category
Changes the category fields and languages you send.
curl -X PATCH 'https://panel.example.com/api/v1/admin/website/categories/3' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"status":"inactive"}'const res = await fetch(`https://panel.example.com/api/v1/admin/website/categories/${id}`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ status: 'inactive' }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/website/categories/' . $id);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['status' => 'inactive']),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Changing the parent MOVES the branch; whatever sits below comes along.
Api::Website()->UpdateCategory(['id' => $id, 'parent' => $newParent]);Deleting a Category
Removes a category and every category beneath it.
curl -X DELETE 'https://panel.example.com/api/v1/admin/website/categories/3' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/website/categories/${id}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const { data } = await res.json();
console.log(data.removed); // [3, 7, 8]$ch = curl_init('https://panel.example.com/api/v1/admin/website/categories/' . $id);
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);// Read the RETURNED list to see how many went; a call you read as one can take a branch.
$gone = Api::Website()->DeleteCategory(['id' => $id])['data']['removed'];Uploading a Category Image
Uploads the category header image, in place of the one before.
curl -X PUT 'https://panel.example.com/api/v1/admin/website/categories/3/image' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"image":"https://ornek.com/kapak.jpg"}'const res = await fetch(`https://panel.example.com/api/v1/admin/website/categories/${id}/image`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ image: 'https://example.com/cover.jpg' }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/website/categories/' . $id . '/image');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['image' => 'https://example.com/cover.jpg']),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// A category has ONE image; unlike a page, there is no kind to choose.
Api::Website()->UploadCategoryImage(['id' => $id, 'image' => $data]);Removing a Category Image
Removes the category header image.
curl -X DELETE 'https://panel.example.com/api/v1/admin/website/categories/3/image' \
-H "Authorization: Bearer $API_KEY"const res = await fetch(`https://panel.example.com/api/v1/admin/website/categories/${id}/image`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/website/categories/' . $id . '/image');
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);// To REPLACE the image there is no need to delete first; the upload takes its place.
Api::Website()->DeleteCategoryImage(['id' => $id]);Pitfalls
Deleting a category also deletes every category beneath it. What you read as removing one record can take a branch of the tree. The removed list in the response tells you what actually went, so read it before counting the call a success. Reading the detail first to see the parent links is the safest course.
The listing endpoint does not return the parent field and gives records in a flat order. You cannot build a tree from it. When you need the hierarchy, read each record from the detail endpoint; there are rarely many categories, so this seldom hurts.
The category type is part of what a record is, and the update ignores it. A category opened for blog posts will not become one for references. Fixing a category opened under the wrong type means creating a new one and moving what sits inside.
The same address can sit side by side in different languages, yet two categories in one language cannot share it. Categories and pages draw on the same address space, so a category can clash with a page as well. Leave the address out and it is built from the title.
Changing the parent on an update moves everything beneath it along. Putting a category under one of its own descendants closes the tree on itself, and that branch drops out of the listings. Before moving one, make sure the target does not sit inside the branch you are moving.
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.