Category Module API & Integration Guide
HTTP contracts for catalog category admin, customer, and mobile APIs.
Overview
Category APIs support:
- admin category CRUD, restore, and sibling reorder
- customer/mobile category listing and slug detail
- slug-history fallback for old slugs
- product kind tagging and filtering
Soft-deleted categories are excluded from normal reads by default.
Routes
| Method | Path | Auth |
|---|---|---|
GET | /api/admin/categories | Admin + Categories_READ |
GET | /api/admin/categories/:id | Admin + Categories_READ |
POST | /api/admin/categories | Admin + Categories_CREATE |
PATCH | /api/admin/categories/:id | Admin + Categories_UPDATE |
DELETE | /api/admin/categories/:id | Admin + Categories_DELETE (soft delete) |
POST | /api/admin/categories/:id/restore | Admin + Categories_UPDATE |
POST | /api/admin/categories/reorder | Admin + Categories_UPDATE |
GET | /api/categories and /api/mobile/categories | Public |
GET | /api/categories/:slug and /api/mobile/categories/:slug | Public |
Admin Query/Body Contracts
GET /api/admin/categories
- supports
search,parentId,isVisible,sort,order, pagination fromQueryDto - supports
includeDeleted(defaultfalse) - supports
productKindfilter:physical|digital|both(exact match, optional)
GET /api/admin/categories/:id
- supports
includeDeleted(defaultfalse)
POST /api/admin/categories
All existing fields plus:
| Field | Type | Required | Description |
|---|---|---|---|
productKind | "physical" | "digital" | "both" | No | Product kind for this category. Omit for unconstrained. |
PATCH /api/admin/categories/:id
All existing fields plus:
| Field | Type | Required | Description |
|---|---|---|---|
productKind | "physical" | "digital" | "both" | null | No | Set to null to clear kind constraint. Omit to leave unchanged. |
POST /api/admin/categories/reorder
{
"parentId": null,
"ids": [5, 7, 9]
}parentId:number | null- all
idsmust be active categories and direct children ofparentId
Admin Response Shape
All admin category responses include:
{
"id": 1,
"name": "Laptops",
"slug": "laptops",
"description": null,
"parentId": null,
"order": 0,
"isVisible": true,
"productKind": "physical",
"imageUrl": null,
"deletedAt": null,
"deletedBy": null,
"createdAt": "2026-06-13T10:00:00.000Z",
"updatedAt": "2026-06-13T10:00:00.000Z"
}productKind is null for categories created before this feature was added.
Customer/Mobile Contracts
-
list defaults:
isVisible=true,pagination=false, sortname asc -
soft-deleted categories are always excluded
-
supports
productKindfilter:physical|digital(customer only —bothis not a valid filter value) -
when
productKind=physicalis provided: returns categories whereproductKind = 'physical'orproductKind = 'both' -
when
productKind=digitalis provided: returns categories whereproductKind = 'digital'orproductKind = 'both' -
when
productKindis omitted: returns all visible active categories regardless of kind -
slug detail resolves:
- current visible + active slug
- fallback to
category_slug_history - only returns if mapped category is visible + active
Customer Response Shape
{
"id": 1,
"name": "Laptops",
"slug": "laptops",
"description": null,
"parentId": null,
"order": 0,
"isVisible": true,
"productKind": "physical",
"imageUrl": null,
"createdAt": "2026-06-13T10:00:00.000Z",
"updatedAt": "2026-06-13T10:00:00.000Z"
}Error Codes
| HTTP | errorCode | Condition |
|---|---|---|
| 400 | CATEGORY_SELF_PARENT | Category set as its own parent |
| 400 | CATEGORY_MOVE_TO_DESCENDANT | Move under descendant |
| 400 | CATEGORY_MISSING_PARENT | Parent not found |
| 400 | CATEGORY_DEPTH_EXCEEDED | Depth > 3 |
| 400 | CATEGORY_DUPLICATE_IDS | Duplicate ids in reorder payload |
| 400 | CATEGORY_INVALID_SORT | Unsupported customer sort field |
| 400 | CATEGORY_REORDER_PARENT_MISMATCH | Reorder ids do not belong to provided parent |
| 400 | — class-validator — | Invalid productKind value (not in allowed enum) |
| 404 | CATEGORY_NOT_FOUND | Category or slug not found |
| 409 | CATEGORY_HAS_CHILDREN | Soft delete blocked by active children |
| 409 | CATEGORY_ALREADY_DELETED | Soft delete requested for already deleted category |
| 409 | CATEGORY_DELETED | Mutation requested on deleted category |
| 409 | CATEGORY_RESTORE_PARENT_DELETED | Restore blocked because parent is deleted |
Cache
Write invalidation on admin create/update/delete/restore/reorder:
catalog:categories:visible*catalog:categories:list:*catalog:category:slug:*
Customer list cache key includes productKind segment — different kind filters are cached independently.