# Categories

Categories form a self-referential tree per tenant. Each category has a slug that is unique within the tenant and auto-generated from its name. Category slugs are the values accepted by the product list's `filter[category]` query parameter, which matches a category and all of its active descendants.

## GET /v1/api/commerce/categories

Returns the tenant's full category tree as nested JSON. Only active categories are included, ordered by `position` at every level. An inactive parent hides its entire subtree: children of an inactive parent are orphaned out of the result, even if they are active themselves. The response is not paginated.

### Parameters

None. No path, query, or body parameters.

### Response fields

Each node in the `data` array (and recursively in each `children` array):

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| id | string (uuid) | always | Category ID. |
| name | string | always | Category name. |
| slug | string | always | URL slug, unique per tenant. Use it as the `filter[category]` value on the product list endpoint. |
| description | string or null | always | Category description. |
| children | array | always | Child categories, same node shape, ordered by position. Empty array for leaf categories. |

```bash title="Request"
curl "https://api.borkol.com/v1/api/commerce/categories" \
  -H "Authorization: Bearer {api_key}" \
  -H "Accept: application/json"
```

```javascript title="Request (JS)"
const res = await fetch("https://api.borkol.com/v1/api/commerce/categories", {
  headers: {
    Authorization: `Bearer ${apiKey}`,
    Accept: "application/json",
  },
});
const { data } = await res.json();
```

```json title="Response"
{
  "data": [
    {
      "id": "7a1b3c5d-2e4f-4a6b-8c0d-1e2f3a4b5c6d",
      "name": "Furniture",
      "slug": "furniture",
      "description": "All furniture",
      "children": [
        {
          "id": "8b2c4d6e-3f5a-4b7c-9d1e-2f3a4b5c6d7e",
          "name": "Chairs",
          "slug": "chairs",
          "description": null,
          "children": []
        }
      ]
    },
    {
      "id": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
      "name": "Verandas",
      "slug": "verandas",
      "description": null,
      "children": []
    }
  ]
}
```

### Errors

| Status | Body | Cause |
| --- | --- | --- |
| 401 | `{"message":"Unauthenticated."}` | Missing or invalid API key. |
| 403 | `{"message":"Invalid ability provided."}` | Key lacks the `commerce:read` scope. |
| 403 | `{"error":"Module not enabled: commerce"}` | Tenant does not have the commerce module enabled. Note the `error` key instead of `message`. |
| 403 | `{"message":"Tenant suspended.","code":"tenant_suspended"}` | Tenant account is suspended. |
| 429 | `{"message":"Too Many Attempts."}` | Rate limit of 120 requests per minute exceeded. |
