Category Module API & Integration Guide
Developer Resources catalog Category Category Module API & Integration Guide HTTP contract reference for catalog category admin and customer/mobile APIs.
Audience: Mobile/web frontend developers
Scope: Category discovery endpoints
Module: Catalog / Category
Admin auth: JwtAuthGuard + RoleGuard + @Permissions(Categories_*)
Customer/mobile auth: public endpoints (@Public())
Surfaces:
Admin: /api/admin/categories
Customer: /api/categories
Mobile: /api/mobile/categories
Category APIs provide admin hierarchy management and public storefront category reads. Customer slug lookup supports old slug compatibility through slug-history fallback.
Category hierarchy: self-referential parent-child model.
Root category: parentId = null.
Visibility flag: isVisible controls storefront inclusion.
Slug continuity: old slugs are retained in category_slug_history.
Method Path Permission GET/api/admin/categoriesCategories_READGET/api/admin/categories/:idCategories_READPOST/api/admin/categoriesCategories_CREATEPATCH/api/admin/categories/:idCategories_UPDATEDELETE/api/admin/categories/:idCategories_DELETEPOST/api/admin/categories/reorderCategories_UPDATEGET/api/categories and /api/mobile/categoriesPublic GET/api/categories/:slug and /api/mobile/categories/:slugPublic
Aspect Details Endpoint GET /api/categories or /api/mobile/categoriesAuth Public Request pagination, parentId, isVisible Response ResponseDto<CategoryDto[]>Errors -
Aspect Details Endpoint GET /api/categories/:slug or /api/mobile/categories/:slugAuth Public Request - Response ResponseDto<CategoryDto>Errors 404 not found
Inherited from QueryDto: pagination, page, size, search
Filters: parentId, isVisible
Sort: name | order | createdAt | updatedAt
Order: asc | desc
Inherited from QueryDto: page, size, search
Defaults: pagination=false, sort=name, order=asc, isVisible=true
Filters: parentId, optional isVisible override
Sort: name | order | createdAt
"
" id ": 1,
" parentId ": null,
" order ": 0,
" isVisible ": true,
"
Category module does not define additional DB enums in its DTO contract. Sort allowlists are DTO-level enums/constraints:
Admin sort: name | order | createdAt | updatedAt
Customer sort: name | order | createdAt
Order: asc | desc
Prefix Usage catalog:categories:list:customer list cache catalog:category:slug:customer detail-by-slug cache
Write invalidation on admin create/update/delete/reorder clears category list/slug keyspaces.
HTTP errorCode Condition 400 CATEGORY_SELF_PARENTCategory set as its own parent 400 CATEGORY_MOVE_TO_DESCENDANTCategory moved under descendant 400 CATEGORY_MISSING_PARENTParent category ID does not exist 400 CATEGORY_DEPTH_EXCEEDEDParent chain exceeds depth 3 400 CATEGORY_DUPLICATE_IDSReorder request contains duplicate IDs 400 CATEGORY_INVALID_SORTUnsupported customer sort field 404 CATEGORY_NOT_FOUNDCategory or slug not found 409 CATEGORY_HAS_CHILDRENDelete blocked by existing child categories
Method Path Auth / Permission Request DTO / Params Success DTO Notes GET /api/admin/categoriesAdmin + Categories_READ QueryCategoriesAdminDto "" page?, size?, pagination?, search?, parentId?, isVisible?, sort?, order? ""CategoryAdminListItemDto[] paginatedAdmin category list GET /api/admin/categories/:idAdmin + Categories_READ path: id (int) CategoryAdminDetailDtoAdmin category detail POST /api/admin/categoriesAdmin + Categories_CREATE body: CreateCategoryDto "" name, slug, description?, parentId?, order?, isVisible?, imageUrl? "" CategoryAdminDetailDtoCreates new category PATCH /api/admin/categories/:idAdmin + Categories_UPDATE path: id (int), body: UpdateCategoryDto "" name?, slug?, description?, parentId?, order?, isVisible?, imageUrl? "" CategoryAdminDetailDtoUpdates category DELETE /api/admin/categories/:idAdmin + Categories_DELETE path: id (int) "" success: true ""Deletes category POST /api/admin/categories/reorderAdmin + Categories_UPDATE body: ReorderCategoriesDto "" ids: number[] "" "" success: true ""Reorders categories GET /api/categoriesPublic QueryCategoriesDto "" page?, size?, parentId?, isVisible?, sort?, order? ""CategoryListItemDto[]Customer category list GET /api/mobile/categoriesPublic QueryCategoriesDto "" page?, size?, parentId?, isVisible?, sort?, order? ""CategoryListItemDto[]Mobile category list GET /api/categories/:slugPublic path: slug (string) CategoryDetailDtoCategory detail by slug (supports historical slugs) GET /api/mobile/categories/:slugPublic path: slug (string) CategoryDetailDtoMobile category detail by slug
Method Path Query Parameters Notes GET /api/admin/categories(no params) Default: page=1, size=20, sort=createdAt, order=desc GET /api/admin/categories?page=2&size=10Custom page and size GET /api/admin/categories?parentId=1Filter by parent GET /api/admin/categories?parentId=nullRoot categories only GET /api/admin/categories?isVisible=trueVisible categories only GET /api/admin/categories?sort=name&order=ascSort by name ascending GET /api/admin/categories?sort=order&order=ascSort by order GET /api/admin/categories?sort=updatedAt&order=descSort by last update GET /api/admin/categories?isVisible=falseHidden categories
Method Path Query Parameters Notes GET /api/categories(no params) Default: no pagination, sort=name, order=asc, isVisible=true GET /api/categories?page=1&size=10Paginated request GET /api/categories?parentId=1Child categories of parent 1 GET /api/categories?parentId=nullRoot categories only GET /api/categories?isVisible=trueExplicit visible filter GET /api/categories?isVisible=falseHidden categories GET /api/categories?sort=name&order=ascSort by name GET /api/categories?sort=order&order=ascSort by display order GET /api/categories?sort=createdAt&order=descSort by creation date GET /api/mobile/categories?parentId=1&isVisible=trueMobile: visible children of parent 1
Method Path Path/Query Parameters Notes GET /api/categories/old-slugslug=old-slug Historical slug fallback GET /api/mobile/categories/tradingslug=trading Mobile slug lookup
Method Path Request Body Notes POST /api/admin/categories"" "name": "Books", "slug": "books", "isVisible": true, "order": 0 ""With visibility and order POST /api/admin/categories"" "name": "Newsletters", "slug": "newsletters", "imageUrl": "https://cdn.example.com/newsletter.jpg" ""With image
Method Path Request Body Notes PATCH /api/admin/categories/1"" "name": "Updated Name" ""Update name only PATCH /api/admin/categories/1"" "slug": "new-slug" ""Update slug PATCH /api/admin/categories/1"" "parentId": 2 ""Move to different parent PATCH /api/admin/categories/1"" "isVisible": false ""Hide category PATCH /api/admin/categories/1"" "order": 5 ""Update display order PATCH /api/admin/categories/1"" "description": "New description" ""Update description
Method Path Request Body Notes POST /api/admin/categories/reorder"" "ids": [5, 2, 7, 1, 3] ""Sets order based on array position
Scenario Constraint Error Self-parent Set parentId to own ID CATEGORY_SELF_PARENTDescendant parent Set parentId to descendant CATEGORY_MOVE_TO_DESCENDANTMissing parent ParentId doesn't exist CATEGORY_MISSING_PARENTDepth exceeded Parent chain > 3 levels CATEGORY_DEPTH_EXCEEDEDHas children Delete category with children CATEGORY_HAS_CHILDREN
HTTP errorCode Message Scenario 400 CATEGORY_SELF_PARENTCategory cannot be its own parent. parentId = self.id 400 CATEGORY_MOVE_TO_DESCENDANTCannot move category under its descendant. Circular hierarchy 400 CATEGORY_MISSING_PARENTParent category not found. Invalid parentId 400 CATEGORY_DEPTH_EXCEEDEDCategory depth cannot exceed 3 levels. Parent chain too deep 400 CATEGORY_DUPLICATE_IDSDuplicate category IDs in reorder request. ids array has duplicates 400 CATEGORY_INVALID_SORTInvalid sort field. Unsupported sort 404 CATEGORY_NOT_FOUNDCategory not found. Invalid ID or slug 409 CATEGORY_HAS_CHILDRENCannot delete category with existing children. Delete with children
Cache Key Pattern TTL (seconds) Invalidation Customer category list catalog:categories:list:parentId:"parentId"-isVisible:"isVisible"-sort:"sort"-order:"order"600 Admin create/update/delete/reorder Category detail by slug catalog:category:slug:"slug"600 Admin update/delete Admin category list catalog:categories:admin:list:pagination:"page"-size:"size"-filters...60 Admin mutations
Route Family Key Pattern Limit Customer list rl:catalog:categories:customer:list-ip:"ip"60 req/min Customer detail rl:catalog:categories:customer:detail-ip:"ip"120 req/min Admin list rl:catalog:categories:admin:list-key:"adminId"60 req/min Admin mutations rl:catalog:categories:admin:mutate-key:"adminId"30 req/min
Field Type Required Validation Notes name string Yes 1-100 chars Category name slug string Yes 1-100 chars, URL-safe URL slug description string No Max 500 chars Category description parentId number No Positive integer Parent category ID order number No Integer Display order isVisible boolean No Default true Visibility flag imageUrl string No Valid URL Category image
Field Type Required Validation Notes name string No 1-100 chars Category name slug string No 1-100 chars, URL-safe URL slug description string No Max 500 chars Category description parentId number No Positive integer Parent category ID order number No Integer Display order isVisible boolean No - Visibility flag imageUrl string No Valid URL Category image
Field Type Required Validation Notes ids number[] Yes Min 1 item, no duplicates Category IDs in desired order
Field Type Required Notes page number No Page number size number No Page size pagination boolean No Enable pagination search string No (admin only) Search query parentId number No Filter by parent isVisible boolean No Filter by visibility sort string No Sort field order string No Sort order
Admin creates root category, creates child category under it, and hierarchy displays correctly.
Admin changes category slug; old slug still resolves via historical slug fallback.
Customer list only returns visible categories; hidden categories filtered out.
Customer requests child categories by parentId; returns only direct children.
Admin attempts to set category as its own parent; receives 400 CATEGORY_SELF_PARENT.
Admin attempts to move category under its descendant; receives 400 CATEGORY_MOVE_TO_DESCENDANT.