Queek docs

Metafields

The store's own typed fields on products and orders, the schema that explains them, and how to filter by one.

A merchant can extend Queek's product and order shapes with fields of their own — fabric, warranty months, a size-chart image, an ERP reference. Two primitives carry them, and they are deliberately different things:

MetafieldsMetadata
WhatTyped, defined fields. The merchant declares custom.fabric is single_line_text once; every value written after that is validated against the definition.Free-form string key/values an integrator writes for its own bookkeeping — an ERP id, a channel reference.
Who reads itThemes, site builders, AI store builders, filters.Only the integrator that wrote it. Queek never interprets or renders it.
On the public APIYes — metafields on every product, keyed namespace.key.No. Metadata is private to the merchant API and to webhooks.
On ordersWritten on the merchant API, read back in webhook payloads.Same.
FilterableYes, exact match.Never.

{} on either means the store has defined or written none.

Reading metafields on a product

Every product a listing or detail call returns carries metafields:

"metafields": {
  "custom.fabric": "cotton",
  "custom.warranty_months": 24,
  "custom.size_chart": "https://cdn.usequeek.com/…/size-chart.jpg"
}

Keys are handles, namespace.key, sorted. Values arrive in the definition's type — a boolean is a JSON boolean, an integer a number, a list.* a JSON array. A media_id field arrives already resolved to an image URL, never as an id, so render it directly.

Free-form metadata is not on this payload. It is an integrator's private bookkeeping and stays on the merchant API.

Reading the schema

A handle alone tells you nothing about what it means, what type it holds or what values are legal. The store's definitions are public exactly because their values already are:

curl https://client.usequeek.com/v1/store/metafield-definitions \
  -H "X-Client-Key: pk_live_your_key_here" \
  -H "Accept: application/json"

data is the list of definitions, ordered by owner_type, namespace, key:

FieldTypeNotes
p_idintegerThe definition's short id.
handlestringnamespace.key — the key you will see on products.
owner_typestringproduct. Only product definitions are public (see below).
namespace, keystringThe two halves of the handle.
typestringOne of the types in the next table.
namestringHuman label. Use it for the field's label.
descriptionstring | nullHelp text. Use it for tooltips; never guess what a handle means.
validationsobjectThe rules values must satisfy — see Validations.
created_at, updated_atISO 8601

The response is not paginated. A store may hold at most 200 definitions across every owner type, so the whole schema always fits in one call.

Order definitions stay private

GET /store/metafield-definitions returns product definitions only. Order metafields are a description of a merchant's back office — ERP ids, wholesale account codes — and no order metafield value is ever public, so neither is its schema. You meet order metafields in webhook payloads and nowhere else on this API.

Types

Nine scalar types, and a list. form of every scalar except json:

TypeValue shapeAlso as a list
single_line_textstringlist.single_line_text
multi_line_textstringlist.multi_line_text
integernumberlist.integer
decimalnumberlist.decimal
booleantrue / falselist.boolean
dateYYYY-MM-DD stringlist.date
urlstringlist.url
jsonany JSON—
media_idan image URL on readlist.media_id — an array of URLs

Validations

validations is honoured per type. A rule the type cannot support is rejected when the definition is created, so a rule you read here always applies.

RuleApplies toMeaning
min, maxnumbersInclusive bounds on the value.
min, maxtextBounds on the character length.
min, maxdateEarliest / latest date, YYYY-MM-DD.
min, maxlist.*Bounds on the list length.
regextextA pattern the value must match.
choicesscalarsThe only values allowed. Render it as a select.

Limits

These are part of the contract, so you can design around them. They are also machine-readable in the OpenAPI document under x-queek-metafields.

LimitValue
Definitions per store (all owner types)200
Metafield values per product or order50
Bytes per serialised value65,536
Metadata keys per resource50
Metadata key length64 characters
Metadata value length500 characters

Filtering products by a metafield

GET /store/products accepts metafield[handle]=value. The category, collection and promotion listings do not take it in v1 — filter the full catalogue and narrow with category_slug instead:

curl "https://client.usequeek.com/v1/store/products?metafield\[custom.fabric\]=cotton&metafield\[custom.fit\]=slim" \
  -H "X-Client-Key: pk_live_your_key_here"

The rules, all of them:

  • Exact match only. No ranges, no IN, no partial or case-insensitive match in v1.
  • Up to 5 handles per request, ANDed. A product must match every one.
  • Scalar types only. json and every list.* type cannot be filtered; asking is a metafield_value_invalid.
  • The value is typed by the definition. metafield[custom.warranty_months]=24 compares as the integer 24; metafield[custom.on_sale]=1, yes and on all compare as true. Text is compared as given.
  • Each value is at most 255 characters.
  • Combine freely with keyword, category_slug, sort, page and per_page.

An undefined handle is refused, not answered with an empty page — an empty list would be indistinguishable from "no product has that value":

{
  "status": "failed",
  "error_code": "metafield_definition_missing",
  "message": "No metafield definition 'custom.colour' exists for product. Create it with POST /api/v1/biz/vendor/metafield-definitions before sending a value.",
  "data": null,
  "error": {
    "code": "metafield_definition_missing",
    "message": "No metafield definition 'custom.colour' exists for product. …",
    "field": "metafield.custom.colour",
    "handle": "custom.colour",
    "owner_type": "product",
    "doc_url": "https://docs.usequeek.com/docs/versioning-and-errors#metafield_definition_missing",
    "request_id": "…"
  }
}

How a merchant defines and writes them

Definitions and values are written on the merchant side, never through this API. The dashboard's own API (/api/v1/biz/vendor/…, vendor-authenticated) is where a merchant or their integration:

  • creates a definition — owner_type, namespace, key, type, name, optional description and validations;
  • writes values on a product or an order as metafields: [{ namespace, key, value }], plus metadata: { … } for free-form bookkeeping. Writes are a partial upsert: an omitted handle keeps its value and "value": null deletes one;
  • reads its own metadata back — a merchant's ERP id round-trips byte for byte.

Once a definition exists its namespace, key, owner_type and type are immutable; only name, description and validations change. Deleting a definition deletes every value written against it.

Order metafields and metadata are written only by the merchant, never by a shopper: a value a visitor could set would be a forged record, not an extension point.

Because a write is validated against the definition, a value that fails its type or its validations is refused with a 422 naming the handle and the rule.

Reserved namespaces

The namespace queek — and any namespace starting queek_ — is reserved for Queek's own first-party fields. A definition there is refused with metafield_namespace_reserved, and a first-party field can never collide with one you already ship. Use a namespace of your own; custom is the conventional one.

Error codes

error.codeStatusWhenExtra keys in error
metafield_definition_missing422A filter names a handle this store has not defined.handle, owner_type, field
metafield_value_invalid422A filter value the definition cannot hold, or a filter on a json / list.* field.handle, owner_type, expected_type, field
metafield_namespace_reserved422A definition was requested in a reserved namespace.namespace

expected_type is the definition's type, so the repair — send a value of that type — is derivable from the response without parsing the message.

In webhooks

Every order webhook payload carries the order's metafields and metadata under data, so a receiver can match the order to its own record without a second call. A change to an order's metafields on the merchant API emits orders/updated on its own — see Webhooks.

On this page