Categories API
Organize products into a hierarchical category structure with up to 2 levels of nesting. Use categories for navigation menus, product filtering, and SEO.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /categories | List all categories |
| POST | /categories | Create a category |
| GET | /categories/:id | Get a category |
| PUT | /categories/:id | Update a category |
| DELETE | /categories/:id | Delete a category (soft delete) |
All endpoints are prefixed with /stores/{storeId}.
Category Hierarchy
Categories support a 2-level hierarchy: root categories and subcategories.
📁 Clothing (root)
├── 👕 T-Shirts (subcategory)
├── 👖 Pants
└── 🧥 Jackets
📁 Electronics (root)
├── 📱 Phones
└── 💻 Laptops⚠️ Maximum Depth: Subcategories cannot have children. Attempting to set a subcategory as a parent will return a validation error.
The Category Object
{
"id": "cat_abc123",
"storeId": "store_xyz789",
"name": "T-Shirts",
"slug": "t-shirts",
"status": "published",
"publishedAt": "2024-01-15T10:00:00.000Z",
"description": "Casual and comfortable t-shirts for everyday wear",
"parentId": "cat_clothing",
"seoTitle": "T-Shirts | My Store",
"seoDescription": "Shop our collection of premium t-shirts",
"seoKeywords": "t-shirts, casual wear, cotton shirts",
"seoImageId": "media_123",
"createdAt": "2024-01-10T08:00:00.000Z",
"updatedAt": "2024-01-15T10:00:00.000Z"
}Fields
| Field | Type | Description |
|---|---|---|
| id | string | Unique identifier (UUID) |
| name | string | Display name (required, max 255 chars) |
| slug | string | URL-safe identifier (required, unique) |
| status | string | "draft", "published", or "archived" |
| publishedAt | string? | ISO timestamp when first published |
| description | string? | Category description |
| parentId | string? | Parent category ID (null for root) |
| seoTitle | string? | SEO page title |
| seoDescription | string? | SEO meta description |
| seoKeywords | string? | SEO keywords |
| seoImageId | string? | Media ID for OG image |
List Categories
GET /stores/{storeId}/categoriesQuery Parameters
| Parameter | Type | Description |
|---|---|---|
| limit | integer | Results per page (1-200, default: 50) |
| offset | integer | Number of items to skip |
| status | string | Filter by status |
| slug | string | Find by exact slug |
| parentId | string | Filter by parent (use "null" for root categories) |
| search | string | Search in name and description |
Example: Get Root Categories
curl "https://api.barecommercecore.com/stores/{storeId}/categories?parentId=null&status=published" \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"Example: Get Subcategories
curl "https://api.barecommercecore.com/stores/{storeId}/categories?parentId=cat_clothing" \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"Create Category
POST /stores/{storeId}/categoriesRequired Fields
name— Display nameslug— URL-safe identifier (unique per store)
Example: Create Root Category
curl -X POST "https://api.barecommercecore.com/stores/{storeId}/categories" \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Clothing",
"slug": "clothing",
"status": "published",
"description": "Apparel and fashion items"
}'Example: Create Subcategory
curl -X POST "https://api.barecommercecore.com/stores/{storeId}/categories" \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "T-Shirts",
"slug": "t-shirts",
"status": "published",
"parentId": "cat_clothing"
}'Get Category
GET /stores/{storeId}/categories/{categoryId}Update Category
PUT /stores/{storeId}/categories/{categoryId}Only include fields you want to change.
Example: Move to Different Parent
// Move to become a subcategory
await updateCategory(categoryId, { parentId: 'cat_new_parent' });
// Move to become a root category
await updateCategory(categoryId, { parentId: null });Hierarchy Rules
- A category cannot be its own parent
- A subcategory (has parentId) cannot become a parent
- Moving a parent with children is allowed — children remain attached
Delete Category
DELETE /stores/{storeId}/categories/{categoryId}Returns 204 No Content on success.
ℹ️ Soft Delete: Sets status to "deleted". The category is excluded from queries but preserved in the database.
ℹ️ Child Categories: When you delete a parent category, its subcategories are orphaned — their
parentIdis set tonull, making them root categories.
Common Patterns
Build Navigation Tree
async function getCategoryTree() {
const { items } = await fetch(
'/stores/{storeId}/categories?status=published&limit=200',
{ headers: { 'Authorization': 'Bearer ' + apiKey } }
).then(r => r.json());
const roots = items.filter(c => !c.parentId);
const children = items.filter(c => c.parentId);
return roots.map(root => ({
...root,
children: children.filter(c => c.parentId === root.id),
}));
}Find by Slug (URL Routing)
async function getCategoryBySlug(slug) {
const { items } = await fetch(
`/stores/{storeId}/categories?slug=${slug}&status=published`,
{ headers: { 'Authorization': 'Bearer ' + apiKey } }
).then(r => r.json());
if (items.length === 0) throw new Error('Category not found');
return items[0];
}Build Breadcrumb Path
async function getCategoryBreadcrumb(categoryId) {
const category = await getCategory(categoryId);
const breadcrumb = [category];
if (category.parentId) {
const parent = await getCategory(category.parentId);
breadcrumb.unshift(parent);
}
return breadcrumb;
}Error Responses
409 Duplicate Slug
{
"error": {
"code": "CONFLICT",
"message": "slug already exists"
}
}400 Invalid Parent (Too Deep)
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{ "field": "parentId", "reason": "Maximum category depth is 2 levels" }
]
}
}400 Self-Reference
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{ "field": "parentId", "reason": "Category cannot be its own parent" }
]
}
}Webhooks
category.created— New category createdcategory.updated— Category modifiedcategory.deleted— Category soft-deleted
Related Guides
- Products — Assign products to categories