API ReferenceEndpointsStorefront catalog

Storefront catalog

The read-only catalogue calls a storefront makes to render itself, authenticated with the sales-channel id (vc_*) in the path plus the browser Origin header of the registered domain. It covers channel capabilities and connection info, the product list, a product by id or by slug, search suggestions, product recommendations, discount badges and banners, the sitemap feed and slug redirects. None of these calls changes catalogue, order or customer data; POST ping only records the storefront heartbeat on the channel. Each operation names the sales-channel scope it needs (usually products:read). Categories, brands, tags and metafields have their own pages.

Ping (storefront heartbeat)

Public heartbeat that marks the channel CONNECTED, records lastPingAt and counts one request. The storefront SDK has no method for it and nothing in the SDK calls it, and a storefront never needs to: any other request to the channel also keeps it in use. Call it only from your own script or health check. No bearer token is required; the endpoint is scoped by connectionId (vc_…) in the URL. Origin validation follows SalesChannelsService.findByConnectionId: LIVE channels and TEST channels with a configured domain require a matching Origin; a TEST channel with no domain configured allows any Origin (see that method’s doc comment). The domain itself is never auto-registered from a ping: it is set only via the dashboard.

POST
/vc/{connectionId}/ping

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.

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.

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 POST "https://api.brainerce.com/api/vc/string/ping" \  -H "origin: string" \  -H "X-SDK-Version: string"
{
  "success": true,
  "connectionId": "vc_abc123",
  "storeName": "string"
}

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

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

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

Get storefront connection info

Public bootstrap payload for the storefront SDK: store identity, allowed scopes, upsell flags, i18n config, and the tracking tag ids (GA4 / GTM / Meta / TikTok) resolved from the merchant’s connected marketplace apps. No bearer token is required; the endpoint is scoped by connectionId (vc_…) in the URL and the Origin header is validated against the channel’s registered domain. tracking is cached for 5 minutes, so a newly connected app starts tagging within that window without any redeploy.

GET
/vc/{connectionId}/info

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/info?locale=string" \  -H "origin: string" \  -H "accept-language: string" \  -H "X-SDK-Version: string"
{
  "id": "cls1a2b3c4d5e6f7g8h9",
  "name": "Acme Coffee",
  "currency": "USD",
  "language": "en",
  "timezone": "Asia/Jerusalem",
  "metaDescription": null,
  "logo": null,
  "contactEmail": null,
  "contactPhone": null,
  "socialLinks": {},
  "donationsEnabled": false,
  "reviewsEnabled": true,
  "connectionId": "vc_abc123",
  "salesChannelId": "vc_abc123",
  "storeName": "Acme Coffee",
  "channelName": "Acme web storefront",
  "channelLogo": null,
  "status": "CONNECTED",
  "salesChannelStatus": "CONNECTED",
  "allowedScopes": [
    "products:read",
    "cart:write",
    "checkout:write"
  ],
  "ordersWriteEnabled": false,
  "guestCheckoutTracking": true,
  "requireEmailVerification": false,
  "requireBirthday": false,
  "sandboxPaymentsEnabled": false,
  "stockAlertsEnabled": true,
  "upsell": {
    "freeShippingThreshold": 100,
    "freeShippingBarEnabled": true,
    "frequentlyBoughtTogetherEnabled": true,
    "cartUpgradeBannerEnabled": true,
    "cartBundleEnabled": true,
    "checkoutOrderBumpEnabled": true
  },
  "i18n": {
    "enabled": true,
    "defaultLocale": "en",
    "defaultDirection": "ltr",
    "supportedLocales": [
      "en",
      "he"
    ],
    "supportedLocaleObjects": [
      {
        "code": "he",
        "direction": "rtl",
        "isDefault": false
      }
    ]
  },
  "seo": {
    "indexNowKey": null,
    "googleSiteVerification": null
  },
  "ucp": {
    "profile": {
      "ucp": {
        "version": "2026-04-08",
        "services": {},
        "capabilities": {},
        "payment_handlers": {}
      }
    }
  },
  "shipping": [
    {
      "countries": [
        "US",
        "CA"
      ],
      "rateType": "FLAT_RATE",
      "amount": 9.9,
      "minDeliveryDays": 2,
      "maxDeliveryDays": 5,
      "handlingTime": 1
    }
  ],
  "tracking": {
    "ga4MeasurementId": "G-ABC123XYZ9",
    "gtmContainerId": "GTM-ABC123",
    "metaPixelId": "123456789012345",
    "tiktokPixelId": "C1234567890ABCDEFGHI"
  }
}

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

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

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

List capabilities

Returns what the merchant configured for this channel: store name, currency and languages, the scopes and checkout settings of the channel, and which optional features exist (payment providers, social login, shipping zones, discount rules, downloadable products, coupons, checkout custom fields, content, donations, gift cards, loyalty). Read it first to decide which parts of the storefront to build.

GET
/vc/{connectionId}/capabilities
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.

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.

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/capabilities" \  -H "origin: string" \  -H "X-SDK-Version: string"
{
  "store": {
    "name": "Acme Coffee",
    "channelName": "Acme web storefront",
    "currency": "USD",
    "language": "en",
    "i18n": {
      "enabled": true,
      "defaultLocale": "en",
      "defaultDirection": "ltr",
      "supportedLocales": [
        "en",
        "he"
      ],
      "supportedLocaleObjects": [
        {
          "code": "he",
          "direction": "rtl",
          "isDefault": false
        }
      ]
    }
  },
  "connection": {
    "allowedScopes": [
      "products:read",
      "cart:write",
      "checkout:write"
    ],
    "ordersWriteEnabled": false,
    "guestCheckoutTracking": true,
    "requireEmailVerification": false,
    "requireBirthday": false,
    "sandboxPaymentsEnabled": false,
    "reservationStrategy": "ON_PAYMENT",
    "reservationTimeout": 15,
    "lowStockWarning": true,
    "lowStockThreshold": 5,
    "stockAlertsEnabled": true
  },
  "features": {
    "paymentProviders": [
      {
        "name": "Stripe",
        "provider": "stripe"
      }
    ],
    "oauthProviders": [
      {
        "provider": "GOOGLE",
        "isEnabled": true
      }
    ],
    "oauthRedirectReady": true,
    "oauthRedirectBlockedReason": "no-domain",
    "hasShippingZones": true,
    "hasDiscountRules": false,
    "hasDownloadableProducts": false,
    "hasCoupons": true,
    "hasCheckoutCustomFields": false,
    "hasContent": false,
    "hasDonations": false,
    "hasGiftCards": false,
    "hasLoyaltyProgram": false,
    "hasReferralProgram": false,
    "hasBirthdayRewards": false,
    "hasBadges": false,
    "hasPaidMembership": false,
    "hasAiRewardRecommendation": false
  }
}

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

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

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

List products

Lists the active products published to this channel, with the channel price overlay and discounts applied. The result is cached for 15 seconds per distinct query and language, and a disabled channel or suspended store can keep serving it for up to that long. Products the merchant did not publish to this channel never appear.

GET
/vc/{connectionId}/products
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

page?integer

Page number, starting at 1.

Default1
limit?integer

Page size. Values above 100 are capped at 100.

Default50
Rangevalue <= 100
search?string

Case-insensitive text search over product name, SKU, description, and the names of its categories, tags and brands.

categories?string

Comma-separated category ids. Each category also matches its published descendants. An id the channel does not publish matches nothing.

brands?string

Comma-separated brand ids. A product matches when it has any of them.

tags?string

Comma-separated tag ids. A product matches when it has any of them.

minPrice?string

Minimum price in the store currency, compared with the product's stored base price (a variable product's parent price), not with a sale price.

maxPrice?string

Maximum price in the store currency, compared the same way as minPrice.

metafields?string

URL-encoded JSON object { "<metafield key>": ["value", ...] }. Only definitions that are filterable, active and published to this channel are applied, the rest are ignored. Values of one key are OR-ed, different keys are AND-ed. Malformed JSON or a non-object answers 400.

sortBy?string

Sort field. Any other value, or none, uses the merchant menu order and then newest first.

Value in"name" | "price" | "createdAt"
sortOrder?string

Sort direction for sortBy. Only desc reverses it; any other value is asc.

Default"asc"
Value in"asc" | "desc"
regionId?string

Buyer region id from regions. When its currency differs from the store currency, each product and variant also carries displayPrice and displayCurrency converted from the latest daily FX rate. A region that charges its own currency uses the buffered charging rate and any manual region price. An unknown id is ignored.

ids?string

Return only these products: comma-separated product ids, at most 100 distinct ids (more answers 400). Duplicates are ignored. The channel rules still apply, so an id that is unknown, belongs to another store or is not published on this channel is absent from the answer. An EMPTY value (ids=) returns no products, never the whole catalogue. It combines with limit: send limit=100 when you ask for up to 100 ids, or the page size cuts the answer short.

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/products?page=1&limit=50&search=mug&categories=clcat_a%2Cclcat_b&brands=string&tags=string&minPrice=10&maxPrice=100&metafields=%7B%22color%22%3A%5B%22red%22%2C%22blue%22%5D%7D&sortBy=name&sortOrder=asc&regionId=string&ids=clx1a2b3c4d5e6f7g8h9%2Cclx9h8g7f6e5d4c3b2a1&locale=string" \  -H "origin: string" \  -H "accept-language: string" \  -H "X-SDK-Version: string"
{
  "data": [
    {}
  ],
  "meta": {
    "page": 1,
    "limit": 50,
    "total": 137,
    "totalPages": 3
  }
}

{
  "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/vc/{connectionId}/products"
}

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

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

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

List products for sitemap generation (slug + updatedAt only)

Lightweight product feed for sitemap generation: id, slug, updatedAt and per-language slugs of every active product published to this channel, newest update first, in one call. Use it instead of paging products, which caps limit at 100.

GET
/vc/{connectionId}/sitemap-products
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

limit?integer

Maximum products returned. Values above 5000 are capped at 5000.

Default5000
Rangevalue <= 5000

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.

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/sitemap-products?limit=5000" \  -H "origin: string" \  -H "X-SDK-Version: string"
{
  "data": [
    {
      "id": "clprod_abc123",
      "slug": "blue-mug",
      "updatedAt": "2019-08-24T14:15:22Z",
      "localeSlugs": {
        "fr": "tasse-bleue"
      }
    }
  ],
  "meta": {
    "total": 120
  }
}

{
  "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}/sitemap-products"
}

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

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

Resolve a renamed slug to its current slug (301 support)

Resolves a renamed slug to the current slug so the storefront can answer with a permanent redirect instead of a 404. Only slugs that were changed are recorded. Unlike the other catalog reads it checks no scope.

GET
/vc/{connectionId}/slug-redirects/{entityType}/{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.

entityTypestring

What the slug belongs to: product or blog. Anything else answers 400.

slugstring

The old slug that no longer resolves.

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.

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/slug-redirects/string/string" \  -H "origin: string" \  -H "X-SDK-Version: string"
{
  "currentSlug": "blue-mug"
}

{
  "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/vc/{connectionId}/slug-redirects/{entityType}/{slug}"
}

{
  "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}/slug-redirects/{entityType}/{slug}"
}

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

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

Get product by slug

Returns one active product by slug, with channel overlay, discount and related-product recommendations. With a non-default Accept-Language the slug is also matched against translated slugs. A product that is not published to this channel is a 404.

GET
/vc/{connectionId}/products/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

Product slug (or its translated slug in the requested language).

Query Parameters

regionId?string

Buyer region id from regions. When its currency differs from the store currency, each product and variant also carries displayPrice and displayCurrency converted from the latest daily FX rate. A region that charges its own currency uses the buffered charging rate and any manual region price. An unknown id is ignored.

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/products/slug/string?regionId=string&locale=string" \  -H "origin: string" \  -H "accept-language: string" \  -H "X-SDK-Version: string"
{
  "id": "clp1a2b3c4d5e6f7g8h9",
  "name": "Blue mug",
  "slug": "blue-mug",
  "sku": "MUG-BLUE",
  "gtin": null,
  "mpn": null,
  "faq": [
    {
      "q": "string",
      "a": "string"
    }
  ],
  "salePriceStartsAt": null,
  "salePriceEndsAt": null,
  "description": "A hand made ceramic mug.",
  "descriptionFormat": "text",
  "seoTitle": null,
  "seoDescription": null,
  "metaDescription": null,
  "type": "SIMPLE",
  "status": "active",
  "basePrice": "24.90",
  "salePrice": "19.90",
  "priceMin": null,
  "priceMax": null,
  "priceVaries": false,
  "avgRating": 4.5,
  "reviewCount": 12,
  "localeSlugs": {
    "he": "ספל-כחול"
  },
  "images": [
    {
      "url": "https://cdn.brainerce.com/products/abc123.jpg",
      "alt": "Blue mug"
    }
  ],
  "categories": [
    {
      "id": "clc1a2b3c4d5e6f7g8h9",
      "name": "Mugs",
      "slug": "mugs",
      "translations": {}
    }
  ],
  "brands": [
    {
      "id": "clb1a2b3c4d5e6f7g8h9",
      "name": "Acme",
      "translations": {}
    }
  ],
  "tags": [
    {
      "id": "clb1a2b3c4d5e6f7g8h9",
      "name": "Acme",
      "translations": {}
    }
  ],
  "inventory": {
    "total": 42,
    "available": 39,
    "trackingMode": "TRACKED",
    "inStock": true,
    "canPurchase": true,
    "backorderMode": "NONE"
  },
  "variants": [
    {
      "id": "clv1a2b3c4d5e6f7g8h9",
      "sku": "MUG-BLUE-L",
      "name": "Blue / Large",
      "translations": {},
      "attributes": {
        "Color": "Blue",
        "Size": "L"
      },
      "price": "24.90",
      "salePrice": "19.90",
      "salePriceStartsAt": "2026-11-01T00:00:00.000Z",
      "salePriceEndsAt": "2026-11-30T23:59:59.000Z",
      "image": {
        "url": "https://cdn.brainerce.com/products/abc123.jpg",
        "alt": "Blue mug"
      },
      "inventory": {
        "total": 42,
        "available": 39,
        "trackingMode": "TRACKED",
        "inStock": true,
        "canPurchase": true,
        "backorderMode": "NONE"
      },
      "displayPrice": "22.40",
      "displaySalePrice": "17.90",
      "displayCurrency": "EUR"
    }
  ],
  "createdAt": "2026-01-15T10:30:00.000Z",
  "updatedAt": "2026-02-01T08:00:00.000Z",
  "productAttributeOptions": [
    {
      "id": "clp1a2b3c4d5e6f7g8h9",
      "attribute": {
        "id": "cla1a2b3c4d5e6f7g8h9",
        "name": "Color",
        "displayType": "COLOR_SWATCH",
        "translations": {}
      },
      "attributeOption": {
        "id": "clo1a2b3c4d5e6f7g8h9",
        "name": "Blue",
        "swatchColor": "#1E40AF",
        "swatchColor2": null,
        "swatchImageUrl": null,
        "translations": {}
      }
    }
  ],
  "metafields": [
    {
      "id": "clm1a2b3c4d5e6f7g8h9",
      "definitionId": "cld1a2b3c4d5e6f7g8h9",
      "definitionKey": "material",
      "definitionName": "Material",
      "type": "TEXT",
      "value": "Ceramic",
      "translations": {},
      "variantId": null
    }
  ],
  "customizationFields": [
    {
      "definitionId": "cld1a2b3c4d5e6f7g8h9",
      "name": "Engraving text",
      "key": "engraving",
      "description": "Up to 20 characters",
      "type": "TEXT",
      "required": false,
      "minLength": 1,
      "maxLength": 20,
      "minValue": 0,
      "maxValue": 100,
      "enumValues": [
        "string"
      ],
      "defaultValue": null,
      "position": 0
    }
  ],
  "modifierGroups": [
    {
      "id": "clg1a2b3c4d5e6f7g8h9",
      "attachmentId": "cla1a2b3c4d5e6f7g8h9",
      "name": "Toppings",
      "translations": {},
      "selectionType": "MULTIPLE",
      "min": 0,
      "max": 3,
      "freeQuantity": 1,
      "required": false,
      "freeAllocationPolicy": "EXPENSIVE_FREE",
      "defaultModifierIds": [
        "string"
      ],
      "modifiers": [
        {
          "id": "clx1a2b3c4d5e6f7g8h9",
          "name": "Extra cheese",
          "description": null,
          "translations": {},
          "priceDelta": "2.50",
          "position": 0,
          "isDefault": false,
          "available": true,
          "excludeFromFree": false,
          "image": {},
          "referencedProductId": null
        }
      ]
    }
  ],
  "kitComponents": [
    {
      "productId": "clk1a2b3c4d5e6f7g8h9",
      "variantId": null,
      "name": "Ceramic mug",
      "sku": null,
      "quantity": 2,
      "image": {}
    }
  ],
  "kitAvailable": 12,
  "kitPricingMode": "FIXED",
  "displayPrice": "22.40",
  "displaySalePrice": "17.90",
  "displayPriceMin": "20.00",
  "displayPriceMax": "30.00",
  "displayCurrency": "EUR",
  "discount": {
    "ruleId": "clr1a2b3c4d5e6f7g8h9",
    "ruleName": "Autumn sale",
    "type": "PRODUCT_DISCOUNT",
    "badgeText": "20% OFF",
    "message": null,
    "originalPrice": "25.00",
    "discountedPrice": "20.00",
    "discountAmount": "5.00"
  },
  "recommendations": {
    "crossSells": [
      {
        "id": "clprd_abc123",
        "name": "string",
        "slug": "blue-mug",
        "basePrice": "24.00",
        "salePrice": "19.99",
        "images": [
          {
            "url": "https://cdn.brainerce.com/products/abc123.jpg",
            "alt": "Blue mug"
          }
        ],
        "type": "SIMPLE",
        "inventory": {
          "total": 42,
          "available": 39,
          "trackingMode": "TRACKED",
          "inStock": true,
          "canPurchase": true
        },
        "targetVariantId": null,
        "requiresVariantSelection": false,
        "pinnedVariant": {
          "id": "clvar_abc123",
          "name": "string",
          "attributes": {}
        },
        "variants": [
          {
            "id": "clvar_abc123",
            "name": "string",
            "attributes": {},
            "image": {
              "url": "https://cdn.brainerce.com/products/abc123.jpg",
              "alt": "Blue mug"
            },
            "price": "24.00",
            "salePrice": null
          }
        ],
        "relationType": "CROSS_SELL"
      }
    ],
    "upsells": [
      {
        "id": "clprd_abc123",
        "name": "string",
        "slug": "blue-mug",
        "basePrice": "24.00",
        "salePrice": "19.99",
        "images": [
          {
            "url": "https://cdn.brainerce.com/products/abc123.jpg",
            "alt": "Blue mug"
          }
        ],
        "type": "SIMPLE",
        "inventory": {
          "total": 42,
          "available": 39,
          "trackingMode": "TRACKED",
          "inStock": true,
          "canPurchase": true
        },
        "targetVariantId": null,
        "requiresVariantSelection": false,
        "pinnedVariant": {
          "id": "clvar_abc123",
          "name": "string",
          "attributes": {}
        },
        "variants": [
          {
            "id": "clvar_abc123",
            "name": "string",
            "attributes": {},
            "image": {
              "url": "https://cdn.brainerce.com/products/abc123.jpg",
              "alt": "Blue mug"
            },
            "price": "24.00",
            "salePrice": null
          }
        ],
        "relationType": "CROSS_SELL"
      }
    ],
    "related": [
      {
        "id": "clprd_abc123",
        "name": "string",
        "slug": "blue-mug",
        "basePrice": "24.00",
        "salePrice": "19.99",
        "images": [
          {
            "url": "https://cdn.brainerce.com/products/abc123.jpg",
            "alt": "Blue mug"
          }
        ],
        "type": "SIMPLE",
        "inventory": {
          "total": 42,
          "available": 39,
          "trackingMode": "TRACKED",
          "inStock": true,
          "canPurchase": true
        },
        "targetVariantId": null,
        "requiresVariantSelection": false,
        "pinnedVariant": {
          "id": "clvar_abc123",
          "name": "string",
          "attributes": {}
        },
        "variants": [
          {
            "id": "clvar_abc123",
            "name": "string",
            "attributes": {},
            "image": {
              "url": "https://cdn.brainerce.com/products/abc123.jpg",
              "alt": "Blue mug"
            },
            "price": "24.00",
            "salePrice": null
          }
        ],
        "relationType": "CROSS_SELL"
      }
    ]
  }
}

{
  "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}/products/slug/{slug}"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/vc/{connectionId}/products/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}/products/slug/{slug}"
}

Get product

Returns one active product by id, with channel overlay, discount and related-product recommendations. A product that is not published to this channel is a 404.

GET
/vc/{connectionId}/products/{productId}
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.

productIdstring

Product id.

Query Parameters

regionId?string

Buyer region id from regions. When its currency differs from the store currency, each product and variant also carries displayPrice and displayCurrency converted from the latest daily FX rate. A region that charges its own currency uses the buffered charging rate and any manual region price. An unknown id is ignored.

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/products/string?regionId=string&locale=string" \  -H "origin: string" \  -H "accept-language: string" \  -H "X-SDK-Version: string"
{
  "id": "clp1a2b3c4d5e6f7g8h9",
  "name": "Blue mug",
  "slug": "blue-mug",
  "sku": "MUG-BLUE",
  "gtin": null,
  "mpn": null,
  "faq": [
    {
      "q": "string",
      "a": "string"
    }
  ],
  "salePriceStartsAt": null,
  "salePriceEndsAt": null,
  "description": "A hand made ceramic mug.",
  "descriptionFormat": "text",
  "seoTitle": null,
  "seoDescription": null,
  "metaDescription": null,
  "type": "SIMPLE",
  "status": "active",
  "basePrice": "24.90",
  "salePrice": "19.90",
  "priceMin": null,
  "priceMax": null,
  "priceVaries": false,
  "avgRating": 4.5,
  "reviewCount": 12,
  "localeSlugs": {
    "he": "ספל-כחול"
  },
  "images": [
    {
      "url": "https://cdn.brainerce.com/products/abc123.jpg",
      "alt": "Blue mug"
    }
  ],
  "categories": [
    {
      "id": "clc1a2b3c4d5e6f7g8h9",
      "name": "Mugs",
      "slug": "mugs",
      "translations": {}
    }
  ],
  "brands": [
    {
      "id": "clb1a2b3c4d5e6f7g8h9",
      "name": "Acme",
      "translations": {}
    }
  ],
  "tags": [
    {
      "id": "clb1a2b3c4d5e6f7g8h9",
      "name": "Acme",
      "translations": {}
    }
  ],
  "inventory": {
    "total": 42,
    "available": 39,
    "trackingMode": "TRACKED",
    "inStock": true,
    "canPurchase": true,
    "backorderMode": "NONE"
  },
  "variants": [
    {
      "id": "clv1a2b3c4d5e6f7g8h9",
      "sku": "MUG-BLUE-L",
      "name": "Blue / Large",
      "translations": {},
      "attributes": {
        "Color": "Blue",
        "Size": "L"
      },
      "price": "24.90",
      "salePrice": "19.90",
      "salePriceStartsAt": "2026-11-01T00:00:00.000Z",
      "salePriceEndsAt": "2026-11-30T23:59:59.000Z",
      "image": {
        "url": "https://cdn.brainerce.com/products/abc123.jpg",
        "alt": "Blue mug"
      },
      "inventory": {
        "total": 42,
        "available": 39,
        "trackingMode": "TRACKED",
        "inStock": true,
        "canPurchase": true,
        "backorderMode": "NONE"
      },
      "displayPrice": "22.40",
      "displaySalePrice": "17.90",
      "displayCurrency": "EUR"
    }
  ],
  "createdAt": "2026-01-15T10:30:00.000Z",
  "updatedAt": "2026-02-01T08:00:00.000Z",
  "productAttributeOptions": [
    {
      "id": "clp1a2b3c4d5e6f7g8h9",
      "attribute": {
        "id": "cla1a2b3c4d5e6f7g8h9",
        "name": "Color",
        "displayType": "COLOR_SWATCH",
        "translations": {}
      },
      "attributeOption": {
        "id": "clo1a2b3c4d5e6f7g8h9",
        "name": "Blue",
        "swatchColor": "#1E40AF",
        "swatchColor2": null,
        "swatchImageUrl": null,
        "translations": {}
      }
    }
  ],
  "metafields": [
    {
      "id": "clm1a2b3c4d5e6f7g8h9",
      "definitionId": "cld1a2b3c4d5e6f7g8h9",
      "definitionKey": "material",
      "definitionName": "Material",
      "type": "TEXT",
      "value": "Ceramic",
      "translations": {},
      "variantId": null
    }
  ],
  "customizationFields": [
    {
      "definitionId": "cld1a2b3c4d5e6f7g8h9",
      "name": "Engraving text",
      "key": "engraving",
      "description": "Up to 20 characters",
      "type": "TEXT",
      "required": false,
      "minLength": 1,
      "maxLength": 20,
      "minValue": 0,
      "maxValue": 100,
      "enumValues": [
        "string"
      ],
      "defaultValue": null,
      "position": 0
    }
  ],
  "modifierGroups": [
    {
      "id": "clg1a2b3c4d5e6f7g8h9",
      "attachmentId": "cla1a2b3c4d5e6f7g8h9",
      "name": "Toppings",
      "translations": {},
      "selectionType": "MULTIPLE",
      "min": 0,
      "max": 3,
      "freeQuantity": 1,
      "required": false,
      "freeAllocationPolicy": "EXPENSIVE_FREE",
      "defaultModifierIds": [
        "string"
      ],
      "modifiers": [
        {
          "id": "clx1a2b3c4d5e6f7g8h9",
          "name": "Extra cheese",
          "description": null,
          "translations": {},
          "priceDelta": "2.50",
          "position": 0,
          "isDefault": false,
          "available": true,
          "excludeFromFree": false,
          "image": {},
          "referencedProductId": null
        }
      ]
    }
  ],
  "kitComponents": [
    {
      "productId": "clk1a2b3c4d5e6f7g8h9",
      "variantId": null,
      "name": "Ceramic mug",
      "sku": null,
      "quantity": 2,
      "image": {}
    }
  ],
  "kitAvailable": 12,
  "kitPricingMode": "FIXED",
  "displayPrice": "22.40",
  "displaySalePrice": "17.90",
  "displayPriceMin": "20.00",
  "displayPriceMax": "30.00",
  "displayCurrency": "EUR",
  "discount": {
    "ruleId": "clr1a2b3c4d5e6f7g8h9",
    "ruleName": "Autumn sale",
    "type": "PRODUCT_DISCOUNT",
    "badgeText": "20% OFF",
    "message": null,
    "originalPrice": "25.00",
    "discountedPrice": "20.00",
    "discountAmount": "5.00"
  },
  "recommendations": {
    "crossSells": [
      {
        "id": "clprd_abc123",
        "name": "string",
        "slug": "blue-mug",
        "basePrice": "24.00",
        "salePrice": "19.99",
        "images": [
          {
            "url": "https://cdn.brainerce.com/products/abc123.jpg",
            "alt": "Blue mug"
          }
        ],
        "type": "SIMPLE",
        "inventory": {
          "total": 42,
          "available": 39,
          "trackingMode": "TRACKED",
          "inStock": true,
          "canPurchase": true
        },
        "targetVariantId": null,
        "requiresVariantSelection": false,
        "pinnedVariant": {
          "id": "clvar_abc123",
          "name": "string",
          "attributes": {}
        },
        "variants": [
          {
            "id": "clvar_abc123",
            "name": "string",
            "attributes": {},
            "image": {
              "url": "https://cdn.brainerce.com/products/abc123.jpg",
              "alt": "Blue mug"
            },
            "price": "24.00",
            "salePrice": null
          }
        ],
        "relationType": "CROSS_SELL"
      }
    ],
    "upsells": [
      {
        "id": "clprd_abc123",
        "name": "string",
        "slug": "blue-mug",
        "basePrice": "24.00",
        "salePrice": "19.99",
        "images": [
          {
            "url": "https://cdn.brainerce.com/products/abc123.jpg",
            "alt": "Blue mug"
          }
        ],
        "type": "SIMPLE",
        "inventory": {
          "total": 42,
          "available": 39,
          "trackingMode": "TRACKED",
          "inStock": true,
          "canPurchase": true
        },
        "targetVariantId": null,
        "requiresVariantSelection": false,
        "pinnedVariant": {
          "id": "clvar_abc123",
          "name": "string",
          "attributes": {}
        },
        "variants": [
          {
            "id": "clvar_abc123",
            "name": "string",
            "attributes": {},
            "image": {
              "url": "https://cdn.brainerce.com/products/abc123.jpg",
              "alt": "Blue mug"
            },
            "price": "24.00",
            "salePrice": null
          }
        ],
        "relationType": "CROSS_SELL"
      }
    ],
    "related": [
      {
        "id": "clprd_abc123",
        "name": "string",
        "slug": "blue-mug",
        "basePrice": "24.00",
        "salePrice": "19.99",
        "images": [
          {
            "url": "https://cdn.brainerce.com/products/abc123.jpg",
            "alt": "Blue mug"
          }
        ],
        "type": "SIMPLE",
        "inventory": {
          "total": 42,
          "available": 39,
          "trackingMode": "TRACKED",
          "inStock": true,
          "canPurchase": true
        },
        "targetVariantId": null,
        "requiresVariantSelection": false,
        "pinnedVariant": {
          "id": "clvar_abc123",
          "name": "string",
          "attributes": {}
        },
        "variants": [
          {
            "id": "clvar_abc123",
            "name": "string",
            "attributes": {},
            "image": {
              "url": "https://cdn.brainerce.com/products/abc123.jpg",
              "alt": "Blue mug"
            },
            "price": "24.00",
            "salePrice": null
          }
        ],
        "relationType": "CROSS_SELL"
      }
    ]
  }
}

{
  "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}/products/{productId}"
}

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

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

List search suggestions

Autocomplete for a search box: matching products and categories published to this channel. A blank q returns empty lists. A product price that cannot be computed is omitted, never returned as zero.

GET
/vc/{connectionId}/search/suggestions
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

q?string

Search text. Trimmed; blank returns { products: [], categories: [] }.

limit?number

Maximum suggestions. Products are capped at 10 (default 5) and categories at 5 (default 3), whatever value is sent.

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/search/suggestions?q=mug&limit=0&locale=string" \  -H "origin: string" \  -H "accept-language: string" \  -H "X-SDK-Version: string"
{
  "products": [
    {
      "id": "string",
      "name": "string",
      "slug": "string",
      "image": "string",
      "price": "19.90",
      "basePrice": "24.90",
      "salePrice": "string",
      "type": "SIMPLE"
    }
  ],
  "categories": [
    {
      "id": "string",
      "name": "string",
      "productCount": 0
    }
  ]
}

{
  "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}/search/suggestions"
}

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

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

List discount banners

Lists the active automatic discount rules that have banner text and are not switched off as banners. Each entry has ruleId, text and type.

GET
/vc/{connectionId}/discount-banners
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.

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.

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/discount-banners" \  -H "origin: string" \  -H "X-SDK-Version: string"
[
  {
    "ruleId": "string",
    "text": "10% off today",
    "type": "string"
  }
]

{
  "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}/discount-banners"
}

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

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

Get product discount badge

Returns the discount badge of a product (ruleId, badgeText, originalPrice, discountedPrice), or JSON null when no automatic rule applies.

GET
/vc/{connectionId}/products/{productId}/discount-badge
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.

productIdstring

Product id.

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.

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/products/string/discount-badge" \  -H "origin: string" \  -H "X-SDK-Version: string"
{
  "ruleId": "string",
  "badgeText": "string",
  "originalPrice": "20.00",
  "discountedPrice": "16.00"
}

{
  "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}/products/{productId}/discount-badge"
}

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

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

List product recommendations

Returns the products related to a product (cross-sells, upsells, related) that are active and published to this channel.

GET
/vc/{connectionId}/products/{productId}/recommendations
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.

productIdstring

Product id.

Query Parameters

type?string

Relation type to return: CROSS_SELL, UPSELL or RELATED. Omitted: all types.

Value in"CROSS_SELL" | "UPSELL" | "RELATED"
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/products/string/recommendations?type=CROSS_SELL&locale=string" \  -H "origin: string" \  -H "accept-language: string" \  -H "X-SDK-Version: string"
{
  "crossSells": [
    {
      "id": "clprd_abc123",
      "name": "string",
      "slug": "blue-mug",
      "basePrice": "24.00",
      "salePrice": "19.99",
      "images": [
        {
          "url": "https://cdn.brainerce.com/products/abc123.jpg",
          "alt": "Blue mug"
        }
      ],
      "type": "SIMPLE",
      "inventory": {
        "total": 42,
        "available": 39,
        "trackingMode": "TRACKED",
        "inStock": true,
        "canPurchase": true
      },
      "targetVariantId": null,
      "requiresVariantSelection": false,
      "pinnedVariant": {
        "id": "clvar_abc123",
        "name": "string",
        "attributes": {}
      },
      "variants": [
        {
          "id": "clvar_abc123",
          "name": "string",
          "attributes": {},
          "image": {
            "url": "https://cdn.brainerce.com/products/abc123.jpg",
            "alt": "Blue mug"
          },
          "price": "24.00",
          "salePrice": null
        }
      ],
      "relationType": "CROSS_SELL"
    }
  ],
  "upsells": [
    {
      "id": "clprd_abc123",
      "name": "string",
      "slug": "blue-mug",
      "basePrice": "24.00",
      "salePrice": "19.99",
      "images": [
        {
          "url": "https://cdn.brainerce.com/products/abc123.jpg",
          "alt": "Blue mug"
        }
      ],
      "type": "SIMPLE",
      "inventory": {
        "total": 42,
        "available": 39,
        "trackingMode": "TRACKED",
        "inStock": true,
        "canPurchase": true
      },
      "targetVariantId": null,
      "requiresVariantSelection": false,
      "pinnedVariant": {
        "id": "clvar_abc123",
        "name": "string",
        "attributes": {}
      },
      "variants": [
        {
          "id": "clvar_abc123",
          "name": "string",
          "attributes": {},
          "image": {
            "url": "https://cdn.brainerce.com/products/abc123.jpg",
            "alt": "Blue mug"
          },
          "price": "24.00",
          "salePrice": null
        }
      ],
      "relationType": "CROSS_SELL"
    }
  ],
  "related": [
    {
      "id": "clprd_abc123",
      "name": "string",
      "slug": "blue-mug",
      "basePrice": "24.00",
      "salePrice": "19.99",
      "images": [
        {
          "url": "https://cdn.brainerce.com/products/abc123.jpg",
          "alt": "Blue mug"
        }
      ],
      "type": "SIMPLE",
      "inventory": {
        "total": 42,
        "available": 39,
        "trackingMode": "TRACKED",
        "inStock": true,
        "canPurchase": true
      },
      "targetVariantId": null,
      "requiresVariantSelection": false,
      "pinnedVariant": {
        "id": "clvar_abc123",
        "name": "string",
        "attributes": {}
      },
      "variants": [
        {
          "id": "clvar_abc123",
          "name": "string",
          "attributes": {},
          "image": {
            "url": "https://cdn.brainerce.com/products/abc123.jpg",
            "alt": "Blue mug"
          },
          "price": "24.00",
          "salePrice": null
        }
      ],
      "relationType": "CROSS_SELL"
    }
  ]
}

{
  "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/vc/{connectionId}/products/{productId}/recommendations"
}

{
  "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}/products/{productId}/recommendations"
}

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

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