API ReferenceEndpointsMetafields

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.

GET
/vc/{connectionId}/metafield-definitions
X-Sales-Channel-Origin<token>

For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.

In: header

Path Parameters

connectionIdstring

Sales channel ID (vc_*), the canonical salesChannelId. connectionId is the deprecated name of the same value and is still the literal path segment.

Header Parameters

originstring

Origin of the storefront page making the call, for example https://shop.example.com. Required: a request with no Origin header is refused with 403. On a LIVE channel its host must equal the channel's registered domain (or one of its subdomains) or match an allowed origin. A TEST channel with no domain accepts any origin; once a domain is set it is matched as on LIVE.

X-SDK-Version?string

Version of the calling SDK (the Brainerce SDK sends it automatically). Informational: it is recorded on the channel and never changes the response.

curl -X GET "https://api.brainerce.com/api/vc/string/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.

GET
/vc/{connectionId}/metafield-filters
X-Sales-Channel-Origin<token>

For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.

In: header

Path Parameters

connectionIdstring

Sales channel ID (vc_*), the canonical salesChannelId. connectionId is the deprecated name of the same value and is still the literal path segment.

Query Parameters

locale?string

Language code, for example he. Used only when no Accept-Language header is sent. A language the store does not support, or the store's default language, returns the default text.

Header Parameters

originstring

Origin of the storefront page making the call, for example https://shop.example.com. Required: a request with no Origin header is refused with 403. On a LIVE channel its host must equal the channel's registered domain (or one of its subdomains) or match an allowed origin. A TEST channel with no domain accepts any origin; once a domain is set it is matched as on LIVE.

accept-language?string

Preferred language, for example he. Its first tag is used when it is one of the store's supported languages other than the default; translated fields are then returned in that language. Falls back to the locale query parameter.

X-SDK-Version?string

Version of the calling SDK (the Brainerce SDK sends it automatically). Informational: it is recorded on the channel and never changes the response.

curl -X GET "https://api.brainerce.com/api/vc/string/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.

POST
/vc/{connectionId}/customization-upload
X-Sales-Channel-Origin<token>

For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.

In: header

Path Parameters

connectionIdstring

Sales channel ID (vc_*), the canonical salesChannelId. connectionId is the deprecated name of the same value and is still the literal path segment.

Query Parameters

fieldKey?string

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

originstring

Origin of the storefront page making the call, for example https://shop.example.com. Required: a request with no Origin header is refused with 403. On a LIVE channel its host must equal the channel's registered domain (or one of its subdomains) or match an allowed origin. A TEST channel with no domain accepts any origin; once a domain is set it is matched as on LIVE.

X-SDK-Version?string

Version of the calling SDK (the Brainerce SDK sends it automatically). Informational: it is recorded on the channel and never changes the response.

filestring

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.

GET
/v1/metafield-definitions
AuthorizationBearer <token>

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.

POST
/v1/metafield-definitions
AuthorizationBearer <token>

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

Idempotency-Key?string

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 Conflict with code: "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 GET returns 400 with code: "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.

See /docs/api/idempotency.

Lengthlength <= 255
namestring

Display name of the field.

Length1 <= length <= 100
keystring

Unique 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.

Match^[a-z][a-z0-9_]*$
Length1 <= length <= 64
description?string

Description of the field.

Lengthlength <= 500
type?string

Value 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.

Default"TEXT"
Value in"TEXT" | "TEXTAREA" | "NUMBER" | "BOOLEAN" | "DATE" | "DATETIME" | "JSON" | "URL" | "COLOR" | "DIMENSION" | "WEIGHT" | "IMAGE" | "GALLERY" | "SELECT" | "MULTI_SELECT"
required?boolean

Whether a value is required. Defaults to false.

Defaultfalse
isCustomerInput?boolean

Show the field on the storefront as an input the customer fills in (for example engraving text). Defaults to false.

Defaultfalse
keepOriginalImage?boolean

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.

Defaultfalse
minLength?integer

Minimum text length for TEXT and TEXTAREA values.

maxLength?integer

Maximum text length for TEXT and TEXTAREA values.

minValue?number

Minimum allowed value for NUMBER fields.

maxValue?number

Maximum allowed value for NUMBER fields.

dateAvailability?DateAvailabilityConstraintsDto

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.

enumValues?array<string | object>

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 }.

defaultValue?string

Default value, as a string in the same format as a stored value.

position?integer

Sort position of the field. Lower values come first.

Default0
productIds?array<string>

Products the customer-input field is limited to. Only valid when isCustomerInput is true. IDs must be unique and belong to the store.

appliesToAllProducts?boolean

Show the customer-input field on every product of the store. Only valid when isCustomerInput is true. Defaults to false.

Defaultfalse
filterable?boolean

Expose the field as a storefront filter. Only valid for SELECT, MULTI_SELECT and BOOLEAN fields. Defaults to false.

Defaultfalse
publishedOn?array<string>

Legacy 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.

platformMetadata?object

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.

source?string

Origin of the definition. Defaults to LOCAL.

Default"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.

GET
/v1/metafield-definitions/{id}
AuthorizationBearer <token>

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

idstring

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.

PATCH
/v1/metafield-definitions/{id}
AuthorizationBearer <token>

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

idstring

Metafield Definition ID

Header Parameters

Idempotency-Key?string

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 Conflict with code: "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 GET returns 400 with code: "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.

See /docs/api/idempotency.

Lengthlength <= 255
name?string

New display name of the field.

Lengthlength <= 100
description?string

New description of the field.

Lengthlength <= 500
type?string

Value type of the field. One of TEXT, TEXTAREA, NUMBER, BOOLEAN, DATE, DATETIME, JSON, URL, COLOR, DIMENSION, WEIGHT, IMAGE, GALLERY, SELECT, MULTI_SELECT.

Value in"TEXT" | "TEXTAREA" | "NUMBER" | "BOOLEAN" | "DATE" | "DATETIME" | "JSON" | "URL" | "COLOR" | "DIMENSION" | "WEIGHT" | "IMAGE" | "GALLERY" | "SELECT" | "MULTI_SELECT"
required?boolean

Whether a value is required.

isCustomerInput?boolean

Show the field on the storefront as an input the customer fills in (for example engraving text).

keepOriginalImage?boolean

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.

minLength?integer | null

Minimum text length for TEXT and TEXTAREA values. Pass null to remove the limit.

maxLength?integer | null

Maximum text length for TEXT and TEXTAREA values. Pass null to remove the limit.

minValue?number | null

Minimum allowed value for NUMBER fields. Pass null to remove the limit.

maxValue?number | null

Maximum allowed value for NUMBER fields. Pass null to remove the limit.

dateAvailability?DateAvailabilityConstraintsDto

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.

enumValues?array<string | object> | null

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.

defaultValue?string | null

Default value, as a string in the same format as a stored value. Pass null to clear.

isActive?boolean

Whether the field is active. New values for an inactive field are rejected.

appliesToAllProducts?boolean

Show the customer-input field on every product of the store. Only valid when isCustomerInput is true.

filterable?boolean

Expose the field as a storefront filter. Only valid for SELECT, MULTI_SELECT and BOOLEAN fields.

position?integer

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.

DELETE
/v1/metafield-definitions/{id}
AuthorizationBearer <token>

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

idstring

Metafield Definition ID

Header Parameters

Idempotency-Key?string

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 Conflict with code: "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 GET returns 400 with code: "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.

See /docs/api/idempotency.

Lengthlength <= 255
curl -X DELETE "https://api.brainerce.com/api/v1/metafield-definitions/string" \  -H "Idempotency-Key: string"
Empty

{
  "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.

PUT
/v1/metafield-definitions/{id}/platforms
AuthorizationBearer <token>

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

idstring

Metafield Definition ID

Header Parameters

Idempotency-Key?string

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 Conflict with code: "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 GET returns 400 with code: "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.

See /docs/api/idempotency.

Lengthlength <= 255
publishedOnarray<string>

Platform 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.

platformMetadata?object | null

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.

GET
/v1/products/{productId}/metafields
AuthorizationBearer <token>

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

productIdstring

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.

PUT
/v1/products/{productId}/metafields/{definitionId}
AuthorizationBearer <token>

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

productIdstring

Product ID

definitionIdstring

Metafield Definition ID

Header Parameters

Idempotency-Key?string

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 Conflict with code: "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 GET returns 400 with code: "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.

See /docs/api/idempotency.

Lengthlength <= 255
valuestring

Value 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.

variantId?string

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.

DELETE
/v1/products/{productId}/metafields/{definitionId}
AuthorizationBearer <token>

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

productIdstring

Product ID

definitionIdstring

Metafield Definition ID

Query Parameters

variantId?string

Delete the value stored for this variant. Without it the product-level value is deleted.

Header Parameters

Idempotency-Key?string

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 Conflict with code: "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 GET returns 400 with code: "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.

See /docs/api/idempotency.

Lengthlength <= 255
curl -X DELETE "https://api.brainerce.com/api/v1/products/string/metafields/string?variantId=string" \  -H "Idempotency-Key: string"
Empty

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