Brands
Brands are manufacturer/label tags applied to products — used for filtering on the storefront and for analytics segmentation. Each brand has its own page with metadata.
List brands
Returns the brands published to this channel, for filter UIs.
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
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
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
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.
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.
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/brands?locale=string" \ -H "origin: string" \ -H "accept-language: string" \ -H "X-SDK-Version: string"{
"brands": [
{
"id": "clbrd_abc123",
"name": "string",
"translations": {}
}
]
}{
"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}/brands"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/brands"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/brands"
}List brands with pagination
Lists brands, 20 per page.
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
true returns only active brands, false only inactive ones. Omit for both.
Only brands published on this platform code (matched against publishedOn).
Text search on the brand name.
Items per page. Default 20. Maximum 100.
201 <= value <= 1001-based page number.
11 <= valuecurl -X GET "https://api.brainerce.com/api/v1/brands?isActive=true&platform=string&search=string&limit=20&page=1"{
"data": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Acme",
"slug": "acme",
"description": "Outdoor gear since 1998.",
"logo": "https://cdn.example.com/brands/acme.png",
"platformIds": {},
"publishedOn": [
"string"
],
"platformMetadata": {},
"source": "INTERNAL",
"syncStatus": {},
"lastSyncedAt": {},
"translations": {},
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"productCount": 12,
"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": 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/brands"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/brands"
}{
"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/brands"
}{
"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 brand
Supports Idempotency-Key header for safe retries.
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
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 Conflictwithcode: "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
GETreturns400withcode: "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.
length <= 255Brand display name. Unique per store.
Store ID, required when calling via admin API key (path param does not exist on POST /v1/brands). Internal callers omit this and the storeId is resolved from auth context.
URL slug. Auto-generated from name when omitted.
Long-form brand description (plain text).
Brand logo URL. Upload via /v1/media first to get a hosted URL.
R2/S3 object key for logo above. When present, asset-deletion cascade can null this brand's logo automatically. Merchants pasting external CDN URLs omit this; the cascade then treats the brand as orphan.
Active state. Inactive brands stay attached to existing products but are hidden from filter UIs.
Multi-language overrides keyed by ISO locale code. Each value carries the translated name. Only name is applied when a locale is requested; other keys are stored but not used.
curl -X POST "https://api.brainerce.com/api/v1/brands" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Audio" }'{
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Acme",
"slug": "acme",
"description": "Outdoor gear since 1998.",
"logo": "https://cdn.example.com/brands/acme.png",
"platformIds": {},
"publishedOn": [
"string"
],
"platformMetadata": {},
"source": "INTERNAL",
"syncStatus": {},
"lastSyncedAt": {},
"translations": {},
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"productCount": 12,
"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/brands"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/brands"
}{
"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/brands"
}{
"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 brand by ID
Returns one brand of this store.
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
Brand ID
curl -X GET "https://api.brainerce.com/api/v1/brands/string"{
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Acme",
"slug": "acme",
"description": "Outdoor gear since 1998.",
"logo": "https://cdn.example.com/brands/acme.png",
"platformIds": {},
"publishedOn": [
"string"
],
"platformMetadata": {},
"source": "INTERNAL",
"syncStatus": {},
"lastSyncedAt": {},
"translations": {},
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"productCount": 12,
"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/brands/{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/brands/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/brands/{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 brand
Supports Idempotency-Key header for safe retries.
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
Brand ID
Header Parameters
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 Conflictwithcode: "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
GETreturns400withcode: "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.
length <= 255Brand display name. Unique per store.
Store ID, required when calling via admin API key (path param does not exist on POST /v1/brands). Internal callers omit this and the storeId is resolved from auth context.
URL slug. Auto-generated from name when omitted.
Long-form brand description (plain text).
Brand logo URL. Upload via /v1/media first to get a hosted URL.
R2/S3 object key for logo above. When present, asset-deletion cascade can null this brand's logo automatically. Merchants pasting external CDN URLs omit this; the cascade then treats the brand as orphan.
Active state. Inactive brands stay attached to existing products but are hidden from filter UIs.
Multi-language overrides keyed by ISO locale code. Each value carries the translated name. Only name is applied when a locale is requested; other keys are stored but not used.
curl -X PATCH "https://api.brainerce.com/api/v1/brands/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Acme",
"slug": "acme",
"description": "Outdoor gear since 1998.",
"logo": "https://cdn.example.com/brands/acme.png",
"platformIds": {},
"publishedOn": [
"string"
],
"platformMetadata": {},
"source": "INTERNAL",
"syncStatus": {},
"lastSyncedAt": {},
"translations": {},
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"productCount": 12,
"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/brands/{id}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/brands/{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/brands/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/brands/{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 brand
Supports Idempotency-Key header for safe retries.
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
Brand ID
Header Parameters
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 Conflictwithcode: "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
GETreturns400withcode: "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.
length <= 255curl -X DELETE "https://api.brainerce.com/api/v1/brands/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/brands/{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/brands/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/brands/{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 brand to a sales-channel site
Makes the brand available on the given sales channel (storefront). Repeating the call is harmless. A sales channel that is not part of this store, or a brand that is not found, answers 404. Supports Idempotency-Key header for safe retries.
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
Brand ID
Header Parameters
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 Conflictwithcode: "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
GETreturns400withcode: "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.
length <= 255Sales channel record ID or its public vc_* connection ID
curl -X POST "https://api.brainerce.com/api/v1/brands/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/brands/{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/brands/{id}/publish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/brands/{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 brand from a sales-channel site
Removes the brand from the given sales channel (storefront). Repeating the call is harmless. A sales channel that is not part of this store, or a brand that is not found, answers 404. Supports Idempotency-Key header for safe retries.
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
Brand ID
Header Parameters
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 Conflictwithcode: "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
GETreturns400withcode: "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.
length <= 255Sales channel record ID or its public vc_* connection ID
curl -X POST "https://api.brainerce.com/api/v1/brands/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/brands/{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/brands/{id}/unpublish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/brands/{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"
}