Categories
Group questions into categories. Categories carry an order, a slug, and an optional description.
Updated 2026-06-14
Categories group questions. Every question belongs to exactly one category. Categories carry a slug (URL-safe identifier), a display name, an explicit order for sort, and an optional description.
List
curl https://api.thefaq.app/api/v1/acme/categories \
-H "Authorization: Bearer $FAQAPP_API_KEY"
Returns every category in the organization in one response, ordered by parent, then order, then creation time. There are no query params.
Response:
{
"data": [
{
"id": "cat_billing",
"slug": "billing",
"name": "Billing",
"description": "Subscriptions, invoices, refunds.",
"order": 1,
"questionCount": 8,
"createdAt": "2026-04-01T10:00:00Z",
"updatedAt": "2026-05-19T14:23:00Z"
}
],
"meta": { "pagination": { "page": 1, "limit": 50, "total": 1, "pages": 1 } }
}
Get by id or slug
curl https://api.thefaq.app/api/v1/acme/categories/billing \
-H "Authorization: Bearer $FAQAPP_API_KEY"
Accepts either id (cat_billing) or slug (billing).
Create
curl -X POST https://api.thefaq.app/api/v1/acme/categories \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Billing",
"description": "Subscriptions, invoices, refunds.",
"order": 1
}'
Body:
name(string, required): display name; slug auto-generated from thisslug(string, optional): override the auto-slugdescription(string, optional): shown on the category landing in default renderersorder(integer, optional, default 0): lower numbers sort first
Required scope: write.
Update
curl -X PATCH https://api.thefaq.app/api/v1/acme/categories/billing \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "order": 2, "description": "Updated description." }'
Any field accepted by create can be patched. Slug changes do not redirect old URLs — plan ahead.
Required scope: write.
Delete
curl -X DELETE https://api.thefaq.app/api/v1/acme/categories/billing \
-H "Authorization: Bearer $FAQAPP_API_KEY"
Returns 204 No Content. Categories with questionCount > 0 cannot be deleted — move or delete the questions first, or pass ?force=true to move them to the default category atomically.
Required scope: write.
Merge
Fold one category into another. The source’s child categories are re-parented to the target, the source’s questions are re-assigned to the target, and the source is optionally soft-deleted. Every statement is org-scoped, so ids from another organization are rejected.
curl -X POST https://api.thefaq.app/api/v1/acme/categories/merge \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sourceId": "cat_legacy",
"targetId": "cat_billing",
"deleteSource": true
}'
Body:
sourceId(string, required): the category to merge from. Must differ fromtargetId.targetId(string, required): the category to merge into.deleteSource(boolean, optional, default false): soft-delete the source after moving its contents.
Response:
{
"data": {
"childrenMoved": 2,
"questionsMoved": 14,
"sourceDeleted": true
}
}
Required scope: admin.
Reorder
Set the sort order of a set of categories in one request. Pass the ids in the order you want them — index 0 becomes order 0, index 1 becomes 1, and so on. Categories not in the list keep their current order.
curl -X POST https://api.thefaq.app/api/v1/acme/categories/reorder \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "ids": ["cat_billing", "cat_account", "cat_legacy"] }'
Body:
ids(string[], required, 1–1000): category ids in the desired order. Every id must belong to this organization, or the whole request is rejected withvalidation_error.
Response:
{ "data": { "updated": 3 } }
Required scope: write.
Content audit
Counts published and draft questions per category and flags empty categories. This is a content report, not an activity log: thefaqapp does not offer a customer-exportable audit log of who changed what.
curl -X POST https://api.thefaq.app/api/v1/acme/categories/audit \
-H "Authorization: Bearer $FAQAPP_API_KEY"
Required scope: write. Returns auditId, status, summary (total, empty, published, drafts), and findings with one entry per category. GET /categories/audit returns the latest result as latest, or null before the first run.
Error codes
validation_error(400): invalid body, or aparentIdor id that belongs to another orginvalid_json(400): body wasn’t valid JSONnot_found(404): id or slug doesn’t exist in this orgslug_conflict(409): no unique slug could be allocated; pass an explicitslugplan_limit_exceeded(403): org hit its category cap