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

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

Header Parameters

originstring
curl -X GET "https://api.brainerce.com/api/vc/string/categories" \  -H "origin: string"
{
  "categories": [
    {
      "id": "clcat_abc123",
      "name": "string",
      "slug": "mugs",
      "parentId": null,
      "image": {},
      "translations": {},
      "children": [
        {
          "id": "clcat_abc123",
          "name": "string",
          "slug": "mugs",
          "parentId": null,
          "image": {},
          "translations": {},
          "children": []
        }
      ]
    }
  ]
}

Get category by slug (SEO landing page data)

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
slugstring

Header Parameters

originstring
curl -X GET "https://api.brainerce.com/api/vc/string/categories/slug/string" \  -H "origin: string"
{
  "id": "clcat_abc123",
  "name": "string",
  "slug": "mugs",
  "description": "string",
  "metaDescription": "string",
  "image": {},
  "breadcrumb": [
    {
      "name": "string",
      "slug": "drinkware"
    }
  ],
  "productCount": 24
}

List categories with pagination

GET
/v1/categories
AuthorizationBearer <token>

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

In: header

Query Parameters

platform?string
search?string
limit?number
page?number
curl -X GET "https://api.brainerce.com/api/v1/categories?platform=string&search=string&limit=0&page=0"
{
  "data": [
    {
      "id": "string",
      "accountId": "string",
      "storeId": "string",
      "name": "string",
      "platformIds": {
        "property1": "string",
        "property2": "string"
      },
      "publishedOn": [
        "string"
      ],
      "platformMetadata": {},
      "parentId": "string",
      "slug": "string",
      "description": "string",
      "metaDescription": "string",
      "image": "string",
      "imageKey": "string",
      "isActive": true,
      "taxBehavior": "string",
      "translations": {},
      "deletedAt": "2019-08-24T14:15:22Z",
      "productCount": 0,
      "products": [
        {
          "id": "string",
          "name": "string",
          "sku": "string"
        }
      ],
      "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": 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"
}

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 → Authentication → 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.

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.

Value in"taxable" | "exempt"
googleTaxonomyId?number

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": "string",
  "accountId": "string",
  "storeId": "string",
  "name": "string",
  "platformIds": {
    "property1": "string",
    "property2": "string"
  },
  "publishedOn": [
    "string"
  ],
  "platformMetadata": {},
  "parentId": "string",
  "slug": "string",
  "description": "string",
  "metaDescription": "string",
  "image": "string",
  "imageKey": "string",
  "isActive": true,
  "taxBehavior": "string",
  "translations": {},
  "deletedAt": "2019-08-24T14:15:22Z",
  "productCount": 0,
  "products": [
    {
      "id": "string",
      "name": "string",
      "sku": "string"
    }
  ],
  "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"
}

Get a single category by ID

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

Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → 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": "string",
  "accountId": "string",
  "storeId": "string",
  "name": "string",
  "platformIds": {
    "property1": "string",
    "property2": "string"
  },
  "publishedOn": [
    "string"
  ],
  "platformMetadata": {},
  "parentId": "string",
  "slug": "string",
  "description": "string",
  "metaDescription": "string",
  "image": "string",
  "imageKey": "string",
  "isActive": true,
  "taxBehavior": "string",
  "translations": {},
  "deletedAt": "2019-08-24T14:15:22Z",
  "productCount": 0,
  "products": [
    {
      "id": "string",
      "name": "string",
      "sku": "string"
    }
  ],
  "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}"
}

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 → Authentication → 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

Empty Object

curl -X PATCH "https://api.brainerce.com/api/v1/categories/string" \  -H "Idempotency-Key: string" \  -H "Content-Type: application/json" \  -d '{}'
{
  "id": "string",
  "accountId": "string",
  "storeId": "string",
  "name": "string",
  "platformIds": {
    "property1": "string",
    "property2": "string"
  },
  "publishedOn": [
    "string"
  ],
  "platformMetadata": {},
  "parentId": "string",
  "slug": "string",
  "description": "string",
  "metaDescription": "string",
  "image": "string",
  "imageKey": "string",
  "isActive": true,
  "taxBehavior": "string",
  "translations": {},
  "deletedAt": "2019-08-24T14:15:22Z",
  "productCount": 0,
  "products": [
    {
      "id": "string",
      "name": "string",
      "sku": "string"
    }
  ],
  "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}"
}

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 → Authentication → 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}"
}

Publish a category to a sales-channel site

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 → Authentication → 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 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": 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}/publish-sales-channel"
}

{
  "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"
}

Unpublish a category from a sales-channel site

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 → Authentication → 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 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": 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}/unpublish-sales-channel"
}

{
  "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"
}

On this page

No Headings