GET/api/v1/variants/{variantId}mg:read
Get one variant, compact, with only the detail asked for
Reads one variant by id: name, code, product, brand, category, image and page. Name canonical attribute or block ids in `attributes` and `blocks` (comma-separated) to add their values under `specifications`; `null` means unknown, never false or zero. Selectors the variant's product type lacks come back in `notApplicable`. Variant ids are opaque tokens: pass back exactly what a `list_variants` or `find_variants_by_vector` result gave you. One indexed statement reads the Resolved Variant with Brand and product joined by key. Ineligible and untyped variants still open by id; a superseded id returns its final surviving variant. The response includes eligibility, channels, the stored palette and selected attributes with their Value Source and exact wording. Success responses carry `Cache-Control: no-store`. Requires the `mg:read` bearer scope.
Parameters
variantId | string | path | The variant id to resolve. |
attributes | string | query | Comma-separated canonical attribute ids to return under `specifications`, e.g. `nrc_rating`. Absent: none. |
blocks | string | query | Comma-separated canonical block ids to return whole, e.g. `acoustic`. Absent: none. |
ifc | boolean | query | `true` adds `ifc`: the IFC 4.3 Pset_ManufacturerTypeInformation properties and classification references. |
Response
200The compact variant, with `specifications` and `notApplicable` present only when detail was asked for.
categoryobject| null
The first original source category, or null when unknown.
categoriesobject[]
All original source categories in source order.
productTypeobject| null
The accepted primary specification type, or null for a color sample or unresolved subject.
sampleSubjectenum
materialpaint_color_sampleunknownconflict
colorOptionValueIdstring| null
hasDeclaredColorboolean
True for a paint color card, paint line, primer or coating: the card is the brand's declared hex, never a photo.
codestring| null
The brand's item code.
hexstring| null
The settled card color hex, or null when unknown. Paint cards show this color and never a photo.
imageobject| null
The settled material card image. Always null for paint color samples and paint/coating product types.
brandobject
The brand. `id` is the slug get_brand takes.
namestring
The variant's own name.
urlstring| null
The brand's page for it, or null when none is known.
eligibleboolean
Whether lists may include this variant. Reads by id include ineligible variants.
paletteobject[]
The stored material palette, including how each band was obtained.
methodenum
statedisolatedcrop
attributesobject
Selected settled attributes with their Value Source and exact source wording.
materialBankIdstring
The variant's Material Bank SKU. Absent: none recorded.
notApplicableobject
Requested blocks or attributes this product type does not carry.
ifcobject
IFC 4.3: Pset_ManufacturerTypeInformation and IfcClassificationReference values. Absent properties are unknown.
classificationReferencesobject[]
Example
curl 'https://beta.materialgraph.com/api/v1/variants/{variantId}' \ -H "Authorization: Bearer $MG_API_KEY"
GET/api/v1/variants/{variantId}/assetsmg:read
List a variant's images and files
Returns one bounded, filtered, cursor-paged page of a variant's images and files: images first (primary image leading), then documents, then other files. `imageRoles` narrows only images and `documentTypes` narrows only documents, so each implies its own kind; asking for both, or pairing one with other kinds, is a 400 rather than a silently widened page. Raw PIM URLs and internal storage/provider metadata are excluded. A variant's assets change when an ingest lands, so success responses carry `Cache-Control: no-store`. Requires the `mg:read` bearer scope.
Parameters
variantId | string | path | The variant id to resolve. |
kinds | string | query | Comma-separated asset kinds to return; omit for every kind. One of: image, document, cad, bim, model_3d, texture, archive, other, unknown. |
imageRoles | string | query | Comma-separated image roles (what an image shows); implies kinds=image. One of: product, swatch, detail, scene, technical, color_chart, sample_collection, other, unknown. |
documentTypes | string | query | Comma-separated document purposes, any match; implies kinds=document. One of: technical_data_sheet, product_sheet, technical_bulletin, sustainability_report, specification, installation_guide, care_maintenance_guide, operation_manual, warranty, parts_list, technical_drawing, test_report, certificate, declaration_of_performance, environmental_product_declaration, health_product_declaration, ingredient_disclosure, safety_data_sheet, brochure, catalogue, color_finish_chart, other, unknown. |
limit | integer | query | Items per page, 1..50. |
cursor | string | query | pageInfo.nextCursor from the previous page, with the same variantId and filters. |
Response
200One page of the variant's assets.
documentCoverageenum
Brand document list state. Absent when documents are filtered out.
availablenone_declarednot_ingestedunavailable_sourcedead_linkfailed_ingest
itemsobject[]
appliesTo"product"
Only 'product': a product-wide document. Absent: this variant's own.
availabilityenum
available: MaterialGraph serves url. unknown: brand's link, unchecked.
availableunknownunavailable
byteSizeinteger
Not on images; absent when unknown.
documentTypesenum[]
Documents only; absent when unknown.
technical_data_sheetproduct_sheettechnical_bulletinsustainability_reportspecificationinstallation_guide+17 more
heightinteger
Images only; absent when unknown.
imageRoleenum
Images only; absent when unknown.
productswatchdetailscenetechnicalcolor_chart+3 more
kindenum
imagedocumentcadbimmodel_3dtexture+3 more
namestring
Not on images; absent when unknown.
presentationenum
Images only; absent when unknown.
edge_to_edgepackshotcutout_marginmontageunknown
urlstring
Absent when availability is unavailable.
widthinteger
Images only; absent when unknown.
primaryAssetIdstring
The variant's primary image. Absent when it has none.
Example
curl 'https://beta.materialgraph.com/api/v1/variants/{variantId}/assets' \ -H "Authorization: Bearer $MG_API_KEY"
GET/api/v1/variantsmg:read
List variants by hard filter, ranked and cursor-paged
Eligible variants, hard-filtered by `filters`, ranked by `optionalFilters` and `orderBy`, cursor-paged. This is the successor to the retired `catalog_by_spec`/`search_browse`/materials-batch/siblings surface: a hard specification across every brand, a category or brand browse, a product's other colorways and a batch lookup by id are all a kind-grouped `filters` object now — `{terms, numbers, presence, anyField}`, every condition across all four ANDed (OR within one field is `in`). `filters`, `optionalFilters`, `orderBy` and `colors` are URL-encoded JSON; `attributes`, `include` and `words` are comma-separated lists; `limit`, `cursor` and `name` are plain values. `optionalFilters` RANK only — they never exclude, and each entry's `weight` (1–10, required) sums into `preference.score` on a matched item. Responses carry `Cache-Control: no-store`. Requires the `mg:read` bearer scope.
Parameters
filters | string | query | URL-encoded JSON `{terms, numbers, presence, anyField}` — every condition across all four arrays (at most 20 in total) MUST match (AND); OR within one field is `in`. `terms` items are `{field, op, values}` (`in`/`all`/`not_in`); on an `in` or `all` over a term attribute, `orText` (1–100 characters) also meets the condition when that phrase appears in the variant's text, and on a `not_in`, `unstated: "pass"` lets through variants that do not state the attribute at all. `numbers` items are `{field, op, value}` (`eq`/`gt`/`gte`/`lt`/`lte`, in the attribute's own canonical unit); `presence` items are `{field, op}` (`exists`/`missing`); `anyField` items are `{fields, op, values}` (`in`/`not_in`, 2–8 term attributes) for one concept stored under several of them, and take `orText` and `unstated` too. `field` is an attribute id, or one of the reserved fields `variant`, `product`, `brand`, `category`, `product_type`, `lifecycle`, `certification_programme`. |
name | string | query | Find variants by name (MG-2222): every word must start a word of the product or variant name. Combines with `filters` (brand, category, and the rest) as an additional AND condition. Ambiguous matches are all returned rather than guessed between. |
optionalFilters | string | query | URL-encoded JSON, the same `{terms, numbers, presence, anyField}` shape as `filters` (with `orText` but not `unstated`), each item also carrying a required `weight` (1–10). Ranks matched items by summed weight; never excludes a non-matching one. |
orderBy | string | query | URL-encoded JSON array of `{field, direction: "asc" | "desc"}`, `field` a numeric attribute id. |
colors | string | query | URL-encoded JSON array of up to four measured-color regions, each `{hex, op: "in" | "not_in", intent?: "required" | "preferred", range: {lightness: [min, max], chroma: [min, max], hue: [start, end] | null}}`. `hex` is `#rrggbb`, the color's own point in the region; lightness and chroma bounds are 0..1; hue is an arc in degrees that wraps when its start is past its end, null for any hue. `in` keeps variants with a large swatch inside the region; `not_in` leaves those out and lets a variant with no measured color pass; `preferred` only orders and never narrows. |
words | string | query | Comma-separated words each variant must name in its text, applied inside the filters. |
attributes | string | query | Comma-separated attribute ids to project under each item's `specifications`, up to 20. |
include | string | query | Comma-separated item fields to add: `image`, `url`. Absent by default — the item is compact on purpose, since a page repeats it up to 50 times. |
searchCatalogueSubset | enum | query | Narrows the page and the cursor to one search catalogue subset, the same vocabulary search and brands take. `materialBankOrderable` keeps variants carrying a Material Bank id. Absent or `all` is every eligible variant. |
collapse | enum | query | `product` pages products rather than variants: each row is the product's lead colorway by the page's own order, and `variantCount` says how many colorways stand behind it. `colorway` pages colorways: a color sold on several substrates is one row. Absent: one row per variant. |
limit | integer | query | Items per page, 1..50. Defaults to 10. |
cursor | string | query | Opaque continuation from the previous page's `pageInfo.endCursor`, bound to the same `filters`/`optionalFilters`/`orderBy`/`searchCatalogueSubset`/`collapse`. A cursor from other criteria is a 400 (`INVALID_CURSOR`). |
Response
200One page of matching variants, with `unresolvedVariantIds` present only when the root `filters` named explicit `variant in` ids that name no variant, `unavailableVariantIds` only when some named a catalogue variant this list cannot show (retired, not orderable, or outside `searchCatalogueSubset`), and `excludedBySearchCatalogueSubset` only when some named a real variant outside the materials catalogue.
excludedBySearchCatalogueSubsetstring[]
Filtered variant ids outside the materials catalogue.
itemsobject[]
categoryobject| null
The first original source category, or null when unknown.
categoriesobject[]
All original source categories in source order.
productTypeobject| null
The accepted primary specification type, or null for a color sample or unresolved subject.
sampleSubjectenum
materialpaint_color_sampleunknownconflict
colorOptionValueIdstring| null
hasDeclaredColorboolean
True for a paint color card, paint line, primer or coating: the card is the brand's declared hex, never a photo.
codestring| null
The brand's item code.
hexstring| null
The settled card color hex, or null when unknown. Paint cards show this color and never a photo.
imageobject| null
The settled material card image. Always null for paint color samples and paint/coating product types.
brandobject
The brand. `id` is the slug get_brand takes.
namestring
The variant's own name.
urlstring| null
The brand's page for it, or null when none is known.
materialBankIdstring
The variant's Material Bank SKU. Absent: none recorded.
notApplicableobject
Requested blocks or attributes this product type does not carry.
variantCountinteger
Eligible variants of this product. Absent: none counted.
nameWordsobject[]
Empty name lookup: each word, and whether a name in scope starts it. Unmatched words were left out unless all or none matched.
preferenceMatchesRemainboolean
False: nothing from this page on meets any optionalFilter.
unavailableVariantIdsstring[]
Filtered ids in the catalogue this list can't show, e.g. retired.
unresolvedVariantIdsstring[]
unstatedstring[]
Filtered attributes no variant in scope states at all.
wordsobject[]
Each word asked for, and whether any variant in scope names it.
Example
curl 'https://beta.materialgraph.com/api/v1/variants' \ -H "Authorization: Bearer $MG_API_KEY"
POST/api/v1/variants/facetsmg:read
Count variants per attribute value under a filter tree
Contextual facet values and exact variant counts over the eligible variants `filters` admits: the options a filter UI shows next to a `list_variants` page. `filters` is the same kind-grouped `{terms, numbers, presence, anyField}` tree `list_variants` takes, less its `orText` and `unstated` additions, validated by the same code. `attributeIds` names 1–10 facetable attributes (see `list_attributes`). A categorical or boolean facet returns its top `valuesPerFacet` values (default 10) with `hasMoreValues`; a numeric facet returns its observed `min`/`max`. `missingVariantCount` counts variants recording no value: unknown, never false or zero. Requires the `mg:read` bearer scope.
Request body
attributeIdsstring[]
1-10 facetable attribute ids or brand.
searchCatalogueSubsetenum
Count only this scope.
allsamplizeCataloguematerialBankOrderablematerialBankNaOrderablematerialBankNaAndCataloguematerialBankEuOrderable+1 more
filtersobject
AND conditions. field: attribute id, variant, product, brand, category, product_type, lifecycle.
anyFieldobject[]
One of values in any of fields (term attributes).
valuesPerFacetinteger
Top values per categorical/boolean facet. Default 10.
Response
200`matchedVariantCount` eligible variants under `filters`, and one facet per requested attribute, in request order.
matchedVariantCountinteger
facetsvariant[]
kind: categoricalobject
missingVariantCountinteger
kind: booleanobject
missingVariantCountinteger
kind: numericobject
missingVariantCountinteger
Example
curl -X POST 'https://beta.materialgraph.com/api/v1/variants/facets' \ -H "Authorization: Bearer $MG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "attributeIds": [ "…" ]}'
POST/api/v1/variants/searchmg:read
Find variants from plain words
Reads `query` into filters, runs them through `list_variants` and answers with what was understood beside a page of variants. `understood` says what each phrase became: a hard `filter`, a ranking `preference`, or `not_applied` when nothing could serve it. `filters`, `optionalFilters` and `name` are exactly what ran, so the three can be sent to `list_variants` to narrow or widen the same search. A phrase with more than one meaning is answered with one and listed in `choices`: send its `handle` with an alternative's `group` and `id` in `selections` to switch it. `unresolved` lists words nothing in the vocabulary could read. A query that applies nothing returns no items, never the whole catalogue; a preference alone still ranks it. `cursor` is the previous page's `pageInfo.endCursor`, tied to the vocabulary version the query was read against; it pages this operation only, not `list_variants`. Requires the `mg:read` bearer scope.
Request body
attributesstring[]
Attribute/block ids to add; id fields always return.
limitinteger
5-10 for examples.
querystring
What to find, in plain words.
selectionsobject[]
Switch a choice: handle, alternative group and id.
searchCatalogueSubsetenum
Only this corpus scope. Absent or all: every variant.
allsamplizeCataloguematerialBankOrderablematerialBankNaOrderablematerialBankNaAndCataloguematerialBankEuOrderable+1 more
Response
200One page of variants with the query interpretation beside it: `understood` always, and `filters`, `optionalFilters`, `name`, `choices` and `unresolved` when the query produced them.
excludedBySearchCatalogueSubsetstring[]
Filtered variant ids outside the materials catalogue.
itemsobject[]
categoryobject| null
The first original source category, or null when unknown.
categoriesobject[]
All original source categories in source order.
productTypeobject| null
The accepted primary specification type, or null for a color sample or unresolved subject.
sampleSubjectenum
materialpaint_color_sampleunknownconflict
colorOptionValueIdstring| null
hasDeclaredColorboolean
True for a paint color card, paint line, primer or coating: the card is the brand's declared hex, never a photo.
codestring| null
The brand's item code.
hexstring| null
The settled card color hex, or null when unknown. Paint cards show this color and never a photo.
imageobject| null
The settled material card image. Always null for paint color samples and paint/coating product types.
brandobject
The brand. `id` is the slug get_brand takes.
namestring
The variant's own name.
urlstring| null
The brand's page for it, or null when none is known.
materialBankIdstring
The variant's Material Bank SKU. Absent: none recorded.
notApplicableobject
Requested blocks or attributes this product type does not carry.
variantCountinteger
Eligible variants of this product. Absent: none counted.
nameWordsobject[]
Empty name lookup: each word, and whether a name in scope starts it. Unmatched words were left out unless all or none matched.
preferenceMatchesRemainboolean
False: nothing from this page on meets any optionalFilter.
unavailableVariantIdsstring[]
Filtered ids in the catalogue this list can't show, e.g. retired.
unresolvedVariantIdsstring[]
unstatedstring[]
Filtered attributes no variant in scope states at all.
wordsobject[]
Each word asked for, and whether any variant in scope names it.
colorsobject[]
The color regions that ran.
hexstring
The color's own point in the region; it orders matches.
intentenum
requiredpreferred
filtersobject
The filters that ran, the scope among them.
anyFieldobject[]
One of values in any of fields (term attributes).
namestring
The paint name looked up.
oneRowPerenum
A row per product, per variant, or per exact paint variant followed by other products.
productvariantpaint_variant_or_product
optionalFiltersobject
The preferences that ran.
outcomeenum
How the search ended.
pagepartial_matchno_matchnothing_understoodout_of_scopebrand_not_in_catalogue
scopeobject
The fixed scope, repeated in filters.
anyFieldobject[]
One of values in any of fields (term attributes).
understoodobject[]
appliedenum
filter narrows; preference only ranks; not_applied did neither.
filterpreferencenot_applied
idstring
The parser's condition id.
kindenum
categorybrandtermnumbercolorpaint+1 more
labelstring
What the words were read as.
textstring
The query words it came from.
Example
curl -X POST 'https://beta.materialgraph.com/api/v1/variants/search' \ -H "Authorization: Bearer $MG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "…"}'
GET/api/v1/variants/by-colormg:read
Find variants by color — contains, palette or rerank
Flat query encoding: zero-based `color0` through `color5`, each with optional `.share`, `.shareMax`, `.dominant` and `.role` fields, e.g. `color0=%23aabbcc&color0.share=0.6`. Lists use repeated query keys; image fields are `imageAssetId`, `imageSourceId`, `imageUrl`, `imageVariantId`. The canonical color-discovery operation, one required `mode`: `contains` (variants holding a swatch for every REQUIRED `colors[]` condition, ordered by preferred conditions held then ColorVec cosine), `palette` (variants whose FULL palette resembles `colors[]`'s target shares, an image's extracted palette, or `targetVariantId`'s own palette, ordered by ColorVec cosine) or `rerank` (reorder a caller-held `variantIds` set by color closeness to `colors[0]` or `targetVariantId`). A color that fails to resolve is reported in `unresolvedColors` with actionable alternatives, never guessed. CONTAINS/PALETTE candidates are gated through `list_variants`' own eligibility and hard filters first. The page is a cursor over that gated, ranked pool, bound to the exact request that minted it — a cursor from different criteria is refused. Requires the `mg:read` bearer scope.
Parameters
color0 | string | query | |
color0.share | number | query | |
color0.shareMax | number | query | |
color0.dominant | enum | query | |
color0.role | enum | query | Default required. |
color1 | string | query | |
color1.share | number | query | |
color1.shareMax | number | query | |
color1.dominant | enum | query | |
color1.role | enum | query | Default required. |
color2 | string | query | |
color2.share | number | query | |
color2.shareMax | number | query | |
color2.dominant | enum | query | |
color2.role | enum | query | Default required. |
color3 | string | query | |
color3.share | number | query | |
color3.shareMax | number | query | |
color3.dominant | enum | query | |
color3.role | enum | query | Default required. |
color4 | string | query | |
color4.share | number | query | |
color4.shareMax | number | query | |
color4.dominant | enum | query | |
color4.role | enum | query | Default required. |
color5 | string | query | |
color5.share | number | query | |
color5.shareMax | number | query | |
color5.dominant | enum | query | |
color5.role | enum | query | Default required. |
brands | string[] | query | |
categoryIds | string[] | query | |
searchCatalogueSubset | enum | query | Only this corpus scope. |
cursor | string | query | |
imageAssetId | string | query | |
imageSourceId | string | query | |
imageUrl | string | query | |
imageVariantId | string | query | |
limit | number | query | |
mode | enum | query | contains: colors[]. palette: colors[0]/targetVariantId/image. rerank: same + variantIds. |
productTypeIds | string[] | query | |
targetVariantId | string | query | |
variantIds | string[] | query | |
Response
200One page of color matches (`contains`/`palette`) or a reordered candidate set (`rerank`), discriminated by `mode`.
oneOf
mode: containsobject
gatedOutinteger
Candidates dropped by eligibility, hard filters or required colors.
matchesobject[]
categoriesstring[]
All original source category IDs in source order; empty when unknown.
coveragenumber
Share of the request's colors matched to a distinct swatch, 0 to 1. Never a probability.
hasDeclaredColorboolean
True for a paint color card, paint line, primer or coating: the card is the brand's declared hex, never a photo.
productTypeIdstring| null
Accepted primary specification type ID, independent of source categories; null when unknown.
pageInfoobject
poolTruncatedboolean
True when matches exist past the checked pool: add productTypeIds or brands.
resolvedColorsobject[]
catalogueVariantobject| null
kindenum
region: a named meaning's own OKLCh bounds, kept — never collapsed to one hex.
pointregion
sharenumber| null
Image-extracted or stored target-variant swatch share; else null.
mode: paletteobject
gatedOutinteger
Candidates dropped by eligibility, hard filters or required colors.
matchesobject[]
categoriesstring[]
All original source category IDs in source order; empty when unknown.
coveragenumber
Share of the request's colors matched to a distinct swatch, 0 to 1. Never a probability.
hasDeclaredColorboolean
True for a paint color card, paint line, primer or coating: the card is the brand's declared hex, never a photo.
productTypeIdstring| null
Accepted primary specification type ID, independent of source categories; null when unknown.
pageInfoobject
poolTruncatedboolean
True when matches exist past the checked pool: add productTypeIds or brands.
resolvedColorsobject[]
catalogueVariantobject| null
kindenum
region: a named meaning's own OKLCh bounds, kept — never collapsed to one hex.
pointregion
sharenumber| null
Image-extracted or stored target-variant swatch share; else null.
mode: rerankobject
searchCatalogueSubsetobject
The corpus the ranked candidates were drawn from — present ONLY when the request narrowed it. ABSENT means the whole graph. The reference is resolved unscoped either way.
descriptionstring
What the scope admits, in one sentence, for a human reader.
scopeenum
Which corpus to answer from. samplizeCatalogue admits published US paint colors regardless of stock. ABSENT (or 'all') means the WHOLE GRAPH — every material MaterialGraph knows, orderable or not; absence is never a narrower default. Three transaction-oriented scopes gate on governed CHANNEL membership: 'materialBankNaOrderable' (Material Bank North America), 'materialBankEuOrderable' (Material Bank Europe) and 'designShopOrderable' (DesignShop, with the products DesignShop hides from browse excluded). 'materialBankNaAndCatalogue' is the one-query union of Material Bank North America and the governed Catalogue editorial discovery corpus; that union does not by itself claim every member is transactable. 'materialBankOrderable' is NOT one of them: it selects materials carrying a Material Bank identity, which is a provenance signal rather than a channel one, and it admits almost the whole graph — use it to exclude crawl-sourced brands, not to mean orderable. A scope answers membership in its named governed corpus, never suitability: scope on channel, then refine on sector. Every scope is applied INSIDE the query: `limit` fills with eligible rows and `counts` describe the scoped corpus, which post-filtering a page cannot give you. An unknown value is a 400 naming it, never a silent fall back to the whole graph.
allsamplizeCataloguematerialBankOrderablematerialBankNaOrderablematerialBankNaAndCataloguematerialBankEuOrderable+1 more
excludedBySearchCatalogueSubsetstring[]
Real variant ids outside `searchCatalogueSubset` or the materials catalogue.
referenceobject
resolutionenum
resolvedambiguous
matchesobject[]
distancenumber| null
CIEDE2000 difference to the assigned swatch; 0 is identical, null without a palette.
resolvedColorsobject[]
catalogueVariantobject| null
kindenum
region: a named meaning's own OKLCh bounds, kept — never collapsed to one hex.
pointregion
sharenumber| null
Image-extracted or stored target-variant swatch share; else null.
Example
curl 'https://beta.materialgraph.com/api/v1/variants/by-color?mode=text' \ -H "Authorization: Bearer $MG_API_KEY"
POST/api/v1/variants/by-vectormg:read
Find variants by semantic or visual similarity
Eligible variants ranked by similarity in the image-lane embedding space (voyage-multimodal-3.5). `query.mode` is `text` (mood words, unanchored), `image` (`query.images`: one to six references, each a catalogue variant or asset, an external URL, or an upload) or `text_and_image` (each image is embedded fused with the text). Several images are combined into one query vector, the mean of their normalised vectors, normalised again; every seed image's variant is left out of the results, and the vector is never returned. `references` echoes the images used, in order. `filters` is the `{terms, numbers, presence, anyField}` grammar `list_variants` takes, less its `orText` and `unstated` additions; a category, brand or variant-id condition rides Pinecone's native metadata, any other condition builds the eligible set in Postgres first and hands it to Pinecone as an allowlist. Every returned id is re-checked through `list_variants` itself with the caller's filters — what that re-check rejects is counted in `scan.rejected`, never hidden. An upload is embedded once and its vector is kept, so a later image-only query on the same upload reads it and spends nothing; with `text` the image is embedded fused with the words, and a URL is embedded on every request. Each image that has to be embedded consumes one request of the key's own `embed` limit, 10 a minute unless the key has another; a catalogue variant seed or a kept upload vector consumes none. Requires the `mg:read` bearer scope.
Request body
attributesstring[]
Attribute or block ids to add.
excludeVariantIdsstring[]
Variant ids to leave out. A seed image's variant is always left out.
filtersobject
AND conditions. field: attribute id, variant, product, brand, category, product_type, lifecycle.
anyFieldobject[]
One of values in any of fields (term attributes).
queryobject
imagesobject[]
One to 6 image references, each with exactly one field. Several are combined into one query, and every seed image's variant is left out. Only for image modes. Each image that has to be embedded spends one of the embed requests.
modeenum
textimagetext_and_image
textstring
Description, mood words included. Only for text modes.
searchCatalogueSubsetenum
Only this corpus scope. Absent or all: every variant.
allsamplizeCataloguematerialBankOrderablematerialBankNaOrderablematerialBankNaAndCataloguematerialBankEuOrderable+1 more
Response
200Eligible variants, most similar first, with the scan and timing receipts.
excludedBySearchCatalogueSubsetstring[]
Filtered variant ids outside the materials catalogue.
itemsobject[]
categoryobject| null
The first original source category, or null when unknown.
categoriesobject[]
All original source categories in source order.
productTypeobject| null
The accepted primary specification type, or null for a color sample or unresolved subject.
sampleSubjectenum
materialpaint_color_sampleunknownconflict
colorOptionValueIdstring| null
hasDeclaredColorboolean
True for a paint color card, paint line, primer or coating: the card is the brand's declared hex, never a photo.
codestring| null
The brand's item code.
hexstring| null
The settled card color hex, or null when unknown. Paint cards show this color and never a photo.
imageobject| null
The settled material card image. Always null for paint color samples and paint/coating product types.
brandobject
The brand. `id` is the slug get_brand takes.
namestring
The variant's own name.
urlstring| null
The brand's page for it, or null when none is known.
materialBankIdstring| null
notApplicableobject
Requested blocks or attributes this product type does not carry.
variantCountinteger
Eligible variants of this product. Absent: none counted.
similaritynumber
Voyage cosine to the query. Ranks only; not a probability.
modeenum
textimagetext_and_image
namedPaintobject
The paint query.text names exactly, by a brand's paint name or code, when the catalogue holds it; the items are what looks like the words. Absent otherwise.
referencesobject[]
The image references the query used, in order. Empty in text mode.
kindenum
urlassetIdvariantIdsourceId
scanobject
exhaustedboolean
True when no further candidates match; false means more may exist.
routeenum
lanemetadataallowlist
unresolvedVariantIdsstring[]
unstatedstring[]
Filtered attributes no variant in scope states at all.
Example
curl -X POST 'https://beta.materialgraph.com/api/v1/variants/by-vector' \ -H "Authorization: Bearer $MG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": { "mode": "text" }}'
GET/api/v1/variants/sampled-togethermg:read
Find sampled together — what designers sampled together with your seeds
The materials designers sampled together with one or more seeds in real Material Bank projects (a sample order shows sampling, not specification), other brands first, then the most projects. Give `variantIds` and/or `materials` (free-text names, resolved to one variant each; the resolved seeds come back in `seeds`, and any reference that matched nothing in `unresolved`), at most 12 together. Each row carries `lift` (the mean over the seeds it pairs with; above 1 is above average), `seedMatchCount` (how many seeds it pairs with), `relation` (`other_brand` is another brand, `brand_sibling` and `colorway` share a seed's) and a one-line `reason`. Ranking is other brands first, then `seedMatchCount`, then lift weighted by the projects behind it, one row per product. `projectType` reads one sector from the closed project-type vocabulary; an unknown sector is refused by name. A page is lean: `include` adds `image` (`imageUrl`) and `color` (`swatches`, `colorFit`, which annotates and never reorders). Sample cards are left out unless `includeSamplingArtifacts` is true, an ops and audit switch. Requires the `mg:read` bearer scope.
Parameters
include | enum[] | query | Optional row fields: image adds imageUrl, color adds swatches. |
limit | integer | query | |
materials | string[] | query | Names to resolve when you hold no ids. Misses come back unresolved. |
projectType | enum | query | Only materials sampled together in projects of this sector. |
variantIds | string[] | query | Seed variants to read. |
includeSamplingArtifacts | enum | query | |
Response
200The sampled-together materials, other brands first, the resolved seeds, and any references that matched nothing.
excludedBySearchCatalogueSubsetstring[]
Seed ids outside the materials catalogue.
sampledTogetherobject[]
colorFitnumber| null
Palette likeness to the seeds. Never reorders.
liftnumber
Mean lift over the seeds it pairs with; above 1 is above average.
reasonstring
Why it was suggested, in one line.
relationenum
other_brand is another brand; brand_sibling and colorway share the seed's.
other_brandbrand_siblingcolorway
seedMatchCountinteger
How many seeds it was sampled with.
seedsobject[]
resolvedFromstring
The id or name this seed came from.
unresolvedstring[]
References that matched no variant.
Example
curl 'https://beta.materialgraph.com/api/v1/variants/sampled-together' \ -H "Authorization: Bearer $MG_API_KEY"
POST/api/v1/variants/resolvemg:read
Resolve a manufacturer page URL or code to a stored variant
Resolves a manufacturer page URL, or a manufacturer code qualified by that URL or a brandId, to a stored variant, its brand, bounded candidates or a named unresolved reason. Exact and scoreless; the submitted URL is never persisted. The body is the `resolve_variant` tool's own output.
Request body
brandIdstring
Brand id from list_brands; qualifies code when no url.
codestring
The brand's own code for the variant, exactly as the brand shows it.
labelsstring[]
Product names shown on the page, to tell URL candidates apart.
urlstring
The brand's product page URL, query and fragment intact.
Response
200The bounded result: identified, placed, ambiguous or unresolved, with evidence.
oneOf
outcome: identifiedobject
evidenceobject[]
kindenum
brand-urlbrand-homepagebrand-codevisible-label
receiptobject
normalizationStepsstring[]
outcome: placedobject
evidenceobject[]
kindenum
brand-urlbrand-homepagebrand-codevisible-label
receiptobject
normalizationStepsstring[]
outcome: ambiguousobject
evidenceobject[]
kindenum
brand-urlbrand-homepagebrand-codevisible-label
receiptobject
normalizationStepsstring[]
outcome: unresolvedobject
evidenceobject[]
kindenum
brand-urlbrand-homepagebrand-codevisible-label
receiptobject
normalizationStepsstring[]
reasonenum
no-stored-urlno-code-match
Example
curl -X POST 'https://beta.materialgraph.com/api/v1/variants/resolve' \ -H "Authorization: Bearer $MG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "brandId": "…", "code": "…"}'