34 "summary": "A site supports a MAXIMUM OF ONE gift card product (documented as a temporary limitation; second create → 409 GIFT_CARD_PRODUCT_ALREADY_EXISTS). A source shop with several gift-card products (different designs, different denomination sets, seasonal variants) CANNOT be migrated one-to-one: collapse them into a single product whose presetVariants union the denominations, and ledger the lost designs/descriptions as fidelity_loss. Check for an existing product before creating — on a non-empty destination the create will fail rather than merge."
35 },
36 {
37 "code": "products-vs-issued-cards",
38 "severity": "warning",
39 "summary": "A gift card product is the purchasable definition (name, denominations, image); issued cards and balances are gift-cards/gift-card. Import both or buyers get a catalog item while existing card holders lose balances — plan them together."
40 },
41 {
42 "code": "denominations-are-presetVariants",
43 "severity": "blocker",
44 "summary": "The denomination field is presetVariants[], NOT 'variants' or 'denominations'. VERIFIED LIVE 2026-08-16: a body using variants[] fails the whole call with 428 CANNOT_CREATE_GIFT_CARD_PRODUCT_WITHOUT_VARIANTS — an error that reads like a missing-data problem but is actually a wrong-field-name problem. Each preset variant carries price (what the buyer pays) and value (the balance loaded), which are allowed to differ for promotional pricing; a customVariant { minValue, maxValue } can coexist with presets for buyer-chosen amounts. At least one preset or a customVariant is required."
49 "summary": "The product image is OPTIONAL (verified live 2026-08-16: create succeeds with no image at all — the earlier 'must already exist' framing overstated it), but when supplied it must be a Wix Media Manager image and needs at least id, width, and height; there is no external-URL import on this surface, unlike stores/promotion. Import source card designs through media/media-file first."
50 },
51 {
52 "code": "expiration-is-a-one-of",
53 "severity": "info",
54 "summary": "expirationType is NONE | FIXED | RELATIVE, paired with a one-of: fixedExpirationDate (a date-time, rejected if in the past — 428 CANNOT_CREATE_GIFT_CARD_PRODUCT_WITH_PAST_EXPIRATION_DATE) or relativeExpirationDate { value, period DAYS|WEEKS|MONTHS|YEARS }. A source policy of 'expires N months after purchase' maps to RELATIVE; a source shop's already-lapsed fixed expiry cannot be recreated and must be ledgered."
55 },
56 {
57 "code": "app-install-seeds-a-product",
58 "severity": "blocker",
59 "summary": "VERIFIED LIVE 2026-10-27: installing the Wix Gift Cards app creates a default product (\"eGift Card\", Wix description and image, presets 25/50/100/150/200) a few seconds after install; a query right after install still returns []. A create then fails 409 GIFT_CARD_PRODUCT_ALREADY_EXISTS. ensureGiftCardProduct queries first, re-queries after that 409, and updates the one product to the source values (PATCH with its revision; presetVariants are replaced whole and kept when omitted, so a source with only a custom range sends presetVariants: [] (verified live: accepted with a customVariant); fields the source lacks, such as description or image, keep the Wix values). The replaced values are returned as `previous` for the journal."
60 }
61 ],
62 "mappingGuidance": [
63 "Map source gift-card product definitions (e.g. PW/YITH WooCommerce gift card products: title, amounts, design image) to name (max 55 chars), description (max 3000), presetVariants[] (max 200) and/or customVariant, and image.",
64 "Because only one gift card product can exist per site, resolve the source's several products into one BEFORE the write: union the denominations into presetVariants[], derive a customVariant range from any 'choose your own amount' source option, and record every collapsed product in the migration ledger.",
65 "Import media first, then the gift card product, then issued cards (gift-cards/gift-card) so references resolve in one pass.",
66 "Write the product with ensureGiftCardProduct, never a bare create. It returns created | adopted | updated-existing-product (with `previous`) | failed and is safe to re-run after an unknown outcome."
84 "note": "Source verification established that gift-card balances are database-only while product definitions are REST-visible."
85 },
86 {
87 "type": "live-run",
88 "path": "anonymized-live-verification",
89 "note": "Verified live: POST /gift-cards/v1/gift-card-products with { name, description, expirationType: NONE, presetVariants: [{ price 25 / value 25 }, { price 45 / value 50 }], customVariant: { minValue 10, maxValue 500 } } → 200 with server-assigned product id and per-preset-variant ids; GET readback preserved every amount and populated formattedAmount/convertedAmount in the site currency (ILS). A first attempt using variants[] instead of presetVariants[] failed with 428 CANNOT_CREATE_GIFT_CARD_PRODUCT_WITHOUT_VARIANTS. No image was supplied and the create still succeeded. DELETE /gift-cards/v1/gift-card-products/{id} → 200 at cleanup. Not exercised: image attachment, FIXED/RELATIVE expiration, and the documented one-product-per-site 409 (only one product was ever created)."
90 },
91 {
92 "type": "live-run",
93 "path": "anonymized-live-verification",
94 "note": "Verified live on a disposable site: products query empty right after install, one seeded \"eGift Card\" product 15 s later; create → 409 GIFT_CARD_PRODUCT_ALREADY_EXISTS; PATCH with revision 1 replaced name, presetVariants and customVariant (revision 2) and kept description and image."
95 }
96 ],
97 "notes": "Authored 2026-08-11 from the docs-survey gap (Gift Card Products). Promoted to verified-live 2026-08-16 by a create/readback/delete probe on an anonymized verification environment, which also CORRECTED two docs-era claims: the denomination field is presetVariants[] (a wrong field name surfaces as a misleading 'without variants' 428), and the image is optional rather than required. The one-gift-card-product-per-site cap — the biggest constraint on this migration path — was found in the create-method docs during that probe and is the reason reliability is partially-reliable rather than reliable. Pairs with gift-cards/gift-card for a complete gift-card migration."