Metafields
Metafields add arbitrary custom fields to products, orders, customers, and other resources. Each metafield definition has a namespace, key, type, and validation rules — values are then attached per-resource.
List metafield definitions
Returns the product metafield definitions (the custom-field schema) that the merchant published to this channel. A definition that is not published is not listed.
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Sales channel ID (vc_*), the canonical salesChannelId. connectionId is the deprecated name of the same value and is still the literal path segment.
Header Parameters
Origin of the storefront page making the call, for example https://shop.example.com. Required: a request with no Origin header is refused with 403. On a LIVE channel its host must equal the channel's registered domain (or one of its subdomains) or match an allowed origin. A TEST channel with no domain accepts any origin; once a domain is set it is matched as on LIVE.
Version of the calling SDK (the Brainerce SDK sends it automatically). Informational: it is recorded on the channel and never changes the response.
curl -X GET "https://api.brainerce.com/api/vc/string/metafield-definitions" \ -H "origin: string" \ -H "X-SDK-Version: string"{
"definitions": [
{
"id": "clmfd_abc123",
"name": "string",
"key": "material",
"description": "string",
"type": "SELECT",
"required": false,
"filterable": true,
"enumValues": [
{}
],
"position": 0
}
]
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/metafield-definitions"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/metafield-definitions"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/metafield-definitions"
}List metafield facet filters with product counts
Returns facet value counts for the metafield definitions that are filterable, active and published to this channel, so a storefront can render "Color: red (12)" without one products query per value. At most 200 definitions are considered. Pass the chosen values to products as metafields.
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Sales channel ID (vc_*), the canonical salesChannelId. connectionId is the deprecated name of the same value and is still the literal path segment.
Query Parameters
Language code, for example he. Used only when no Accept-Language header is sent. A language the store does not support, or the store's default language, returns the default text.
Header Parameters
Origin of the storefront page making the call, for example https://shop.example.com. Required: a request with no Origin header is refused with 403. On a LIVE channel its host must equal the channel's registered domain (or one of its subdomains) or match an allowed origin. A TEST channel with no domain accepts any origin; once a domain is set it is matched as on LIVE.
Preferred language, for example he. Its first tag is used when it is one of the store's supported languages other than the default; translated fields are then returned in that language. Falls back to the locale query parameter.
Version of the calling SDK (the Brainerce SDK sends it automatically). Informational: it is recorded on the channel and never changes the response.
curl -X GET "https://api.brainerce.com/api/vc/string/metafield-filters?locale=string" \ -H "origin: string" \ -H "accept-language: string" \ -H "X-SDK-Version: string"{
"filters": [
{
"id": "clmfd_abc123",
"key": "string",
"name": "string",
"type": "SELECT",
"enumValues": [
{
"value": "red",
"label": "Red"
}
],
"values": [
{
"value": "cotton",
"count": 12
}
]
}
]
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/metafield-filters"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/metafield-filters"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/metafield-filters"
}Upload customization file
Uploads one buyer-supplied image and returns the URL to use as the value of an IMAGE or GALLERY customer-input customization field (a metafield definition with isCustomerInput). Upload BEFORE add-to-cart: the cart rejects any IMAGE/GALLERY value that is not a URL this endpoint returned for the same store, so an external URL cannot be pasted in.
Send multipart/form-data with a single file part. JPEG, PNG, WebP and GIF only — the declared content type is cross-checked against the file's magic bytes, and SVG is refused outright. Hard limits are 10 MB and 40 megapixels per file, one file per request.
By default the file is stored as a regular image: converted to WebP and shrunk to at most 2048 px. Pass the field's key as the fieldKey query parameter and, when the merchant has switched on keepOriginalImage for that field, the file is instead kept at the pixel size and in the format you sent, so the merchant can print it. Either way EXIF (including GPS) is removed and its rotation applied. A fieldKey that matches no active customer-input IMAGE/GALLERY field is not an error: the file is stored as a regular image. Stored bytes count against the merchant's plan storage quota. Rate limited to 10 uploads per minute. Uploads never referenced by a cart line are swept by the customer-uploads cleanup job.
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Sales channel ID (vc_*), the canonical salesChannelId. connectionId is the deprecated name of the same value and is still the literal path segment.
Query Parameters
The customization field's key. Lets the merchant keep the file at full resolution (print quality) for that field. Omit it and the file is stored as a regular image.
Header Parameters
Origin of the storefront page making the call, for example https://shop.example.com. Required: a request with no Origin header is refused with 403. On a LIVE channel its host must equal the channel's registered domain (or one of its subdomains) or match an allowed origin. A TEST channel with no domain accepts any origin; once a domain is set it is matched as on LIVE.
Version of the calling SDK (the Brainerce SDK sends it automatically). Informational: it is recorded on the channel and never changes the response.
The image to store. JPEG, PNG, WebP or GIF; 10 MB and 40 MP maximum.
curl -X POST "https://api.brainerce.com/api/vc/string/customization-upload?fieldKey=string" \ -H "origin: string" \ -H "X-SDK-Version: string" \ -F file="string"{
"url": "https://cdn.brainerce.com/customizations/abc123.png",
"key": "customizations/abc123.png",
"width": 1200,
"height": 800
}{
"statusCode": 400,
"code": "VALIDATION_FAILED",
"message": "name should not be empty, price must be a positive number",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/customization-upload"
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/customization-upload"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/customization-upload"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/customization-upload"
}List metafield definitions
Returns every metafield definition of the store.
Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
curl -X GET "https://api.brainerce.com/api/v1/metafield-definitions"[
{
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Warranty Info",
"key": "warranty_info",
"description": "Fabric the product is made of",
"type": "TEXT",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"keepOriginalImage": true,
"minLength": 1,
"maxLength": 100,
"minValue": 0,
"maxValue": 1000,
"dateAvailability": {
"minDate": "2026-12-01",
"maxDate": "2026-12-31",
"blockedWeekdays": [
6
],
"blockedDates": [
"string"
],
"businessHours": [
{
"weekday": 6,
"open": "09:00",
"close": "17:00"
}
],
"slotDurationMinutes": 0
},
"enumValues": [
{
"label": "Cotton",
"value": "cotton",
"swatchColor": "#FFFFFF",
"swatchImageUrl": "https://cdn.example.com/swatches/cotton.png"
}
],
"defaultValue": "Cotton",
"position": 0,
"isActive": true,
"publishedOn": [
"META"
],
"platformIds": {},
"platformMetadata": {},
"syncStatus": {},
"lastSyncedAt": {},
"source": "LOCAL",
"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": 14
},
"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"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}Create a new metafield definition
Supports Idempotency-Key header for safe retries.
Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255Display name of the field.
1 <= length <= 100Unique key of the field in the store. Starts with a lowercase letter, then lowercase letters, digits and underscores. Creating a key that belongs to a deleted field reactivates that field with the new name, type, description and position.
^[a-z][a-z0-9_]*$1 <= length <= 64Description of the field.
length <= 500Value type of the field. One of TEXT, TEXTAREA, NUMBER, BOOLEAN, DATE, DATETIME, JSON, URL, COLOR, DIMENSION, WEIGHT, IMAGE, GALLERY, SELECT, MULTI_SELECT. Defaults to TEXT. JSON cannot be used as customer input.
"TEXT""TEXT" | "TEXTAREA" | "NUMBER" | "BOOLEAN" | "DATE" | "DATETIME" | "JSON" | "URL" | "COLOR" | "DIMENSION" | "WEIGHT" | "IMAGE" | "GALLERY" | "SELECT" | "MULTI_SELECT"Whether a value is required. Defaults to false.
falseShow the field on the storefront as an input the customer fills in (for example engraving text). Defaults to false.
falseIMAGE and GALLERY customer-input fields only. false (default): a buyer upload is a regular image, converted to WebP and shrunk to 2048px. true: kept at full resolution in its own format, for the merchant to print. Rejected on any other field.
falseMinimum text length for TEXT and TEXTAREA values.
Maximum text length for TEXT and TEXTAREA values.
Minimum allowed value for NUMBER fields.
Maximum allowed value for NUMBER fields.
Date constraints for DATE and DATETIME fields: minDate, maxDate, blockedWeekdays, blockedDates, and for DATETIME also businessHours and slotDurationMinutes. The checkout-only keys leadTimeMinutes, maxDaysAhead and cutoffTime are rejected on product metafields. Ignored for other types.
Allowed options for SELECT and MULTI_SELECT fields. Plain strings or { label, value, swatchColor?, swatchImageUrl? } objects; a string is stored as { label: v, value: v }.
Default value, as a string in the same format as a stored value.
Sort position of the field. Lower values come first.
0Products the customer-input field is limited to. Only valid when isCustomerInput is true. IDs must be unique and belong to the store.
Show the customer-input field on every product of the store. Only valid when isCustomerInput is true. Defaults to false.
falseExpose the field as a storefront filter. Only valid for SELECT, MULTI_SELECT and BOOLEAN fields. Defaults to false.
falseLegacy and record-only: platform codes the field is marked as published on. Nothing is pushed to any platform. Every listed platform needs an entry in platformMetadata.
Legacy and record-only per-platform configuration keyed by platform code. Required for every platform in publishedOn. Only META (field: custom_label_0 to custom_label_4) and TIKTOK (attributeName) are shape-checked; any other platform code is free-form.
Origin of the definition. Defaults to LOCAL.
"LOCAL"curl -X POST "https://api.brainerce.com/api/v1/metafield-definitions" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "name": "Warranty info", "key": "warranty_info" }'{
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Warranty Info",
"key": "warranty_info",
"description": "Fabric the product is made of",
"type": "TEXT",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"keepOriginalImage": true,
"minLength": 1,
"maxLength": 100,
"minValue": 0,
"maxValue": 1000,
"dateAvailability": {
"minDate": "2026-12-01",
"maxDate": "2026-12-31",
"blockedWeekdays": [
6
],
"blockedDates": [
"string"
],
"businessHours": [
{
"weekday": 6,
"open": "09:00",
"close": "17:00"
}
],
"slotDurationMinutes": 0
},
"enumValues": [
{
"label": "Cotton",
"value": "cotton",
"swatchColor": "#FFFFFF",
"swatchImageUrl": "https://cdn.example.com/swatches/cotton.png"
}
],
"defaultValue": "Cotton",
"position": 0,
"isActive": true,
"publishedOn": [
"META"
],
"platformIds": {},
"platformMetadata": {},
"syncStatus": {},
"lastSyncedAt": {},
"source": "LOCAL",
"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": 14
},
"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"
}{
"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/metafield-definitions"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}Get a single metafield definition by ID
Returns one metafield definition of this store.
Admin API key (server-to-server). Issue via the dashboard at Settings → API keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Path Parameters
Metafield Definition ID
curl -X GET "https://api.brainerce.com/api/v1/metafield-definitions/string"{
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Warranty Info",
"key": "warranty_info",
"description": "Fabric the product is made of",
"type": "TEXT",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"keepOriginalImage": true,
"minLength": 1,
"maxLength": 100,
"minValue": 0,
"maxValue": 1000,
"dateAvailability": {
"minDate": "2026-12-01",
"maxDate": "2026-12-31",
"blockedWeekdays": [
6
],
"blockedDates": [
"string"
],
"businessHours": [
{
"weekday": 6,
"open": "09:00",
"close": "17:00"
}
],
"slotDurationMinutes": 0
},
"enumValues": [
{
"label": "Cotton",
"value": "cotton",
"swatchColor": "#FFFFFF",
"swatchImageUrl": "https://cdn.example.com/swatches/cotton.png"
}
],
"defaultValue": "Cotton",
"position": 0,
"isActive": true,
"publishedOn": [
"META"
],
"platformIds": {},
"platformMetadata": {},
"syncStatus": {},
"lastSyncedAt": {},
"source": "LOCAL",
"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": 14
},
"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}"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}Update a metafield definition
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
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 <= 255New display name of the field.
length <= 100New description of the field.
length <= 500Value type of the field. One of TEXT, TEXTAREA, NUMBER, BOOLEAN, DATE, DATETIME, JSON, URL, COLOR, DIMENSION, WEIGHT, IMAGE, GALLERY, SELECT, MULTI_SELECT.
"TEXT" | "TEXTAREA" | "NUMBER" | "BOOLEAN" | "DATE" | "DATETIME" | "JSON" | "URL" | "COLOR" | "DIMENSION" | "WEIGHT" | "IMAGE" | "GALLERY" | "SELECT" | "MULTI_SELECT"Whether a value is required.
Show the field on the storefront as an input the customer fills in (for example engraving text).
IMAGE and GALLERY customer-input fields only. false (default): a buyer upload is a regular image, converted to WebP and shrunk to 2048px. true: kept at full resolution in its own format, for the merchant to print. Rejected on any other field.
Minimum text length for TEXT and TEXTAREA values. Pass null to remove the limit.
Maximum text length for TEXT and TEXTAREA values. Pass null to remove the limit.
Minimum allowed value for NUMBER fields. Pass null to remove the limit.
Maximum allowed value for NUMBER fields. Pass null to remove the limit.
Date constraints for DATE and DATETIME fields: minDate, maxDate, blockedWeekdays, blockedDates, and for DATETIME also businessHours and slotDurationMinutes. The checkout-only keys leadTimeMinutes, maxDaysAhead and cutoffTime are rejected on product metafields. Ignored for other types. Pass null to remove all constraints.
Allowed options for SELECT and MULTI_SELECT fields. Plain strings or { label, value, swatchColor?, swatchImageUrl? } objects; a string is stored as { label: v, value: v }. Pass null to clear all options.
Default value, as a string in the same format as a stored value. Pass null to clear.
Whether the field is active. New values for an inactive field are rejected.
Show the customer-input field on every product of the store. Only valid when isCustomerInput is true.
Expose the field as a storefront filter. Only valid for SELECT, MULTI_SELECT and BOOLEAN fields.
Sort position of the field. Lower values come first.
curl -X PATCH "https://api.brainerce.com/api/v1/metafield-definitions/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Warranty Info",
"key": "warranty_info",
"description": "Fabric the product is made of",
"type": "TEXT",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"keepOriginalImage": true,
"minLength": 1,
"maxLength": 100,
"minValue": 0,
"maxValue": 1000,
"dateAvailability": {
"minDate": "2026-12-01",
"maxDate": "2026-12-31",
"blockedWeekdays": [
6
],
"blockedDates": [
"string"
],
"businessHours": [
{
"weekday": 6,
"open": "09:00",
"close": "17:00"
}
],
"slotDurationMinutes": 0
},
"enumValues": [
{
"label": "Cotton",
"value": "cotton",
"swatchColor": "#FFFFFF",
"swatchImageUrl": "https://cdn.example.com/swatches/cotton.png"
}
],
"defaultValue": "Cotton",
"position": 0,
"isActive": true,
"publishedOn": [
"META"
],
"platformIds": {},
"platformMetadata": {},
"syncStatus": {},
"lastSyncedAt": {},
"source": "LOCAL",
"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": 14
},
"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}"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}Delete a metafield definition
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
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}"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}Replace platform publishing configuration
Deprecated and record-only: the platform list and config are stored on the definition, but nothing is pushed to any platform. Only META and TIKTOK configs are shape-checked; other platform codes are free-form. 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
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 <= 255Platform codes the field is marked as published on. Replaces the stored list. Record-only: nothing is pushed to any platform. Every listed platform needs an entry in platformMetadata.
Per-platform configuration keyed by platform code. Pass null to clear. Only META (field: custom_label_0 to custom_label_4) and TIKTOK (attributeName) are shape-checked; any other platform code is free-form.
curl -X PUT "https://api.brainerce.com/api/v1/metafield-definitions/string/platforms" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "publishedOn": [ "META" ] }'{
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Warranty Info",
"key": "warranty_info",
"description": "Fabric the product is made of",
"type": "TEXT",
"required": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"keepOriginalImage": true,
"minLength": 1,
"maxLength": 100,
"minValue": 0,
"maxValue": 1000,
"dateAvailability": {
"minDate": "2026-12-01",
"maxDate": "2026-12-31",
"blockedWeekdays": [
6
],
"blockedDates": [
"string"
],
"businessHours": [
{
"weekday": 6,
"open": "09:00",
"close": "17:00"
}
],
"slotDurationMinutes": 0
},
"enumValues": [
{
"label": "Cotton",
"value": "cotton",
"swatchColor": "#FFFFFF",
"swatchImageUrl": "https://cdn.example.com/swatches/cotton.png"
}
],
"defaultValue": "Cotton",
"position": 0,
"isActive": true,
"publishedOn": [
"META"
],
"platformIds": {},
"platformMetadata": {},
"syncStatus": {},
"lastSyncedAt": {},
"source": "LOCAL",
"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": 14
},
"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"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}Get metafields for a product
Returns the metafield values set on the product.
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
Product ID
curl -X GET "https://api.brainerce.com/api/v1/products/string/metafields"[
{
"id": "clx1a2b3c4d5e6f7g8h9",
"productId": "clx1a2b3c4d5e6f7g8h9",
"variantId": "clx1a2b3c4d5e6f7g8h9",
"metafieldDefinitionId": "clx1a2b3c4d5e6f7g8h9",
"value": "Cotton",
"translations": {},
"syncStatus": {},
"source": "LOCAL",
"lastModifiedBy": "api-key-user",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"definition": {
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Material",
"key": "material",
"description": "Fabric the product is made of",
"type": "TEXT",
"required": true,
"minLength": 1,
"maxLength": 100,
"minValue": "0",
"maxValue": "1000",
"enumValues": [
"string"
],
"defaultValue": "Cotton",
"dateAvailability": {
"minDate": "2026-12-01",
"maxDate": "2026-12-31",
"blockedWeekdays": [
6
],
"blockedDates": [
"string"
],
"businessHours": [
{
"weekday": 6,
"open": "09:00",
"close": "17:00"
}
],
"slotDurationMinutes": 0
},
"isActive": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"keepOriginalImage": true,
"position": 0,
"publishedOn": [
"string"
],
"platformIds": {},
"platformMetadata": {},
"syncStatus": {},
"lastSyncedAt": {},
"source": "LOCAL",
"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"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}Upsert a product metafield value
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
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 <= 255Value as a string, in the format of the field type: NUMBER a numeric string, BOOLEAN true/false/1/0, DATE YYYY-MM-DD, DATETIME an ISO 8601 instant, COLOR a 6 digit hex code such as #FF0000, URL an absolute URL, JSON valid JSON text, MULTI_SELECT a JSON array of option values. Checked against the field limits and options; an empty string is rejected when the field is required.
Variant the value belongs to. Omit for a product-level value. The variant must belong to the product.
curl -X PUT "https://api.brainerce.com/api/v1/products/string/metafields/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "value": "Cotton" }'{
"id": "clx1a2b3c4d5e6f7g8h9",
"productId": "clx1a2b3c4d5e6f7g8h9",
"variantId": "clx1a2b3c4d5e6f7g8h9",
"metafieldDefinitionId": "clx1a2b3c4d5e6f7g8h9",
"value": "Cotton",
"translations": {},
"syncStatus": {},
"source": "LOCAL",
"lastModifiedBy": "api-key-user",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"definition": {
"id": "clx1a2b3c4d5e6f7g8h9",
"accountId": "clx1a2b3c4d5e6f7g8h9",
"storeId": "clx1a2b3c4d5e6f7g8h9",
"name": "Material",
"key": "material",
"description": "Fabric the product is made of",
"type": "TEXT",
"required": true,
"minLength": 1,
"maxLength": 100,
"minValue": "0",
"maxValue": "1000",
"enumValues": [
"string"
],
"defaultValue": "Cotton",
"dateAvailability": {
"minDate": "2026-12-01",
"maxDate": "2026-12-31",
"blockedWeekdays": [
6
],
"blockedDates": [
"string"
],
"businessHours": [
{
"weekday": 6,
"open": "09:00",
"close": "17:00"
}
],
"slotDurationMinutes": 0
},
"isActive": true,
"isCustomerInput": true,
"appliesToAllProducts": true,
"filterable": true,
"keepOriginalImage": true,
"position": 0,
"publishedOn": [
"string"
],
"platformIds": {},
"platformMetadata": {},
"syncStatus": {},
"lastSyncedAt": {},
"source": "LOCAL",
"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}"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}Delete a product metafield value
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
Product ID
Metafield Definition ID
Query Parameters
Delete the value stored for this variant. Without it the product-level value is deleted.
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}"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/store"
}