Categories
Top-level grouping of related help articles.
Help center content — categories and articles. Public-facing CMS module: content is authored in the admin and published to the help-web frontend. All text fields are plaintext (no encryption); the article body is stored as Markdown source.
Available over HTTP (/v1/help/<service>) and WebSocket (help.<service>.*). See Enbox API for transport details, error codes, and query operators.
Warning: The HTTP transport publishes the same CRUD operations as the WebSocket transport, but the request/response shapes differ: HTTP uses REST conventions (path params, query string, JSON body) and returns the bare
resultpayload; WebSocket wraps everything in the JSON-RPC 2.0 envelope (jsonrpc/result/id). The per-operation examples below show both.
Service: help.categories
Top-level grouping of related help articles. A category’s public visibility is derived, not stored: it appears on the help index iff it has at least one published article. Category carries no is_public flag and no timestamps (reference data, rarely edited).
Fields
| Field | Type | Required | Description |
|---|---|---|---|
id |
string |
— | Primary key. Read-only, auto-generated |
slug |
string |
✅ | URL-safe identifier, unique across categories |
title |
string |
✅ | Display title (default-locale / English) |
description |
string |
One-line description shown on the help index. Default "" |
|
icon |
string |
Bootstrap Icons class for the category tile (e.g. "bi-life-preserver"). Default "bi-life-preserver" |
|
color |
string? |
Brand color (hex, e.g. "#0d6efd"). The gradient end is derived in CSS. null = default theme accent |
|
category_translation |
CategoryTranslation[] | Per-locale overlays. Inline — edited on the parent form, not a top-level service |
CategoryTranslation
Inline overlay edited on the Category form, not published as a top-level service. Translatable fields are nullable so a partial translation keeps the base value where the overlay is NULL (NULL = inherit base). UniqueConstraint(["source_id", "language_id"]) — one translation per (category, language). language_id FK → common_language with on_delete=PROTECT: deleting a language still referenced by translations is blocked.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string |
— | Primary key. Read-only. Omit when creating |
source_id |
string |
— | Parent category id. Read-only, auto-set from the parent |
language_id |
string |
✅ | Language of this translation (FK → common_language) |
title |
string? |
Translated category title. null = inherit base |
|
description |
string? |
Translated category description. null = inherit base |
find
List categories with filtering, sorting, and pagination.
HTTP
Request
GET /v1/help/categories?fields=id,slug,title,description,icon,color,category_translation.id,category_translation.language_id,category_translation.title,category_translation.description&sort=[{"field":"title","dir":"asc"}]&limit=100
Authorization: Bearer <token>
Response
{
"items": [
{
"id": "1920438291700",
"slug": "getting-started",
"title": "Getting started",
"description": "Set up Enbox and learn the basics.",
"icon": "bi-rocket-takeoff",
"color": "#0d6efd",
"category_translation": [
{
"id": "1920438291710",
"language_id": "1920438290002",
"title": "Premiers pas",
"description": "Configurez Enbox et apprenez les bases."
}
]
},
{
"id": "1920438291720",
"slug": "billing",
"title": "Billing and payments",
"description": "Plans, invoices, and payment methods.",
"icon": "bi-credit-card",
"color": null,
"category_translation": []
}
],
"total": 2
}
WebSocket
Request
{
"jsonrpc": "2.0",
"method": "help.categories.find",
"params": {
"fields": [
"id", "slug", "title", "description", "icon", "color",
"category_translation.id", "category_translation.language_id",
"category_translation.title", "category_translation.description"
],
"sort": [{ "field": "title", "dir": "asc" }],
"limit": 100
},
"id": 1
}
Response
{
"jsonrpc": "2.0",
"result": {
"items": [
{
"id": "1920438291700",
"slug": "getting-started",
"title": "Getting started",
"description": "Set up Enbox and learn the basics.",
"icon": "bi-rocket-takeoff",
"color": "#0d6efd",
"category_translation": [
{
"id": "1920438291710",
"language_id": "1920438290002",
"title": "Premiers pas",
"description": "Configurez Enbox et apprenez les bases."
}
]
},
{
"id": "1920438291720",
"slug": "billing",
"title": "Billing and payments",
"description": "Plans, invoices, and payment methods.",
"icon": "bi-credit-card",
"color": null,
"category_translation": []
}
],
"total": 2
},
"id": 1
}
findOneById
Fetch a single category by primary key.
HTTP
Request
GET /v1/help/categories/1920438291700?fields=id,slug,title,description,icon,color,category_translation.id,category_translation.language_id,category_translation.title,category_translation.description
Authorization: Bearer <token>
Response
{
"id": "1920438291700",
"slug": "getting-started",
"title": "Getting started",
"description": "Set up Enbox and learn the basics.",
"icon": "bi-rocket-takeoff",
"color": "#0d6efd",
"category_translation": [
{
"id": "1920438291710",
"language_id": "1920438290002",
"title": "Premiers pas",
"description": "Configurez Enbox et apprenez les bases."
}
]
}
WebSocket
Request
{
"jsonrpc": "2.0",
"method": "help.categories.findOneById",
"params": {
"id": "1920438291700",
"fields": [
"id", "slug", "title", "description", "icon", "color",
"category_translation.id", "category_translation.language_id",
"category_translation.title", "category_translation.description"
]
},
"id": 2
}
Response
{
"jsonrpc": "2.0",
"result": {
"id": "1920438291700",
"slug": "getting-started",
"title": "Getting started",
"description": "Set up Enbox and learn the basics.",
"icon": "bi-rocket-takeoff",
"color": "#0d6efd",
"category_translation": [
{
"id": "1920438291710",
"language_id": "1920438290002",
"title": "Premiers pas",
"description": "Configurez Enbox et apprenez les bases."
}
]
},
"id": 2
}
create
Create a new category. The server assigns id.
HTTP
Request
POST /v1/help/categories
Authorization: Bearer <token>
Content-Type: application/json
{
"document": {
"slug": "security",
"title": "Account security",
"description": "Passwords, 2FA, and device sessions.",
"icon": "bi-shield-lock",
"color": "#dc3545",
"category_translation": [
{ "language_id": "1920438290002", "title": "Sécurité du compte" }
]
}
}
Response
{
"id": "1920438291730",
"slug": "security",
"title": "Account security"
}
WebSocket
Request
{
"jsonrpc": "2.0",
"method": "help.categories.create",
"params": {
"document": {
"slug": "security",
"title": "Account security",
"description": "Passwords, 2FA, and device sessions.",
"icon": "bi-shield-lock",
"color": "#dc3545",
"category_translation": [
{ "language_id": "1920438290002", "title": "Sécurité du compte" }
]
}
},
"id": 3
}
Response
{
"jsonrpc": "2.0",
"result": {
"id": "1920438291730",
"slug": "security",
"title": "Account security"
},
"id": 3
}
updateOneById
Partial update — only specified fields change; omitted fields are untouched. Nested collections (category_translation) are updated automatically: items with id are updated, items without id are created, items missing from the array are deleted.
HTTP
Request
PATCH /v1/help/categories/1920438291700
Authorization: Bearer <token>
Content-Type: application/json
{
"document": {
"description": "Install Enbox and learn the basics in 5 minutes.",
"icon": "bi-rocket-takeoff"
}
}
Response
{
"id": "1920438291700",
"description": "Install Enbox and learn the basics in 5 minutes.",
"icon": "bi-rocket-takeoff"
}
WebSocket
Request
{
"jsonrpc": "2.0",
"method": "help.categories.updateOneById",
"params": {
"id": "1920438291700",
"document": {
"description": "Install Enbox and learn the basics in 5 minutes.",
"icon": "bi-rocket-takeoff"
}
},
"id": 4
}
Response
{
"jsonrpc": "2.0",
"result": {
"id": "1920438291700",
"description": "Install Enbox and learn the basics in 5 minutes.",
"icon": "bi-rocket-takeoff"
},
"id": 4
}
replaceOneById
Full replacement — all writable fields must be provided. Unlike updateOneById, omitted fields are reset to defaults. Nested collections (category_translation) are not accepted in this method — use updateOneById to modify them.
HTTP
Request
PUT /v1/help/categories/1920438291700
Authorization: Bearer <token>
Content-Type: application/json
{
"document": {
"slug": "getting-started",
"title": "Getting started",
"description": "Install Enbox and learn the basics in 5 minutes.",
"icon": "bi-rocket-takeoff",
"color": "#0d6efd"
}
}
Response
{
"id": "1920438291700",
"slug": "getting-started",
"title": "Getting started",
"description": "Install Enbox and learn the basics in 5 minutes.",
"icon": "bi-rocket-takeoff",
"color": "#0d6efd"
}
WebSocket
Request
{
"jsonrpc": "2.0",
"method": "help.categories.replaceOneById",
"params": {
"id": "1920438291700",
"document": {
"slug": "getting-started",
"title": "Getting started",
"description": "Install Enbox and learn the basics in 5 minutes.",
"icon": "bi-rocket-takeoff",
"color": "#0d6efd"
}
},
"id": 5
}
Response
{
"jsonrpc": "2.0",
"result": {
"id": "1920438291700",
"slug": "getting-started",
"title": "Getting started",
"description": "Install Enbox and learn the basics in 5 minutes.",
"icon": "bi-rocket-takeoff",
"color": "#0d6efd"
},
"id": 5
}
update
Batch update multiple categories in a single transaction (all-or-nothing). See Batch operations.
HTTP
Request
PATCH /v1/help/categories
Authorization: Bearer <token>
Content-Type: application/json
{
"items": [
{ "id": "1920438291700", "document": { "color": "#198754" } },
{ "id": "1920438291720", "document": { "color": "#6f42c1" } }
]
}
Response
{
"affected": 2,
"items": [
{ "id": "1920438291700", "color": "#198754" },
{ "id": "1920438291720", "color": "#6f42c1" }
]
}
WebSocket
Request
{
"jsonrpc": "2.0",
"method": "help.categories.update",
"params": {
"items": [
{ "id": "1920438291700", "document": { "color": "#198754" } },
{ "id": "1920438291720", "document": { "color": "#6f42c1" } }
]
},
"id": 6
}
Response
{
"jsonrpc": "2.0",
"result": {
"affected": 2,
"items": [
{ "id": "1920438291700", "color": "#198754" },
{ "id": "1920438291720", "color": "#6f42c1" }
]
},
"id": 6
}
deleteOneById
Delete a category. All articles and translations belonging to it are deleted with it (cascade).
HTTP
Request
DELETE /v1/help/categories/1920438291730
Authorization: Bearer <token>
Response
{
"id": "1920438291730",
"slug": "security",
"title": "Account security"
}
WebSocket
Request
{
"jsonrpc": "2.0",
"method": "help.categories.deleteOneById",
"params": {
"id": "1920438291730"
},
"id": 7
}
Response
{
"jsonrpc": "2.0",
"result": {
"id": "1920438291730",
"slug": "security",
"title": "Account security"
},
"id": 7
}
delete
Batch delete categories in a single transaction (all-or-nothing). See Batch operations.
HTTP
Request
DELETE /v1/help/categories
Authorization: Bearer <token>
Content-Type: application/json
{
"items": [
{ "id": "1920438291730" },
{ "id": "1920438291740" }
]
}
Response
{
"affected": 2,
"items": [
{ "id": "1920438291730" },
{ "id": "1920438291740" }
]
}
WebSocket
Request
{
"jsonrpc": "2.0",
"method": "help.categories.delete",
"params": {
"items": [
{ "id": "1920438291730" },
{ "id": "1920438291740" }
]
},
"id": 8
}
Response
{
"jsonrpc": "2.0",
"result": {
"affected": 2,
"items": [
{ "id": "1920438291730" },
{ "id": "1920438291740" }
]
},
"id": 8
}