API ReferenceEndpointsCategories

Categories

Categories organize products into a hierarchical taxonomy (e.g. "Clothing → Tops → T-shirts"). Each product can belong to multiple categories. Categories have SEO metadata, banners, and per-channel publishing.

List categories

Returns the category tree of categories the merchant published to this channel, with the number of products in each. A category that was not published to this channel is not listed.

GET
/vc/{connectionId}/categories
X-Sales-Channel-Origin<token>

For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.

In: header

Path Parameters

connectionIdstring

Sales channel ID (vc_*), the canonical salesChannelId. connectionId is the deprecated name of the same value and is still the literal path segment.

Query Parameters

locale?string

Language code, for example he. Used only when no Accept-Language header is sent. A language the store does not support, or the store's default language, returns the default text.

Header Parameters

originstring

Origin of the storefront page making the call, for example https://shop.example.com. Required: a request with no Origin header is refused with 403. On a LIVE channel its host must equal the channel's registered domain (or one of its subdomains) or match an allowed origin. A TEST channel with no domain accepts any origin; once a domain is set it is matched as on LIVE.

accept-language?string

Preferred language, for example he. Its first tag is used when it is one of the store's supported languages other than the default; translated fields are then returned in that language. Falls back to the locale query parameter.

X-SDK-Version?string

Version of the calling SDK (the Brainerce SDK sends it automatically). Informational: it is recorded on the channel and never changes the response.

curl -X GET "https://api.brainerce.com/api/vc/string/categories?locale=string" \  -H "origin: string" \  -H "accept-language: string" \  -H "X-SDK-Version: string"
{
  "categories": [
    {
      "id": "clcat_abc123",
      "name": "string",
      "slug": "mugs",
      "parentId": null,
      "image": "https://cdn.brainerce.com/categories/mugs.jpg",
      "translations": {},
      "children": [
        {
          "id": "clcat_abc123",
          "name": "string",
          "slug": "mugs",
          "parentId": null,
          "image": "https://cdn.brainerce.com/categories/mugs.jpg",
          "translations": {},
          "children": []
        }
      ]
    }
  ]
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/vc/{connectionId}/categories"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/vc/{connectionId}/categories"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/vc/{connectionId}/categories"
}

Get category by slug (SEO landing page data)

Returns one published category by slug: name, description HTML, SEO meta, breadcrumb and product count. List its products with products?categories=<id>.

GET
/vc/{connectionId}/categories/slug/{slug}
X-Sales-Channel-Origin<token>

For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.

In: header

Path Parameters

connectionIdstring

Sales channel ID (vc_*), the canonical salesChannelId. connectionId is the deprecated name of the same value and is still the literal path segment.

slugstring

Category slug.

Query Parameters

locale?string

Language code, for example he. Used only when no Accept-Language header is sent. A language the store does not support, or the store's default language, returns the default text.

Header Parameters

originstring

Origin of the storefront page making the call, for example https://shop.example.com. Required: a request with no Origin header is refused with 403. On a LIVE channel its host must equal the channel's registered domain (or one of its subdomains) or match an allowed origin. A TEST channel with no domain accepts any origin; once a domain is set it is matched as on LIVE.

accept-language?string

Preferred language, for example he. Its first tag is used when it is one of the store's supported languages other than the default; translated fields are then returned in that language. Falls back to the locale query parameter.

X-SDK-Version?string

Version of the calling SDK (the Brainerce SDK sends it automatically). Informational: it is recorded on the channel and never changes the response.

curl -X GET "https://api.brainerce.com/api/vc/string/categories/slug/string?locale=string" \  -H "origin: string" \  -H "accept-language: string" \  -H "X-SDK-Version: string"
{
  "id": "clcat_abc123",
  "name": "string",
  "slug": "mugs",
  "description": "string",
  "metaDescription": "string",
  "image": "https://cdn.brainerce.com/categories/mugs.jpg",
  "breadcrumb": [
    {
      "name": "string",
      "slug": "drinkware"
    }
  ],
  "productCount": 24
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/vc/{connectionId}/categories/slug/{slug}"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/vc/{connectionId}/categories/slug/{slug}"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/vc/{connectionId}/categories/slug/{slug}"
}

List categories with pagination

Lists categories, 20 per page.

GET
/v1/categories
AuthorizationBearer <token>

Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.

In: header

Query Parameters

isActive?boolean

true returns only active categories, false only inactive ones. Omit for both.

platform?string

Only categories published on this platform code (matched against publishedOn).

search?string

Text search on the category name.

limit?integer

Items per page. Default 20. Maximum 100.

Default20
Range1 <= value <= 100
page?integer

1-based page number.

Default1
Range1 <= value
curl -X GET "https://api.brainerce.com/api/v1/categories?isActive=true&platform=string&search=string&limit=20&page=1"
{
  "data": [
    {
      "id": "clx1a2b3c4d5e6f7g8h9",
      "accountId": "clx1a2b3c4d5e6f7g8h9",
      "storeId": "clx1a2b3c4d5e6f7g8h9",
      "name": "Shoes",
      "platformIds": {},
      "publishedOn": [
        "string"
      ],
      "platformMetadata": {
        "GOOGLE_TAXONOMY": {
          "taxonomyId": 0,
          "taxonomyPath": "string",
          "source": "auto",
          "resolvedAt": "2019-08-24T14:15:22Z"
        },
        "property1": {},
        "property2": {}
      },
      "parentId": "clx1a2b3c4d5e6f7g8h9",
      "slug": "shoes",
      "description": "All footwear",
      "metaDescription": "Shop shoes for every season",
      "image": "https://cdn.example.com/categories/shoes.jpg",
      "imageKey": "categories/shoes.jpg",
      "isActive": true,
      "taxBehavior": "taxable",
      "translations": {},
      "deletedAt": "2019-08-24T14:15:22Z",
      "productCount": 24,
      "products": [
        {
          "id": "clx1a2b3c4d5e6f7g8h9",
          "name": "Classic T-Shirt",
          "sku": "TSHIRT-BLK-M"
        }
      ],
      "channelPublishes": [
        {
          "salesChannel": {
            "id": "clx1a2b3c4d5e6f7g8h9",
            "name": "My storefront",
            "connectionId": "vc_9f3a2b1c8d7e6f5a"
          },
          "connection": {
            "id": "clx1a2b3c4d5e6f7g8h9",
            "name": "My storefront",
            "connectionId": "vc_9f3a2b1c8d7e6f5a"
          }
        }
      ],
      "vibeCodedPublishes": [
        {
          "salesChannel": {
            "id": "clx1a2b3c4d5e6f7g8h9",
            "name": "My storefront",
            "connectionId": "vc_9f3a2b1c8d7e6f5a"
          },
          "connection": {
            "id": "clx1a2b3c4d5e6f7g8h9",
            "name": "My storefront",
            "connectionId": "vc_9f3a2b1c8d7e6f5a"
          }
        }
      ],
      "createdAt": "2019-08-24T14:15:22Z",
      "updatedAt": "2019-08-24T14:15:22Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 137,
    "totalPages": 7
  }
}

{
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "message": "name should not be empty, price must be a positive number",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/store"
}

Create a new category

Supports Idempotency-Key header for safe retries.

POST
/v1/categories
AuthorizationBearer <token>

Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.

In: header

Header Parameters

Idempotency-Key?string

Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.

  • Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
  • Reusing a key with a different body returns 409 Conflict with code: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response.
  • Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
  • Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
  • Sending this header on a GET returns 400 with code: "IDEMPOTENCY_KEY_NOT_SUPPORTED" — GETs are already idempotent.
  • Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.

See /docs/api/idempotency.

Lengthlength <= 255
namestring

Category display name.

storeId?string

Store ID. See CreateBrandDto.storeId notes; resolved from auth when omitted.

parentId?string

Parent category ID. Omit for a root category. Categories form a tree, and depth-2 is the practical limit before the storefront filter UI degrades.

isActive?boolean

Active state. Inactive categories stay attached to products but are hidden from storefront filters.

source?string

Origin platform. Defaults to INTERNAL. Connector-sourced categories are managed by the connector and auto-deactivate on disconnect.

Default"INTERNAL"
Value in"INTERNAL" | "SHOPIFY" | "WOOCOMMERCE" | "TIKTOK" | "META"
image?string

Category banner image URL. Upload via /v1/media first.

imageKey?string

R2/S3 object key for image above. When present, asset-deletion cascade can null this category's image automatically.

taxBehavior?string

Tax inheritance. taxable (default) inherits the product's tax category; exempt overrides every product in this category to be tax-exempt regardless of the product's own setting.

Default"taxable"
Value in"taxable" | "exempt"
googleTaxonomyId?integer

Merchant override for Google's numeric product taxonomy id (Merchant Center google_product_category). Omit to let the name-based auto-resolver assign one.

description?string

Long-form category copy (HTML) rendered on the storefront category landing page.

metaDescription?string

for the category page. 50-160 characters recommended.

curl -X POST "https://api.brainerce.com/api/v1/categories" \  -H "Idempotency-Key: string" \  -H "Content-Type: application/json" \  -d '{    "name": "Headphones"  }'
{
  "id": "clx1a2b3c4d5e6f7g8h9",
  "accountId": "clx1a2b3c4d5e6f7g8h9",
  "storeId": "clx1a2b3c4d5e6f7g8h9",
  "name": "Shoes",
  "platformIds": {},
  "publishedOn": [
    "string"
  ],
  "platformMetadata": {
    "GOOGLE_TAXONOMY": {
      "taxonomyId": 0,
      "taxonomyPath": "string",
      "source": "auto",
      "resolvedAt": "2019-08-24T14:15:22Z"
    },
    "property1": {},
    "property2": {}
  },
  "parentId": "clx1a2b3c4d5e6f7g8h9",
  "slug": "shoes",
  "description": "All footwear",
  "metaDescription": "Shop shoes for every season",
  "image": "https://cdn.example.com/categories/shoes.jpg",
  "imageKey": "categories/shoes.jpg",
  "isActive": true,
  "taxBehavior": "taxable",
  "translations": {},
  "deletedAt": "2019-08-24T14:15:22Z",
  "productCount": 24,
  "products": [
    {
      "id": "clx1a2b3c4d5e6f7g8h9",
      "name": "Classic T-Shirt",
      "sku": "TSHIRT-BLK-M"
    }
  ],
  "channelPublishes": [
    {
      "salesChannel": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      },
      "connection": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      }
    }
  ],
  "vibeCodedPublishes": [
    {
      "salesChannel": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      },
      "connection": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      }
    }
  ],
  "createdAt": "2019-08-24T14:15:22Z",
  "updatedAt": "2019-08-24T14:15:22Z"
}

{
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "message": "name should not be empty, price must be a positive number",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/store"
}

Get a single category by ID

Returns one category of this store.

GET
/v1/categories/{id}
AuthorizationBearer <token>

Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.

In: header

Path Parameters

idstring

Category ID

curl -X GET "https://api.brainerce.com/api/v1/categories/string"
{
  "id": "clx1a2b3c4d5e6f7g8h9",
  "accountId": "clx1a2b3c4d5e6f7g8h9",
  "storeId": "clx1a2b3c4d5e6f7g8h9",
  "name": "Shoes",
  "platformIds": {},
  "publishedOn": [
    "string"
  ],
  "platformMetadata": {
    "GOOGLE_TAXONOMY": {
      "taxonomyId": 0,
      "taxonomyPath": "string",
      "source": "auto",
      "resolvedAt": "2019-08-24T14:15:22Z"
    },
    "property1": {},
    "property2": {}
  },
  "parentId": "clx1a2b3c4d5e6f7g8h9",
  "slug": "shoes",
  "description": "All footwear",
  "metaDescription": "Shop shoes for every season",
  "image": "https://cdn.example.com/categories/shoes.jpg",
  "imageKey": "categories/shoes.jpg",
  "isActive": true,
  "taxBehavior": "taxable",
  "translations": {},
  "deletedAt": "2019-08-24T14:15:22Z",
  "productCount": 24,
  "products": [
    {
      "id": "clx1a2b3c4d5e6f7g8h9",
      "name": "Classic T-Shirt",
      "sku": "TSHIRT-BLK-M"
    }
  ],
  "channelPublishes": [
    {
      "salesChannel": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      },
      "connection": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      }
    }
  ],
  "vibeCodedPublishes": [
    {
      "salesChannel": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      },
      "connection": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      }
    }
  ],
  "createdAt": "2019-08-24T14:15:22Z",
  "updatedAt": "2019-08-24T14:15:22Z"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/store"
}

Update a category

Supports Idempotency-Key header for safe retries.

PATCH
/v1/categories/{id}
AuthorizationBearer <token>

Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.

In: header

Path Parameters

idstring

Category ID

Header Parameters

Idempotency-Key?string

Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.

  • Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
  • Reusing a key with a different body returns 409 Conflict with code: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response.
  • Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
  • Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
  • Sending this header on a GET returns 400 with code: "IDEMPOTENCY_KEY_NOT_SUPPORTED" — GETs are already idempotent.
  • Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.

See /docs/api/idempotency.

Lengthlength <= 255
name?string

New category display name.

parentId?string | null

Parent category ID. Pass null to make this a root category.

isActive?boolean

Active state. Inactive categories stay attached to products but are hidden from storefront filters.

image?string | null

Category banner image URL. Upload via /v1/media first. Pass null to clear.

imageKey?string | null

R2/S3 object key for image. Pass null to clear it.

taxBehavior?string

Tax inheritance. taxable inherits the product's tax category; exempt makes every product in this category tax-exempt regardless of the product's own setting.

Value in"taxable" | "exempt"
translations?object

Translated category fields keyed by ISO locale code. Merged into the stored translations: a locale sent here replaces that locale, other locales are kept.

googleTaxonomyId?integer | null

Merchant override for Google's numeric product taxonomy id (Merchant Center google_product_category). A valid id pins it permanently; null clears the override and re-resolves it from the current name.

description?string | null

Long-form category copy (HTML) shown on the storefront category page. Pass null to clear.

metaDescription?string | null

<meta name="description"> for the category page. 50 to 160 characters recommended. Pass null to clear.

curl -X PATCH "https://api.brainerce.com/api/v1/categories/string" \  -H "Idempotency-Key: string" \  -H "Content-Type: application/json" \  -d '{}'
{
  "id": "clx1a2b3c4d5e6f7g8h9",
  "accountId": "clx1a2b3c4d5e6f7g8h9",
  "storeId": "clx1a2b3c4d5e6f7g8h9",
  "name": "Shoes",
  "platformIds": {},
  "publishedOn": [
    "string"
  ],
  "platformMetadata": {
    "GOOGLE_TAXONOMY": {
      "taxonomyId": 0,
      "taxonomyPath": "string",
      "source": "auto",
      "resolvedAt": "2019-08-24T14:15:22Z"
    },
    "property1": {},
    "property2": {}
  },
  "parentId": "clx1a2b3c4d5e6f7g8h9",
  "slug": "shoes",
  "description": "All footwear",
  "metaDescription": "Shop shoes for every season",
  "image": "https://cdn.example.com/categories/shoes.jpg",
  "imageKey": "categories/shoes.jpg",
  "isActive": true,
  "taxBehavior": "taxable",
  "translations": {},
  "deletedAt": "2019-08-24T14:15:22Z",
  "productCount": 24,
  "products": [
    {
      "id": "clx1a2b3c4d5e6f7g8h9",
      "name": "Classic T-Shirt",
      "sku": "TSHIRT-BLK-M"
    }
  ],
  "channelPublishes": [
    {
      "salesChannel": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      },
      "connection": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      }
    }
  ],
  "vibeCodedPublishes": [
    {
      "salesChannel": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      },
      "connection": {
        "id": "clx1a2b3c4d5e6f7g8h9",
        "name": "My storefront",
        "connectionId": "vc_9f3a2b1c8d7e6f5a"
      }
    }
  ],
  "createdAt": "2019-08-24T14:15:22Z",
  "updatedAt": "2019-08-24T14:15:22Z"
}

{
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "message": "name should not be empty, price must be a positive number",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/store"
}

Delete a category

Supports Idempotency-Key header for safe retries.

DELETE
/v1/categories/{id}
AuthorizationBearer <token>

Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.

In: header

Path Parameters

idstring

Category ID

Header Parameters

Idempotency-Key?string

Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.

  • Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
  • Reusing a key with a different body returns 409 Conflict with code: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response.
  • Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
  • Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
  • Sending this header on a GET returns 400 with code: "IDEMPOTENCY_KEY_NOT_SUPPORTED" — GETs are already idempotent.
  • Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.

See /docs/api/idempotency.

Lengthlength <= 255
curl -X DELETE "https://api.brainerce.com/api/v1/categories/string" \  -H "Idempotency-Key: string"
Empty

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/store"
}

Publish a category to a sales-channel site

Makes the category available on the given sales channel (storefront). Repeating the call is harmless. A sales channel that is not part of this store, or a category that is not found, answers 404. Supports Idempotency-Key header for safe retries.

POST
/v1/categories/{id}/publish-sales-channel
AuthorizationBearer <token>

Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.

In: header

Path Parameters

idstring

Category ID

Header Parameters

Idempotency-Key?string

Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.

  • Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
  • Reusing a key with a different body returns 409 Conflict with code: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response.
  • Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
  • Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
  • Sending this header on a GET returns 400 with code: "IDEMPOTENCY_KEY_NOT_SUPPORTED" — GETs are already idempotent.
  • Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.

See /docs/api/idempotency.

Lengthlength <= 255
salesChannelIdstring

Sales channel record ID or its public vc_* connection ID

curl -X POST "https://api.brainerce.com/api/v1/categories/string/publish-sales-channel" \  -H "Idempotency-Key: string" \  -H "Content-Type: application/json" \  -d '{    "salesChannelId": "string"  }'
{
  "success": true
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}/publish-sales-channel"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}/publish-sales-channel"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}/publish-sales-channel"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/store"
}

Unpublish a category from a sales-channel site

Removes the category from the given sales channel (storefront). Repeating the call is harmless. A sales channel that is not part of this store, or a category that is not found, answers 404. Supports Idempotency-Key header for safe retries.

POST
/v1/categories/{id}/unpublish-sales-channel
AuthorizationBearer <token>

Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.

In: header

Path Parameters

idstring

Category ID

Header Parameters

Idempotency-Key?string

Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.

  • Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
  • Reusing a key with a different body returns 409 Conflict with code: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response.
  • Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
  • Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
  • Sending this header on a GET returns 400 with code: "IDEMPOTENCY_KEY_NOT_SUPPORTED" — GETs are already idempotent.
  • Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.

See /docs/api/idempotency.

Lengthlength <= 255
salesChannelIdstring

Sales channel record ID or its public vc_* connection ID

curl -X POST "https://api.brainerce.com/api/v1/categories/string/unpublish-sales-channel" \  -H "Idempotency-Key: string" \  -H "Content-Type: application/json" \  -d '{    "salesChannelId": "string"  }'
{
  "success": true
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}/unpublish-sales-channel"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}/unpublish-sales-channel"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/categories/{id}/unpublish-sales-channel"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/store"
}