Taxonomy & IDs
BrandsGateway accepts integer term IDs, never names or slugs. You can let the portal resolve your vocabulary for you, or hold the lookup tables yourself — this page is the second option.
values block
and the portal maps them to IDs for you — on
POST /api/v1/validate and on the product write alike. Read
on only if you want to hold the lookup tables yourself, for offline
mapping or because your feed needs rules ours do not cover.
The reference sets
Brands
product_brand Fetch & cacheThe designer or label. One brand per product. Brands are curated by BrandsGateway — a brand that is not on the platform cannot be created from a feed.
Categories
product_cat Fetch & cacheThe shop's browsable category tree. A product usually carries both a parent and a leaf category (e.g. Women 19 and Knitwear 26).
Product groups
product_group Fetch & cacheThe merchandising hierarchy that drives filtering, size axes and harmonised codes. Send the full ancestor chain, leaf last — e.g. Clothing 71651, Sweaters 71673, Sweatshirts 71675.
Genders
product_gender Fixed setExactly three terms. Fixed platform-wide.
| ID | Name | Slug | Note |
|---|---|---|---|
| 71575 | Men | men | — |
| 71576 | Women | women | — |
| 71577 | Unisex | unisex | — |
Conditions
product_condition Fixed setStock condition. Drives whether returns are accepted, so it is never inferred — it must be sent.
| ID | Name | Slug | Note |
|---|---|---|---|
| 71354 | New with tags | new-with-tags | The default for new-season stock. |
Attributes (colour & size)
pa_* Fixed setColour is attribute 14 and is never a variation axis. Size attributes are per sizing system; pick the one that matches how your feed expresses sizes and send its term slugs in variation attributes.
| ID | Name | Slug | Note |
|---|---|---|---|
| 14 | Colour | pa_color | Always sent with variation: false. |
| 10 | Italian Size WOMEN | pa_italian-size-women | variation: true |
| 11 | Italian Size MEN | pa_italian-size-men | variation: true |
| 25 | Shoe Size EU | pa_shoe-size-eu | variation: true |
Seeing what we accept
The values BrandsGateway accepts for a field come back from the
validator, in the payload you are already sending. Put your own words in
a values block and POST it to
/api/v1/validate: anything that maps is resolved silently,
and anything that does not is listed in unresolved — with
the closest accepted values, how many values that field has, and a few
examples of them.
# One call, your own words, no credential needed.
curl -s -X POST https://vendors.brandsgateway.com/api/v1/validate \
-H 'Content-Type: application/json' \
-d '{
"values": { "brand": "Gucci", "gender": "Donna", "color": "Nero" },
"product": { "type": "simple", "name": "Leather Bag" }
}' | jq '.unresolved'
[
{
"field": "gender",
"value": "Donna",
"code": "missing_gender",
"message": "Could not map gender \"Donna\".",
"suggestions": [ { "name": "Women", "confidence": 0.86 } ],
"accepted": { "count": 3, "examples": ["Men", "Women", "Unisex"] }
}
]
GET /api/v1/reference and
GET /api/v1/reference/{set} will serve the full sets for
offline mapping. They are not available yet; the validator above is how
you see accepted values today.
Matching your values
Vendor feeds are inconsistent in ways that break naive equality: casing varies, ampersands arrive HTML-encoded, whitespace doubles up. Normalise both sides before comparing, and never fall back to fuzzy matching in production — a silently wrong brand is worse than a recorded failure.
// Build the map once, then never think about names again.
// Normalise aggressively — vendor feeds are inconsistent about case,
// ampersands and HTML entities.
const normalise = (s) =>
String(s)
.replace(/&/g, "&")
.replace(/�?39;/g, "'")
.replace(/\s+/g, " ")
.trim()
.toLowerCase();
const brandIndex = new Map(
brands.map((b) => [normalise(b.name), b.id])
);
function resolveBrand(vendorBrandName) {
const id = brandIndex.get(normalise(vendorBrandName));
if (!id) {
// Do NOT guess, and do NOT invent an ID. Record it and skip the
// product — an unmapped brand is a mapping task, not a data error.
throw new UnmappedValue("missing_brand", vendorBrandName);
}
return [{ id }];
}
Sizes deserve their own attention
Colour is one attribute (id 14) and is never a variation axis. Sizes are many attributes, one per sizing system — Italian women's, Italian men's, EU shoe sizes, and so on. Choose the attribute that matches how your feed already expresses sizes and use its term slugs directly.
// Sizes are the hardest mapping, because the axis differs by product.
// Pick the attribute that matches how YOUR feed expresses sizes, then use
// that attribute's term slugs — do not translate between sizing systems.
const attribute = { id: 10, slug: "pa_italian-size-women" };
const sizeIndex = new Map(
termsFor(attribute.id).map((t) => [normalise(t.name), t.slug])
);
function variationAttributes(vendorSize) {
const slug = sizeIndex.get(normalise(vendorSize));
if (!slug) throw new UnmappedValue("missing_size_mapping", vendorSize);
return { [attribute.slug]: slug };
}
Product groups vs categories
They look similar and do different jobs, so both are required:
- Categories are the shop's browsable navigation — what a customer clicks through.
- Groups are the merchandising hierarchy. They drive filtering, determine which size axis a product has, and carry the harmonised-code prefix used for customs paperwork.
Send the full ancestor chain of groups with the leaf last. A product in Sweatshirts sends Clothing, Sweaters and Sweatshirts — sending only the leaf loses filtering, and sending only the container leaves the product with no size axis.
Countries of origin
meta_data._bgorigincountry takes an ISO-3166-1 alpha-2 code.
Any valid code is accepted; these are the ones that appear most often in
vendor feeds.
IT
Italy
CN
China
PT
Portugal
RO
Romania
TR
Turkey
ES
Spain
FR
France
BG
Bulgaria
TN
Tunisia
IN
India
VN
Vietnam
RS
Serbia
EU, * or
Made in Italy fail as
missing_country. Resolve
them to a real country code in your own mapping layer.