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 → 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
length <= 191GTIN (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
length <= 500Variant attribute map
Variant price in the store currency, as a decimal in major units (19.99 means 19.99, not cents). Same unit as the product basePrice; a variable product basePrice is its lowest variant price. When omitted the variant is sold at the product basePrice.
Variant sale price in the store currency, a decimal in major units like price. Greater than 0 and lower than the variant price (the one sent with it, or the stored one), otherwise the request is refused with a 400. Pass null to take the variant off sale.
Variant sale-price effective window start (ISO 8601). Overrides the product window for this variant. Pass null to clear.
Variant sale-price effective window end (ISO 8601). See salePriceStartsAt. Pass null to clear.
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)
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)
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.
curl -X PATCH "https://api.brainerce.com/api/v1/products/string/variants/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "clx1a2b3c4d5e6f7g8h9",
"productId": "clx1a2b3c4d5e6f7g8h9",
"sku": "TSHIRT-BLK-M",
"name": "Black / M",
"attributes": {
"size": "S",
"color": "Red"
},
"price": "19.90",
"salePrice": "24.90",
"costPrice": "12.00",
"salePriceStartsAt": "2019-08-24T14:15:22Z",
"salePriceEndsAt": "2019-08-24T14:15:22Z",
"displayPrice": "29.90",
"displaySalePrice": "24.90",
"displayCurrency": "USD",
"image": "string",
"position": 0,
"status": "active",
"inventory": {
"trackingMode": "TRACKED",
"total": 42,
"reserved": 3,
"available": 39,
"inStock": true,
"canPurchase": true,
"lastInventorySyncAt": "2019-08-24T14:15:22Z"
},
"isDownloadable": true,
"downloadData": {
"files": [
{
"id": "clx1a2b3c4d5e6f7g8h9",
"name": "photos.zip",
"url": "https://cdn.example.com/downloads/photos.zip",
"storageKey": "downloads/photos.zip",
"size": 5242880,
"mimeType": "application/zip"
}
],
"downloadLimit": 3,
"downloadExpiry": 30
},
"shippingClassId": "clx1a2b3c4d5e6f7g8h9",
"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}"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}