Blog Categories require blog scopes. Reads use read_blog; writes use write_blog. Blog Categories support name, slug, description, seo_title, seo_description, and template_handle fields. slug is optional on create and generated from the name when omitted; on update, a supplied slug must be non-empty and valid. On create, omitting template_handle assigns default_blog_category. Use default_blog_category for the default Blog Category template, or pass an alternate Blog Category template handle configured for the store. Omit template_handle on update to leave the current assignment unchanged; an empty string is invalid. Deleting a blog category assigned to blog posts is blocked until those posts are moved or unassigned. AI translation is not exposed through the Store API.
Endpoints#
Blog Category limits
Fetch Blog Category limits and per-field constraints.
Returns the per-field maximum lengths and request caps that apply to Blog Category endpoints. Useful for clients to validate inputs before sending them and to size UIs.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
List blog categories
List blog categories for the store.
Returns paginated Blog Categories. Use search to filter by name or slug. Invalid page or limit values are rejected; unsupported sort values fall back to the service's stable default ordering.
Query parameters
| Name | Type | Description |
|---|---|---|
page
|
integer |
Page number. |
limit
|
integer |
Page size. |
search
|
string |
Search Blog Categories by name or slug. |
sort_by
|
string |
Sort field from the Blog Category list contract.
Allowed values
namepost_countcreated_atupdated_at |
sort_direction
|
string |
Sort direction from the Blog Category list contract.
Allowed values
ascdesc |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400VALIDATION_LIST_INVALID_PAGEpage must be a positive integer.
-
400VALIDATION_LIST_INVALID_LIMITlimit must be a positive integer within the contract cap.
-
400BLOG_CATEGORY_SEARCH_TOO_LONGSearch exceeds the Blog Category contract max length.
Get a blog category
Fetch one blog category by id.
Returns the Blog Category if it belongs to the token's store.
Path parameters
| Name | Type | Description |
|---|---|---|
id
required
|
uuid |
Blog Category id. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400STORE_API_INVALID_CATEGORY_IDBlog Category id is not a valid UUID.
-
404NOT_FOUNDBlog Category does not exist in this store.
Create a blog category
Create a blog category.
Creates a Blog Category. name is required. slug is optional on create; when omitted or empty, the backend generates it from the name. Optional SEO and template fields follow the Blog Category resource contract.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
name
required
|
string |
Blog Category name. |
slug
|
string |
Optional slug. Omit to generate from name. |
description
|
string |
Optional plain-text description. |
seo_title
|
string |
Optional SEO title. |
seo_description
|
string |
Optional SEO description. |
template_handle
|
string |
Template assignment. On create, omitting this field or sending an empty string assigns |
Errors
-
400STORE_API_INVALID_REQUEST_BODYRequest body is not valid JSON.
-
400BLOG_CATEGORY_NAME_REQUIREDName is empty after normalization.
-
400BLOG_CATEGORY_NAME_EMPTYA provided update name is empty after normalization.
-
400BLOG_CATEGORY_NAME_TOO_LONGName exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_SLUG_REQUIREDSlug is empty on update. Blank slug auto-generation is only available on create.
-
400BLOG_CATEGORY_SLUG_FORMATSlug is not valid for Blog Category URLs.
-
400BLOG_CATEGORY_SLUG_TOO_LONGSlug exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_SLUG_GENERATION_FAILEDA slug could not be generated from the supplied name.
-
400BLOG_CATEGORY_UNIQUE_SLUG_GENERATION_FAILEDA unique generated slug could not be found; supply a slug explicitly.
-
400BLOG_CATEGORY_DESCRIPTION_TOO_LONGDescription exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_SEO_TITLE_TOO_LONGSEO title exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_SEO_DESCRIPTION_TOO_LONGSEO description exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_LIMIT_REACHEDStore Blog Category cap has been reached.
-
400TEMPLATE_HANDLE_INVALIDTemplate handle is not valid for Blog Category templates.
-
400TEMPLATE_HANDLE_NOT_FOUNDTemplate handle does not exist on the store's primary active theme for Blog Category.
-
409BLOG_CATEGORY_DUPLICATEName or slug already exists in this store.
Update a blog category
Update a blog category.
Updates provided Blog Category fields. Omitted fields are left unchanged. When slug is provided it must be non-empty and valid; create is the only path that auto-generates a blank slug from the name.
Path parameters
| Name | Type | Description |
|---|---|---|
id
required
|
uuid |
Blog Category id. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
name
|
string |
Blog Category name. |
slug
|
string |
New slug. Omit to leave the current slug unchanged; an empty value is invalid. |
description
|
string |
Optional plain-text description. |
seo_title
|
string |
Optional SEO title. |
seo_description
|
string |
Optional SEO description. |
template_handle
|
string |
Template assignment. On create, omitting this field or sending an empty string assigns |
create_redirect
|
boolean |
When slug changes, create a redirect from the previous slug. |
Errors
-
400STORE_API_INVALID_CATEGORY_IDBlog Category id is not a valid UUID.
-
400STORE_API_INVALID_REQUEST_BODYRequest body is not valid JSON.
-
400TRANSLATION_SOURCE_FIELD_HAS_TRANSLATIONSClearing a source field is blocked while translated values exist.
-
404NOT_FOUNDBlog Category does not exist in this store.
-
400BLOG_CATEGORY_NAME_REQUIREDName is empty after normalization.
-
400BLOG_CATEGORY_NAME_EMPTYA provided update name is empty after normalization.
-
400BLOG_CATEGORY_NAME_TOO_LONGName exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_SLUG_REQUIREDSlug is empty on update. Blank slug auto-generation is only available on create.
-
400BLOG_CATEGORY_SLUG_FORMATSlug is not valid for Blog Category URLs.
-
400BLOG_CATEGORY_SLUG_TOO_LONGSlug exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_SLUG_GENERATION_FAILEDA slug could not be generated from the supplied name.
-
400BLOG_CATEGORY_UNIQUE_SLUG_GENERATION_FAILEDA unique generated slug could not be found; supply a slug explicitly.
-
400BLOG_CATEGORY_DESCRIPTION_TOO_LONGDescription exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_SEO_TITLE_TOO_LONGSEO title exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_SEO_DESCRIPTION_TOO_LONGSEO description exceeds the Blog Category contract max length.
-
400BLOG_CATEGORY_LIMIT_REACHEDStore Blog Category cap has been reached.
-
400TEMPLATE_HANDLE_INVALIDTemplate handle is not valid for Blog Category templates.
-
400TEMPLATE_HANDLE_NOT_FOUNDTemplate handle does not exist on the store's primary active theme for Blog Category.
-
409BLOG_CATEGORY_DUPLICATEName or slug already exists in this store.
Delete a blog category
Delete a blog category.
Deletes a Blog Category only when no blog posts are assigned to it. Assigned posts block deletion.
Path parameters
| Name | Type | Description |
|---|---|---|
id
required
|
uuid |
Blog Category id. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400STORE_API_INVALID_CATEGORY_IDBlog Category id is not a valid UUID.
-
404NOT_FOUNDBlog Category does not exist in this store.
-
409BLOG_CATEGORY_HAS_POSTSBlog Category is assigned to blog posts and cannot be deleted until posts are removed from it.
Bulk delete blog categories
Delete multiple blog categories.
Deletes unassigned Blog Categories together. Any that are missing, or still assigned to blog posts, are reported as failures and left in place.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
category_ids
required
|
array<uuid> |
Blog Category ids to delete. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYRequest body is not valid JSON.
-
400STORE_API_INVALID_CATEGORY_IDOne category id is not a valid UUID.
-
400BLOG_CATEGORY_BULK_NO_IDSNo Blog Category ids were provided.
-
400BLOG_CATEGORY_BULK_DELETE_TOO_MANYBatch exceeds the Blog Category bulk delete cap.
-
409BLOG_CATEGORY_BULK_RACEDBlog Category changed during deletion. Retry with fresh data.
-
400STORE_API_INVALID_CATEGORY_IDBlog Category id is not a valid UUID.
-
404NOT_FOUNDBlog Category does not exist in this store.
-
409BLOG_CATEGORY_HAS_POSTSBlog Category is assigned to blog posts and cannot be deleted until posts are removed from it.
Fields#
Field |
Kind |
Create |
Update |
Required |
Translatable |
|---|---|---|---|---|---|
|
text |
Yes |
Yes |
create |
Yes |
|
slug |
Yes |
Yes |
Yes |
|
|
textarea |
Yes |
Yes |
Yes |
|
|
text |
Yes |
Yes |
Yes |
|
|
textarea |
Yes |
Yes |
Yes |
|
|
template |
Yes |
Yes |
No |
|
|
boolean |
No |
Yes |
No |
|
|
integer |
No |
No |
No |
|
|
datetime |
No |
No |
No |
|
|
datetime |
No |
No |
No |
|
|
url |
No |
No |
No |
No |
Webhook events#
Blog Category webhook events are declared by the Blog Category resource contract. The event cards below include the topic, subscription scope, store permission, payload schema, and sample payload.
Blog category created
Fired when a blog category is created.
Payload fields
| Field | Type | Description |
|---|---|---|
blog_category.id |
string |
Always present |
blog_category.name |
string |
Can be removed/added via the Payload builder |
blog_category.slug |
string |
Can be removed/added via the Payload builder |
blog_category.description |
string |
Can be removed/added via the Payload builder |
blog_category.seo_title |
string |
Can be removed/added via the Payload builder |
blog_category.seo_description |
string |
Can be removed/added via the Payload builder |
blog_category.template_handle |
string |
Can be removed/added via the Payload builder |
blog_category.post_count |
integer |
Can be removed/added via the Payload builder |
blog_category.created_at |
string |
Can be removed/added via the Payload builder |
blog_category.updated_at |
string |
Can be removed/added via the Payload builder |
Blog category updated
Fired when a blog category is updated.
Payload fields
| Field | Type | Description |
|---|---|---|
blog_category.id |
string |
Always present |
blog_category.name |
string |
Can be removed/added via the Payload builder |
blog_category.slug |
string |
Can be removed/added via the Payload builder |
blog_category.description |
string |
Can be removed/added via the Payload builder |
blog_category.seo_title |
string |
Can be removed/added via the Payload builder |
blog_category.seo_description |
string |
Can be removed/added via the Payload builder |
blog_category.template_handle |
string |
Can be removed/added via the Payload builder |
blog_category.post_count |
integer |
Can be removed/added via the Payload builder |
blog_category.created_at |
string |
Can be removed/added via the Payload builder |
blog_category.updated_at |
string |
Can be removed/added via the Payload builder |
Blog category deleted
Fired when a blog category is deleted.
Payload fields
| Field | Type | Description |
|---|---|---|
blog_category.id |
string |
Always present |
blog_category.name |
string |
Can be removed/added via the Payload builder |
blog_category.slug |
string |
Can be removed/added via the Payload builder |