32 "decision": "Pre-create brands (single: { brand: { name } }; bulk: POST /stores/v3/bulk/brands/create { brands: [{ name }], returnEntity }), crosswalk the server-assigned ids, then assign products by brand.id. Verified live 2026-08-16 including the bulk path, product assignment by id, and DELETE /stores/v3/brands/{id}. Query with POST /stores/v3/brands/query."
33 },
34 "fallbacks": [
35 {
36 "classification": "cms",
37 "when": "Use only for source brand metadata beyond the name (logo, description, archive copy) — the Wix Brand object carries a name only."
38 }
39 ],
40 "reliability": {
41 "status": "reliable",
42 "flags": []
43 },
44 "pitfalls": [
45 {
46 "code": "name-only-object",
47 "severity": "warning",
48 "summary": "The Wix Brand object is {id, name, revision, dates} only; source brand logos and descriptions have no native home and are dropped unless preserved via the CMS fallback. Record the loss in the faithfulness ledger."
49 },
50 {
51 "code": "unique-name-double-create",
52 "severity": "warning",
53 "summary": "VERIFIED LIVE 2026-08-16: brand name is unique — a second create with the same name returns 409 ALREADY_EXISTS (uniqueConstraintViolation on name). Retries and resumed runs must be crosswalk-guarded or query-first; the failure is per-brand for single creates and would fail that item inside a bulk batch."
58 "summary": "RESOLVED 2026-08-16 (live, n=1): passing product.brand = { name } for a brand name that ALREADY EXISTS does not 409 and does not duplicate — the product came back bound to the existing brand's id. So inline-by-name and pre-create can coexist without write failures. Pre-create by id is still the preferred path because it is the only one that gives the crosswalk a deterministic id at write time and it survives name normalisation differences (case/whitespace variants were not probed)."
59 },
60 {
61 "code": "bulk-results-are-per-item",
62 "severity": "warning",
63 "summary": "POST /stores/v3/bulk/brands/create returns results[] with itemMetadata.{id, originalIndex, success} plus bulkActionMetadata.{totalSuccesses, totalFailures, undetailedFailures} — the usual Stores bulk contract. Correlate by originalIndex, never by position, and never infer success from the HTTP 200. returnEntity:true additionally returns the brand object; itemMetadata.id alone is enough for a crosswalk."
64 },
65 {
66 "code": "bulk-batch-duplicate-names",
67 "severity": "warning",
68 "summary": "VERIFIED LIVE 2026-10-27: two items with the same name inside ONE bulk create batch: one item fails ALREADY_EXISTS (with a zero id) and the other succeeds. The reviewed writer createStoresBrand creates one brand per call and reuses an existing brand by exact-name query on 409, so no batch-level dedupe is needed."
69 }
70 ],
71 "mappingGuidance": [
72 "Pre-create brands via POST /stores/v3/bulk/brands/create, record the server-assigned IDs in the crosswalk, then assign products by brand.id — never by brand.name — so the crosswalk stays deterministic.",
73 "If a run does use inline product.brand.name, do not also pre-create the same names in the same run: pick one path per run and let the crosswalk adopt the id the product create returns.",
74 "Source brand-archive URLs have no Wix equivalent; record each in the URL-preservation map with a redirect decision (category/search target or drop)."
97 "note": "product.brand: pass name to auto-create, or existing id to assign"
98 },
99 {
100 "type": "live-run",
101 "path": "anonymized-live-verification",
102 "note": "Earlier guidance folded source brand terms into product.brand before the standalone Brands V3 surface was confirmed."
103 },
104 {
105 "type": "live-run",
106 "path": "anonymized-live-verification",
107 "note": "Verified live: brand created via inline product.brand.name (adopted into crosswalk, via=inline-product-create); the preferred bulk pre-create endpoint was NOT exercised in that run"
108 },
109 {
110 "type": "live-run",
111 "path": "anonymized-live-verification",
112 "note": "Verified live: POST /stores/v3/brands → 200 (<anonymized-id>); POST /stores/v3/bulk/brands/create with 2 brands → 200, totalSuccesses 2 with per-item ids; probe product created with brand:{id} → bound correctly; second probe product with brand:{name:<existing>} → bound to the SAME existing brand id (no duplicate, no 409); duplicate single create → 409 ALREADY_EXISTS; brands query by $startsWith read all three back; both products and all three brands deleted, query empty afterwards"
113 }
114 ],
115 "notes": "Brands V3 provides standalone CRUD and bulk create, and the product object references brands by ID or auto-creates them by name. Live verification covered single and bulk pre-create plus product attachment and established that inline by-name attachment binds to an existing brand rather than failing or duplicating it."