Skip to main content
Categories are returned as a flat list. The tree structure lives in parent_id — assemble it client-side when you need a nested view.

Fields

object
string
required
Always "article_category".
id
uuid
required
Server-generated identifier.
knowledge_base_id
uuid | null
The knowledge base this category belongs to. Required on create — every new category must be scoped to a knowledge base. Must reference a knowledge base in your organization; a foreign or nonexistent id returns 422 "A referenced resource does not exist."
parent_id
uuid | null
The parent category, or null if this is a root. When set, must reference a category in your organization; a foreign or nonexistent id returns 422 "A referenced resource does not exist." Trees of arbitrary depth are allowed; in practice keep it shallow.
name
string
required
Display name shown in the KB UI and category pickers.
slug
string
required
URL-safe handle. Unique across the org.
description
string | null
Optional one-liner shown in the dashboard and on the public KB index.
icon
string
required
Lucide-style icon handle. Drives the icon shown in navigation, breadcrumbs, and row chips. Defaults to "folder-closed" if you don’t set it on create.
Supported values: folder-closed, folder-open, book-open, file-text, help-circle, lightbulb, message-square, settings, star, zap, shield, globe, archive. Any other value returns invalid_payload.
sort_order
integer
required
Position among siblings sharing the same parent_id. Lower comes first. Must be an integer — a non-integer value is rejected with invalid_payload. Re-order by PATCHing the sort_order field on every sibling that moves.
created_at
datetime
required
ISO-8601 timestamp of insertion.

Example

{
  "object": "article_category",
  "id": "5d694e14-5440-4f5d-9e8a-7c3b2a1d0f9e",
  "knowledge_base_id": "2c1b4a9f-7e8d-4a3c-9b1f-6e5d4c3b2a1f",
  "parent_id": null,
  "name": "Returns",
  "slug": "returns",
  "description": "Policies and processes for product returns.",
  "icon": "folder-closed",
  "sort_order": 0,
  "created_at": "2026-05-22T13:50:00+00:00"
}

Building a tree from the flat list

The API returns categories flat. Construct a tree by indexing on id and grouping by parent_id.
function buildTree(categories) {
  const byId = new Map()
  for (const c of categories) {
    byId.set(c.id, { ...c, children: [] })
  }
  const roots = []
  for (const c of byId.values()) {
    if (c.parent_id) {
      byId.get(c.parent_id)?.children.push(c)
    } else {
      roots.push(c)
    }
  }
  const bySort = (a, b) => a.sort_order - b.sort_order
  const walk = (n) => {
    n.children.sort(bySort)
    n.children.forEach(walk)
  }
  roots.sort(bySort)
  roots.forEach(walk)
  return roots
}

const flat = await fetch("https://api.awardee.dev/v1/article-categories", {
  headers: { Authorization: `Bearer ${API_KEY}` },
}).then((r) => r.json())

const tree = buildTree(flat.data)
For a single subtree, pass ?parent_id=<id> to get just the direct children. To enumerate a whole branch, fetch the full list once and walk the tree in memory — it’s almost always cheaper than recursive API calls.