Categories
Categories API
Manage product categories for the authenticated store. Categories support a nested tree structure via parent_id, allowing you to build multi-level category hierarchies.
List Categories
Retrieve all categories for the store. Returns a flat list with parent_id for client-side tree building, ordered by position_index then name.
GET /api/apps/v1/categories
Authentication
Required. Must include valid app credentials.
Scope
read:products
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
parent_id | string | -- | Filter by parent category. Use null or 0 for root categories, or a category ID for children of that category |
Example Request
curl -X GET "https://api.selorax.io/api/apps/v1/categories" \
-H "Authorization: Bearer <token>"Get only root categories:
curl -X GET "https://api.selorax.io/api/apps/v1/categories?parent_id=null" \
-H "Authorization: Bearer <token>"Get children of a specific category:
curl -X GET "https://api.selorax.io/api/apps/v1/categories?parent_id=5" \
-H "X-Client-Id: sx_app_..." \
-H "X-Client-Secret: sx_secret_..." \
-H "X-Store-Id: 22"Response
{
"data": [
{
"category_id": 5,
"store_id": 22,
"name": "Flowers",
"slug": "flowers",
"image": "categories/flowers.jpg",
"parent_id": null,
"is_featured": 1,
"position_index": 1,
"created_at": "2025-01-10T08:00:00.000Z",
"updated_at": "2025-06-01T12:00:00.000Z",
"products_count": 24
},
{
"category_id": 8,
"store_id": 22,
"name": "Roses",
"slug": "roses",
"image": null,
"parent_id": 5,
"is_featured": 0,
"position_index": 1,
"created_at": "2025-01-10T08:30:00.000Z",
"updated_at": "2025-06-01T12:00:00.000Z",
"products_count": 12
},
{
"category_id": 6,
"store_id": 22,
"name": "Gift Baskets",
"slug": "gift-baskets",
"image": "categories/gift-baskets.jpg",
"parent_id": null,
"is_featured": 0,
"position_index": 2,
"created_at": "2025-01-10T09:00:00.000Z",
"updated_at": "2025-03-15T10:00:00.000Z",
"products_count": 8
}
],
"status": 200
}Response Fields
| Field | Type | Description |
|---|---|---|
category_id | integer | Unique category identifier |
store_id | integer | Store the category belongs to |
name | string | Category name |
slug | string | URL-friendly slug |
image | string or null | Category image path |
parent_id | integer or null | Parent category ID (null for root categories) |
is_featured | integer (0 or 1) | Whether the category is featured |
position_index | integer or null | Sort order within its level |
products_count | integer | Number of active products in this category |
created_at | string (ISO 8601) | When the category was created |
updated_at | string (ISO 8601) | When the category was last updated |
Building a Category Tree
The list endpoint returns a flat array. To build a tree on the client side, group items by parent_id — entries with parent_id: null are root nodes, and child nodes reference their parent's category_id.
Node.js Example
const response = await fetch(
"https://api.selorax.io/api/apps/v1/categories",
{ headers: { Authorization: "Bearer sx_at_..." } }
);
const { data } = await response.json();
// Build tree from flat list
const roots = data.filter(c => c.parent_id === null);
const children = data.filter(c => c.parent_id !== null);
roots.forEach(root => {
root.children = children.filter(c => c.parent_id === root.category_id);
});Python Example
import requests
response = requests.get(
"https://api.selorax.io/api/apps/v1/categories",
headers={"Authorization": "Bearer sx_at_..."},
)
categories = response.json()["data"]
for cat in categories:
indent = " " if cat["parent_id"] else ""
print(f"{indent}{cat['name']} ({cat['products_count']} products)")Get Category
Retrieve a single category by ID, including its direct children.
GET /api/apps/v1/categories/:category_id
Authentication
Required. Must include valid app credentials.
Scope
read:products
Path Parameters
| Parameter | Type | Description |
|---|---|---|
category_id | integer | The category ID |
Example Request
curl -X GET "https://api.selorax.io/api/apps/v1/categories/5" \
-H "Authorization: Bearer <token>"Response
{
"data": {
"category_id": 5,
"store_id": 22,
"name": "Flowers",
"slug": "flowers",
"image": "categories/flowers.jpg",
"parent_id": null,
"is_featured": 1,
"position_index": 1,
"created_at": "2025-01-10T08:00:00.000Z",
"updated_at": "2025-06-01T12:00:00.000Z",
"products_count": 24,
"children": [
{
"category_id": 8,
"name": "Roses",
"slug": "roses",
"image": null,
"is_featured": 0,
"position_index": 1,
"products_count": 12
},
{
"category_id": 9,
"name": "Tulips",
"slug": "tulips",
"image": null,
"is_featured": 0,
"position_index": 2,
"products_count": 6
}
]
},
"status": 200
}Error Responses
If the category_id does not exist or does not belong to the authenticated store:
{
"message": "Category not found.",
"status": 404
}Create Category
Create a new category. A URL slug is auto-generated from the name if not provided.
POST /api/apps/v1/categories
Authentication
Required. Must include valid app credentials.
Scope
write:products
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Category name (max 255 characters) |
slug | string | No | URL-friendly slug (max 45 characters). Auto-generated from name if omitted |
parent_id | integer or null | No | Parent category ID for nesting. Must belong to the same store |
image | string | No | Category image path |
is_featured | integer | No | 1 to feature, 0 otherwise (default 0) |
position_index | integer | No | Sort position within its level |
Example Request
curl -X POST "https://api.selorax.io/api/apps/v1/categories" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Indoor Plants",
"parent_id": null,
"is_featured": 1,
"position_index": 3
}'Create a subcategory:
curl -X POST "https://api.selorax.io/api/apps/v1/categories" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Succulents",
"parent_id": 10,
"position_index": 1
}'Response
{
"data": {
"category_id": 10,
"store_id": 22,
"name": "Indoor Plants",
"slug": "indoor-plants",
"image": null,
"parent_id": null,
"is_featured": 1,
"position_index": 3,
"created_at": "2025-06-20T10:00:00.000Z",
"updated_at": "2025-06-20T10:00:00.000Z"
},
"message": "Category created.",
"status": 201
}Slug Uniqueness
If the generated slug already exists for the same store, a numeric suffix is appended automatically (e.g. indoor-plants-2).
Error Responses
| Code | Status | Meaning |
|---|---|---|
invalid_token | 401 | Token is expired or invalid |
insufficient_scope | 403 | App does not have write:products scope |
invalid_parent | 400 | The specified parent_id does not exist in this store |
| -- | 400 | Validation error (missing name, etc.) |
Update Category
Update an existing category. Only provided fields are modified.
PUT /api/apps/v1/categories/:category_id
Authentication
Required. Must include valid app credentials.
Scope
write:products
Path Parameters
| Parameter | Type | Description |
|---|---|---|
category_id | integer | The category ID to update |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Category name (max 255 characters) |
slug | string | No | URL-friendly slug (max 45 characters) |
parent_id | integer or null | No | Parent category ID. Set to null to make it a root category |
image | string | No | Category image path |
is_featured | integer | No | 1 to feature, 0 otherwise |
position_index | integer or null | No | Sort position |
At least one field must be provided.
Example Request
curl -X PUT "https://api.selorax.io/api/apps/v1/categories/10" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Houseplants",
"is_featured": 0,
"position_index": 5
}'Response
{
"data": {
"category_id": 10,
"store_id": 22,
"name": "Houseplants",
"slug": "indoor-plants",
"image": null,
"parent_id": null,
"is_featured": 0,
"position_index": 5,
"created_at": "2025-06-20T10:00:00.000Z",
"updated_at": "2025-06-20T15:30:00.000Z"
},
"message": "Category updated.",
"status": 200
}Error Responses
| Code | Status | Meaning |
|---|---|---|
invalid_token | 401 | Token is expired or invalid |
insufficient_scope | 403 | App does not have write:products scope |
invalid_parent | 400 | The specified parent_id does not exist in this store |
self_parent | 400 | A category cannot be its own parent |
| -- | 400 | Validation error |
| -- | 404 | Category not found |
Delete Category
Delete a category. The category must have no products attached — reassign or remove products first.
DELETE /api/apps/v1/categories/:category_id
Authentication
Required. Must include valid app credentials.
Scope
write:products
Path Parameters
| Parameter | Type | Description |
|---|---|---|
category_id | integer | The category ID to delete |
Example Request
curl -X DELETE "https://api.selorax.io/api/apps/v1/categories/10" \
-H "Authorization: Bearer <token>"Response
{
"message": "Category deleted.",
"status": 200
}Error Responses
| Code | Status | Meaning |
|---|---|---|
invalid_token | 401 | Token is expired or invalid |
insufficient_scope | 403 | App does not have write:products scope |
category_has_products | 400 | Cannot delete a category that has products assigned to it |
| -- | 404 | Category not found |
Category with products error:
{
"message": "Cannot delete category with 12 attached product(s). Remove or reassign products first.",
"code": "category_has_products",
"status": 400
}