Skip to content

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"

Query params:

  • limit (1–100, default 50)
  • cursor (opaque, from the previous response's meta.pagination.cursor)
  • q (text search across name + description)

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": { "limit": 50, "cursor": null, "hasMore": false } }
}

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 this
  • slug (string, optional): override the auto-slug
  • description (string, optional): shown on the category landing in default renderers
  • order (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 from targetId.
  • 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 with validation_error.

Response:

{ "data": { "updated": 3 } }

Required scope: write.

Audit log

Every create/update/delete writes an audit entry. Retrieve recent ones:

curl https://api.thefaq.app/api/v1/acme/categories/audit \
  -H "Authorization: Bearer $FAQAPP_API_KEY"

Returns the last 100 mutations with actor (member id or API-key fingerprint), action, before/after diffs, and timestamps.

Error codes

  • category_not_found (404): id or slug doesn't exist in this org
  • validation_failed (400): required field missing or wrong type
  • slug_conflict (409): slug already taken in this org
  • category_not_empty (409): delete attempted on category with questions — use ?force=true or move questions first
  • plan_limit_reached (402): org hit its category cap