Public API (v1)
The external integrator REST API under /v1/*. Stable, versioned, auth via api-key (issue from the dashboard at Settings → Authentication → API Keys). Use this when calling Brainerce from outside the dashboard — a headless storefront, ERP sync, BI pipeline, etc. Every endpoint requires a scope (products:read, orders:write, …) on the key. The /v1/ prefix is a versioning anchor — there is no v2 planned, but a future breaking change would ship under /v2/ without disrupting /v1/ integrators.
Get store information
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
curl -X GET "https://api.brainerce.com/api/v1/store"{
"id": "string",
"accountId": "string",
"connectedPlatforms": [
"string"
]
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}{
"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/store"
}List products with pagination
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
curl -X GET "https://api.brainerce.com/api/v1/products?page=0&limit=0&search=string&status=string&type=string&sortBy=string&sortOrder=string®ionId=string"{
"data": [
{
"id": "string",
"name": "string",
"slug": "string",
"localeSlugs": {
"property1": "string",
"property2": "string"
},
"description": "string",
"descriptionFormat": "text",
"basePrice": "49.90",
"salePrice": "string",
"costPrice": "string",
"priceMin": "string",
"priceMax": "string",
"priceVaries": true,
"displayPrice": "string",
"displaySalePrice": "string",
"displayPriceMin": "string",
"displayPriceMax": "string",
"displayCurrency": "string",
"gtin": "string",
"mpn": "string",
"salePriceStartsAt": "2019-08-24T14:15:22Z",
"salePriceEndsAt": "2019-08-24T14:15:22Z",
"shippingWeightValue": 0,
"shippingWeightUnit": "string",
"shippingLengthValue": 0,
"shippingWidthValue": 0,
"shippingHeightValue": 0,
"shippingDimensionUnit": "string",
"metaDescription": "string",
"status": "string",
"sku": "string",
"type": "SIMPLE",
"kitPricingMode": "FIXED",
"kitDiscountValue": 0,
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"menuOrder": 0,
"taxBehavior": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"variants": [
{
"id": "string",
"productId": "string",
"sku": "string",
"name": "string",
"attributes": {},
"price": "19.90",
"salePrice": "string",
"costPrice": "string",
"displayPrice": "string",
"displaySalePrice": "string",
"displayCurrency": "string",
"image": "string",
"position": 0,
"status": "string",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"shippingClassId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"images": [
{
"url": "string",
"position": 0,
"isMain": true,
"alt": "string",
"id": "string",
"key": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"size": 0,
"mimeType": "string",
"createdAt": "2019-08-24T14:15:22Z",
"source": "string",
"importStatus": "string",
"importError": "string"
}
],
"channels": {},
"translations": {},
"categories": [
{
"id": "string",
"name": "string",
"taxBehavior": "string"
}
],
"brands": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"attributes": [
"string"
],
"productAttributeOptions": [
{
"id": "string",
"attributeId": "string",
"attributeOptionId": "string",
"platform": "string",
"attribute": {
"id": "string",
"name": "string",
"displayType": "string"
},
"attributeOption": {
"id": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string"
}
}
],
"tags": [
"string"
],
"metafields": [
{
"id": "string",
"definitionId": "string",
"definitionKey": "string",
"definitionName": "string",
"type": "string",
"value": "string",
"variantId": "string"
}
],
"customizationFields": [
{
"definitionId": "string",
"name": "string",
"key": "string",
"description": "string",
"type": "string",
"required": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"enumValues": [
"string"
],
"defaultValue": "string",
"position": 0
}
],
"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"
}
}
],
"channelSync": {},
"shippingClassId": "string",
"shippingClass": {
"id": "string",
"name": "string"
},
"crossSells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"upsells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"related": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"bundleOfferCount": 0,
"orderBumpCount": 0,
"avgRating": 0,
"reviewCount": 0,
"seoScore": {
"score": 0,
"band": "excellent",
"hasUnresolvedError": true
},
"modifierGroups": [
{
"attachmentId": "string",
"groupId": "string",
"variantId": "string",
"position": 0,
"minOverride": 0,
"maxOverride": 0,
"freeQuantityOverride": 0,
"requiredOverride": true,
"freeAllocationPolicyOverride": "EXPENSIVE_FREE",
"defaultModifierIds": [
"string"
],
"name": "string",
"internalName": "string",
"description": "string",
"translations": {},
"selectionType": "SINGLE",
"minSelections": 0,
"maxSelections": 0,
"freeQuantity": 0,
"required": true,
"freeAllocationPolicy": "EXPENSIVE_FREE",
"status": "string",
"modifiers": [
{
"id": "string",
"name": "string",
"description": "string",
"translations": {},
"priceDelta": "2.50",
"sku": "string",
"image": {},
"position": 0,
"isDefault": true,
"available": true,
"referencedProductId": "string",
"status": "string"
}
]
}
]
}
],
"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/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/v1/products"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products"
}Create a new product
Supports Idempotency-Key header for safe retries.
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
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 <= 255Display name of the product. Required.
URL slug. Letters, numbers, and hyphens only. Auto-generated from name when omitted.
Stock keeping unit, meaning your internal product code.
Global Trade Item Number (universal barcode: EAN/UPC/ISBN). Required by Google Shopping, Facebook Catalog, and TikTok Shop on most categories. Validated against the checksum digit.
Manufacturer Part Number, paired with brand when no GTIN exists. Max 70 chars.
Your own stable identifier for this product in the SOURCE system (supplier feed, legacy store, ERP). Unique per store. Its purpose is safe retries on bulk imports: re-sending a batch after a timeout matches on this value and skips the product instead of creating a duplicate. Not a marketplace id: those are managed per-connection and are not settable here.
length <= 191Sale-price effective window start (ISO 8601). Google Merchant Center sale_price_effective_date. Both this and salePriceEndsAt must be set together, or neither applies.
Sale-price effective window end (ISO 8601). See salePriceStartsAt.
Shipping weight numeric value. Paired with shippingWeightUnit.
Shipping weight unit.
"kg" | "lb" | "g" | "oz"Shipping package length. Paired with shippingDimensionUnit.
Shipping package width. Paired with shippingDimensionUnit.
Shipping package height. Paired with shippingDimensionUnit.
Unit shared by shippingLengthValue/shippingWidthValue/shippingHeightValue.
"cm" | "in"SEO meta description (≤160 chars). Used by Google Search snippets, social link previews (WhatsApp/Telegram/Twitter), email previews, and schema.org JSON-LD. Falls back to a stripped/truncated description when omitted.
length <= 160Long-form product description. Accepts HTML, and the backend strips dangerous tags/attributes (<script>, inline event handlers, <iframe>, …) before saving. Hard cap of 65 535 characters.
length <= 65535Base list price in the store currency. Must be ≥ 0.
0 <= valueSale price (must be < basePrice). When present, the storefront displays it as the active price with basePrice shown struck-through.
0 <= valueInternal cost (what you pay your supplier). Used for margin reporting only, and never shown to shoppers.
0 <= valuePublish state. active = visible to shoppers; draft = only visible in the dashboard.
"active" | "draft"Product structure. SIMPLE = single SKU; VARIABLE = parent of multiple variants (size, color, …); KIT = a bundle priced from component products. A KIT may be created with no components yet — it is simply not purchasable until it has at least one.
"SIMPLE" | "VARIABLE" | "KIT"How a KIT is priced. FIXED (default) — you set basePrice and it stays put. SUM — the kit costs exactly what its components cost, recomputed on every read, so a component going on sale lowers the kit price on its own. SUM_MINUS_PERCENT — that sum less kitDiscountValue percent. Ignored on SIMPLE and VARIABLE products.
"FIXED" | "SUM" | "SUM_MINUS_PERCENT"Percent off the component sum, 0-100. Required when kitPricingMode is SUM_MINUS_PERCENT; ignored otherwise.
0 <= value <= 100If true, the product is a digital download, so checkout issues a signed URL after payment instead of triggering shipping.
Digital-download configuration. Required when isDownloadable=true. files[] are uploaded via /v1/media. downloadLimit = max downloads per order (null = unlimited). downloadExpiry = hours until the signed URL expires (null = no expiry).
Empty Object
Inventory configuration for SIMPLE products. total = current stock count; trackingMode: TRACKED (default) decrements on each sale and blocks oversells; UNLIMITED accepts any order; DISABLED hides stock UI. Ignored for VARIABLE products, whose variants carry their own inventory.
Empty Object
Array of variants. Required (and non-empty) for VARIABLE products, at most 500. Each variant carries its own price, SKU, and inventory.
Array of existing category IDs (from GET /categories / list_categories). Unknown/cross-store IDs are rejected with 400. To assign by name, creating the category if it does not exist, use categoryNames instead.
Category names to assign. Each name is matched case-insensitively to an existing category and auto-created if none exists, so there is no need to look up IDs first. Merged with any IDs passed in categories.
Array of existing brand IDs. Unknown/cross-store IDs are rejected with 400. To assign by name, creating the brand if it does not exist, use brandNames instead.
Brand names to assign. Each name is matched case-insensitively to an existing brand and auto-created if none exists. Merged with any IDs passed in brands.
Free-form tags for filtering and segmentation.
Product images. Each entry: { url, position, isMain }. Upload via /v1/media first to get a signed URL.
Sales channels this product should publish to. Each platform syncs the product separately and can have per-channel overrides (see channels).
Per-platform field overrides. Keyed by platform code, value is a partial product object that overrides the canonical fields for that channel only.
Empty Object
Tax category. taxable is the default; exempt skips all tax calculation.
"taxable" | "exempt"Multi-language overrides. Keyed by ISO locale code (he, ar, es, …). Each value is a partial product with translated name / description / metaDescription. Falls back to the canonical fields for missing locales.
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/products" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "name": "Premium Wireless Headphones", "basePrice": 299.99, "type": "SIMPLE" }'{
"id": "string",
"name": "string",
"slug": "string",
"localeSlugs": {
"property1": "string",
"property2": "string"
},
"description": "string",
"descriptionFormat": "text",
"basePrice": "49.90",
"salePrice": "string",
"costPrice": "string",
"priceMin": "string",
"priceMax": "string",
"priceVaries": true,
"displayPrice": "string",
"displaySalePrice": "string",
"displayPriceMin": "string",
"displayPriceMax": "string",
"displayCurrency": "string",
"gtin": "string",
"mpn": "string",
"salePriceStartsAt": "2019-08-24T14:15:22Z",
"salePriceEndsAt": "2019-08-24T14:15:22Z",
"shippingWeightValue": 0,
"shippingWeightUnit": "string",
"shippingLengthValue": 0,
"shippingWidthValue": 0,
"shippingHeightValue": 0,
"shippingDimensionUnit": "string",
"metaDescription": "string",
"status": "string",
"sku": "string",
"type": "SIMPLE",
"kitPricingMode": "FIXED",
"kitDiscountValue": 0,
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"menuOrder": 0,
"taxBehavior": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"variants": [
{
"id": "string",
"productId": "string",
"sku": "string",
"name": "string",
"attributes": {},
"price": "19.90",
"salePrice": "string",
"costPrice": "string",
"displayPrice": "string",
"displaySalePrice": "string",
"displayCurrency": "string",
"image": "string",
"position": 0,
"status": "string",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"shippingClassId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"images": [
{
"url": "string",
"position": 0,
"isMain": true,
"alt": "string",
"id": "string",
"key": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"size": 0,
"mimeType": "string",
"createdAt": "2019-08-24T14:15:22Z",
"source": "string",
"importStatus": "string",
"importError": "string"
}
],
"channels": {},
"translations": {},
"categories": [
{
"id": "string",
"name": "string",
"taxBehavior": "string"
}
],
"brands": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"attributes": [
"string"
],
"productAttributeOptions": [
{
"id": "string",
"attributeId": "string",
"attributeOptionId": "string",
"platform": "string",
"attribute": {
"id": "string",
"name": "string",
"displayType": "string"
},
"attributeOption": {
"id": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string"
}
}
],
"tags": [
"string"
],
"metafields": [
{
"id": "string",
"definitionId": "string",
"definitionKey": "string",
"definitionName": "string",
"type": "string",
"value": "string",
"variantId": "string"
}
],
"customizationFields": [
{
"definitionId": "string",
"name": "string",
"key": "string",
"description": "string",
"type": "string",
"required": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"enumValues": [
"string"
],
"defaultValue": "string",
"position": 0
}
],
"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"
}
}
],
"channelSync": {},
"shippingClassId": "string",
"shippingClass": {
"id": "string",
"name": "string"
},
"crossSells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"upsells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"related": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"bundleOfferCount": 0,
"orderBumpCount": 0,
"avgRating": 0,
"reviewCount": 0,
"seoScore": {
"score": 0,
"band": "excellent",
"hasUnresolvedError": true
},
"modifierGroups": [
{
"attachmentId": "string",
"groupId": "string",
"variantId": "string",
"position": 0,
"minOverride": 0,
"maxOverride": 0,
"freeQuantityOverride": 0,
"requiredOverride": true,
"freeAllocationPolicyOverride": "EXPENSIVE_FREE",
"defaultModifierIds": [
"string"
],
"name": "string",
"internalName": "string",
"description": "string",
"translations": {},
"selectionType": "SINGLE",
"minSelections": 0,
"maxSelections": 0,
"freeQuantity": 0,
"required": true,
"freeAllocationPolicy": "EXPENSIVE_FREE",
"status": "string",
"modifiers": [
{
"id": "string",
"name": "string",
"description": "string",
"translations": {},
"priceDelta": "2.50",
"sku": "string",
"image": {},
"position": 0,
"isDefault": true,
"available": true,
"referencedProductId": "string",
"status": "string"
}
]
}
]
}{
"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/products"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/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/v1/products"
}Get a single product by ID
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
Product ID
Query Parameters
curl -X GET "https://api.brainerce.com/api/v1/products/string?regionId=string"{
"id": "string",
"name": "string",
"slug": "string",
"localeSlugs": {
"property1": "string",
"property2": "string"
},
"description": "string",
"descriptionFormat": "text",
"basePrice": "49.90",
"salePrice": "string",
"costPrice": "string",
"priceMin": "string",
"priceMax": "string",
"priceVaries": true,
"displayPrice": "string",
"displaySalePrice": "string",
"displayPriceMin": "string",
"displayPriceMax": "string",
"displayCurrency": "string",
"gtin": "string",
"mpn": "string",
"salePriceStartsAt": "2019-08-24T14:15:22Z",
"salePriceEndsAt": "2019-08-24T14:15:22Z",
"shippingWeightValue": 0,
"shippingWeightUnit": "string",
"shippingLengthValue": 0,
"shippingWidthValue": 0,
"shippingHeightValue": 0,
"shippingDimensionUnit": "string",
"metaDescription": "string",
"status": "string",
"sku": "string",
"type": "SIMPLE",
"kitPricingMode": "FIXED",
"kitDiscountValue": 0,
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"menuOrder": 0,
"taxBehavior": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"variants": [
{
"id": "string",
"productId": "string",
"sku": "string",
"name": "string",
"attributes": {},
"price": "19.90",
"salePrice": "string",
"costPrice": "string",
"displayPrice": "string",
"displaySalePrice": "string",
"displayCurrency": "string",
"image": "string",
"position": 0,
"status": "string",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"shippingClassId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"images": [
{
"url": "string",
"position": 0,
"isMain": true,
"alt": "string",
"id": "string",
"key": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"size": 0,
"mimeType": "string",
"createdAt": "2019-08-24T14:15:22Z",
"source": "string",
"importStatus": "string",
"importError": "string"
}
],
"channels": {},
"translations": {},
"categories": [
{
"id": "string",
"name": "string",
"taxBehavior": "string"
}
],
"brands": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"attributes": [
"string"
],
"productAttributeOptions": [
{
"id": "string",
"attributeId": "string",
"attributeOptionId": "string",
"platform": "string",
"attribute": {
"id": "string",
"name": "string",
"displayType": "string"
},
"attributeOption": {
"id": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string"
}
}
],
"tags": [
"string"
],
"metafields": [
{
"id": "string",
"definitionId": "string",
"definitionKey": "string",
"definitionName": "string",
"type": "string",
"value": "string",
"variantId": "string"
}
],
"customizationFields": [
{
"definitionId": "string",
"name": "string",
"key": "string",
"description": "string",
"type": "string",
"required": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"enumValues": [
"string"
],
"defaultValue": "string",
"position": 0
}
],
"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"
}
}
],
"channelSync": {},
"shippingClassId": "string",
"shippingClass": {
"id": "string",
"name": "string"
},
"crossSells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"upsells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"related": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"bundleOfferCount": 0,
"orderBumpCount": 0,
"avgRating": 0,
"reviewCount": 0,
"seoScore": {
"score": 0,
"band": "excellent",
"hasUnresolvedError": true
},
"modifierGroups": [
{
"attachmentId": "string",
"groupId": "string",
"variantId": "string",
"position": 0,
"minOverride": 0,
"maxOverride": 0,
"freeQuantityOverride": 0,
"requiredOverride": true,
"freeAllocationPolicyOverride": "EXPENSIVE_FREE",
"defaultModifierIds": [
"string"
],
"name": "string",
"internalName": "string",
"description": "string",
"translations": {},
"selectionType": "SINGLE",
"minSelections": 0,
"maxSelections": 0,
"freeQuantity": 0,
"required": true,
"freeAllocationPolicy": "EXPENSIVE_FREE",
"status": "string",
"modifiers": [
{
"id": "string",
"name": "string",
"description": "string",
"translations": {},
"priceDelta": "2.50",
"sku": "string",
"image": {},
"position": 0,
"isDefault": true,
"available": true,
"referencedProductId": "string",
"status": "string"
}
]
}
]
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{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/products/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}"
}Update a product
Supports Idempotency-Key header for safe retries.
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
Product 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 <= 255Display name of the product.
URL slug. Letters, numbers, and hyphens only. Changing the slug breaks existing shopper bookmarks for this product.
Stock keeping unit, meaning your internal product code.
Global Trade Item Number (universal barcode: EAN/UPC/ISBN). Validated against the checksum digit. Pass an empty string to clear.
Manufacturer Part Number, paired with brand when no GTIN exists. Max 70 chars.
length <= 70Sale-price effective window start (ISO 8601). Pass null to clear.
Sale-price effective window end (ISO 8601). Pass null to clear.
Shipping weight numeric value. Pass null to clear.
Shipping weight unit.
"kg" | "lb" | "g" | "oz"Shipping package length. Pass null to clear.
Shipping package width. Pass null to clear.
Shipping package height. Pass null to clear.
Unit shared by the dimension fields.
"cm" | "in"SEO meta description (≤160 chars). Used by Google Search snippets and social link previews. Falls back to a stripped/truncated description when omitted.
length <= 160Long-form product description. Accepts HTML, and the backend strips dangerous tags/attributes (<script>, inline event handlers, <iframe>, …) before saving. Hard cap of 65 535 characters.
length <= 65535Base list price in the store currency.
0 <= valueSale price (must be < basePrice). When present, the storefront displays it as the active price with basePrice shown struck-through. Pass null to take the product OFF sale. Omitting the field leaves the existing sale price untouched, which is not the same thing (D76: the dashboard form sent undefined for an emptied box, so a sale could be started and never ended).
0 <= valueInternal cost (what you pay your supplier). Used for margin reporting only, and never shown to shoppers. Pass null to clear.
Publish state. active = visible to shoppers; draft = only visible in the dashboard.
"active" | "draft"Product structure. SIMPLE = single SKU; VARIABLE = parent of multiple variants.
"SIMPLE" | "VARIABLE" | "KIT"How a KIT is priced. FIXED (default) — you set basePrice and it stays put. SUM — the kit costs exactly what its components cost, recomputed on every read, so a component going on sale lowers the kit price on its own. SUM_MINUS_PERCENT — that sum less kitDiscountValue percent. Ignored on SIMPLE and VARIABLE products.
"FIXED" | "SUM" | "SUM_MINUS_PERCENT"Percent off the component sum, 0-100. Required when kitPricingMode is SUM_MINUS_PERCENT; ignored otherwise.
0 <= value <= 100If true, the product is a digital download, so checkout issues a signed URL after payment instead of triggering shipping.
When true, the product is flagged for re-sync to connected platforms on the next sync job.
Per-platform field overrides. Keyed by platform code (SHOPIFY, TIKTOK, …); value is a partial product object that overrides the canonical fields for that channel only.
Empty Object
Free-form tags for filtering and segmentation.
Existing category IDs to assign (replaces the current set). Pass [] to remove all categories. Unknown/cross-store IDs are rejected with 400. To assign by name, creating the category if missing, use categoryNames.
Category names to assign (case-insensitive match, auto-created if missing). Additive: names are ADDED to the product, joining the set in categories when that is also sent, otherwise to the product's current categories (they are not replaced).
Existing brand IDs to assign (replaces the current set). Pass [] to remove all brands. Unknown/cross-store IDs are rejected with 400. To assign by name, creating the brand if missing, use brandNames.
Brand names to assign (case-insensitive match, auto-created if missing). Additive: names are ADDED to the set in brands when that is also sent, otherwise to the product's current brands (they are not replaced).
Product images. Each entry: { url, position, isMain }. Upload via /v1/media first to get a signed URL.
Display order within the catalog/category listing. Lower values render first. Mirrors WooCommerce menu_order.
ID of the shipping class this product belongs to (used by shipping-rate rules). Pass null to clear.
ID of the tax class this product belongs to (drives differential tax rates at checkout). Pass null to clear (falls back to category/store-default/Standard).
Digital-download configuration. Required when isDownloadable=true. files[] are uploaded via /v1/media. downloadLimit = max downloads per order (null = unlimited). downloadExpiry = hours until the signed URL expires (null = no expiry).
Empty Object
Tax category. taxable is the default; exempt skips all tax calculation.
"taxable" | "exempt"Multi-language overrides. Keyed by ISO locale code (he, ar, es, …). Each value is a partial product with translated name / description / metaDescription.
Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/products/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"name": "string",
"slug": "string",
"localeSlugs": {
"property1": "string",
"property2": "string"
},
"description": "string",
"descriptionFormat": "text",
"basePrice": "49.90",
"salePrice": "string",
"costPrice": "string",
"priceMin": "string",
"priceMax": "string",
"priceVaries": true,
"displayPrice": "string",
"displaySalePrice": "string",
"displayPriceMin": "string",
"displayPriceMax": "string",
"displayCurrency": "string",
"gtin": "string",
"mpn": "string",
"salePriceStartsAt": "2019-08-24T14:15:22Z",
"salePriceEndsAt": "2019-08-24T14:15:22Z",
"shippingWeightValue": 0,
"shippingWeightUnit": "string",
"shippingLengthValue": 0,
"shippingWidthValue": 0,
"shippingHeightValue": 0,
"shippingDimensionUnit": "string",
"metaDescription": "string",
"status": "string",
"sku": "string",
"type": "SIMPLE",
"kitPricingMode": "FIXED",
"kitDiscountValue": 0,
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"menuOrder": 0,
"taxBehavior": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"variants": [
{
"id": "string",
"productId": "string",
"sku": "string",
"name": "string",
"attributes": {},
"price": "19.90",
"salePrice": "string",
"costPrice": "string",
"displayPrice": "string",
"displaySalePrice": "string",
"displayCurrency": "string",
"image": "string",
"position": 0,
"status": "string",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"shippingClassId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"images": [
{
"url": "string",
"position": 0,
"isMain": true,
"alt": "string",
"id": "string",
"key": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"size": 0,
"mimeType": "string",
"createdAt": "2019-08-24T14:15:22Z",
"source": "string",
"importStatus": "string",
"importError": "string"
}
],
"channels": {},
"translations": {},
"categories": [
{
"id": "string",
"name": "string",
"taxBehavior": "string"
}
],
"brands": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"attributes": [
"string"
],
"productAttributeOptions": [
{
"id": "string",
"attributeId": "string",
"attributeOptionId": "string",
"platform": "string",
"attribute": {
"id": "string",
"name": "string",
"displayType": "string"
},
"attributeOption": {
"id": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string"
}
}
],
"tags": [
"string"
],
"metafields": [
{
"id": "string",
"definitionId": "string",
"definitionKey": "string",
"definitionName": "string",
"type": "string",
"value": "string",
"variantId": "string"
}
],
"customizationFields": [
{
"definitionId": "string",
"name": "string",
"key": "string",
"description": "string",
"type": "string",
"required": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"enumValues": [
"string"
],
"defaultValue": "string",
"position": 0
}
],
"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"
}
}
],
"channelSync": {},
"shippingClassId": "string",
"shippingClass": {
"id": "string",
"name": "string"
},
"crossSells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"upsells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"related": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"bundleOfferCount": 0,
"orderBumpCount": 0,
"avgRating": 0,
"reviewCount": 0,
"seoScore": {
"score": 0,
"band": "excellent",
"hasUnresolvedError": true
},
"modifierGroups": [
{
"attachmentId": "string",
"groupId": "string",
"variantId": "string",
"position": 0,
"minOverride": 0,
"maxOverride": 0,
"freeQuantityOverride": 0,
"requiredOverride": true,
"freeAllocationPolicyOverride": "EXPENSIVE_FREE",
"defaultModifierIds": [
"string"
],
"name": "string",
"internalName": "string",
"description": "string",
"translations": {},
"selectionType": "SINGLE",
"minSelections": 0,
"maxSelections": 0,
"freeQuantity": 0,
"required": true,
"freeAllocationPolicy": "EXPENSIVE_FREE",
"status": "string",
"modifiers": [
{
"id": "string",
"name": "string",
"description": "string",
"translations": {},
"priceDelta": "2.50",
"sku": "string",
"image": {},
"position": 0,
"isDefault": true,
"available": true,
"referencedProductId": "string",
"status": "string"
}
]
}
]
}{
"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/products/{id}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{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/products/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}"
}Delete a product
Supports Idempotency-Key header for safe retries.
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
Product ID
Query Parameters
Platforms to delete from (comma-separated)
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/products/string?platforms=string" \ -H "Idempotency-Key: string"{
"success": true,
"jobIds": [
"string"
],
"warnings": [
"string"
]
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{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/products/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}"
}Create many products in one call (queued)
Queues a batch of products for creation and returns a jobId immediately. It does NOT wait for the import to finish. Every field accepted by POST /v1/products is accepted per row, including variants, categories, brands, tags, images, translations and tax behavior. Max 1000 products per request (500 recommended). For a 3,000-50,000 product catalog, send several requests of that size carrying the same importId, then poll GET /v1/products/bulk/import/{importId} for the whole import. Rows whose sku or externalId already exist are skipped by default (see conflictStrategy), so re-sending a batch after a timeout does not duplicate the catalog. The Idempotency-Key header is honored as well and returns the original jobId on replay.
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
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 <= 255Products to create. Each entry accepts every field POST /v1/products accepts. Max 1000 per request (500 recommended), so chunk larger catalogs and pass the same importId on every chunk. Rows are validated individually: an invalid row is reported as a row failure and does NOT reject the batch.
Groups several chunked requests into one logical import so status can be read for the whole catalog rather than per chunk. Generate one value client-side and send it on every chunk. Any string you choose; it is not validated against anything.
length <= 191How to handle a row whose sku or externalId already exists in the store. skip (default) counts it under skipped and moves on, which is the safe choice for retries. error records it as a failure instead, which is what you want when a duplicate means the source file is wrong.
"skip" | "error"Channel sync behavior. coalesced (default) suppresses the per-product connector push and files ONE sync per affected sales channel when the import finishes. That is necessary because connectors are rate-limited per catalog (Meta allows 100 batch requests/hour). none writes to Brainerce only and leaves channels to the next reconciliation.
"coalesced" | "none"Durable dedup key for this batch. Re-sending the same key returns the ORIGINAL jobId instead of importing again. On HTTP the Idempotency-Key header does the same thing and is preferred; this field exists because it is stored in the database rather than in Redis with a 24h TTL, and because the MCP tool has no HTTP headers to carry one.
length <= 191curl -X POST "https://api.brainerce.com/api/v1/products/bulk" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "products": [ { "name": "Premium Wireless Headphones", "basePrice": 299.99, "type": "SIMPLE" } ] }'{
"jobId": "string",
"importId": "string",
"status": "QUEUED",
"total": 0,
"replayed": 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/products/bulk"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/bulk"
}{
"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/products/bulk"
}{
"statusCode": 409,
"code": "CONFLICT",
"message": "The request conflicts with the current state of the resource",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/bulk"
}Get bulk product creation status
Counters for one queued batch: total, processed, succeeded, failed, skipped, pending. skipped counts rows whose sku/externalId already existed. They are NOT failures and NOT creations. Status is QUEUED, RUNNING, COMPLETED, COMPLETED_WITH_ERRORS, FAILED or CANCELLED; COMPLETED_WITH_ERRORS means every row was attempted and some failed, which is not something to retry wholesale. read the per-row failures from the errors endpoint instead.
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
Job ID returned by POST /v1/products/bulk
curl -X GET "https://api.brainerce.com/api/v1/products/bulk/string"{
"jobId": "string",
"importId": "string",
"status": "string",
"total": 0,
"processed": 0,
"succeeded": 0,
"failed": 0,
"skipped": 0,
"pending": 0,
"conflictStrategy": "string",
"syncMode": "string",
"errorMessage": "string",
"startedAt": "2019-08-24T14:15:22Z",
"finishedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"jobCount": 0
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/bulk/{jobId}"
}Get aggregate status for a chunked import
Rolls every batch sharing this importId into one set of counters, so a 50,000-product catalog sent as 100 requests is polled once rather than 100 times. The aggregate status is the least-complete state across the chunks: any chunk still QUEUED or RUNNING keeps the whole import unfinished. finishedAt stays null until every chunk has finished.
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
The importId sent on every chunk
curl -X GET "https://api.brainerce.com/api/v1/products/bulk/import/string"{
"jobId": "string",
"importId": "string",
"status": "string",
"total": 0,
"processed": 0,
"succeeded": 0,
"failed": 0,
"skipped": 0,
"pending": 0,
"conflictStrategy": "string",
"syncMode": "string",
"errorMessage": "string",
"startedAt": "2019-08-24T14:15:22Z",
"finishedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"jobCount": 0
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/bulk/import/{importId}"
}List per-product failures for a bulk create job
One entry per failed product, carrying the 1-indexed row from your submitted array plus sku, externalId, productName, a code (VALIDATION / DUPLICATE / PLAN_LIMIT / INTERNAL) and the message. Every failure is recorded and nothing is truncated, so this is paginated.
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
Job ID returned by POST /v1/products/bulk
Query Parameters
Page number (default 1)
Page size (default 50, max 100)
curl -X GET "https://api.brainerce.com/api/v1/products/bulk/string/errors?page=string&limit=string"{
"data": [
{
"row": 0,
"sku": "string",
"externalId": "string",
"productName": "string",
"code": "string",
"message": "string"
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 137,
"totalPages": 7
}
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/bulk/{jobId}/errors"
}Get kit components
Returns the kit's components with each one's live price and stock, the resolved kit price, its per-component split, the pricing mode, and how many kits can be sold. A component whose product or pinned variant is not published reports zero stock and takes the kit's sellable count to zero with it, however much stock the other components hold. A product that is not a KIT returns an empty, unsellable shape rather than a 404.
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
Kit product ID
curl -X GET "https://api.brainerce.com/api/v1/products/string/kit-components"{
"components": [
{
"id": "pkc_01H...",
"componentProductId": "prod_01H...",
"componentVariantId": "pv_01H...",
"quantity": 2,
"position": 0,
"name": "Riedel tumbler — 300ml",
"sku": "GLS-300",
"unitPrice": "12.90",
"available": 40,
"image": "https://cdn.example.com/glass.jpg"
}
],
"pricingMode": "FIXED",
"discountValue": 10,
"price": "246.00",
"allocationMinor": [
13536,
7973,
3091
],
"available": 12
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/kit-components"
}{
"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/products/{id}/kit-components"
}Set kit components
Replaces the kit's component list in a single transaction and returns it re-resolved. Rejects a product that is not a KIT, a component from another store, a component that is itself a KIT, a VARIABLE component with no variant pinned, a variant that does not belong to its product, a duplicate slot, the kit itself, and a component whose product or pinned variant is not published. That last check runs over the whole list you send, not only the rows you changed, so once a product already inside a kit is unpublished no edit to that kit saves until you publish it again or drop it.
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
Kit product ID
How the kit is priced. FIXED (default) — the merchant types a price and it stays put. SUM — the kit costs exactly what its contents cost, recomputed on every read, so a component going on sale drops the kit price on its own. SUM_MINUS_PERCENT — that sum less kitDiscountValue percent. Omit to leave the current mode unchanged.
"FIXED" | "SUM" | "SUM_MINUS_PERCENT"Percent off the component sum. Required when pricingMode is SUM_MINUS_PERCENT, ignored otherwise. 0-100.
0 <= value <= 100The kit's full component list, replacing whatever it had. Order is preserved as position. An empty array clears the kit — it then has no price and cannot be bought until components are added back.
items <= 30curl -X PUT "https://api.brainerce.com/api/v1/products/string/kit-components" \ -H "Content-Type: application/json" \ -d '{ "components": [ { "componentProductId": "prod_01H...", "quantity": 2 } ] }'{
"components": [
{
"id": "pkc_01H...",
"componentProductId": "prod_01H...",
"componentVariantId": "pv_01H...",
"quantity": 2,
"position": 0,
"name": "Riedel tumbler — 300ml",
"sku": "GLS-300",
"unitPrice": "12.90",
"available": 40,
"image": "https://cdn.example.com/glass.jpg"
}
],
"pricingMode": "FIXED",
"discountValue": 10,
"price": "246.00",
"allocationMinor": [
13536,
7973,
3091
],
"available": 12
}{
"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/products/{id}/kit-components"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/kit-components"
}{
"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/products/{id}/kit-components"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/kit-components"
}Convert a SIMPLE product to VARIABLE
Converts the product type and migrates existing price/inventory into a first variant. Idempotent, and returns 400 if already VARIABLE.
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
Product ID
curl -X PATCH "https://api.brainerce.com/api/v1/products/string/convert-to-variable"{
"id": "string",
"name": "string",
"slug": "string",
"localeSlugs": {
"property1": "string",
"property2": "string"
},
"description": "string",
"descriptionFormat": "text",
"basePrice": "49.90",
"salePrice": "string",
"costPrice": "string",
"priceMin": "string",
"priceMax": "string",
"priceVaries": true,
"displayPrice": "string",
"displaySalePrice": "string",
"displayPriceMin": "string",
"displayPriceMax": "string",
"displayCurrency": "string",
"gtin": "string",
"mpn": "string",
"salePriceStartsAt": "2019-08-24T14:15:22Z",
"salePriceEndsAt": "2019-08-24T14:15:22Z",
"shippingWeightValue": 0,
"shippingWeightUnit": "string",
"shippingLengthValue": 0,
"shippingWidthValue": 0,
"shippingHeightValue": 0,
"shippingDimensionUnit": "string",
"metaDescription": "string",
"status": "string",
"sku": "string",
"type": "SIMPLE",
"kitPricingMode": "FIXED",
"kitDiscountValue": 0,
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"menuOrder": 0,
"taxBehavior": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"variants": [
{
"id": "string",
"productId": "string",
"sku": "string",
"name": "string",
"attributes": {},
"price": "19.90",
"salePrice": "string",
"costPrice": "string",
"displayPrice": "string",
"displaySalePrice": "string",
"displayCurrency": "string",
"image": "string",
"position": 0,
"status": "string",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"shippingClassId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"images": [
{
"url": "string",
"position": 0,
"isMain": true,
"alt": "string",
"id": "string",
"key": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"size": 0,
"mimeType": "string",
"createdAt": "2019-08-24T14:15:22Z",
"source": "string",
"importStatus": "string",
"importError": "string"
}
],
"channels": {},
"translations": {},
"categories": [
{
"id": "string",
"name": "string",
"taxBehavior": "string"
}
],
"brands": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"attributes": [
"string"
],
"productAttributeOptions": [
{
"id": "string",
"attributeId": "string",
"attributeOptionId": "string",
"platform": "string",
"attribute": {
"id": "string",
"name": "string",
"displayType": "string"
},
"attributeOption": {
"id": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string"
}
}
],
"tags": [
"string"
],
"metafields": [
{
"id": "string",
"definitionId": "string",
"definitionKey": "string",
"definitionName": "string",
"type": "string",
"value": "string",
"variantId": "string"
}
],
"customizationFields": [
{
"definitionId": "string",
"name": "string",
"key": "string",
"description": "string",
"type": "string",
"required": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"enumValues": [
"string"
],
"defaultValue": "string",
"position": 0
}
],
"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"
}
}
],
"channelSync": {},
"shippingClassId": "string",
"shippingClass": {
"id": "string",
"name": "string"
},
"crossSells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"upsells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"related": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"bundleOfferCount": 0,
"orderBumpCount": 0,
"avgRating": 0,
"reviewCount": 0,
"seoScore": {
"score": 0,
"band": "excellent",
"hasUnresolvedError": true
},
"modifierGroups": [
{
"attachmentId": "string",
"groupId": "string",
"variantId": "string",
"position": 0,
"minOverride": 0,
"maxOverride": 0,
"freeQuantityOverride": 0,
"requiredOverride": true,
"freeAllocationPolicyOverride": "EXPENSIVE_FREE",
"defaultModifierIds": [
"string"
],
"name": "string",
"internalName": "string",
"description": "string",
"translations": {},
"selectionType": "SINGLE",
"minSelections": 0,
"maxSelections": 0,
"freeQuantity": 0,
"required": true,
"freeAllocationPolicy": "EXPENSIVE_FREE",
"status": "string",
"modifiers": [
{
"id": "string",
"name": "string",
"description": "string",
"translations": {},
"priceDelta": "2.50",
"sku": "string",
"image": {},
"position": 0,
"isDefault": true,
"available": true,
"referencedProductId": "string",
"status": "string"
}
]
}
]
}{
"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/products/{id}/convert-to-variable"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/convert-to-variable"
}{
"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/products/{id}/convert-to-variable"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/convert-to-variable"
}Convert a VARIABLE product back to SIMPLE
Merges the last remaining variant back into the parent product. Returns 400 if the product still has multiple variants, so delete the extras first.
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
Product ID
curl -X PATCH "https://api.brainerce.com/api/v1/products/string/convert-to-simple"{
"id": "string",
"name": "string",
"slug": "string",
"localeSlugs": {
"property1": "string",
"property2": "string"
},
"description": "string",
"descriptionFormat": "text",
"basePrice": "49.90",
"salePrice": "string",
"costPrice": "string",
"priceMin": "string",
"priceMax": "string",
"priceVaries": true,
"displayPrice": "string",
"displaySalePrice": "string",
"displayPriceMin": "string",
"displayPriceMax": "string",
"displayCurrency": "string",
"gtin": "string",
"mpn": "string",
"salePriceStartsAt": "2019-08-24T14:15:22Z",
"salePriceEndsAt": "2019-08-24T14:15:22Z",
"shippingWeightValue": 0,
"shippingWeightUnit": "string",
"shippingLengthValue": 0,
"shippingWidthValue": 0,
"shippingHeightValue": 0,
"shippingDimensionUnit": "string",
"metaDescription": "string",
"status": "string",
"sku": "string",
"type": "SIMPLE",
"kitPricingMode": "FIXED",
"kitDiscountValue": 0,
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"menuOrder": 0,
"taxBehavior": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"variants": [
{
"id": "string",
"productId": "string",
"sku": "string",
"name": "string",
"attributes": {},
"price": "19.90",
"salePrice": "string",
"costPrice": "string",
"displayPrice": "string",
"displaySalePrice": "string",
"displayCurrency": "string",
"image": "string",
"position": 0,
"status": "string",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"shippingClassId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"images": [
{
"url": "string",
"position": 0,
"isMain": true,
"alt": "string",
"id": "string",
"key": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"size": 0,
"mimeType": "string",
"createdAt": "2019-08-24T14:15:22Z",
"source": "string",
"importStatus": "string",
"importError": "string"
}
],
"channels": {},
"translations": {},
"categories": [
{
"id": "string",
"name": "string",
"taxBehavior": "string"
}
],
"brands": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"attributes": [
"string"
],
"productAttributeOptions": [
{
"id": "string",
"attributeId": "string",
"attributeOptionId": "string",
"platform": "string",
"attribute": {
"id": "string",
"name": "string",
"displayType": "string"
},
"attributeOption": {
"id": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string"
}
}
],
"tags": [
"string"
],
"metafields": [
{
"id": "string",
"definitionId": "string",
"definitionKey": "string",
"definitionName": "string",
"type": "string",
"value": "string",
"variantId": "string"
}
],
"customizationFields": [
{
"definitionId": "string",
"name": "string",
"key": "string",
"description": "string",
"type": "string",
"required": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"enumValues": [
"string"
],
"defaultValue": "string",
"position": 0
}
],
"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"
}
}
],
"channelSync": {},
"shippingClassId": "string",
"shippingClass": {
"id": "string",
"name": "string"
},
"crossSells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"upsells": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"related": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"bundleOfferCount": 0,
"orderBumpCount": 0,
"avgRating": 0,
"reviewCount": 0,
"seoScore": {
"score": 0,
"band": "excellent",
"hasUnresolvedError": true
},
"modifierGroups": [
{
"attachmentId": "string",
"groupId": "string",
"variantId": "string",
"position": 0,
"minOverride": 0,
"maxOverride": 0,
"freeQuantityOverride": 0,
"requiredOverride": true,
"freeAllocationPolicyOverride": "EXPENSIVE_FREE",
"defaultModifierIds": [
"string"
],
"name": "string",
"internalName": "string",
"description": "string",
"translations": {},
"selectionType": "SINGLE",
"minSelections": 0,
"maxSelections": 0,
"freeQuantity": 0,
"required": true,
"freeAllocationPolicy": "EXPENSIVE_FREE",
"status": "string",
"modifiers": [
{
"id": "string",
"name": "string",
"description": "string",
"translations": {},
"priceDelta": "2.50",
"sku": "string",
"image": {},
"position": 0,
"isDefault": true,
"available": true,
"referencedProductId": "string",
"status": "string"
}
]
}
]
}{
"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/products/{id}/convert-to-simple"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/convert-to-simple"
}{
"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/products/{id}/convert-to-simple"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/convert-to-simple"
}Get inventory for a product
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
Product ID
curl -X GET "https://api.brainerce.com/api/v1/products/string/inventory"{
"id": "string",
"productId": "string",
"trackingMode": "TRACKED",
"backorderMode": "string",
"backorderLimit": 0,
"total": 0,
"reserved": 0,
"available": 0,
"lowStockThreshold": 0,
"lastInventorySyncAt": "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/products/{id}/inventory"
}{
"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/products/{id}/inventory"
}Update inventory for a product
Supports Idempotency-Key header for safe retries. ⛔ Rejects a KIT with 400: a kit holds no stock of its own — its availability is MIN(floor(component.available / quantity)), recomputed from its components on every read. Set the stock on the component products instead.
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
Product 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 <= 255New absolute stock level
Variant ID (optional)
curl -X PUT "https://api.brainerce.com/api/v1/products/string/inventory" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "quantity": 0 }'{
"id": "string",
"productId": "string",
"trackingMode": "TRACKED",
"backorderMode": "string",
"backorderLimit": 0,
"total": 0,
"reserved": 0,
"available": 0,
"lowStockThreshold": 0,
"lastInventorySyncAt": "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/products/{id}/inventory"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/inventory"
}{
"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/products/{id}/inventory"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/inventory"
}Create a variant for a product
Create a variant under a VARIABLE product. Supports Idempotency-Key header for safe retries.
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
Parent product 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 <= 255Stock keeping unit
GTIN (UPC/EAN/JAN/ISBN). Falls back to product GTIN when omitted.
Manufacturer part number. Falls back to product MPN when omitted.
length <= 70Variant display name
Variant attribute map
Empty Object
Variant price (in minor units of store currency)
Variant sale price
Variant unit cost (COGS) override, which falls back to the product costPrice for margin analytics. Merchant-internal: never exposed on public storefront responses.
Initial stock quantity for this variant
0 <= valueVariant-specific image (URL string or image object)
Empty Object
Position in variant list (0-indexed)
0 <= valueVariant status
"active" | "draft"Whether this variant is a digital download
Download payload for digital variants (files + limits)
Empty Object
Per-variant shipping class ID. null/undefined inherits from parent product.
Per-variant tax class ID. null/undefined inherits from product → category → store default.
curl -X POST "https://api.brainerce.com/api/v1/products/string/variants" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"productId": "string",
"sku": "string",
"name": "string",
"attributes": {},
"price": "19.90",
"salePrice": "string",
"costPrice": "string",
"displayPrice": "string",
"displaySalePrice": "string",
"displayCurrency": "string",
"image": "string",
"position": 0,
"status": "string",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"shippingClassId": "string",
"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/products/{id}/variants"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants"
}{
"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/products/{id}/variants"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants"
}Bulk save variants
Create, update, and delete variants in a single transaction. Items with isDeleted: true are removed; items without id (or with an id starting with new-) are created; the rest are updated. Supports Idempotency-Key header for safe retries.
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
Parent product 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 <= 255Variant inputs (create/update/delete in one call)
Optional product-level attribute links to set alongside the variants
curl -X POST "https://api.brainerce.com/api/v1/products/string/variants/bulk" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "variants": [ { "sku": "TSHIRT-S-RED", "attributes": { "size": "S", "color": "Red" }, "stock": 100, "isEnabled": true } ] }'{
"created": 2,
"updated": 3,
"deleted": 1,
"variants": [
{}
]
}{
"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/products/{id}/variants/bulk"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/bulk"
}{
"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/products/{id}/variants/bulk"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/bulk"
}Update a variant
Patch a single variant: only supplied fields are updated. This is how you set the real price of a VARIABLE product. Supports Idempotency-Key header for safe retries.
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
Parent product ID
Variant 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 <= 255Stock keeping unit
GTIN (UPC/EAN/JAN/ISBN). Falls back to product GTIN when omitted.
Manufacturer part number. Falls back to product MPN when omitted.
length <= 70Variant display name
Variant attribute map
Empty Object
Variant price (in minor units of store currency)
Variant sale price
Variant unit cost (COGS) override, which falls back to the product costPrice for margin analytics. Pass null to clear. Merchant-internal: never exposed on public storefront responses.
Variant-specific image (URL string or image object)
Empty Object
Position in variant list (0-indexed)
0 <= valueVariant status
"active" | "draft"Whether this variant is a digital download
Download payload for digital variants (files + limits)
Empty Object
Per-variant shipping class ID. null/undefined inherits from parent product.
Per-variant tax class ID. null clears it; resolution then falls back to product → category → store default.
Per-channel overrides keyed by vc_* connectionId. Value is a partial variant object; a nested translations[locale] object holds per-channel localized fields.
Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/products/string/variants/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"productId": "string",
"sku": "string",
"name": "string",
"attributes": {},
"price": "19.90",
"salePrice": "string",
"costPrice": "string",
"displayPrice": "string",
"displaySalePrice": "string",
"displayCurrency": "string",
"image": "string",
"position": 0,
"status": "string",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "string",
"name": "string",
"url": "string",
"storageKey": "string",
"size": 0,
"mimeType": "string"
}
],
"downloadLimit": 0,
"downloadExpiry": 0
},
"shippingClassId": "string",
"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/products/{id}/variants/{variantId}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/{variantId}"
}{
"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/products/{id}/variants/{variantId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/{variantId}"
}Delete a variant
Delete a variant by ID. Supports Idempotency-Key header for safe retries.
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
Parent product ID
Variant 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/products/string/variants/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/{variantId}"
}{
"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/products/{id}/variants/{variantId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/{variantId}"
}Get variant inventory
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
Parent product ID
Variant ID
curl -X GET "https://api.brainerce.com/api/v1/products/string/variants/string/inventory"{
"trackingMode": "TRACKED",
"total": 0,
"reserved": 0,
"available": 0,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/{variantId}/inventory"
}{
"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/products/{id}/variants/{variantId}/inventory"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/{variantId}/inventory"
}Update variant inventory
Adjust a variant’s inventory. Provide newTotal to set absolute stock, trackingMode to switch tracking strategy, and optionally reason for the audit log. Supports Idempotency-Key header for safe retries.
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
Parent product ID
Variant 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 <= 255New absolute stock total. Must be a non-negative integer.
0 <= valueInventory tracking strategy for this variant
"TRACKED" | "UNLIMITED" | "DISABLED"Optional reason for the adjustment (recorded in the audit log)
curl -X PATCH "https://api.brainerce.com/api/v1/products/string/variants/string/inventory" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"trackingMode": "TRACKED",
"total": 0,
"reserved": 0,
"available": 0,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "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/products/{id}/variants/{variantId}/inventory"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/{variantId}/inventory"
}{
"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/products/{id}/variants/{variantId}/inventory"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/variants/{variantId}/inventory"
}Publish a product to a sales-channel site
Makes the product visible on the given sales channel (vibe-coded storefront). Accepts either the sales-channel record ID or its public vc_* connection ID. Supports Idempotency-Key header for safe retries.
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
Product 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 ID (record ID or vc_* connection ID)
curl -X POST "https://api.brainerce.com/api/v1/products/string/publish-sales-channel" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "salesChannelId": "string" }'{
"success": true,
"publish": {
"id": "clx1a2b3c4d5e6f7g8h9",
"salesChannelId": "string",
"storeId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"productId": "string"
},
"connectionName": "My storefront"
}{
"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/products/{id}/publish-sales-channel"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{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/products/{id}/publish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/publish-sales-channel"
}Unpublish a product from a sales-channel site
Hides the product from the given sales channel and clears its per-channel overrides. Accepts either the sales-channel record ID or its public vc_* connection ID. Supports Idempotency-Key header for safe retries.
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
Product 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 ID (record ID or vc_* connection ID)
curl -X POST "https://api.brainerce.com/api/v1/products/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/products/{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/products/{id}/unpublish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{id}/unpublish-sales-channel"
}Publish a coupon to a sales-channel site
Makes the coupon redeemable on the given sales channel (vibe-coded storefront). Accepts either the sales-channel record ID or its public vc_* connection ID. Supports Idempotency-Key header for safe retries.
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
Coupon 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 ID (record ID or vc_* connection ID)
curl -X POST "https://api.brainerce.com/api/v1/coupons/string/publish-sales-channel" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "salesChannelId": "string" }'{
"success": true,
"publish": {
"id": "clx1a2b3c4d5e6f7g8h9",
"salesChannelId": "string",
"storeId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"couponId": "string"
},
"connectionName": "My storefront"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{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/coupons/{id}/publish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{id}/publish-sales-channel"
}Unpublish a coupon from a sales-channel site
Supports Idempotency-Key header for safe retries.
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
Coupon 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 ID (record ID or vc_* connection ID)
curl -X POST "https://api.brainerce.com/api/v1/coupons/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/coupons/{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/coupons/{id}/unpublish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{id}/unpublish-sales-channel"
}List media library assets
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
Filename / name search
curl -X GET "https://api.brainerce.com/api/v1/media?page=0&limit=0&search=string"{
"data": [
{
"id": "string",
"url": "string",
"key": "string",
"thumbnailUrl": "string",
"mimeType": "image/webp",
"width": 0,
"height": 0,
"size": 0,
"name": "string",
"alt": "string",
"createdAt": "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/media"
}{
"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/media"
}Upload or ingest a media asset
Send multipart/form-data with either a binary file part (≤10 MB) or a sourceUrl field to ingest a remote image by URL (fetched server-side through the SSRF-safe downloader). Returns the created asset.
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
Binary file (≤10 MB)
Remote http(s) image URL to ingest (alternative to file)
curl -X POST "https://api.brainerce.com/api/v1/media"{
"id": "string",
"url": "string",
"key": "string",
"thumbnailUrl": "string",
"mimeType": "image/webp",
"width": 0,
"height": 0,
"size": 0,
"name": "string",
"alt": "string",
"createdAt": "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/media"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/media"
}{
"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/media"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/media"
}Get a media asset by ID
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
Asset ID
curl -X GET "https://api.brainerce.com/api/v1/media/string"{
"id": "string",
"url": "string",
"key": "string",
"thumbnailUrl": "string",
"mimeType": "image/webp",
"width": 0,
"height": 0,
"size": 0,
"name": "string",
"alt": "string",
"createdAt": "2019-08-24T14:15:22Z"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/media/{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/media/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/media/{id}"
}Update media asset metadata
Update the asset’s alt text and/or display name. Supports Idempotency-Key.
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
Asset 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 <= 255Accessibility alt text for the asset.
Display name / title of the asset in the media library.
curl -X PATCH "https://api.brainerce.com/api/v1/media/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"url": "string",
"key": "string",
"thumbnailUrl": "string",
"mimeType": "image/webp",
"width": 0,
"height": 0,
"size": 0,
"name": "string",
"alt": "string",
"createdAt": "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/media/{id}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/media/{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/media/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/media/{id}"
}Delete a media asset
Soft-deletes the asset and removes its key from every product/variant/category/brand/store/modifier that referenced it. Supports Idempotency-Key.
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
Asset 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/media/string" \ -H "Idempotency-Key: string"{
"success": true
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/media/{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/media/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/media/{id}"
}List orders with pagination
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
curl -X GET "https://api.brainerce.com/api/v1/orders?page=0&limit=0&status=string&sortBy=string&sortOrder=string"{
"data": [
{
"id": "string",
"storeId": "string",
"externalId": "string",
"orderNumber": "string",
"platform": "string",
"sourceName": "string",
"totalAmount": "string",
"subtotal": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"pricesIncludeTax": true,
"breakdown": [
{
"name": "VAT",
"rate": 17,
"amount": 12.45
}
],
"currency": "string"
},
"shippingAmount": "string",
"discountAmount": "string",
"couponCode": "string",
"couponDiscount": "string",
"coupon": {
"title": "string",
"type": "string",
"value": "string"
},
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": 0
}
],
"customFieldValues": {},
"adminFieldValues": {},
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"currency": "string",
"status": "string",
"financialStatus": "string",
"statusLabel": {
"id": "string",
"name": "string",
"color": "string",
"canonicalStatus": "string",
"isSystem": true
},
"notes": "string",
"paymentMethod": "string",
"isTestOrder": true,
"customer": {
"email": "string",
"name": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"name": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"name": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"phone": "string"
},
"items": [
{
"productId": "string",
"variantId": "string",
"sku": "string",
"name": "string",
"quantity": 0,
"price": "string",
"unitPrice": "string",
"totalPrice": "string",
"image": "string"
}
],
"createdAt": "2019-08-24T14:15:22Z",
"syncWarning": "string",
"paymentStatus": "string",
"paymentProviderType": "string",
"paymentProviderName": "string",
"paymentId": "string",
"paymentExternalId": "string",
"paymentAmount": "string",
"paymentCurrency": "string",
"paymentRefundedAmount": "string",
"invoiceUrl": "string",
"invoiceNumber": "string",
"numberOfPayments": 0,
"paymentCapabilities": {
"refund": true,
"manualRefundUrl": "string"
},
"refunds": [
{
"id": "string",
"amount": "string",
"reason": "string",
"status": "string",
"type": "string",
"source": "string",
"createdAt": "2019-08-24T14:15:22Z"
}
],
"tenders": [
{
"id": "string",
"type": "string",
"amountBase": "string",
"currencyBase": "string",
"giftCard": {
"id": "string",
"codeLast4": "string"
}
}
],
"isRead": true,
"downloadMeta": {
"files": [
{
"fileId": "string",
"productId": "string",
"productName": "string",
"fileName": "string",
"downloadsUsed": 0,
"downloadLimit": 0,
"expiresAt": "2019-08-24T14:15:22Z"
}
]
},
"trackingNumber": "string",
"trackingUrl": "string",
"carrier": "string",
"shippingSelection": {
"carrier": "string",
"service": "string",
"methodName": "string",
"amount": "string"
},
"deliveryType": "string",
"pickupLocationData": {
"name": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string",
"rateName": "string"
}
}
],
"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/orders"
}{
"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/orders"
}Create a new order
Honors Idempotency-Key header: retries with the same key return the original response. See /docs/api/idempotency.
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
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 <= 255Line items being purchased (maximum 500)
Customer details for the order. Optional for guest orders.
Existing Brainerce customer ID (mutually exclusive with customer)
External system identifier for this order (idempotency aid for migrations).
Initial order status. Most callers should NOT set this, because the system manages status transitions through the payment + fulfillment pipeline. Setting to a paid-looking status (e.g. SHIPPED, DELIVERED) without going through payment will be rejected: the controller currently forces the status to PENDING on creation regardless of caller input, to prevent payment-bypass.
"PENDING" | "PROCESSING" | "SHIPPED" | "DELIVERED" | "CANCELLED" | "REFUNDED"Currency code (ISO-4217). Defaults to the store currency.
Total discount amount applied
Applied coupon code (snapshot)
Shipping amount
Tax amount
Payment method identifier
Free-form notes attached to the order
Source name (e.g. "web", "pos", "import")
Optional shipping address. Shape matches the standard OrderAddress payload.
Empty Object
Optional billing address. Shape matches the standard OrderAddress payload.
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/orders" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "productId": "prd_01H...", "quantity": 1, "price": 19.99 } ] }'{
"id": "string",
"storeId": "string",
"externalId": "string",
"orderNumber": "string",
"platform": "string",
"sourceName": "string",
"totalAmount": "string",
"subtotal": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"pricesIncludeTax": true,
"breakdown": [
{
"name": "VAT",
"rate": 17,
"amount": 12.45
}
],
"currency": "string"
},
"shippingAmount": "string",
"discountAmount": "string",
"couponCode": "string",
"couponDiscount": "string",
"coupon": {
"title": "string",
"type": "string",
"value": "string"
},
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": 0
}
],
"customFieldValues": {},
"adminFieldValues": {},
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"currency": "string",
"status": "string",
"financialStatus": "string",
"statusLabel": {
"id": "string",
"name": "string",
"color": "string",
"canonicalStatus": "string",
"isSystem": true
},
"notes": "string",
"paymentMethod": "string",
"isTestOrder": true,
"customer": {
"email": "string",
"name": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"name": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"name": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"phone": "string"
},
"items": [
{
"productId": "string",
"variantId": "string",
"sku": "string",
"name": "string",
"quantity": 0,
"price": "string",
"unitPrice": "string",
"totalPrice": "string",
"image": "string"
}
],
"createdAt": "2019-08-24T14:15:22Z",
"syncWarning": "string",
"paymentStatus": "string",
"paymentProviderType": "string",
"paymentProviderName": "string",
"paymentId": "string",
"paymentExternalId": "string",
"paymentAmount": "string",
"paymentCurrency": "string",
"paymentRefundedAmount": "string",
"invoiceUrl": "string",
"invoiceNumber": "string",
"numberOfPayments": 0,
"paymentCapabilities": {
"refund": true,
"manualRefundUrl": "string"
},
"refunds": [
{
"id": "string",
"amount": "string",
"reason": "string",
"status": "string",
"type": "string",
"source": "string",
"createdAt": "2019-08-24T14:15:22Z"
}
],
"tenders": [
{
"id": "string",
"type": "string",
"amountBase": "string",
"currencyBase": "string",
"giftCard": {
"id": "string",
"codeLast4": "string"
}
}
],
"isRead": true,
"downloadMeta": {
"files": [
{
"fileId": "string",
"productId": "string",
"productName": "string",
"fileName": "string",
"downloadsUsed": 0,
"downloadLimit": 0,
"expiresAt": "2019-08-24T14:15:22Z"
}
]
},
"trackingNumber": "string",
"trackingUrl": "string",
"carrier": "string",
"shippingSelection": {
"carrier": "string",
"service": "string",
"methodName": "string",
"amount": "string"
},
"deliveryType": "string",
"pickupLocationData": {
"name": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string",
"rateName": "string"
}
}{
"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/orders"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders"
}{
"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/orders"
}Get a single order by ID
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
Order ID
curl -X GET "https://api.brainerce.com/api/v1/orders/string"{
"id": "string",
"storeId": "string",
"externalId": "string",
"orderNumber": "string",
"platform": "string",
"sourceName": "string",
"totalAmount": "string",
"subtotal": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"pricesIncludeTax": true,
"breakdown": [
{
"name": "VAT",
"rate": 17,
"amount": 12.45
}
],
"currency": "string"
},
"shippingAmount": "string",
"discountAmount": "string",
"couponCode": "string",
"couponDiscount": "string",
"coupon": {
"title": "string",
"type": "string",
"value": "string"
},
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": 0
}
],
"customFieldValues": {},
"adminFieldValues": {},
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"currency": "string",
"status": "string",
"financialStatus": "string",
"statusLabel": {
"id": "string",
"name": "string",
"color": "string",
"canonicalStatus": "string",
"isSystem": true
},
"notes": "string",
"paymentMethod": "string",
"isTestOrder": true,
"customer": {
"email": "string",
"name": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"name": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"name": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"phone": "string"
},
"items": [
{
"productId": "string",
"variantId": "string",
"sku": "string",
"name": "string",
"quantity": 0,
"price": "string",
"unitPrice": "string",
"totalPrice": "string",
"image": "string"
}
],
"createdAt": "2019-08-24T14:15:22Z",
"syncWarning": "string",
"paymentStatus": "string",
"paymentProviderType": "string",
"paymentProviderName": "string",
"paymentId": "string",
"paymentExternalId": "string",
"paymentAmount": "string",
"paymentCurrency": "string",
"paymentRefundedAmount": "string",
"invoiceUrl": "string",
"invoiceNumber": "string",
"numberOfPayments": 0,
"paymentCapabilities": {
"refund": true,
"manualRefundUrl": "string"
},
"refunds": [
{
"id": "string",
"amount": "string",
"reason": "string",
"status": "string",
"type": "string",
"source": "string",
"createdAt": "2019-08-24T14:15:22Z"
}
],
"tenders": [
{
"id": "string",
"type": "string",
"amountBase": "string",
"currencyBase": "string",
"giftCard": {
"id": "string",
"codeLast4": "string"
}
}
],
"isRead": true,
"downloadMeta": {
"files": [
{
"fileId": "string",
"productId": "string",
"productName": "string",
"fileName": "string",
"downloadsUsed": 0,
"downloadLimit": 0,
"expiresAt": "2019-08-24T14:15:22Z"
}
]
},
"trackingNumber": "string",
"trackingUrl": "string",
"carrier": "string",
"shippingSelection": {
"carrier": "string",
"service": "string",
"methodName": "string",
"amount": "string"
},
"deliveryType": "string",
"pickupLocationData": {
"name": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string",
"rateName": "string"
}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{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/orders/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{id}"
}Update an order
Supports Idempotency-Key header for safe retries.
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
Order 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 <= 255New order status
curl -X PATCH "https://api.brainerce.com/api/v1/orders/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"storeId": "string",
"externalId": "string",
"orderNumber": "string",
"platform": "string",
"sourceName": "string",
"totalAmount": "string",
"subtotal": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"pricesIncludeTax": true,
"breakdown": [
{
"name": "VAT",
"rate": 17,
"amount": 12.45
}
],
"currency": "string"
},
"shippingAmount": "string",
"discountAmount": "string",
"couponCode": "string",
"couponDiscount": "string",
"coupon": {
"title": "string",
"type": "string",
"value": "string"
},
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": 0
}
],
"customFieldValues": {},
"adminFieldValues": {},
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"currency": "string",
"status": "string",
"financialStatus": "string",
"statusLabel": {
"id": "string",
"name": "string",
"color": "string",
"canonicalStatus": "string",
"isSystem": true
},
"notes": "string",
"paymentMethod": "string",
"isTestOrder": true,
"customer": {
"email": "string",
"name": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"name": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"name": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"phone": "string"
},
"items": [
{
"productId": "string",
"variantId": "string",
"sku": "string",
"name": "string",
"quantity": 0,
"price": "string",
"unitPrice": "string",
"totalPrice": "string",
"image": "string"
}
],
"createdAt": "2019-08-24T14:15:22Z",
"syncWarning": "string",
"paymentStatus": "string",
"paymentProviderType": "string",
"paymentProviderName": "string",
"paymentId": "string",
"paymentExternalId": "string",
"paymentAmount": "string",
"paymentCurrency": "string",
"paymentRefundedAmount": "string",
"invoiceUrl": "string",
"invoiceNumber": "string",
"numberOfPayments": 0,
"paymentCapabilities": {
"refund": true,
"manualRefundUrl": "string"
},
"refunds": [
{
"id": "string",
"amount": "string",
"reason": "string",
"status": "string",
"type": "string",
"source": "string",
"createdAt": "2019-08-24T14:15:22Z"
}
],
"tenders": [
{
"id": "string",
"type": "string",
"amountBase": "string",
"currencyBase": "string",
"giftCard": {
"id": "string",
"codeLast4": "string"
}
}
],
"isRead": true,
"downloadMeta": {
"files": [
{
"fileId": "string",
"productId": "string",
"productName": "string",
"fileName": "string",
"downloadsUsed": 0,
"downloadLimit": 0,
"expiresAt": "2019-08-24T14:15:22Z"
}
]
},
"trackingNumber": "string",
"trackingUrl": "string",
"carrier": "string",
"shippingSelection": {
"carrier": "string",
"service": "string",
"methodName": "string",
"amount": "string"
},
"deliveryType": "string",
"pickupLocationData": {
"name": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string",
"rateName": "string"
}
}{
"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/orders/{id}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{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/orders/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{id}"
}Live carrier rates for an order
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
Order ID
curl -X GET "https://api.brainerce.com/api/v1/orders/string/shipments/app-rates"[
{
"id": "string",
"name": "USPS Priority",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"carrier": "string",
"service": "string"
}
]{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{id}/shipments/app-rates"
}{
"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/orders/{id}/shipments/app-rates"
}Buy a shipping label via the installed shipping app
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
Order ID
Opaque rate id returned by the installed shipping app, passed back verbatim. Do not parse it.
Override default parcel dimensions from app config
Label file format. ZPL/EPL drive warehouse thermal printers; PDF prints from a browser. If the carrier cannot produce the requested format it returns its closest match.
"PDF""PDF" | "PNG" | "ZPL" | "EPL"Customs contents type for a cross-border shipment. Ignored for domestic labels.
"merchandise""merchandise" | "gift" | "documents" | "sample" | "return"curl -X POST "https://api.brainerce.com/api/v1/orders/string/shipments/app-label" \ -H "Content-Type: application/json" \ -d '{ "rateId": "rate_8f123456789abcdef" }'{
"shipmentId": "string",
"labelUrl": "string",
"trackingNumber": "string",
"carrier": "string"
}{
"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/orders/{id}/shipments/app-label"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{id}/shipments/app-label"
}{
"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/orders/{id}/shipments/app-label"
}Shipments and tracking history for an order
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
Order ID
curl -X GET "https://api.brainerce.com/api/v1/orders/string/shipments"[
{
"id": "string",
"carrier": "ups",
"service": "ground",
"status": "string",
"trackingNumber": "string",
"trackingUrl": "string",
"labelUrl": "string",
"labelFormat": "string",
"estimatedDeliveryDate": "2019-08-24T14:15:22Z",
"actualDeliveryDate": "2019-08-24T14:15:22Z",
"rate": "string",
"rateCurrency": "string",
"createdAt": "2019-08-24T14:15:22Z",
"events": [
{
"status": "in_transit",
"statusDetail": "arrived_at_facility",
"message": "string",
"location": {},
"occurredAt": "2019-08-24T14:15:22Z"
}
]
}
]{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{id}/shipments"
}{
"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/orders/{id}/shipments"
}List order custom field definitions
The merchant-defined fields that can be written onto an order. Call this first to discover the key and type of each field — those keys are what PATCH /v1/orders/{id}/custom-fields accepts. Inactive definitions are included so a caller can tell "the merchant disabled this field" apart from "the merchant never created it".
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
curl -X GET "https://api.brainerce.com/api/v1/order-custom-fields"[
{
"id": "string",
"storeId": "string",
"name": "Licence key",
"key": "licence_key",
"description": "string",
"type": "TEXT",
"required": true,
"isPublic": true,
"position": 0,
"isActive": true,
"options": {},
"minLength": 0,
"maxLength": 0,
"minValue": "string",
"maxValue": "string",
"dateAvailability": {},
"translations": {},
"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/order-custom-fields"
}{
"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/order-custom-fields"
}Get the custom field values on an order
Returns the stored values keyed by definition key. These are the merchant-managed fields on the order (adminFieldValues), not the ones a shopper filled in at checkout.
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
Order ID
curl -X GET "https://api.brainerce.com/api/v1/orders/string/custom-fields"{
"orderId": "string",
"fields": {
"licence_key": "ABCD-EFGH-IJKL",
"activated_at": "2026-09-09"
}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{id}/custom-fields"
}{
"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/orders/{id}/custom-fields"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{id}/custom-fields"
}Set custom field values on an order
Merges the supplied values into the order. Omitted keys keep their current value; null clears a non-required field. Values are coerced to the definition type and rejected with a 400 when they cannot be — a key with no active definition is ignored instead, so read the response to confirm what was stored.
Where a value ends up: it shows on the order in the dashboard, reaches the storefront through the SDK when the definition's isPublic is on, and travels to every order email as orderCustomFields. No default email template prints that variable — until the merchant adds the block to their template once, a value written here is stored correctly and seen by nobody. Writing a field is not the same as the customer being told.
Supports Idempotency-Key header for safe retries.
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
Order 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 <= 255Values to write, keyed by definition key. This is a MERGE: keys you omit keep their current value. Send null to clear one (a required field refuses this). A key with no active definition on the store is IGNORED rather than rejected, so a caller writing an optional field the merchant has not created yet does not fail the whole request — read the response fields to see what was actually stored.
Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/orders/string/custom-fields" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "fields": { "licence_key": "ABCD-EFGH-IJKL" } }'{
"orderId": "string",
"fields": {
"licence_key": "ABCD-EFGH-IJKL",
"activated_at": "2026-09-09"
}
}{
"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/orders/{id}/custom-fields"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{id}/custom-fields"
}{
"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/orders/{id}/custom-fields"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/orders/{id}/custom-fields"
}[Not implemented] Trigger a sync to platforms
This endpoint is not implemented. It returns 501 Not Implemented. Use the per-resource publish endpoints (e.g. POST /v1/coupons/{id}/sync, POST /v1/categories/{id}/publish-sales-channel) instead.
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
curl -X POST "https://api.brainerce.com/api/v1/sync"{
"statusCode": 501,
"code": "NOT_IMPLEMENTED",
"message": "The generic sync trigger has been removed; use per-resource publish endpoints",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/sync"
}[Not implemented] Get sync job status
This endpoint is not implemented. It returns 501 Not Implemented. There is no generic sync job pipeline behind /v1/sync.
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
Sync Job ID
curl -X GET "https://api.brainerce.com/api/v1/sync/string"{
"statusCode": 501,
"code": "NOT_IMPLEMENTED",
"message": "The generic sync trigger has been removed; use per-resource publish endpoints",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/sync/{jobId}"
}Create a new customer
Honors Idempotency-Key header. See /docs/api/idempotency.
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
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 <= 255Customer email, unique per store. Used for login (when password is set) and order lookup.
Phone number (E.164 format recommended for SMS notifications).
First name.
Last name.
Plaintext password. When provided, the customer is created as a registered account (can log in). When omitted, a guest record is created (orders can still link by email).
8 <= lengthMarketing consent flag. Required for transactional vs marketing email split.
Birthday month (1-12) for the loyalty birthday gift. Month and day only, with no year. Send it together with birthDay or not at all; one without the other is rejected.
1 <= value <= 12Birthday day of month (1-31). Send it together with birthMonth or not at all. The day must exist in that month, so 30 February is rejected.
1 <= value <= 31Free-form tags for segmentation (VIP, B2B, beta-tester, …).
Free-form customer segment/role set by the merchant (e.g. "wholesale", "vip", "ambassador"). Returned on /customers/me so storefront code can branch on it to build custom, role-gated features. Not settable by the customer themselves: admin dashboard/API only.
length <= 50FIRST-TOUCH sales channel for a customer being created here. Creating a customer through the dashboard or API is not itself a channel sighting, so this stays null unless you say otherwise. Set it when you know where the person actually came from (migrating from another system, a phone order taken for a specific storefront). Accepts the internal SalesChannel id or the public vc_* connectionId. Attach them to the channels they SHOP on separately, via the publish endpoint.
Arbitrary JSON metadata. Useful for storing integration-specific IDs (your ERP customer number, CRM contact id, …).
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/customers" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]" }'{
"id": "cust_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+14155552671",
"hasAccount": true,
"emailVerified": true,
"acceptsMarketing": true,
"birthMonth": 4,
"birthDay": 17,
"tags": [
"vip",
"newsletter"
],
"role": "wholesale",
"totalOrders": 12,
"totalSpent": "1284.50",
"lastOrderAt": "2026-05-10T14:32:11.000Z",
"rfm": {
"r": 5,
"f": 4,
"m": 5,
"score": "5-4-5",
"segment": "champion"
},
"createdAt": "2025-08-01T09:00:00.000Z",
"loyaltyPointsBalance": 240,
"isLoyaltyMember": true,
"acquisitionSalesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"channelPublishes": [
{
"salesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"firstSeenAt": "2026-03-04T08:12:00.000Z",
"lastSeenAt": "2026-08-11T19:40:22.000Z"
}
],
"metadata": {
"erpId": "CUST-00421"
},
"loyaltyMembershipId": "clmem_abc123",
"platformConnections": [
{
"platformCode": "shopify",
"externalId": "7654321098765"
}
],
"addresses": [
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
],
"updatedAt": "2026-05-12T11:24:08.000Z"
}{
"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/customers"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers"
}{
"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/customers"
}Get a customer by ID
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
Customer ID
curl -X GET "https://api.brainerce.com/api/v1/customers/string"{
"id": "cust_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+14155552671",
"hasAccount": true,
"emailVerified": true,
"acceptsMarketing": true,
"birthMonth": 4,
"birthDay": 17,
"tags": [
"vip",
"newsletter"
],
"role": "wholesale",
"totalOrders": 12,
"totalSpent": "1284.50",
"lastOrderAt": "2026-05-10T14:32:11.000Z",
"rfm": {
"r": 5,
"f": 4,
"m": 5,
"score": "5-4-5",
"segment": "champion"
},
"createdAt": "2025-08-01T09:00:00.000Z",
"loyaltyPointsBalance": 240,
"isLoyaltyMember": true,
"acquisitionSalesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"channelPublishes": [
{
"salesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"firstSeenAt": "2026-03-04T08:12:00.000Z",
"lastSeenAt": "2026-08-11T19:40:22.000Z"
}
],
"metadata": {
"erpId": "CUST-00421"
},
"loyaltyMembershipId": "clmem_abc123",
"platformConnections": [
{
"platformCode": "shopify",
"externalId": "7654321098765"
}
],
"addresses": [
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
],
"updatedAt": "2026-05-12T11:24:08.000Z",
"marketingStatus": "SUBSCRIBED"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{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/customers/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}"
}Update a customer
Supports Idempotency-Key header for safe retries.
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
Customer 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 <= 255Customer email. Changing email re-triggers verification (the new address must be verified before sensitive operations).
Phone number.
First name.
Last name.
Marketing consent flag.
Birthday month (1-12) for the loyalty birthday gift. Month and day only, no year. Send null for BOTH fields to remove a stored birthday; sending neither leaves it untouched, so an edit form that simply omits an emptied field can correct a birthday but never clear one.
Birthday day of month (1-31). Send null for BOTH fields to remove a stored birthday; sending neither leaves it untouched, so an edit form that simply omits an emptied field can correct a birthday but never clear one.
Replace the customer's tag list. Pass [] to clear all tags.
Free-form customer segment/role set by the merchant (e.g. "wholesale", "vip", "ambassador"). Pass an empty string to clear it. Not settable by the customer themselves: admin dashboard/API only.
length <= 50Override the FIRST-TOUCH sales channel, the channel this customer came in through. Normally stamped automatically at registration / OAuth / checkout and then never changed; this is the merchant correction for customers created from the dashboard or imported from a file, where no channel was ever known. Accepts the internal SalesChannel id or the public vc_* connectionId. Pass an empty string to clear it back to "unknown". Does NOT change which channels the customer is active in: that is the publish/unpublish endpoints.
Replace metadata JSON (full replacement, not merge).
Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/customers/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "cust_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+14155552671",
"hasAccount": true,
"emailVerified": true,
"acceptsMarketing": true,
"birthMonth": 4,
"birthDay": 17,
"tags": [
"vip",
"newsletter"
],
"role": "wholesale",
"totalOrders": 12,
"totalSpent": "1284.50",
"lastOrderAt": "2026-05-10T14:32:11.000Z",
"rfm": {
"r": 5,
"f": 4,
"m": 5,
"score": "5-4-5",
"segment": "champion"
},
"createdAt": "2025-08-01T09:00:00.000Z",
"loyaltyPointsBalance": 240,
"isLoyaltyMember": true,
"acquisitionSalesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"channelPublishes": [
{
"salesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"firstSeenAt": "2026-03-04T08:12:00.000Z",
"lastSeenAt": "2026-08-11T19:40:22.000Z"
}
],
"metadata": {
"erpId": "CUST-00421"
},
"loyaltyMembershipId": "clmem_abc123",
"platformConnections": [
{
"platformCode": "shopify",
"externalId": "7654321098765"
}
],
"addresses": [
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
],
"updatedAt": "2026-05-12T11:24:08.000Z"
}{
"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/customers/{id}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{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/customers/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}"
}Attach a customer to a sales channel
Marks the customer as active in the given sales channel. Normally automatic, because the platform records a channel when the customer registers, signs in, or checks out there, so use this for migrations and corrections. A customer belongs to one store but can be active in any number of its channels. Accepts either the sales-channel record ID or its public vc_* connection ID. Idempotent, and supports the Idempotency-Key header for safe retries. Does NOT change the first-touch channel (acquisitionSalesChannelId on the update endpoint).
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
Customer 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 ID (record ID or vc_* connection ID)
curl -X POST "https://api.brainerce.com/api/v1/customers/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/customers/{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/customers/{id}/publish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/publish-sales-channel"
}Detach a customer from a sales channel
Removes the customer from the given sales channel. This is a correction, NOT a block: it does not prevent that person from buying on that storefront, and the channel is recorded again the next time they sign in or order there. Supports the Idempotency-Key header for safe retries.
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
Customer 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 ID (record ID or vc_* connection ID)
curl -X POST "https://api.brainerce.com/api/v1/customers/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/customers/{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/customers/{id}/unpublish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/unpublish-sales-channel"
}Get a customer by email
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
curl -X GET "https://api.brainerce.com/api/v1/customers/by-email?email=string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/by-email"
}{
"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/customers/by-email"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/by-email"
}Customer login
Supports Idempotency-Key header for safe retries.
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
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 <= 255Customer email address used at registration.
Customer password (plaintext over HTTPS, and never logged).
curl -X POST "https://api.brainerce.com/api/v1/customers/login" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "password": "CorrectHorse-Battery-Staple9" }'{
"customer": {
"id": "string",
"email": "[email protected]",
"firstName": "string",
"lastName": "string",
"phone": "string",
"emailVerified": true
},
"token": "string",
"expiresAt": "2019-08-24T14:15:22Z",
"requiresVerification": 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/customers/login"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/login"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/login"
}Customer registration
Supports Idempotency-Key header for safe retries.
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
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 <= 255Customer email, unique per store. Becomes the login identifier.
Password (≥ 8 chars, must match PASSWORD_REGEX: at least one uppercase, lowercase, number, and special char).
8 <= lengthFirst name.
Last name.
Phone number (E.164 format recommended).
Marketing consent flag (gates promo emails / SMS).
Birthday month (1-12) for the loyalty birthday gift. Month and day only, with no year. Send it together with birthDay or not at all. Optional on most channels; a channel with requireBirthday turned on rejects a registration that omits it.
1 <= value <= 12Birthday day of month (1-31). Send it together with birthMonth or not at all. The day must exist in that month, so 30 February is rejected.
1 <= value <= 31Privacy-policy acceptance flag, required by some stores before account creation. The frontend should require this checkbox when the store enables it.
Loyalty referral share code (REF-XXXXXXXX) from a referrer's link. Validated asynchronously after registration, so an invalid code never fails the registration itself.
curl -X POST "https://api.brainerce.com/api/v1/customers/register" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "password": "CorrectHorse-Battery-Staple9" }'{
"customer": {
"id": "string",
"email": "[email protected]",
"firstName": "string",
"lastName": "string",
"phone": "string",
"emailVerified": true
},
"token": "string",
"expiresAt": "2019-08-24T14:15:22Z",
"requiresVerification": 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/customers/register"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/register"
}Request password reset
Supports Idempotency-Key header for safe retries.
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
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 <= 255Email address to send the password-reset link to. Endpoint always responds 200 (no enumeration); the email is only sent if a matching customer exists.
curl -X POST "https://api.brainerce.com/api/v1/customers/forgot-password" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]" }'{
"message": "If an account exists with that email, a reset link has been sent"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/forgot-password"
}Reset password with token
Supports Idempotency-Key header for safe retries.
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
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 <= 255Single-use reset token from the password-reset email. Tokens expire after 1 hour and are invalidated on use.
New password (≥ 8 chars, must match PASSWORD_REGEX: at least one uppercase, lowercase, number, and special char).
8 <= lengthcurl -X POST "https://api.brainerce.com/api/v1/customers/reset-password" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "token": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6", "newPassword": "CorrectHorse-Battery-Staple9" }'{
"message": "If an account exists with that email, a reset link has been sent"
}{
"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/customers/reset-password"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/reset-password"
}Get customer addresses
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
Customer ID
curl -X GET "https://api.brainerce.com/api/v1/customers/string/addresses"[
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
]{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}{
"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/customers/{id}/addresses"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}Add a customer address
Supports Idempotency-Key header for safe retries.
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
Customer 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 <= 255Friendly label shown in the address picker UI.
First name on the address.
Last name on the address.
Company name (B2B).
Street address line 1.
Street address line 2 (apt/suite).
City.
State / Province.
Postal / ZIP code.
ISO 3166-1 alpha-2 country code.
Phone (E.164 recommended).
Mark this address as the customer's default. Promoting a new default automatically demotes the previous one.
curl -X POST "https://api.brainerce.com/api/v1/customers/string/addresses" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "firstName": "Jane", "lastName": "Doe", "line1": "123 Main St", "city": "San Francisco", "postalCode": "94103", "country": "US" }'{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}{
"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/customers/{id}/addresses"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}{
"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/customers/{id}/addresses"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}Update a customer address
Supports Idempotency-Key header for safe retries.
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
Customer ID
Address 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 <= 255Friendly label.
First name.
Last name.
Company.
Street line 1.
Street line 2.
City.
State / Province.
Postal / ZIP.
ISO country code.
Phone.
Promote this address to be the customer's default.
curl -X PATCH "https://api.brainerce.com/api/v1/customers/string/addresses/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}{
"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/customers/{id}/addresses/{addressId}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}{
"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/customers/{id}/addresses/{addressId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}Delete a customer address
Supports Idempotency-Key header for safe retries.
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
Customer ID
Address 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/customers/string/addresses/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}{
"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/customers/{id}/addresses/{addressId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}Get customer orders
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
Customer ID
Query Parameters
curl -X GET "https://api.brainerce.com/api/v1/customers/string/orders?page=0&limit=0"{
"data": [
{
"id": "string",
"externalId": "string",
"orderNumber": "#1001",
"status": "string",
"totalAmount": "string",
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"couponCode": "string",
"couponDiscount": "string",
"ruleDiscountAmount": "string",
"appliedDiscounts": [
{}
],
"shippingAmount": "string",
"taxAmount": "string",
"shippingAddress": {},
"billingAddress": {},
"items": [
{
"productId": "string",
"variantId": "string",
"sku": "string",
"name": "string",
"quantity": 0,
"price": "string",
"unitPrice": "string",
"totalPrice": "string",
"image": "string",
"customizations": {},
"modifiers": [
{
"modifierId": "string",
"groupId": "string",
"groupName": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string"
}
]
}
],
"paymentMethod": "string",
"financialStatus": "string",
"fulfillmentStatus": "string",
"trackingNumber": "string",
"trackingUrl": "string",
"carrier": "string",
"shippedAt": "2019-08-24T14:15:22Z",
"deliveredAt": "2019-08-24T14:15:22Z",
"statusHistory": [
{}
],
"platform": "string",
"createdAt": "2019-08-24T14:15:22Z",
"notes": "string",
"hasDownloads": true
}
],
"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/customers/{id}/orders"
}{
"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/customers/{id}/orders"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/orders"
}Create a new cart
Supports Idempotency-Key header for safe retries.
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
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 <= 255Existing session token to attach this cart to. Omit on the first call, and the server will generate a fresh token and return it on the response. Only supply on retry / explicit re-attach flows.
Customer id to associate the cart with. Only honoured for admin / server-to-server callers. Sales-channel callers must instead send a Authorization: Bearer <customer-token> header.
GA4 gtag.js client_id (from gtag('get', measurementId, 'client_id', cb)), forwarded so a later server-side purchase event can stitch to this browser session. Omit if unavailable, and never send a synthesized id.
length <= 100GA4 gtag.js session_id (from gtag('get', measurementId, 'session_id', cb)), forwarded alongside analyticsClientId for the same stitch.
length <= 100curl -X POST "https://api.brainerce.com/api/v1/cart?customerId=string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart"
}{
"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/cart"
}Get cart by session 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
Cart session token
curl -X GET "https://api.brainerce.com/api/v1/cart/session/string"{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/session/{sessionToken}"
}{
"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/cart/session/{sessionToken}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/session/{sessionToken}"
}Get cart by customer ID
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
Customer ID
curl -X GET "https://api.brainerce.com/api/v1/cart/customer/string"{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/customer/{customerId}"
}{
"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/cart/customer/{customerId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/customer/{customerId}"
}Get cart by ID
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
Cart ID
curl -X GET "https://api.brainerce.com/api/v1/cart/string"{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}"
}{
"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/cart/{cartId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}"
}Add item to cart
Supports Idempotency-Key header for safe retries.
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
Cart 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 <= 255Product to add.
Variant id for the product, if it has variants.
Number of units to add (1..1000).
1 <= value <= 1000Shopper-facing note attached to this line item ("Please gift-wrap"). Max 2000 chars.
length <= 2000Arbitrary JSON metadata you want to carry through to the order line. Not displayed in the storefront UI. Max 4 KB, depth ≤ 3, no prototype keys.
Empty Object
GA4 gtag.js client_id (from gtag('get', measurementId, 'client_id', cb)), forwarded so a later server-side purchase event can stitch to this browser session. Written onto the cart if not already set. Omit if unavailable, and never send a synthesized id.
length <= 100GA4 gtag.js session_id (from gtag('get', measurementId, 'session_id', cb)), forwarded alongside analyticsClientId for the same stitch.
length <= 100Modifier selections grouped by modifierGroupId, in click-order. Omit for products without modifier groups.
Nested combo specs (for modifiers with referencedProductId). Keyed by parent modifier id; validator rejects depth > 3.
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/cart/string/items" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "productId": "prod_abc123", "quantity": 1 }'{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"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/cart/{cartId}/items"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/items"
}{
"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/cart/{cartId}/items"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/items"
}Clear all items from cart
Supports Idempotency-Key header for safe retries.
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
Cart 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/cart/string/items" \ -H "Idempotency-Key: string"{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/items"
}{
"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/cart/{cartId}/items"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/items"
}Update cart item
Supports Idempotency-Key header for safe retries.
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
Cart ID
Cart Item 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 <= 255New quantity (0 to 1000). Setting quantity: 0 removes the line, same as DELETE.
0 <= value <= 1000New shopper-facing note for this line.
New modifier selections. PRD §7.2.3: present means REPLACE all existing selections on this line. Omit to keep the existing selections unchanged.
New nested combo selections. Same REPLACE semantics as selections.
Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/cart/string/items/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"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/cart/{cartId}/items/{itemId}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/items/{itemId}"
}{
"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/cart/{cartId}/items/{itemId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/items/{itemId}"
}Remove item from cart
Supports Idempotency-Key header for safe retries.
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
Cart ID
Cart Item 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/cart/string/items/string" \ -H "Idempotency-Key: string"{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/items/{itemId}"
}{
"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/cart/{cartId}/items/{itemId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/items/{itemId}"
}Apply coupon to cart
Supports Idempotency-Key header for safe retries.
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
Cart 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 <= 255Coupon code (case-insensitive). Validation runs server-side, and invalid codes return 400 with code: COUPON_INVALID or COUPON_USAGE_LIMIT_REACHED.
curl -X POST "https://api.brainerce.com/api/v1/cart/string/coupon" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "code": "SUMMER25" }'{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"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/cart/{cartId}/coupon"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/coupon"
}{
"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/cart/{cartId}/coupon"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/coupon"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/coupon"
}Remove coupon from cart
Supports Idempotency-Key header for safe retries.
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
Cart 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/cart/string/coupon" \ -H "Idempotency-Key: string"{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/coupon"
}{
"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/cart/{cartId}/coupon"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/{cartId}/coupon"
}Merge guest cart into customer cart
Supports Idempotency-Key header for safe retries.
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
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 <= 255Guest cart session token
Customer ID to merge into
curl -X POST "https://api.brainerce.com/api/v1/cart/merge" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "sessionToken": "string", "customerId": "string" }'{
"id": "string",
"sessionToken": "string",
"customerId": "string",
"status": "string",
"currency": "string",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"promoDiscountTotal": "string",
"couponCode": "string",
"appliedDiscounts": [
{
"ruleId": "string",
"ruleName": "string",
"type": "string",
"discountAmount": "string",
"description": "string"
}
],
"nudges": [
{
"ruleId": "string",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "string",
"quantityNeeded": 0
}
],
"items": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"currentUnitPrice": "string",
"priceChanged": true,
"priceDelta": "string",
"priceDirection": "increased",
"isAvailable": true,
"unavailableReason": "PRODUCT_DRAFT",
"discountAmount": "string",
"promoDiscountAmount": "string",
"promoSource": "string",
"promoSourceId": "string",
"notes": "string",
"metadata": {},
"customizations": {},
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
]
},
"variant": {
"id": "string",
"name": "string",
"sku": "string",
"image": {}
},
"modifiers": [
{
"modifierId": "string",
"modifierGroupId": "string",
"name": "string",
"priceDelta": "string",
"freeApplied": true,
"effectivePrice": "string",
"positionInGroup": 0
}
],
"modifiersTotal": "string",
"parentCartItemId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"itemCount": 0,
"hasPriceChanges": true,
"hasUnavailableItems": true,
"unavailableItemIds": [
"string"
],
"expiresAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}{
"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/cart/merge"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/merge"
}{
"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/cart/merge"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/cart/merge"
}Create checkout from cart
Honors Idempotency-Key header. See /docs/api/idempotency. Strongly recommended on this endpoint.
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
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 <= 255ID of the cart to convert into a checkout. The cart must belong to the same store and contain at least one purchasable line item.
ID of the logged-in customer to attach to the checkout. When omitted, the checkout is treated as a guest checkout and the customer record (if any) is matched/created from the email on setCustomerInfo.
Subset of cart line-item IDs to include in this checkout. Use this for "buy now" / express-checkout flows that purchase a single item from a larger cart. When omitted, every line item in the cart is included.
ID of the region to associate with this checkout (multi-region commerce). The region must belong to the same store. Recorded for reporting + provider scoping. FX-at-checkout: when the region currency differs from the store base AND its payment provider can settle that currency (presentment-enabled, which today means Stripe), the checkout pins a charging rate and the payment intent is charged in the region currency; the response carries a presentment overlay with the charged amounts. Otherwise the checkout is charged in the store base currency (presentment unavailable → safe fallback). When omitted, the store default region applies.
curl -X POST "https://api.brainerce.com/api/v1/checkout" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "cartId": "cart_01HQ7Z2YK3M8N4P5R6S7T8V9W0" }'{
"id": "string",
"status": "string",
"email": "string",
"customerId": "string",
"deliveryType": "shipping",
"pickupLocation": {
"id": "string",
"name": "string",
"rateName": "string",
"address": {
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string"
},
"phone": "string",
"hours": "string",
"instructions": "string",
"price": "string",
"currency": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"shippingRateId": "string",
"shippingMethod": {
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
},
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"shippingAmount": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"breakdown": [
{
"name": "string",
"rate": 0,
"amount": 0
}
],
"currency": "string"
},
"total": "string",
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": "string"
}
],
"customFieldValues": {},
"couponCode": "string",
"tenders": [
{
"tenderId": "string",
"amountApplied": "string"
}
],
"providerAmountDue": "string",
"notes": "string",
"lineItems": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"discountAmount": "string",
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
],
"isDownloadable": true
},
"variant": {
"id": "string",
"name": "string",
"sku": "string"
},
"notes": "string",
"metadata": {},
"customizations": {}
}
],
"itemCount": 0,
"availableShippingRates": [
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
],
"expiresAt": "2019-08-24T14:15:22Z",
"recoveryEmailSentAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"presentment": {
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"shippingAmount": "string",
"taxAmount": "string",
"surchargeAmount": "string",
"total": "string",
"fxChargingRate": "string",
"fxBufferPercent": "string"
}
}{
"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/checkout"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout"
}{
"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/checkout"
}Get checkout
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
Checkout ID
curl -X GET "https://api.brainerce.com/api/v1/checkout/string"{
"id": "string",
"status": "string",
"email": "string",
"customerId": "string",
"deliveryType": "shipping",
"pickupLocation": {
"id": "string",
"name": "string",
"rateName": "string",
"address": {
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string"
},
"phone": "string",
"hours": "string",
"instructions": "string",
"price": "string",
"currency": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"shippingRateId": "string",
"shippingMethod": {
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
},
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"shippingAmount": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"breakdown": [
{
"name": "string",
"rate": 0,
"amount": 0
}
],
"currency": "string"
},
"total": "string",
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": "string"
}
],
"customFieldValues": {},
"couponCode": "string",
"tenders": [
{
"tenderId": "string",
"amountApplied": "string"
}
],
"providerAmountDue": "string",
"notes": "string",
"lineItems": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"discountAmount": "string",
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
],
"isDownloadable": true
},
"variant": {
"id": "string",
"name": "string",
"sku": "string"
},
"notes": "string",
"metadata": {},
"customizations": {}
}
],
"itemCount": 0,
"availableShippingRates": [
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
],
"expiresAt": "2019-08-24T14:15:22Z",
"recoveryEmailSentAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"presentment": {
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"shippingAmount": "string",
"taxAmount": "string",
"surchargeAmount": "string",
"total": "string",
"fxChargingRate": "string",
"fxBufferPercent": "string"
}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}"
}{
"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/checkout/{checkoutId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}"
}Delete a checkout
Supports Idempotency-Key header for safe retries.
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
Checkout 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/checkout/string" \ -H "Idempotency-Key: string"{
"success": true
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}"
}{
"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/checkout/{checkoutId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}"
}Set customer info on checkout
Supports Idempotency-Key header for safe retries.
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
Checkout 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 <= 255Shopper email address. Used for order confirmation, abandoned-checkout recovery, and matching/creating the customer record.
Shopper first name. Optional at this step, but required later if no shipping address is set.
Shopper last name. Optional at this step, but required later if no shipping address is set.
Shopper phone number in E.164 format.
Whether the shopper opted in to marketing communications. When true, the customer record is flagged for marketing email/SMS lists.
Order-level note from the shopper ("Please leave at the door"). Stored on the cart and copied onto the order at completion, then shown to the merchant in the dashboard and included in the confirmation email. Max 2000 chars. Send an empty string to clear a previously-set note.
length <= 2000GA4 gtag.js client_id (from gtag('get', measurementId, 'client_id', cb)), forwarded so the server-side purchase event can stitch to this browser session. Written onto the cart if not already set. Omit if unavailable, and never send a synthesized id.
length <= 100GA4 gtag.js session_id (from gtag('get', measurementId, 'session_id', cb)), forwarded alongside analyticsClientId for the same stitch.
length <= 100Hostname of the external referrer that brought this shopper (last non-direct touch), auto-attached by the storefront SDK from its brainerce_attr capture. Raw host on purpose, because the platform classifies it (AI/organic/social) at read time. Omit if unknown.
length <= 253utm_source of the last non-direct touch, auto-attached alongside trafficReferrerHost.
length <= 150utm_medium of the last non-direct touch.
length <= 150utm_campaign of the last non-direct touch.
length <= 150curl -X PATCH "https://api.brainerce.com/api/v1/checkout/string/customer" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]" }'{
"id": "string",
"status": "string",
"email": "string",
"customerId": "string",
"deliveryType": "shipping",
"pickupLocation": {
"id": "string",
"name": "string",
"rateName": "string",
"address": {
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string"
},
"phone": "string",
"hours": "string",
"instructions": "string",
"price": "string",
"currency": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"shippingRateId": "string",
"shippingMethod": {
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
},
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"shippingAmount": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"breakdown": [
{
"name": "string",
"rate": 0,
"amount": 0
}
],
"currency": "string"
},
"total": "string",
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": "string"
}
],
"customFieldValues": {},
"couponCode": "string",
"tenders": [
{
"tenderId": "string",
"amountApplied": "string"
}
],
"providerAmountDue": "string",
"notes": "string",
"lineItems": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"discountAmount": "string",
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
],
"isDownloadable": true
},
"variant": {
"id": "string",
"name": "string",
"sku": "string"
},
"notes": "string",
"metadata": {},
"customizations": {}
}
],
"itemCount": 0,
"availableShippingRates": [
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
],
"expiresAt": "2019-08-24T14:15:22Z",
"recoveryEmailSentAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"presentment": {
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"shippingAmount": "string",
"taxAmount": "string",
"surchargeAmount": "string",
"total": "string",
"fxChargingRate": "string",
"fxBufferPercent": "string"
}
}{
"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/checkout/{checkoutId}/customer"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/customer"
}{
"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/checkout/{checkoutId}/customer"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/customer"
}Set shipping address and get available rates
Supports Idempotency-Key header for safe retries.
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
Checkout 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 <= 255Recipient first name.
Recipient last name.
Company / organization name for the address (used on invoices and customs forms).
Primary street address line (street number + street name).
Secondary address line (apartment, suite, unit, building, floor, …).
City / locality.
State / province / region code or name. Required by some shipping carriers (e.g. USPS, UPS) for US/CA/AU addresses. Use the ISO-3166-2 subdivision code when possible (e.g. CA for California).
Postal / ZIP code.
ISO-3166-1 alpha-2 country code (uppercase, 2 letters).
Recipient phone number in E.164 format. Used by carriers for delivery notifications.
Shopper email address. Used for order confirmation, abandoned-checkout recovery, and matching/creating the customer record.
Whether the shopper opted in to marketing communications at checkout. When true, the customer record is flagged for marketing email/SMS lists.
Order-level note from the shopper ("Please leave at the door"). Rides along with the address step so single-page checkouts need no extra call. Copied onto the order at completion, then shown to the merchant in the dashboard and included in the confirmation email. Max 2000 chars. Send an empty string to clear a previously-set note.
length <= 2000GA4 gtag.js client_id (from gtag('get', measurementId, 'client_id', cb)), forwarded so the server-side purchase event can stitch to this browser session. Written onto the cart if not already set. Omit if unavailable, and never send a synthesized id.
length <= 100GA4 gtag.js session_id (from gtag('get', measurementId, 'session_id', cb)), forwarded alongside analyticsClientId for the same stitch.
length <= 100Hostname of the external referrer that brought this shopper (last non-direct touch), auto-attached by the storefront SDK from its brainerce_attr capture. Raw host on purpose, because the platform classifies it (AI/organic/social) at read time. Omit if unknown.
length <= 253utm_source of the last non-direct touch, auto-attached alongside trafficReferrerHost.
length <= 150utm_medium of the last non-direct touch.
length <= 150utm_campaign of the last non-direct touch.
length <= 150The placeId of the autocomplete suggestion the shopper picked (from checkout/address-autocomplete). Send it whenever the address came from the autocomplete: the server re-resolves it to exact rooftop coordinates and matches polygon ("draw on map") shipping zones against those, instead of re-geocoding the typed address lines. Without it, matching falls back to geocoding the text, which is materially less accurate (a same-named street in another city can outrank the right one). Note there is deliberately NO lat/lng field here: zone matching decides which shipping rate is offered and charged, so coordinates are never taken from the caller.
length <= 512The same sessionToken used for the checkout/address-autocomplete calls that produced placeId. Optional: the resolved place is cached server-side for 24h by placeId, so the normal flow (autocomplete → address-details → this call) hits that cache and needs no token. Pass it when you have it so that a cache miss still bills within the original autocomplete session instead of opening a new one.
length <= 200curl -X PATCH "https://api.brainerce.com/api/v1/checkout/string/shipping-address" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "firstName": "Jane", "lastName": "Doe", "line1": "123 Main Street", "city": "San Francisco", "postalCode": "94105", "country": "US", "email": "[email protected]" }'{
"checkout": {
"id": "string",
"status": "string",
"email": "string",
"customerId": "string",
"deliveryType": "shipping",
"pickupLocation": {
"id": "string",
"name": "string",
"rateName": "string",
"address": {
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string"
},
"phone": "string",
"hours": "string",
"instructions": "string",
"price": "string",
"currency": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"shippingRateId": "string",
"shippingMethod": {
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
},
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"shippingAmount": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"breakdown": [
{
"name": "string",
"rate": 0,
"amount": 0
}
],
"currency": "string"
},
"total": "string",
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": "string"
}
],
"customFieldValues": {},
"couponCode": "string",
"tenders": [
{
"tenderId": "string",
"amountApplied": "string"
}
],
"providerAmountDue": "string",
"notes": "string",
"lineItems": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"discountAmount": "string",
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
],
"isDownloadable": true
},
"variant": {
"id": "string",
"name": "string",
"sku": "string"
},
"notes": "string",
"metadata": {},
"customizations": {}
}
],
"itemCount": 0,
"availableShippingRates": [
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
],
"expiresAt": "2019-08-24T14:15:22Z",
"recoveryEmailSentAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"presentment": {
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"shippingAmount": "string",
"taxAmount": "string",
"surchargeAmount": "string",
"total": "string",
"fxChargingRate": "string",
"fxBufferPercent": "string"
}
},
"rates": [
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
]
}{
"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/checkout/{checkoutId}/shipping-address"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/shipping-address"
}{
"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/checkout/{checkoutId}/shipping-address"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/shipping-address"
}Get available shipping rates
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
Checkout ID
curl -X GET "https://api.brainerce.com/api/v1/checkout/string/shipping-rates"[
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
]{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/shipping-rates"
}{
"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/checkout/{checkoutId}/shipping-rates"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/shipping-rates"
}Select shipping method
Supports Idempotency-Key header for safe retries.
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
Checkout 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 <= 255ID of the shipping rate to apply to the checkout. The ID must come from the availableShippingRates array on the checkout response (set after a shipping address is provided). For carrier-sourced rates the ID is opaque and only valid for the current checkout snapshot.
curl -X PATCH "https://api.brainerce.com/api/v1/checkout/string/shipping-method" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "shippingRateId": "rate_01HQ7Z2YK3M8N4P5R6S7T8V9W0" }'{
"id": "string",
"status": "string",
"email": "string",
"customerId": "string",
"deliveryType": "shipping",
"pickupLocation": {
"id": "string",
"name": "string",
"rateName": "string",
"address": {
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string"
},
"phone": "string",
"hours": "string",
"instructions": "string",
"price": "string",
"currency": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"shippingRateId": "string",
"shippingMethod": {
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
},
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"shippingAmount": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"breakdown": [
{
"name": "string",
"rate": 0,
"amount": 0
}
],
"currency": "string"
},
"total": "string",
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": "string"
}
],
"customFieldValues": {},
"couponCode": "string",
"tenders": [
{
"tenderId": "string",
"amountApplied": "string"
}
],
"providerAmountDue": "string",
"notes": "string",
"lineItems": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"discountAmount": "string",
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
],
"isDownloadable": true
},
"variant": {
"id": "string",
"name": "string",
"sku": "string"
},
"notes": "string",
"metadata": {},
"customizations": {}
}
],
"itemCount": 0,
"availableShippingRates": [
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
],
"expiresAt": "2019-08-24T14:15:22Z",
"recoveryEmailSentAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"presentment": {
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"shippingAmount": "string",
"taxAmount": "string",
"surchargeAmount": "string",
"total": "string",
"fxChargingRate": "string",
"fxBufferPercent": "string"
}
}{
"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/checkout/{checkoutId}/shipping-method"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/shipping-method"
}{
"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/checkout/{checkoutId}/shipping-method"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/shipping-method"
}Set billing address
Supports Idempotency-Key header for safe retries.
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
Checkout 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 <= 255Recipient first name.
Recipient last name.
Company / organization name for the address (used on invoices and customs forms).
Primary street address line (street number + street name).
Secondary address line (apartment, suite, unit, building, floor, …).
City / locality.
State / province / region code or name. Required by some shipping carriers (e.g. USPS, UPS) for US/CA/AU addresses. Use the ISO-3166-2 subdivision code when possible (e.g. CA for California).
Postal / ZIP code.
ISO-3166-1 alpha-2 country code (uppercase, 2 letters).
Recipient phone number in E.164 format. Used by carriers for delivery notifications.
When true, the billing address is set identically to the previously-saved shipping address and the address fields on this request are ignored.
curl -X PATCH "https://api.brainerce.com/api/v1/checkout/string/billing-address" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "firstName": "Jane", "lastName": "Doe", "line1": "123 Main Street", "city": "San Francisco", "postalCode": "94105", "country": "US" }'{
"id": "string",
"status": "string",
"email": "string",
"customerId": "string",
"deliveryType": "shipping",
"pickupLocation": {
"id": "string",
"name": "string",
"rateName": "string",
"address": {
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string"
},
"phone": "string",
"hours": "string",
"instructions": "string",
"price": "string",
"currency": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"shippingRateId": "string",
"shippingMethod": {
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
},
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"shippingAmount": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"breakdown": [
{
"name": "string",
"rate": 0,
"amount": 0
}
],
"currency": "string"
},
"total": "string",
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": "string"
}
],
"customFieldValues": {},
"couponCode": "string",
"tenders": [
{
"tenderId": "string",
"amountApplied": "string"
}
],
"providerAmountDue": "string",
"notes": "string",
"lineItems": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"discountAmount": "string",
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
],
"isDownloadable": true
},
"variant": {
"id": "string",
"name": "string",
"sku": "string"
},
"notes": "string",
"metadata": {},
"customizations": {}
}
],
"itemCount": 0,
"availableShippingRates": [
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
],
"expiresAt": "2019-08-24T14:15:22Z",
"recoveryEmailSentAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"presentment": {
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"shippingAmount": "string",
"taxAmount": "string",
"surchargeAmount": "string",
"total": "string",
"fxChargingRate": "string",
"fxBufferPercent": "string"
}
}{
"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/checkout/{checkoutId}/billing-address"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/billing-address"
}{
"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/checkout/{checkoutId}/billing-address"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/billing-address"
}Apply a gift card to a checkout
Supports Idempotency-Key header for safe retries.
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
Checkout 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 <= 255The gift card code as the shopper typed it. Case, spaces and dashes are all tolerated, and characters excluded from the code alphabet (I, L, O, U) are corrected to the ones they are mistaken for.
curl -X POST "https://api.brainerce.com/api/v1/checkout/string/gift-card" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "code": "A1B2-C3D4-E5F6-G7H8-J9K0" }'{
"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/checkout/{checkoutId}/gift-card"
}{
"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/checkout/{checkoutId}/gift-card"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/gift-card"
}Remove a gift card from a checkout
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
Checkout ID
Tender id returned when the card was applied
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/checkout/string/gift-card/string" \ -H "Idempotency-Key: string"Check a gift card balance
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
The gift card code as the shopper typed it. Case, spaces and dashes are all tolerated, and characters excluded from the code alphabet (I, L, O, U) are corrected to the ones they are mistaken for.
curl -X POST "https://api.brainerce.com/api/v1/gift-cards/balance" \ -H "Content-Type: application/json" \ -d '{ "code": "A1B2-C3D4-E5F6-G7H8-J9K0" }'List gift cards
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
curl -X GET "https://api.brainerce.com/api/v1/gift-cards?search=string&filter=string&limit=0&page=0"Issue a gift card
Returns the plaintext code EXACTLY ONCE. It is stored only as an HMAC and cannot be retrieved again by anyone, including this API — persist it from this response or deliver it. A note is required: issuing stored value with no stated reason is not auditable. Refused when gift cards are switched off for the store.
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
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 <= 255Amount to load onto the card, as a decimal string.
Why this card was issued. Required, and stored on the ledger row itself — issuing value with no stated reason is not auditable, and this is the entry a finance review will read a year from now.
Link the card to a customer.
Expiry. Must be in the future. Leave unset for a card that does not expire.
Recipient email, for delivery.
Recipient name, for the delivery email.
A message from the buyer to the recipient.
curl -X POST "https://api.brainerce.com/api/v1/gift-cards" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "amount": "200.00", "note": "Goodwill for order ORD-20260902-0041, damaged in transit" }'Outstanding gift card liability
Per currency. Expired value is reported separately and is NOT written off — whether expiry extinguishes the obligation is an open legal question, so it is never folded into either side.
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
curl -X GET "https://api.brainerce.com/api/v1/gift-cards/liability"Disable or reactivate many gift cards
DISABLED stops new holds; ACTIVE returns a card to service. REVOKED is not accepted in bulk — it belongs to re-issue, which moves the balance to a replacement first. There is no delete, here or anywhere: the ledger is append-only and a card may carry a statutory retention life.
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
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 <= 255Gift card ids to update.
DISABLED stops new holds; ACTIVE puts the card back in service. REVOKED is deliberately not accepted in bulk — it belongs to re-issue, which moves the balance to a replacement first.
"ACTIVE" | "DISABLED"curl -X PATCH "https://api.brainerce.com/api/v1/gift-cards/bulk/status" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "giftCardIds": [ "string" ], "status": "ACTIVE" }'Get a gift card and its full ledger
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
Gift card ID
curl -X GET "https://api.brainerce.com/api/v1/gift-cards/string"Re-issue a gift card onto a new code
The answer to a customer losing their code. Mints a new code, moves the WHOLE balance to it, and REVOKES the old card — this is not a resend, and the old code stops working. Refused while a checkout holds value on the card. The original expiry carries forward, so this cannot restart an expiry clock. Returns the new code exactly once.
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
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 <= 255Why the card is being replaced. Required, and recorded on the ledger rows of both the revoked card and its replacement.
curl -X POST "https://api.brainerce.com/api/v1/gift-cards/string/reissue" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "note": "string" }'Adjust a gift card balance
Signed decimal: "25.00" adds, "-25.00" takes away. A note is REQUIRED and is written to the ledger permanently — this is the row a finance review reads a year from now. A debit cannot take the balance below what live checkout holds have already reserved.
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
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 <= 255Signed decimal string. "25.00" credits the card, "-25.00" debits it.
Why. Required, and recorded on the ledger row.
curl -X PATCH "https://api.brainerce.com/api/v1/gift-cards/string/adjust" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "delta": "-25.00", "note": "string" }'Enable, disable or revoke a gift card
Deliberately does NOT touch live holds: a checkout that already reserved value settles normally, because pulling it out from under a shopper mid-payment would strand a provider charge already in flight. Disabling stops NEW holds, which is what off actually means.
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
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 <= 255DISABLED and REVOKED stop NEW holds. Neither touches a hold a checkout is already carrying — pulling value out from under a shopper mid-payment would strand a provider charge that is already in flight.
"ACTIVE" | "DISABLED" | "REVOKED"curl -X PATCH "https://api.brainerce.com/api/v1/gift-cards/string/status" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "status": "ACTIVE" }'Apply coupon to checkout
Supports Idempotency-Key header for safe retries.
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
Checkout 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 <= 255Coupon code (case-insensitive). Validation runs server-side, and invalid codes return 400 with code: COUPON_INVALID or COUPON_USAGE_LIMIT_REACHED.
curl -X POST "https://api.brainerce.com/api/v1/checkout/string/coupon" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "code": "SUMMER25" }'{
"id": "string",
"status": "string",
"email": "string",
"customerId": "string",
"deliveryType": "shipping",
"pickupLocation": {
"id": "string",
"name": "string",
"rateName": "string",
"address": {
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string"
},
"phone": "string",
"hours": "string",
"instructions": "string",
"price": "string",
"currency": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"shippingRateId": "string",
"shippingMethod": {
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
},
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"shippingAmount": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"breakdown": [
{
"name": "string",
"rate": 0,
"amount": 0
}
],
"currency": "string"
},
"total": "string",
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": "string"
}
],
"customFieldValues": {},
"couponCode": "string",
"tenders": [
{
"tenderId": "string",
"amountApplied": "string"
}
],
"providerAmountDue": "string",
"notes": "string",
"lineItems": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"discountAmount": "string",
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
],
"isDownloadable": true
},
"variant": {
"id": "string",
"name": "string",
"sku": "string"
},
"notes": "string",
"metadata": {},
"customizations": {}
}
],
"itemCount": 0,
"availableShippingRates": [
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
],
"expiresAt": "2019-08-24T14:15:22Z",
"recoveryEmailSentAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"presentment": {
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"shippingAmount": "string",
"taxAmount": "string",
"surchargeAmount": "string",
"total": "string",
"fxChargingRate": "string",
"fxBufferPercent": "string"
}
}{
"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/checkout/{checkoutId}/coupon"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/coupon"
}{
"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/checkout/{checkoutId}/coupon"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/coupon"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/coupon"
}Remove coupon from checkout
Supports Idempotency-Key header for safe retries.
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
Checkout 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/checkout/string/coupon" \ -H "Idempotency-Key: string"{
"id": "string",
"status": "string",
"email": "string",
"customerId": "string",
"deliveryType": "shipping",
"pickupLocation": {
"id": "string",
"name": "string",
"rateName": "string",
"address": {
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string"
},
"phone": "string",
"hours": "string",
"instructions": "string",
"price": "string",
"currency": "string"
},
"shippingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"billingAddress": {
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
},
"shippingRateId": "string",
"shippingMethod": {
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
},
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"ruleDiscountAmount": "string",
"appliedRules": [
{
"id": "string",
"name": "string",
"type": "string",
"discountAmount": "string"
}
],
"shippingAmount": "string",
"taxAmount": "string",
"taxBreakdown": {
"subtotal": 0,
"shippingNet": 0,
"totalTax": 0,
"total": 0,
"breakdown": [
{
"name": "string",
"rate": 0,
"amount": 0
}
],
"currency": "string"
},
"total": "string",
"surchargeAmount": "string",
"appliedSurcharges": [
{
"key": "string",
"name": "string",
"value": {},
"amount": "string"
}
],
"customFieldValues": {},
"couponCode": "string",
"tenders": [
{
"tenderId": "string",
"amountApplied": "string"
}
],
"providerAmountDue": "string",
"notes": "string",
"lineItems": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"quantity": 0,
"unitPrice": "string",
"discountAmount": "string",
"product": {
"id": "string",
"name": "string",
"sku": "string",
"images": [
{}
],
"isDownloadable": true
},
"variant": {
"id": "string",
"name": "string",
"sku": "string"
},
"notes": "string",
"metadata": {},
"customizations": {}
}
],
"itemCount": 0,
"availableShippingRates": [
{
"id": "string",
"name": "string",
"description": "string",
"price": "string",
"currency": "string",
"estimatedDays": 0,
"source": "manual",
"carrier": "string",
"service": "string",
"speedTier": "cheapest"
}
],
"expiresAt": "2019-08-24T14:15:22Z",
"recoveryEmailSentAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"reservation": {
"hasReservation": true,
"expiresAt": "2019-08-24T14:15:22Z",
"remainingSeconds": 0,
"strategy": "ON_PAYMENT",
"countdownMessage": "string"
},
"presentment": {
"currency": "string",
"subtotal": "string",
"discountAmount": "string",
"shippingAmount": "string",
"taxAmount": "string",
"surchargeAmount": "string",
"total": "string",
"fxChargingRate": "string",
"fxBufferPercent": "string"
}
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/coupon"
}{
"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/checkout/{checkoutId}/coupon"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/coupon"
}Complete checkout and create order
Requires Idempotency-Key header, because this is the most critical endpoint to retry safely. Without an idempotency key, a network timeout during card capture can produce two orders. See /docs/api/idempotency.
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
Checkout ID
Header Parameters
REQUIRED on this endpoint — it moves money, so an omitted key is refused with a 400 rather than risking a double charge on retry.
Because the key is mandatory here, this endpoint also fails closed: if the once-only lock cannot be taken (the lock store is unreachable) the request is refused with 503 Service Unavailable and code: "IDEMPOTENCY_LOCK_UNAVAILABLE", and nothing is processed — no order, no charge. Retry with the same key after a short backoff; do NOT generate a new one, and do not confuse this with IDEMPOTENCY_KEY_REUSED, which is a 409 telling you the opposite.
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 POST "https://api.brainerce.com/api/v1/checkout/string/complete" \ -H "Idempotency-Key: string"{
"orderId": "string",
"orderNumber": "string",
"status": "string",
"total": "46.96",
"message": "string"
}{
"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/checkout/{checkoutId}/complete"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/complete"
}{
"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/checkout/{checkoutId}/complete"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/complete"
}{
"statusCode": 409,
"code": "CONFLICT",
"message": "The request conflicts with the current state of the resource",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/complete"
}{
"statusCode": 503,
"code": "INTERNAL_SERVER_ERROR",
"message": "Internal server error",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/checkout/{checkoutId}/complete"
}List coupons with pagination
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
curl -X GET "https://api.brainerce.com/api/v1/coupons?sortOrder=string&sortBy=string&platform=string&type=string&status=string&search=string&limit=0&page=0"{
"data": [
{
"id": "string",
"code": "SUMMER20",
"title": "string",
"description": "string",
"type": "string",
"value": "string",
"startsAt": "2019-08-24T14:15:22Z",
"endsAt": "2019-08-24T14:15:22Z",
"status": "string",
"usageLimit": 0,
"usageLimitPerCustomer": 0,
"usageCount": 0,
"minimumOrderAmount": "string",
"maximumDiscount": "string",
"conditions": {},
"applicableProducts": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"excludedProducts": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"applicableCategories": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"excludedCategories": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"regionIds": [
"string"
],
"combinesWithOther": true,
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"channels": {},
"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/coupons"
}{
"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/coupons"
}Create a new coupon
Honors Idempotency-Key header. See /docs/api/idempotency.
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
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 <= 255Redemption code. Case-insensitive, and unique per store.
Human-readable title shown in the dashboard list.
Internal description (not shown to shoppers).
Discount type. PERCENTAGE = value is a percent (0-100); FIXED_AMOUNT = value is in store currency.
"PERCENTAGE" | "FIXED_AMOUNT"Discount amount. Interpretation depends on type: 25 for PERCENTAGE means 25% off; 25 for FIXED_AMOUNT means $25 off.
0 <= valueISO 8601 start date. Coupon is inactive before this timestamp.
ISO 8601 end date. Coupon is inactive after this timestamp.
Initial status. Defaults to ACTIVE. Use SCHEDULED when startsAt is in the future.
"ACTIVE" | "SCHEDULED" | "EXPIRED" | "DISABLED"Total redemption cap across all customers. Omit for unlimited.
0 <= valuePer-customer redemption cap (requires customerId on the checkout).
0 <= valueMinimum cart subtotal to redeem.
0 <= valueCap on the discount value for PERCENTAGE coupons (e.g. "25% off, up to $50"). Ignored for FIXED_AMOUNT.
0 <= valueAdvanced conditions (customer segment, sales channel, …). Free-form JSON.
Empty Object
Restrict redemption to specific product IDs.
Restrict the coupon to specific regions (PRD §24). Empty/omitted = applies in all regions. Holds Region IDs of this store.
Exclude specific product IDs from the coupon.
Restrict redemption to specific category IDs.
Exclude specific category IDs from the coupon.
When false (default), this coupon cannot stack with other discount sources (other coupons, automatic discount rules). When true, it stacks.
Sales channels to publish the coupon to.
Per-platform field overrides (keyed by platform code). Useful when the platform uses a different code or wants a different title.
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/coupons" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "code": "SUMMER25", "type": "PERCENTAGE", "value": 25 }'{
"id": "string",
"code": "SUMMER20",
"title": "string",
"description": "string",
"type": "string",
"value": "string",
"startsAt": "2019-08-24T14:15:22Z",
"endsAt": "2019-08-24T14:15:22Z",
"status": "string",
"usageLimit": 0,
"usageLimitPerCustomer": 0,
"usageCount": 0,
"minimumOrderAmount": "string",
"maximumDiscount": "string",
"conditions": {},
"applicableProducts": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"excludedProducts": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"applicableCategories": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"excludedCategories": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"regionIds": [
"string"
],
"combinesWithOther": true,
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"channels": {},
"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",
"validationWarnings": [
{
"platform": "SHOPIFY",
"warnings": [
"SHOPIFY does not support product exclusions - will be ignored on sync"
]
}
]
}{
"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/coupons"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons"
}{
"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/coupons"
}Get platform capabilities for coupon features
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
curl -X GET "https://api.brainerce.com/api/v1/coupons/platform-capabilities"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/platform-capabilities"
}{
"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/coupons/platform-capabilities"
}Get a single coupon by ID
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
Coupon ID
curl -X GET "https://api.brainerce.com/api/v1/coupons/string"{
"id": "string",
"code": "SUMMER20",
"title": "string",
"description": "string",
"type": "string",
"value": "string",
"startsAt": "2019-08-24T14:15:22Z",
"endsAt": "2019-08-24T14:15:22Z",
"status": "string",
"usageLimit": 0,
"usageLimitPerCustomer": 0,
"usageCount": 0,
"minimumOrderAmount": "string",
"maximumDiscount": "string",
"conditions": {},
"applicableProducts": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"excludedProducts": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"applicableCategories": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"excludedCategories": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"regionIds": [
"string"
],
"combinesWithOther": true,
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"channels": {},
"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/coupons/{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/coupons/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{id}"
}Update a coupon
Supports Idempotency-Key header for safe retries.
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
Coupon 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 <= 255Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/coupons/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"code": "SUMMER20",
"title": "string",
"description": "string",
"type": "string",
"value": "string",
"startsAt": "2019-08-24T14:15:22Z",
"endsAt": "2019-08-24T14:15:22Z",
"status": "string",
"usageLimit": 0,
"usageLimitPerCustomer": 0,
"usageCount": 0,
"minimumOrderAmount": "string",
"maximumDiscount": "string",
"conditions": {},
"applicableProducts": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"excludedProducts": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"applicableCategories": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"excludedCategories": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"regionIds": [
"string"
],
"combinesWithOther": true,
"needsSync": true,
"lastSyncedAt": "2019-08-24T14:15:22Z",
"channels": {},
"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/coupons/{id}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{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/coupons/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{id}"
}Delete a coupon
Supports Idempotency-Key header for safe retries.
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
Coupon 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 <= 255Optional platforms to remove the coupon from
curl -X DELETE "https://api.brainerce.com/api/v1/coupons/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"success": true,
"jobIds": [
"string"
],
"warnings": [
"string"
]
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{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/coupons/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{id}"
}Sync a coupon to all connected platforms
Supports Idempotency-Key header for safe retries.
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
Coupon 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 POST "https://api.brainerce.com/api/v1/coupons/string/sync" \ -H "Idempotency-Key: string"{
"success": true,
"message": "string",
"jobIds": [
"string"
]
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{id}/sync"
}{
"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/coupons/{id}/sync"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{id}/sync"
}Publish a coupon to specific platforms
Supports Idempotency-Key header for safe retries.
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
Coupon 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 <= 255Platforms to publish the coupon to
curl -X POST "https://api.brainerce.com/api/v1/coupons/string/publish" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "platforms": [ "string" ] }'{
"message": "string",
"jobIds": [
"string"
]
}{
"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/coupons/{id}/publish"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{id}/publish"
}{
"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/coupons/{id}/publish"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/coupons/{id}/publish"
}List categories with pagination
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
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.
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
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 <= 255Category display name.
Store ID. See CreateBrandDto.storeId notes; resolved from auth when omitted.
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.
Active state. Inactive categories stay attached to products but are hidden from storefront filters.
Origin platform. Defaults to INTERNAL. Connector-sourced categories are managed by the connector and auto-deactivate on disconnect.
"INTERNAL" | "SHOPIFY" | "WOOCOMMERCE" | "TIKTOK" | "META"Category banner image URL. Upload via /v1/media first.
R2/S3 object key for image above. When present, asset-deletion cascade can null this category's image automatically.
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.
"taxable" | "exempt"Merchant override for Google's numeric product taxonomy id (Merchant Center google_product_category). Omit to let the name-based auto-resolver assign one.
Long-form category copy (HTML) rendered on the storefront category landing page.
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
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
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.
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
Category 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 <= 255Empty 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.
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
Category 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/categories/string" \ -H "Idempotency-Key: string"{
"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.
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
Category 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 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.
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
Category 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 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"
}List brands with pagination
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
curl -X GET "https://api.brainerce.com/api/v1/brands?platform=string&search=string&limit=0&page=0"{
"data": [
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"slug": "string",
"description": "string",
"logo": "string",
"platformIds": {
"property1": "string",
"property2": "string"
},
"publishedOn": [
"string"
],
"platformMetadata": {},
"source": "string",
"syncStatus": {
"property1": "string",
"property2": "string"
},
"lastSyncedAt": {
"property1": "string",
"property2": "string"
},
"translations": {},
"isActive": true,
"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/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"
}Create a new brand
Supports Idempotency-Key header for safe retries.
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
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 translated name / description.
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/brands" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Audio" }'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"slug": "string",
"description": "string",
"logo": "string",
"platformIds": {
"property1": "string",
"property2": "string"
},
"publishedOn": [
"string"
],
"platformMetadata": {},
"source": "string",
"syncStatus": {
"property1": "string",
"property2": "string"
},
"lastSyncedAt": {
"property1": "string",
"property2": "string"
},
"translations": {},
"isActive": true,
"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/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"
}Get a single brand by ID
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
Brand ID
curl -X GET "https://api.brainerce.com/api/v1/brands/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"slug": "string",
"description": "string",
"logo": "string",
"platformIds": {
"property1": "string",
"property2": "string"
},
"publishedOn": [
"string"
],
"platformMetadata": {},
"source": "string",
"syncStatus": {
"property1": "string",
"property2": "string"
},
"lastSyncedAt": {
"property1": "string",
"property2": "string"
},
"translations": {},
"isActive": true,
"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/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}"
}Update a brand
Supports Idempotency-Key header for safe retries.
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
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 <= 255Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/brands/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"slug": "string",
"description": "string",
"logo": "string",
"platformIds": {
"property1": "string",
"property2": "string"
},
"publishedOn": [
"string"
],
"platformMetadata": {},
"source": "string",
"syncStatus": {
"property1": "string",
"property2": "string"
},
"lastSyncedAt": {
"property1": "string",
"property2": "string"
},
"translations": {},
"isActive": true,
"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/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}"
}Delete a brand
Supports Idempotency-Key header for safe retries.
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
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}"
}Publish a brand to a sales-channel site
Supports Idempotency-Key header for safe retries.
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
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 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": 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}/publish-sales-channel"
}{
"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"
}Unpublish a brand from a sales-channel site
Supports Idempotency-Key header for safe retries.
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
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 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": 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}/unpublish-sales-channel"
}{
"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"
}List tags with pagination
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
curl -X GET "https://api.brainerce.com/api/v1/tags?platform=string&search=string&limit=0&page=0"{
"data": [
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"platformIds": {
"property1": "string",
"property2": "string"
},
"publishedOn": [
"string"
],
"translations": {},
"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"
}
}
],
"isActive": true,
"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/tags"
}{
"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/tags"
}Create a new tag
Supports Idempotency-Key header for safe retries.
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
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 <= 255Tag name. Case-insensitive, and unique per store.
Active state. Inactive tags stay attached to existing products but are hidden from filter UIs.
Origin platform. Defaults to INTERNAL. Platform-sourced tags (SHOPIFY, WOOCOMMERCE, …) are managed by the connector and auto-deactivate when the source platform disconnects.
"INTERNAL" | "SHOPIFY" | "WOOCOMMERCE" | "TIKTOK" | "META"curl -X POST "https://api.brainerce.com/api/v1/tags" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "name": "summer-2026" }'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"platformIds": {
"property1": "string",
"property2": "string"
},
"publishedOn": [
"string"
],
"translations": {},
"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"
}
}
],
"isActive": true,
"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/tags"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tags"
}{
"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/tags"
}Get a single tag by ID
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
Tag ID
curl -X GET "https://api.brainerce.com/api/v1/tags/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"platformIds": {
"property1": "string",
"property2": "string"
},
"publishedOn": [
"string"
],
"translations": {},
"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"
}
}
],
"isActive": true,
"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/tags/{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/tags/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tags/{id}"
}Delete a tag
Supports Idempotency-Key header for safe retries.
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
Tag 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/tags/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tags/{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/tags/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tags/{id}"
}Publish a tag to a sales-channel site
Supports Idempotency-Key header for safe retries.
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
Tag 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 ID
curl -X POST "https://api.brainerce.com/api/v1/tags/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/tags/{id}/publish-sales-channel"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tags/{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/tags/{id}/publish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tags/{id}/publish-sales-channel"
}Unpublish a tag from a sales-channel site
Supports Idempotency-Key header for safe retries.
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
Tag 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 ID
curl -X POST "https://api.brainerce.com/api/v1/tags/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/tags/{id}/unpublish-sales-channel"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tags/{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/tags/{id}/unpublish-sales-channel"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tags/{id}/unpublish-sales-channel"
}List attributes with pagination
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
curl -X GET "https://api.brainerce.com/api/v1/attributes?platform=string&source=string&search=string&limit=0&page=0"{
"data": [
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"displayType": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"productCount": 0,
"options": [
{
"id": "string",
"attributeId": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"position": 0,
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"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/attributes"
}{
"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/attributes"
}Create a new attribute
Supports Idempotency-Key header for safe retries.
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
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 <= 255Empty Object
curl -X POST "https://api.brainerce.com/api/v1/attributes" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"displayType": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"productCount": 0,
"options": [
{
"id": "string",
"attributeId": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"position": 0,
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"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/attributes"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/attributes"
}{
"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/attributes"
}Get a single attribute by ID
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
Attribute ID
curl -X GET "https://api.brainerce.com/api/v1/attributes/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"displayType": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"productCount": 0,
"options": [
{
"id": "string",
"attributeId": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"position": 0,
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"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/attributes/{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/attributes/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/attributes/{id}"
}Update an attribute
Supports Idempotency-Key header for safe retries.
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
Attribute 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 <= 255Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/attributes/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"displayType": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"productCount": 0,
"options": [
{
"id": "string",
"attributeId": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"position": 0,
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"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/attributes/{id}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/attributes/{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/attributes/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/attributes/{id}"
}Delete an attribute
Supports Idempotency-Key header for safe retries.
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
Attribute 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/attributes/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/attributes/{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/attributes/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/attributes/{id}"
}Get attribute options
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
Attribute ID
Query Parameters
curl -X GET "https://api.brainerce.com/api/v1/attributes/string/options?platform=string"[
{
"id": "string",
"attributeId": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"position": 0,
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"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/attributes/{id}/options"
}{
"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/attributes/{id}/options"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/attributes/{id}/options"
}Create an attribute option
Supports Idempotency-Key header for safe retries.
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
Attribute 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 <= 255Empty Object
curl -X POST "https://api.brainerce.com/api/v1/attributes/string/options" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"attributeId": "string",
"name": "string",
"value": "string",
"swatchColor": "string",
"swatchColor2": "string",
"swatchImageUrl": "string",
"source": "string",
"platform": "string",
"externalId": "string",
"platformMetadata": {},
"translations": {},
"position": 0,
"isActive": true,
"deletedAt": "2019-08-24T14:15:22Z",
"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/attributes/{id}/options"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/attributes/{id}/options"
}{
"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/attributes/{id}/options"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/attributes/{id}/options"
}List shipping zones with pagination
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
curl -X GET "https://api.brainerce.com/api/v1/shipping/zones?page=0&limit=0&search=string&isActive=true"{
"data": [
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "US Domestic",
"countries": [
"string"
],
"regions": {},
"postalCodes": {},
"geometry": {},
"hasGeometry": true,
"geometryLabels": [
"string"
],
"regionIds": [
"string"
],
"salesChannelIds": [
"string"
],
"priority": 0,
"isActive": true,
"rateSource": "string",
"platformSettings": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"rates": [
{
"id": "string",
"zoneId": "string",
"name": "Standard Shipping",
"description": "string",
"type": "string",
"rateConfig": {},
"minDeliveryDays": 0,
"maxDeliveryDays": 0,
"handlingTime": 0,
"taxStatus": "string",
"minOrderAmount": "string",
"maxCost": "string",
"classCosts": {},
"classCalculationType": "string",
"isActive": true,
"platformSettings": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"_count": {
"rates": 0
},
"ratesCount": 0
}
],
"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/shipping/zones"
}{
"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/shipping/zones"
}Create a new shipping zone
Supports Idempotency-Key header for safe retries.
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
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 <= 255Display name (shown in the dashboard, never to shoppers).
ISO 3166-1 alpha-2 country codes covered by this zone.
Per-country region (state/province) restriction. Keyed by ISO country code; value is an array of subdivision codes. Addresses outside the listed regions do not match the zone.
Empty Object
Per-country postal-code patterns (exact, prefix 941*, or range 94100-94199). Further narrows the zone after regions.
Empty Object
Polygon zone definition, a hand-drawn shape ("draw on map"). GeoJSON Polygon or MultiPolygon, ring coordinates in [lng, lat] order (RFC 7946). Independent of countries/regions/postalCodes: a zone matches if the address satisfies either the country-list coverage or the polygon coverage, so both may be set on the same zone.
Empty Object
Display-only label per shape in geometry (index 0 = the Polygon, or a MultiPolygon's Nth part), e.g. the searched place name ("Tel Aviv") instead of a generic "Custom area N". Purely cosmetic; never used for matching.
Region restriction (PRD §25). Region IDs this zone is limited to. Empty/omitted = available for any region (default). Non-empty = the zone is only offered to checkouts whose region is in the list.
Sales-channel restriction. SalesChannel.id values (the public vc_* connectionId also accepted). Empty/omitted = available on every channel (default). Non-empty = the zone is only offered to checkouts from a channel in the list.
Match priority: a lower value is evaluated first. Defaults to 0.
00 <= valueWhether this zone participates in rate calculation. Defaults to true.
truecurl -X POST "https://api.brainerce.com/api/v1/shipping/zones" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "name": "United States", "countries": [ "US", "CA", "MX" ] }'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "US Domestic",
"countries": [
"string"
],
"regions": {},
"postalCodes": {},
"geometry": {},
"hasGeometry": true,
"geometryLabels": [
"string"
],
"regionIds": [
"string"
],
"salesChannelIds": [
"string"
],
"priority": 0,
"isActive": true,
"rateSource": "string",
"platformSettings": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"rates": [
{
"id": "string",
"zoneId": "string",
"name": "Standard Shipping",
"description": "string",
"type": "string",
"rateConfig": {},
"minDeliveryDays": 0,
"maxDeliveryDays": 0,
"handlingTime": 0,
"taxStatus": "string",
"minOrderAmount": "string",
"maxCost": "string",
"classCosts": {},
"classCalculationType": "string",
"isActive": true,
"platformSettings": {},
"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/shipping/zones"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones"
}{
"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/shipping/zones"
}Get a single shipping zone by ID
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
Shipping Zone ID
curl -X GET "https://api.brainerce.com/api/v1/shipping/zones/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "US Domestic",
"countries": [
"string"
],
"regions": {},
"postalCodes": {},
"geometry": {},
"hasGeometry": true,
"geometryLabels": [
"string"
],
"regionIds": [
"string"
],
"salesChannelIds": [
"string"
],
"priority": 0,
"isActive": true,
"rateSource": "string",
"platformSettings": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"rates": [
{
"id": "string",
"zoneId": "string",
"name": "Standard Shipping",
"description": "string",
"type": "string",
"rateConfig": {},
"minDeliveryDays": 0,
"maxDeliveryDays": 0,
"handlingTime": 0,
"taxStatus": "string",
"minOrderAmount": "string",
"maxCost": "string",
"classCosts": {},
"classCalculationType": "string",
"isActive": true,
"platformSettings": {},
"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/shipping/zones/{zoneId}"
}{
"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/shipping/zones/{zoneId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}"
}Update a shipping zone
Supports Idempotency-Key header for safe retries.
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
Shipping Zone 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 <= 255Display name.
ISO 3166-1 alpha-2 country codes covered by this zone.
Per-country region restriction (subdivision codes).
Empty Object
Per-country postal-code patterns.
Empty Object
Polygon zone definition ("draw on map"). GeoJSON Polygon or MultiPolygon, [lng, lat] ring coordinates. Pass null to clear a previously-set polygon. Omit to leave unchanged.
Empty Object
Display-only label per shape in geometry (index 0 = the Polygon, or a MultiPolygon's Nth part). Purely cosmetic; never used for matching. Omit to leave unchanged.
Region restriction (PRD §25). Region IDs this zone is limited to. Empty array = available for any region. Omit to leave unchanged.
Sales-channel restriction. SalesChannel.id values (the public vc_* connectionId also accepted). Empty array = available on every channel. Omit to leave unchanged.
Match priority: a lower value is evaluated first.
0 <= valueWhether this zone participates in rate calculation.
Per-platform overrides (e.g. Shopify zone ID mapping). Keyed by platform code; value is platform-specific.
Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/shipping/zones/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "US Domestic",
"countries": [
"string"
],
"regions": {},
"postalCodes": {},
"geometry": {},
"hasGeometry": true,
"geometryLabels": [
"string"
],
"regionIds": [
"string"
],
"salesChannelIds": [
"string"
],
"priority": 0,
"isActive": true,
"rateSource": "string",
"platformSettings": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"rates": [
{
"id": "string",
"zoneId": "string",
"name": "Standard Shipping",
"description": "string",
"type": "string",
"rateConfig": {},
"minDeliveryDays": 0,
"maxDeliveryDays": 0,
"handlingTime": 0,
"taxStatus": "string",
"minOrderAmount": "string",
"maxCost": "string",
"classCosts": {},
"classCalculationType": "string",
"isActive": true,
"platformSettings": {},
"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/shipping/zones/{zoneId}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}"
}{
"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/shipping/zones/{zoneId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}"
}Delete a shipping zone
Supports Idempotency-Key header for safe retries.
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
Shipping Zone 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/shipping/zones/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}"
}{
"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/shipping/zones/{zoneId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}"
}Get shipping rates for a zone
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
Shipping Zone ID
curl -X GET "https://api.brainerce.com/api/v1/shipping/zones/string/rates"[
{
"id": "string",
"zoneId": "string",
"name": "Standard Shipping",
"description": "string",
"type": "string",
"rateConfig": {},
"minDeliveryDays": 0,
"maxDeliveryDays": 0,
"handlingTime": 0,
"taxStatus": "string",
"minOrderAmount": "string",
"maxCost": "string",
"classCosts": {},
"classCalculationType": "string",
"isActive": true,
"platformSettings": {},
"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/shipping/zones/{zoneId}/rates"
}{
"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/shipping/zones/{zoneId}/rates"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}/rates"
}Create a shipping rate for a zone
Supports Idempotency-Key header for safe retries.
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
Shipping Zone 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 <= 255Display name shown to shoppers at checkout (e.g. "Standard", "Express").
Optional short description shown alongside the rate at checkout.
Rate calculation strategy.
"FLAT_RATE" | "WEIGHT_BASED" | "PRICE_BASED" | "FREE" | "LOCAL_PICKUP"Type-specific configuration. Shape depends on type; see the DTO docs. For FLAT_RATE use { amount: number }.
Empty Object
Minimum delivery time in business days (inclusive).
0 <= valueMaximum delivery time in business days (inclusive).
0 <= valueInternal handling time in business days before the package ships.
1 <= valueWhether the delivery charge itself is taxed. TAXABLE (the default when omitted) taxes it at the Standard rate; NONE leaves postage untaxed.
"TAXABLE""TAXABLE" | "NONE"Minimum cart subtotal required for this rate to be offered. Use to hide low-value carts from free shipping.
0 <= valueOptional cap on the computed cost. Useful for WEIGHT_BASED rates to prevent runaway charges.
0 <= valueWhether this rate is offered. Defaults to true.
truePer-shipping-class cost overrides. Keyed by ShippingClass.id; value is either a flat amount or { first, additional } for first-item + each-additional pricing.
Empty Object
How classCosts are aggregated when the cart mixes classes. per_class charges once per distinct class; per_order once for the whole order; per_item per line-item.
"per_class" | "per_order" | "per_item"curl -X POST "https://api.brainerce.com/api/v1/shipping/zones/string/rates" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "name": "Standard Shipping", "type": "FLAT_RATE", "rateConfig": { "amount": 9.99 } }'{
"id": "string",
"zoneId": "string",
"name": "Standard Shipping",
"description": "string",
"type": "string",
"rateConfig": {},
"minDeliveryDays": 0,
"maxDeliveryDays": 0,
"handlingTime": 0,
"taxStatus": "string",
"minOrderAmount": "string",
"maxCost": "string",
"classCosts": {},
"classCalculationType": "string",
"isActive": true,
"platformSettings": {},
"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/shipping/zones/{zoneId}/rates"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}/rates"
}{
"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/shipping/zones/{zoneId}/rates"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}/rates"
}Update a shipping rate
Supports Idempotency-Key header for safe retries.
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
Shipping Zone ID
Shipping Rate 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 <= 255Display name shown to shoppers.
Short description shown alongside the rate.
Rate calculation strategy.
"FLAT_RATE" | "WEIGHT_BASED" | "PRICE_BASED" | "FREE" | "LOCAL_PICKUP"Type-specific configuration; shape depends on type.
Empty Object
Minimum delivery time in business days.
0 <= valueMaximum delivery time in business days.
0 <= valueInternal handling time in business days.
1 <= valueWhether shipping itself is taxable.
"TAXABLE" | "NONE"Minimum cart subtotal for this rate to be offered.
0 <= valueOptional cap on the computed cost.
0 <= valueWhether this rate is offered.
Per-platform overrides (e.g. Shopify rate ID mapping). Keyed by platform code.
Empty Object
Per-shipping-class cost overrides.
Empty Object
How classCosts are aggregated when the cart mixes classes.
"per_class" | "per_order" | "per_item"curl -X PATCH "https://api.brainerce.com/api/v1/shipping/zones/string/rates/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"zoneId": "string",
"name": "Standard Shipping",
"description": "string",
"type": "string",
"rateConfig": {},
"minDeliveryDays": 0,
"maxDeliveryDays": 0,
"handlingTime": 0,
"taxStatus": "string",
"minOrderAmount": "string",
"maxCost": "string",
"classCosts": {},
"classCalculationType": "string",
"isActive": true,
"platformSettings": {},
"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/shipping/zones/{zoneId}/rates/{rateId}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}/rates/{rateId}"
}{
"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/shipping/zones/{zoneId}/rates/{rateId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}/rates/{rateId}"
}Delete a shipping rate
Supports Idempotency-Key header for safe retries.
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
Shipping Zone ID
Shipping Rate 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/shipping/zones/string/rates/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}/rates/{rateId}"
}{
"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/shipping/zones/{zoneId}/rates/{rateId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/shipping/zones/{zoneId}/rates/{rateId}"
}List tax rates for the store
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
curl -X GET "https://api.brainerce.com/api/v1/tax/rates"[
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "California Sales Tax",
"country": "string",
"region": "string",
"postalCode": "string",
"rate": "8.25",
"taxType": "string",
"isInclusive": true,
"priority": 0,
"stackable": true,
"exceptionCountries": [
"string"
],
"isActive": true,
"taxClassId": "string",
"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/tax/rates"
}{
"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/tax/rates"
}Create a new tax rate
Supports Idempotency-Key header for safe retries.
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
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 <= 255Display name shown on invoices and the storefront tax line.
Tax rate as a percentage (e.g. 8.5 for 8.5%). Range 0 to 100.
0 <= value <= 100ISO 3166-1 alpha-2 country code this rate applies to. REQUIRED — there is no global fallback rate. TaxRate.country is NOT NULL in the schema, so a country-less rate cannot be stored at all; omitting this is a 400, not a catch-all. A rate that must cover several countries names one here and lists the rest in exceptionCountries.
State/province code (ISO 3166-2 subdivision part, e.g. CA for California). Narrows the match within country.
Exact postal code, compared case-insensitively with spaces and hyphens ignored. Wildcards, prefixes (941*) and ranges (94100-94199) are NOT supported, and match nothing. Narrows the match within region.
Tax category label (e.g. sales, vat, gst). Shown on invoices and used for reporting; does not affect calculation.
When true, prices are tax-inclusive (VAT-style): the rate is backed out of the displayed price instead of added on top.
falseTiebreak between rates of EQUAL specificity: the LOWER number wins. Specificity is decided first (a postal-code rate beats a region rate, which beats a country-wide rate), so priority only matters between rates scoped the same way.
Whether this rate participates in calculation. Defaults to true.
trueAdditional ISO country codes where this rate also applies (in addition to the same-country rule). Useful for trade blocs that share a tax (e.g. EU reverse-charge schemes).
Charge this rate TOGETHER WITH the other stackable rates that match the same address, instead of the single most specific one. This is how Canada works: GST 5% (country-level) + PST/QST (province-level), both stackable, both charged on the same pre-tax base — the buyer sees two tax lines. Leave false (the default) and the historic rule applies: the most specific matching rate wins alone and every other match is discarded. An HST province is a single non-stackable province row, so it wins at 13% without adding GST. Stacking is additive, never tax-on-tax, and never crosses a tax class: a class-specific rate replaces the Standard rates rather than adding to them, so a class that needs GST + reduced QST needs both rows entered in that class.
falseTax class this rate applies to. Omit (or null) for the Standard rate that applies to products without an explicit class.
curl -X POST "https://api.brainerce.com/api/v1/tax/rates" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "name": "California Sales Tax", "rate": 8.5, "country": "US" }'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "California Sales Tax",
"country": "string",
"region": "string",
"postalCode": "string",
"rate": "8.25",
"taxType": "string",
"isInclusive": true,
"priority": 0,
"stackable": true,
"exceptionCountries": [
"string"
],
"isActive": true,
"taxClassId": "string",
"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/tax/rates"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax/rates"
}{
"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/tax/rates"
}Get a single tax rate by ID
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
Tax Rate ID
curl -X GET "https://api.brainerce.com/api/v1/tax/rates/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "California Sales Tax",
"country": "string",
"region": "string",
"postalCode": "string",
"rate": "8.25",
"taxType": "string",
"isInclusive": true,
"priority": 0,
"stackable": true,
"exceptionCountries": [
"string"
],
"isActive": true,
"taxClassId": "string",
"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/tax/rates/{rateId}"
}{
"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/tax/rates/{rateId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax/rates/{rateId}"
}Update a tax rate
Supports Idempotency-Key header for safe retries.
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
Tax Rate 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 <= 255Display name shown on invoices and the storefront tax line.
Tax rate as a percentage (0 to 100).
0 <= value <= 100ISO 3166-1 alpha-2 country code. Optional only in the PATCH sense: omit it and the rate keeps the country it already has. It cannot be cleared. TaxRate.country is NOT NULL, there is no global fallback rate, and sending null is rejected. A rate covering several countries names one here and lists the rest in exceptionCountries.
State/province subdivision code.
Exact postal code (case-insensitive, spaces and hyphens ignored). Prefixes and ranges are NOT supported.
Tax category label (e.g. sales, vat, gst).
Treat prices as tax-inclusive (VAT-style).
Tiebreak between rates of EQUAL specificity: the LOWER number wins. More specific rates (postal > region > country) win regardless of priority.
Whether this rate participates in calculation.
Additional ISO country codes where this rate also applies.
Charge this rate together with the other stackable rates matching the same address (Canada GST + PST/QST) instead of the single most specific one. Flipping an existing rate to true changes what future checkouts collect — check the other rates on the store first, because rates that used to be mutually exclusive will start being charged together.
Tax class this rate applies to. Null/omit = Standard (applies to unclassed products).
curl -X PATCH "https://api.brainerce.com/api/v1/tax/rates/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "California Sales Tax",
"country": "string",
"region": "string",
"postalCode": "string",
"rate": "8.25",
"taxType": "string",
"isInclusive": true,
"priority": 0,
"stackable": true,
"exceptionCountries": [
"string"
],
"isActive": true,
"taxClassId": "string",
"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/tax/rates/{rateId}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax/rates/{rateId}"
}{
"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/tax/rates/{rateId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax/rates/{rateId}"
}Delete a tax rate
Supports Idempotency-Key header for safe retries.
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
Tax Rate 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/tax/rates/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax/rates/{rateId}"
}{
"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/tax/rates/{rateId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax/rates/{rateId}"
}List available country tax presets
Ready-made rate tables a store can apply in one call instead of hand-entering every province.
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
curl -X GET "https://api.brainerce.com/api/v1/tax/presets"[
{
"key": "CA",
"country": "string",
"label": "string",
"description": "string",
"rateCount": 0
}
]{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax/presets"
}{
"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/tax/presets"
}Apply a country tax preset
Writes a whole country's rate table in one transaction. CA writes the federal GST 5% plus every province's HST or PST/QST, already flagged so GST and PST/QST stack correctly and HST does not. Refuses with 409 when the store already has rates for that country — delete them first to replace them. Supports Idempotency-Key for safe retries.
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
Preset key, e.g. CA
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 POST "https://api.brainerce.com/api/v1/tax/presets/string/apply" \ -H "Idempotency-Key: string"{
"preset": "CA",
"created": 0,
"rates": [
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "California Sales Tax",
"country": "string",
"region": "string",
"postalCode": "string",
"rate": "8.25",
"taxType": "string",
"isInclusive": true,
"priority": 0,
"stackable": true,
"exceptionCountries": [
"string"
],
"isActive": true,
"taxClassId": "string",
"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/tax/presets/{presetKey}/apply"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax/presets/{presetKey}/apply"
}{
"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/tax/presets/{presetKey}/apply"
}{
"statusCode": 409,
"code": "CONFLICT",
"message": "The request conflicts with the current state of the resource",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax/presets/{presetKey}/apply"
}List the store tax classes
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
curl -X GET "https://api.brainerce.com/api/v1/tax-classes"{
"data": [
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Reduced rate",
"slug": "reduced-rate",
"description": "string",
"isDefault": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
]
}{
"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/tax-classes"
}Create a tax class
Supports Idempotency-Key header for safe retries.
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
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 <= 255Empty Object
curl -X POST "https://api.brainerce.com/api/v1/tax-classes" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Reduced rate",
"slug": "reduced-rate",
"description": "string",
"isDefault": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}{
"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/tax-classes"
}Get a tax class with its dependent counts
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
Tax Class ID
curl -X GET "https://api.brainerce.com/api/v1/tax-classes/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Reduced rate",
"slug": "reduced-rate",
"description": "string",
"isDefault": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"dependents": {
"productCount": 0,
"variantCount": 0,
"categoryCount": 0,
"taxRateCount": 0
}
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax-classes/{id}"
}Update a tax class
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
Tax Class 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 <= 255Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/tax-classes/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Reduced rate",
"slug": "reduced-rate",
"description": "string",
"isDefault": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax-classes/{id}"
}Delete a tax class (409 while dependents exist)
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
Tax Class 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/tax-classes/string" \ -H "Idempotency-Key: string"{
"statusCode": 409,
"code": "CONFLICT",
"message": "The request conflicts with the current state of the resource",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/tax-classes/{id}"
}Set this tax class as the store default
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
Tax Class ID
curl -X PATCH "https://api.brainerce.com/api/v1/tax-classes/string/set-default"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Reduced rate",
"slug": "reduced-rate",
"description": "string",
"isDefault": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}Bulk-assign a tax class to products / variants / categories
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
Tax Class ID
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/tax-classes/string/assign" \ -H "Content-Type: application/json" \ -d '{}'{
"updated": 0
}Merge this tax class into another, moving all FKs, then delete it
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
Source Tax Class ID
Target Tax Class ID
curl -X POST "https://api.brainerce.com/api/v1/tax-classes/string/merge-into/string"List the store regions
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
curl -X GET "https://api.brainerce.com/api/v1/regions?page=string&limit=string"{
"data": [
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Israel",
"slug": "israel",
"currency": "string",
"fxBufferPercent": "string",
"countries": [
"string"
],
"provinces": {},
"taxInclusive": true,
"automaticTaxes": true,
"isDefault": true,
"isActive": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"paymentProviders": [
{
"id": "string",
"regionId": "string",
"appInstallationId": "string",
"isEnabled": true,
"createdAt": "2019-08-24T14:15:22Z"
}
]
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 137,
"totalPages": 7
}
}{
"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/regions"
}Create a region
Supports Idempotency-Key header for safe retries.
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
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 <= 255Empty Object
curl -X POST "https://api.brainerce.com/api/v1/regions" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Israel",
"slug": "israel",
"currency": "string",
"fxBufferPercent": "string",
"countries": [
"string"
],
"provinces": {},
"taxInclusive": true,
"automaticTaxes": true,
"isDefault": true,
"isActive": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"paymentProviders": [
{
"id": "string",
"regionId": "string",
"appInstallationId": "string",
"isEnabled": true,
"createdAt": "2019-08-24T14:15:22Z"
}
]
}{
"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/regions"
}Get a region
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
Region ID
curl -X GET "https://api.brainerce.com/api/v1/regions/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Israel",
"slug": "israel",
"currency": "string",
"fxBufferPercent": "string",
"countries": [
"string"
],
"provinces": {},
"taxInclusive": true,
"automaticTaxes": true,
"isDefault": true,
"isActive": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"paymentProviders": [
{
"id": "string",
"regionId": "string",
"appInstallationId": "string",
"isEnabled": true,
"createdAt": "2019-08-24T14:15:22Z"
}
]
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/regions/{regionId}"
}Update a region
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
Region 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 <= 255Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/regions/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Israel",
"slug": "israel",
"currency": "string",
"fxBufferPercent": "string",
"countries": [
"string"
],
"provinces": {},
"taxInclusive": true,
"automaticTaxes": true,
"isDefault": true,
"isActive": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"paymentProviders": [
{
"id": "string",
"regionId": "string",
"appInstallationId": "string",
"isEnabled": true,
"createdAt": "2019-08-24T14:15:22Z"
}
]
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/regions/{regionId}"
}Delete a region
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
Region 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/regions/string" \ -H "Idempotency-Key: string"List installed providers compatible with this region
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
Region ID
curl -X GET "https://api.brainerce.com/api/v1/regions/string/compatible-providers"[
{
"id": "string",
"appId": "string",
"app": {
"id": "string",
"name": "string",
"slug": "string"
}
}
]Set this region as the store default
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
Region ID
curl -X PATCH "https://api.brainerce.com/api/v1/regions/string/set-default"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Israel",
"slug": "israel",
"currency": "string",
"fxBufferPercent": "string",
"countries": [
"string"
],
"provinces": {},
"taxInclusive": true,
"automaticTaxes": true,
"isDefault": true,
"isActive": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"paymentProviders": [
{
"id": "string",
"regionId": "string",
"appInstallationId": "string",
"isEnabled": true,
"createdAt": "2019-08-24T14:15:22Z"
}
]
}Replace the region enabled payment providers
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
Region ID
Empty Object
curl -X PUT "https://api.brainerce.com/api/v1/regions/string/payment-providers" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Israel",
"slug": "israel",
"currency": "string",
"fxBufferPercent": "string",
"countries": [
"string"
],
"provinces": {},
"taxInclusive": true,
"automaticTaxes": true,
"isDefault": true,
"isActive": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"paymentProviders": [
{
"id": "string",
"regionId": "string",
"appInstallationId": "string",
"isEnabled": true,
"createdAt": "2019-08-24T14:15:22Z"
}
]
}List the region manual price overrides
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
Region ID
Query Parameters
curl -X GET "https://api.brainerce.com/api/v1/regions/string/prices?productId=string&page=string&limit=string"{
"data": [
{
"id": "string",
"productId": "string",
"variantId": "string",
"price": "string",
"salePrice": "string",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 137,
"totalPages": 7
}
}{
"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/regions/{regionId}/prices"
}Bulk upsert/remove the region manual price overrides
Supports Idempotency-Key header for safe retries.
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
Region 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 <= 255Empty Object
curl -X PUT "https://api.brainerce.com/api/v1/regions/string/prices" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"upserted": 0,
"removed": 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/v1/regions/{regionId}/prices"
}Delete one manual price override
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
Region ID
Region price 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/regions/string/prices/string" \ -H "Idempotency-Key: string"Add countries to a region
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
Region ID
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/regions/string/countries" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Israel",
"slug": "israel",
"currency": "string",
"fxBufferPercent": "string",
"countries": [
"string"
],
"provinces": {},
"taxInclusive": true,
"automaticTaxes": true,
"isDefault": true,
"isActive": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"paymentProviders": [
{
"id": "string",
"regionId": "string",
"appInstallationId": "string",
"isEnabled": true,
"createdAt": "2019-08-24T14:15:22Z"
}
]
}Remove a country from a region
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
Region ID
ISO 3166-1 alpha-2 country code
curl -X DELETE "https://api.brainerce.com/api/v1/regions/string/countries/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Israel",
"slug": "israel",
"currency": "string",
"fxBufferPercent": "string",
"countries": [
"string"
],
"provinces": {},
"taxInclusive": true,
"automaticTaxes": true,
"isDefault": true,
"isActive": true,
"metadata": {},
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"paymentProviders": [
{
"id": "string",
"regionId": "string",
"appInstallationId": "string",
"isEnabled": true,
"createdAt": "2019-08-24T14:15:22Z"
}
]
}List metafield definitions
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
curl -X GET "https://api.brainerce.com/api/v1/metafield-definitions"[
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Warranty Info",
"key": "warranty_info",
"description": "string",
"type": "string",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"dateAvailability": {},
"enumValues": [
{
"label": "string",
"value": "string",
"swatchColor": "string",
"swatchImageUrl": "string"
}
],
"defaultValue": "string",
"position": 0,
"isActive": true,
"publishedOn": [
"SHOPIFY"
],
"platformIds": {
"property1": "string",
"property2": "string"
},
"platformMetadata": {},
"syncStatus": {
"property1": "string",
"property2": "string"
},
"lastSyncedAt": {
"property1": "string",
"property2": "string"
},
"source": "string",
"products": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"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"
}
}
],
"_count": {
"values": 0
},
"translations": {},
"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/metafield-definitions"
}{
"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/metafield-definitions"
}Create a new metafield definition
Supports Idempotency-Key header for safe retries.
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
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 <= 255Empty Object
curl -X POST "https://api.brainerce.com/api/v1/metafield-definitions" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Warranty Info",
"key": "warranty_info",
"description": "string",
"type": "string",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"dateAvailability": {},
"enumValues": [
{
"label": "string",
"value": "string",
"swatchColor": "string",
"swatchImageUrl": "string"
}
],
"defaultValue": "string",
"position": 0,
"isActive": true,
"publishedOn": [
"SHOPIFY"
],
"platformIds": {
"property1": "string",
"property2": "string"
},
"platformMetadata": {},
"syncStatus": {
"property1": "string",
"property2": "string"
},
"lastSyncedAt": {
"property1": "string",
"property2": "string"
},
"source": "string",
"products": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"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"
}
}
],
"_count": {
"values": 0
},
"translations": {},
"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/metafield-definitions"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-definitions"
}{
"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/metafield-definitions"
}Get a single metafield definition by ID
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
Metafield Definition ID
curl -X GET "https://api.brainerce.com/api/v1/metafield-definitions/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Warranty Info",
"key": "warranty_info",
"description": "string",
"type": "string",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"dateAvailability": {},
"enumValues": [
{
"label": "string",
"value": "string",
"swatchColor": "string",
"swatchImageUrl": "string"
}
],
"defaultValue": "string",
"position": 0,
"isActive": true,
"publishedOn": [
"SHOPIFY"
],
"platformIds": {
"property1": "string",
"property2": "string"
},
"platformMetadata": {},
"syncStatus": {
"property1": "string",
"property2": "string"
},
"lastSyncedAt": {
"property1": "string",
"property2": "string"
},
"source": "string",
"products": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"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"
}
}
],
"_count": {
"values": 0
},
"translations": {},
"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/metafield-definitions/{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/metafield-definitions/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-definitions/{id}"
}Update a metafield definition
Supports Idempotency-Key header for safe retries.
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
Metafield Definition 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 <= 255Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/metafield-definitions/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Warranty Info",
"key": "warranty_info",
"description": "string",
"type": "string",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"dateAvailability": {},
"enumValues": [
{
"label": "string",
"value": "string",
"swatchColor": "string",
"swatchImageUrl": "string"
}
],
"defaultValue": "string",
"position": 0,
"isActive": true,
"publishedOn": [
"SHOPIFY"
],
"platformIds": {
"property1": "string",
"property2": "string"
},
"platformMetadata": {},
"syncStatus": {
"property1": "string",
"property2": "string"
},
"lastSyncedAt": {
"property1": "string",
"property2": "string"
},
"source": "string",
"products": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"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"
}
}
],
"_count": {
"values": 0
},
"translations": {},
"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/metafield-definitions/{id}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-definitions/{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/metafield-definitions/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-definitions/{id}"
}Delete a metafield definition
Supports Idempotency-Key header for safe retries.
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
Metafield Definition 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/metafield-definitions/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-definitions/{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/metafield-definitions/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-definitions/{id}"
}Replace platform publishing configuration
Supports Idempotency-Key header for safe retries.
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
Metafield Definition 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 <= 255Empty Object
curl -X PUT "https://api.brainerce.com/api/v1/metafield-definitions/string/platforms" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Warranty Info",
"key": "warranty_info",
"description": "string",
"type": "string",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"minLength": 0,
"maxLength": 0,
"minValue": 0,
"maxValue": 0,
"dateAvailability": {},
"enumValues": [
{
"label": "string",
"value": "string",
"swatchColor": "string",
"swatchImageUrl": "string"
}
],
"defaultValue": "string",
"position": 0,
"isActive": true,
"publishedOn": [
"SHOPIFY"
],
"platformIds": {
"property1": "string",
"property2": "string"
},
"platformMetadata": {},
"syncStatus": {
"property1": "string",
"property2": "string"
},
"lastSyncedAt": {
"property1": "string",
"property2": "string"
},
"source": "string",
"products": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "Summer Collection"
}
],
"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"
}
}
],
"_count": {
"values": 0
},
"translations": {},
"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/metafield-definitions/{id}/platforms"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-definitions/{id}/platforms"
}{
"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/metafield-definitions/{id}/platforms"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-definitions/{id}/platforms"
}Get metafields for a product
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
Product ID
curl -X GET "https://api.brainerce.com/api/v1/products/string/metafields"[
{
"id": "string",
"productId": "string",
"variantId": "string",
"metafieldDefinitionId": "string",
"value": "string",
"translations": {},
"syncStatus": {},
"source": "string",
"lastModifiedBy": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"definition": {
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"key": "string",
"description": "string",
"type": "string",
"required": true,
"minLength": 0,
"maxLength": 0,
"minValue": "string",
"maxValue": "string",
"enumValues": {},
"defaultValue": "string",
"dateAvailability": {},
"isActive": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"position": 0,
"publishedOn": [
"string"
],
"platformIds": {},
"platformMetadata": {},
"syncStatus": {},
"lastSyncedAt": {},
"source": "string",
"translations": {},
"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/products/{productId}/metafields"
}{
"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/products/{productId}/metafields"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{productId}/metafields"
}Delete a product metafield value
Supports Idempotency-Key header for safe retries.
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
Product ID
Metafield Definition ID
Query Parameters
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/products/string/metafields/string?variantId=string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{productId}/metafields/{definitionId}"
}{
"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/products/{productId}/metafields/{definitionId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{productId}/metafields/{definitionId}"
}Upsert a product metafield value
Supports Idempotency-Key header for safe retries.
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
Product ID
Metafield Definition 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 <= 255Empty Object
curl -X PUT "https://api.brainerce.com/api/v1/products/string/metafields/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"productId": "string",
"variantId": "string",
"metafieldDefinitionId": "string",
"value": "string",
"translations": {},
"syncStatus": {},
"source": "string",
"lastModifiedBy": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"definition": {
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "string",
"key": "string",
"description": "string",
"type": "string",
"required": true,
"minLength": 0,
"maxLength": 0,
"minValue": "string",
"maxValue": "string",
"enumValues": {},
"defaultValue": "string",
"dateAvailability": {},
"isActive": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"position": 0,
"publishedOn": [
"string"
],
"platformIds": {},
"platformMetadata": {},
"syncStatus": {},
"lastSyncedAt": {},
"source": "string",
"translations": {},
"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/products/{productId}/metafields/{definitionId}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{productId}/metafields/{definitionId}"
}{
"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/products/{productId}/metafields/{definitionId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{productId}/metafields/{definitionId}"
}Get email settings for store
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
curl -X GET "https://api.brainerce.com/api/v1/email/settings"{
"id": "string",
"accountId": "string",
"storeId": "string",
"emailsEnabled": true,
"defaultFromName": "string",
"defaultReplyTo": "string",
"eventSettings": {},
"hourlyRateLimit": 0,
"customDomainId": "string",
"dailyCampaignSendLimit": 0,
"clickTrackingEnabled": true,
"footerAddress": "string",
"footerSocialLinks": {},
"footerCustomText": "string",
"fontFamily": "string",
"deliveryProviderOverride": "string",
"sesTenantName": "string",
"marketingSendingPaused": true,
"marketingPauseReason": "string",
"marketingPausedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"customDomain": {
"id": "string",
"storeId": "string",
"domain": "mail.mystore.com",
"status": "string",
"dnsRecords": {},
"provider": "string",
"providerIdentityId": "string",
"providerRegion": "string",
"mailFromDomain": "string",
"dkimStatus": "string",
"mailFromStatus": "string",
"resendDomainId": "string",
"verifiedAt": "2019-08-24T14:15:22Z",
"lastCheckedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
},
"hasOwnerEmail": true
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/settings"
}{
"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/email/settings"
}Update email settings for store
Supports Idempotency-Key header for safe retries.
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
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 <= 255Whether emails are enabled for this store
trueTrack link clicks in marketing campaigns. Off by default, because enabling it starts recording which recipients clicked, so the store owner must opt in rather than inherit it. Opens are never tracked.
Default from name for emails
Reply-to email address
Per-event settings
Empty Object
Hourly rate limit for emails
1001 <= value <= 1000Custom domain ID to use for sending
Physical postal address shown in the footer of marketing mail. Required before any marketing-class message can be sent. CAN-SPAM mandates a visible business address, and the send is refused without one.
curl -X PUT "https://api.brainerce.com/api/v1/email/settings" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"emailsEnabled": true,
"defaultFromName": "string",
"defaultReplyTo": "string",
"eventSettings": {},
"hourlyRateLimit": 0,
"customDomainId": "string",
"dailyCampaignSendLimit": 0,
"clickTrackingEnabled": true,
"footerAddress": "string",
"footerSocialLinks": {},
"footerCustomText": "string",
"fontFamily": "string",
"deliveryProviderOverride": "string",
"sesTenantName": "string",
"marketingSendingPaused": true,
"marketingPauseReason": "string",
"marketingPausedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"customDomain": {
"id": "string",
"storeId": "string",
"domain": "mail.mystore.com",
"status": "string",
"dnsRecords": {},
"provider": "string",
"providerIdentityId": "string",
"providerRegion": "string",
"mailFromDomain": "string",
"dkimStatus": "string",
"mailFromStatus": "string",
"resendDomainId": "string",
"verifiedAt": "2019-08-24T14:15:22Z",
"lastCheckedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
},
"hasOwnerEmail": 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/email/settings"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/settings"
}{
"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/email/settings"
}Get Storefront Bot settings for every connection on the store
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
curl -X GET "https://api.brainerce.com/api/v1/storefront-bot/settings"{
"connections": [
{
"salesChannelId": "string",
"connectionId": "vc_9f3a2b1c8d7e6f5a",
"name": "string"
}
],
"settings": [
{
"salesChannelId": "string",
"connectionId": "string",
"name": "string",
"enabled": true,
"displayName": "Assistant",
"avatarUrl": "string",
"personaJson": {},
"escalationJson": {},
"retentionJson": {},
"localeJson": {},
"dailySpendCeilingUsd": 0
}
]
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/storefront-bot/settings"
}{
"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/storefront-bot/settings"
}Update one connection’s Storefront Bot settings
Only fields present in the body are changed. Supports Idempotency-Key header for safe retries.
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
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 <= 255Empty Object
curl -X PUT "https://api.brainerce.com/api/v1/storefront-bot/settings" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"salesChannelId": "string",
"connectionId": "string",
"name": "string",
"enabled": true,
"displayName": "Assistant",
"avatarUrl": "string",
"personaJson": {},
"escalationJson": {},
"retentionJson": {},
"localeJson": {},
"dailySpendCeilingUsd": 0
}{
"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/storefront-bot/settings"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/storefront-bot/settings"
}{
"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/storefront-bot/settings"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/storefront-bot/settings"
}List Storefront Bot conversations
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
curl -X GET "https://api.brainerce.com/api/v1/storefront-bot/conversations?salesChannelId=string&page=0&limit=0"{
"data": [
{
"id": "string",
"salesChannelId": "string",
"title": "string",
"locale": "string",
"customerName": "string",
"lastMessage": {
"role": "string",
"content": "string",
"createdAt": "2019-08-24T14:15:22Z"
},
"messageCount": 0,
"unread": true,
"lastActivityAt": "2019-08-24T14:15:22Z",
"createdAt": "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/storefront-bot/conversations"
}{
"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/storefront-bot/conversations"
}Get one Storefront Bot conversation transcript
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
Conversation id
curl -X GET "https://api.brainerce.com/api/v1/storefront-bot/conversations/string"{
"id": "string",
"salesChannelId": "string",
"title": "string",
"locale": "string",
"customerName": "string",
"customerEmail": "[email protected]",
"merchantReadAt": "2019-08-24T14:15:22Z",
"lastActivityAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"messages": [
{
"id": "string",
"role": "string",
"content": "string",
"createdAt": "2019-08-24T14:15:22Z"
}
],
"summarizedHistory": "string"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/storefront-bot/conversations/{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/storefront-bot/conversations/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/storefront-bot/conversations/{id}"
}Summarize a Storefront Bot conversation
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
Conversation id
curl -X POST "https://api.brainerce.com/api/v1/storefront-bot/conversations/string/summarize"{
"summarized": true,
"summary": "string"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/storefront-bot/conversations/{id}/summarize"
}{
"statusCode": 402,
"code": "PLAN_AI_CREDITS_EXHAUSTED",
"message": "AI credit balance exhausted for this billing period",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/storefront-bot/conversations/{id}/summarize"
}{
"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/storefront-bot/conversations/{id}/summarize"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/storefront-bot/conversations/{id}/summarize"
}Get all email templates for store
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
curl -X GET "https://api.brainerce.com/api/v1/email/templates"{
"templates": [
{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Order Confirmation",
"eventType": "string",
"language": "string",
"subject": "Order {{orderNumber}} Confirmed",
"htmlContent": "string",
"textContent": "string",
"variables": {},
"isDefault": true,
"isActive": true,
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
],
"language": "string",
"supportedLanguages": [
"string"
]
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/templates"
}{
"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/email/templates"
}Create a new email template
Supports Idempotency-Key header for safe retries.
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
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 <= 255Template display name
Event type this template is for
"ORDER_CONFIRMATION" | "ORDER_SHIPPED" | "ORDER_CANCELLED" | "ORDER_COMPLETED" | "ORDER_REFUNDED" | "ORDER_NOTE" | "NEW_ORDER_ADMIN" | "NEW_CUSTOMER" | "LOW_STOCK_ALERT" | "CART_ABANDONED" | "EMAIL_VERIFICATION" | "TEAM_INVITATION" | "ORDERS_LINKED" | "STORE_INVITATION" | "STORE_ROLE_CHANGED" | "STORE_DELETED" | "EXPORT_COMPLETE" | "SCHEDULED_BACKUP_SUCCESS" | "SCHEDULED_BACKUP_FAILED" | "PASSWORD_RESET" | "INQUIRY_NEW_ADMIN" | "INQUIRY_REPLY_CUSTOMER" | "INQUIRY_CONFIRMATION_CUSTOMER" | "MARKETING_CAMPAIGN"Locale this template is for (must be in store.supportedLanguages)
Email subject line (supports Handlebars)
HTML content of the email (supports Handlebars)
Plain text content of the email
Variable schema for this template
Empty Object
Whether this template is active
truecurl -X POST "https://api.brainerce.com/api/v1/email/templates" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "name": "Order Confirmation", "eventType": "ORDER_CONFIRMATION", "language": "en", "subject": "Order #{{orderNumber}} Confirmed", "htmlContent": "<h1>Thank you for your order!</h1>" }'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Order Confirmation",
"eventType": "string",
"language": "string",
"subject": "Order {{orderNumber}} Confirmed",
"htmlContent": "string",
"textContent": "string",
"variables": {},
"isDefault": true,
"isActive": true,
"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/email/templates"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/templates"
}{
"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/email/templates"
}Get email template by ID
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
Template ID
curl -X GET "https://api.brainerce.com/api/v1/email/templates/string"{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Order Confirmation",
"eventType": "string",
"language": "string",
"subject": "Order {{orderNumber}} Confirmed",
"htmlContent": "string",
"textContent": "string",
"variables": {},
"isDefault": true,
"isActive": true,
"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/email/templates/{templateId}"
}{
"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/email/templates/{templateId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/templates/{templateId}"
}Delete an email template
Supports Idempotency-Key header for safe retries.
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
Template 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/email/templates/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/templates/{templateId}"
}{
"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/email/templates/{templateId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/templates/{templateId}"
}Update an email template
Supports Idempotency-Key header for safe retries.
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
Template 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 <= 255Template display name
Email subject line (supports Handlebars)
HTML content of the email (supports Handlebars)
Plain text content of the email
Variable schema for this template
Empty Object
Whether this template is active
curl -X PUT "https://api.brainerce.com/api/v1/email/templates/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"accountId": "string",
"storeId": "string",
"name": "Order Confirmation",
"eventType": "string",
"language": "string",
"subject": "Order {{orderNumber}} Confirmed",
"htmlContent": "string",
"textContent": "string",
"variables": {},
"isDefault": true,
"isActive": true,
"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/email/templates/{templateId}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/templates/{templateId}"
}{
"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/email/templates/{templateId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/templates/{templateId}"
}Preview an email template with sample data
Supports Idempotency-Key header for safe retries.
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
Template 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 <= 255Sample variables for rendering the template
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/email/templates/string/preview" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"subject": "string",
"html": "string",
"text": "string"
}{
"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/email/templates/{templateId}/preview"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/templates/{templateId}/preview"
}{
"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/email/templates/{templateId}/preview"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/email/templates/{templateId}/preview"
}Get pending metafield conflicts
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
curl -X GET "https://api.brainerce.com/api/v1/metafield-conflicts"[
{
"id": "string",
"storeId": "string",
"productId": "string",
"metafieldDefinitionId": "string",
"sourcePlatform": "string",
"sourceValue": "string",
"currentValue": "string",
"status": "string",
"resolution": "string",
"resolvedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"product": {
"id": "string",
"name": "string",
"sku": "string"
},
"definition": {
"id": "string",
"name": "string",
"key": "string",
"type": "string"
}
}
]{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-conflicts"
}{
"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/metafield-conflicts"
}Resolve a metafield conflict
Supports Idempotency-Key header for safe retries.
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
Conflict 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 <= 255Empty Object
curl -X POST "https://api.brainerce.com/api/v1/metafield-conflicts/string/resolve" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"storeId": "string",
"productId": "string",
"metafieldDefinitionId": "string",
"sourcePlatform": "string",
"sourceValue": "string",
"currentValue": "string",
"status": "string",
"resolution": "string",
"resolvedAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"product": {
"id": "string",
"name": "string",
"sku": "string"
},
"definition": {
"id": "string",
"name": "string",
"key": "string",
"type": "string"
}
}{
"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/metafield-conflicts/{conflictId}/resolve"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-conflicts/{conflictId}/resolve"
}{
"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/metafield-conflicts/{conflictId}/resolve"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-conflicts/{conflictId}/resolve"
}Ignore a metafield conflict
Supports Idempotency-Key header for safe retries.
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
Conflict 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 POST "https://api.brainerce.com/api/v1/metafield-conflicts/string/ignore" \ -H "Idempotency-Key: string"{
"id": "string",
"storeId": "string",
"productId": "string",
"metafieldDefinitionId": "string",
"sourcePlatform": "string",
"sourceValue": "string",
"currentValue": "string",
"status": "string",
"resolution": "string",
"resolvedAt": "2019-08-24T14:15:22Z",
"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/metafield-conflicts/{conflictId}/ignore"
}{
"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/metafield-conflicts/{conflictId}/ignore"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/metafield-conflicts/{conflictId}/ignore"
}Get all OAuth provider configurations
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
curl -X GET "https://api.brainerce.com/api/v1/oauth-providers"[
{
"id": "string",
"storeId": "string",
"provider": "GOOGLE",
"clientId": "string",
"isEnabled": true,
"providerConfig": {},
"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/oauth-providers"
}{
"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/oauth-providers"
}Configure an OAuth provider
Supports Idempotency-Key header for safe retries.
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
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 <= 255Empty Object
curl -X POST "https://api.brainerce.com/api/v1/oauth-providers" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"storeId": "string",
"provider": "GOOGLE",
"clientId": "string",
"isEnabled": true,
"providerConfig": {},
"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/oauth-providers"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/oauth-providers"
}{
"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/oauth-providers"
}Get OAuth provider configuration
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
OAuth provider (GOOGLE, FACEBOOK, GITHUB)
curl -X GET "https://api.brainerce.com/api/v1/oauth-providers/string"{
"id": "string",
"storeId": "string",
"provider": "GOOGLE",
"clientId": "string",
"isEnabled": true,
"providerConfig": {},
"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/oauth-providers/{provider}"
}{
"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/oauth-providers/{provider}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/oauth-providers/{provider}"
}Update OAuth provider configuration
Supports Idempotency-Key header for safe retries.
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
OAuth provider (GOOGLE, FACEBOOK, GITHUB)
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 <= 255Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/oauth-providers/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "string",
"storeId": "string",
"provider": "GOOGLE",
"clientId": "string",
"isEnabled": true,
"providerConfig": {},
"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/oauth-providers/{provider}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/oauth-providers/{provider}"
}{
"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/oauth-providers/{provider}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/oauth-providers/{provider}"
}Delete OAuth provider configuration
Supports Idempotency-Key header for safe retries.
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
OAuth provider (GOOGLE, FACEBOOK, GITHUB)
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/oauth-providers/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/oauth-providers/{provider}"
}{
"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/oauth-providers/{provider}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/oauth-providers/{provider}"
}List reviews for a product (admin view, includes hidden)
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
Product ID
Query Parameters
"visible" | "hidden" | "all"curl -X GET "https://api.brainerce.com/api/v1/products/string/reviews?page=0&limit=0&visibility=visible"{
"data": [
{
"id": "string",
"productId": "string",
"authorName": "string",
"rating": 1,
"body": "string",
"verifiedPurchase": true,
"hiddenAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"customerId": "string",
"authorEmail": "[email protected]",
"orderId": "string",
"updatedAt": "2019-08-24T14:15:22Z",
"images": [
{
"id": "string",
"url": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"position": 0,
"assetKey": "string",
"approvedAt": "2019-08-24T14:15:22Z",
"hiddenAt": "2019-08-24T14:15:22Z",
"createdAt": "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/products/{productId}/reviews"
}{
"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/products/{productId}/reviews"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{productId}/reviews"
}Submit a product review (server-to-server)
Supports Idempotency-Key header for safe retries.
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
Product 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 <= 255Reviewer display name. 1-100 chars, no HTML angle brackets (a basic XSS guard; full sanitization happens server-side).
1 <= length <= 100Optional reviewer email, used for verified-buyer matching. It is never mailed: Brainerce sends no notification when a review is submitted or published, and there is no template for one.
length <= 200Star rating, 1-5 (integer).
1 <= value <= 5Review body (≤ 5000 chars). Markdown is rendered as plain text, and links are stripped.
length <= 5000Media library storage keys to attach as review photos, in display order. This is the import path: upload the images through the normal media endpoints first, then pass their keys here. Keys must belong to the same store. Photos imported this way publish immediately regardless of the store's approval setting, since a server-to-server caller has already vetted them.
items <= 5curl -X POST "https://api.brainerce.com/api/v1/products/string/reviews" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "authorName": "Jane D.", "rating": 5 }'{
"id": "string",
"productId": "string",
"authorName": "string",
"rating": 1,
"body": "string",
"verifiedPurchase": true,
"hiddenAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"images": [
{
"id": "string",
"url": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"position": 0
}
]
}{
"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/products/{productId}/reviews"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{productId}/reviews"
}{
"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/products/{productId}/reviews"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/products/{productId}/reviews"
}Hide a review from the storefront
Supports Idempotency-Key header for safe retries.
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
Review 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 PATCH "https://api.brainerce.com/api/v1/reviews/string/hide" \ -H "Idempotency-Key: string"{
"id": "string",
"productId": "string",
"authorName": "string",
"rating": 1,
"body": "string",
"verifiedPurchase": true,
"hiddenAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"customerId": "string",
"authorEmail": "[email protected]",
"orderId": "string",
"updatedAt": "2019-08-24T14:15:22Z",
"images": [
{
"id": "string",
"url": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"position": 0,
"assetKey": "string",
"approvedAt": "2019-08-24T14:15:22Z",
"hiddenAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z"
}
]
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/reviews/{id}/hide"
}{
"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/reviews/{id}/hide"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/reviews/{id}/hide"
}Unhide a previously hidden review
Supports Idempotency-Key header for safe retries.
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
Review 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 PATCH "https://api.brainerce.com/api/v1/reviews/string/show" \ -H "Idempotency-Key: string"{
"id": "string",
"productId": "string",
"authorName": "string",
"rating": 1,
"body": "string",
"verifiedPurchase": true,
"hiddenAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z",
"customerId": "string",
"authorEmail": "[email protected]",
"orderId": "string",
"updatedAt": "2019-08-24T14:15:22Z",
"images": [
{
"id": "string",
"url": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"position": 0,
"assetKey": "string",
"approvedAt": "2019-08-24T14:15:22Z",
"hiddenAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z"
}
]
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/reviews/{id}/show"
}{
"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/reviews/{id}/show"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/reviews/{id}/show"
}Hide a single review photo, leaving the review itself visible
Supports Idempotency-Key header for safe retries.
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
Review photo 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 PATCH "https://api.brainerce.com/api/v1/review-images/string/hide" \ -H "Idempotency-Key: string"{
"id": "string",
"url": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"position": 0,
"assetKey": "string",
"approvedAt": "2019-08-24T14:15:22Z",
"hiddenAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/review-images/{id}/hide"
}{
"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/review-images/{id}/hide"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/review-images/{id}/hide"
}Show a review photo (also approves one that was awaiting a decision)
Supports Idempotency-Key header for safe retries.
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
Review photo 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 PATCH "https://api.brainerce.com/api/v1/review-images/string/show" \ -H "Idempotency-Key: string"{
"id": "string",
"url": "string",
"thumbnailUrl": "string",
"width": 0,
"height": 0,
"position": 0,
"assetKey": "string",
"approvedAt": "2019-08-24T14:15:22Z",
"hiddenAt": "2019-08-24T14:15:22Z",
"createdAt": "2019-08-24T14:15:22Z"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/review-images/{id}/show"
}{
"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/review-images/{id}/show"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/review-images/{id}/show"
}Get the newsletter signup benefit settings
Returns null when the store has never configured a benefit. enabled: false means configured but switched off — two different states, and a storefront should treat both as "offer nothing".
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
curl -X GET "https://api.brainerce.com/api/v1/newsletter-benefit/settings"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/newsletter-benefit/settings"
}{
"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/newsletter-benefit/settings"
}Create or replace the newsletter signup benefit settings
A FULL REPLACEMENT, not a patch: every field is written, so omitting one clears it. Bumps the stored settings version.
Changing these settings never rewrites a promise already made. Signups still waiting for a confirmation click keep the terms they were shown at signup, and coupons already issued are untouched.
Supports Idempotency-Key header for safe retries.
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
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 <= 255Turn the benefit on or off. Off stops new offers immediately; coupons already issued keep working, and signups still waiting for a confirmation click keep the terms they were shown.
"PERCENTAGE" | "FIXED_AMOUNT"Percent (1-100) for PERCENTAGE, or an amount in the store currency for FIXED_AMOUNT.
Minimum order subtotal required to use the coupon.
Cap on the discount a percentage benefit may produce. Ignored — and stored as null — for a fixed-amount benefit.
Whether the coupon may stack with other discounts.
Days the coupon stays usable, counted from issuance.
Hours a signup stays eligible, counted from the moment the form was submitted. A confirmation click after this still subscribes the address but earns no coupon — the confirmation LINK itself never expires, so this is the only deadline in the flow.
Restrict the coupon to buyers with no previous order in this store. Checked against the address the coupon is bound to, including guest orders.
Product IDs the coupon applies to.
Sales channels the issued coupon may be redeemed on. Leave empty for every enabled channel — an empty list is expanded at issuance, because a coupon with no channel rows is refused on every vibe-coded storefront.
Localized copy: { "en": { "headline": "...", "terms": "..." }, "he": { ... } }. Shown on the signup form and repeated in the email.
Empty Object
curl -X PUT "https://api.brainerce.com/api/v1/newsletter-benefit/settings" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "enabled": true, "discountType": "PERCENTAGE", "discountValue": 0, "combinesWithOther": true, "validityDays": 0, "eligibilityTtlHours": 0, "firstOrderOnly": 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/newsletter-benefit/settings"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/newsletter-benefit/settings"
}{
"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/newsletter-benefit/settings"
}List issued newsletter benefits
Paginated { data, meta }, newest first. redeemed is derived from the coupon having been used, so it is accurate the moment an order completes.
There is deliberately NO email filter: a lookup-by-address would turn this into a "does this person shop here" probe for any leaked key with coupons:read. Filter the page you get back.
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
Store the grants belong to. Required.
120value <= 100"PENDING" | "ISSUING" | "ISSUED" | "EXPIRED" | "FAILED"Signups created on or after this ISO-8601 date.
Signups created on or before this ISO-8601 date.
curl -X GET "https://api.brainerce.com/api/v1/newsletter-benefit/grants?storeId=string&page=1&limit=20&status=PENDING&from=string&to=string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/newsletter-benefit/grants"
}{
"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/newsletter-benefit/grants"
}Re-send an issued newsletter benefit
Re-queues the SAME coupon code. It never mints a second one, so a support ticket cannot turn into two discounts. For a benefit whose issuance failed before any coupon existed, this retries the issuance and mails whatever comes out.
Rejects a signup that has not been confirmed yet, and one that lapsed before any coupon was minted: in both cases there is nothing to re-send and nothing that may be created.
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
Grant ID from the grants list
curl -X POST "https://api.brainerce.com/api/v1/newsletter-benefit/grants/string/resend"{
"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/newsletter-benefit/grants/{grantId}/resend"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/newsletter-benefit/grants/{grantId}/resend"
}{
"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/newsletter-benefit/grants/{grantId}/resend"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/newsletter-benefit/grants/{grantId}/resend"
}