Catalog V1 to V3 Conversion Guide

This guide aims to assist developers in migrating from the Stores Catalog V1 API to the V3 API. It outlines key changes in the product object structure and provides detailed conversion tables for various components.

Major Changes

  1. Product to Variant Field Relocation: Several fields have moved from the product level to the variant level, including price and sale price. This change allows for more granular control per variant.
  2. Universal Variants: Every product now has at least one variant. Products without options are treated as 'single variant products'.
  3. Variant Management: The manageVariants field has been removed. All products now have variants:
    1. Products without options are considered single variant products
    2. Products with at least one option (equivalent to managedVariants: true in V1) may have multiple variants
  4. Discount Replacement: The discount field has been replaced by the sale price field at the variant level.
  5. Price Data Changes: priceData and convertedPriceData are no longer available.
  6. Options and Customizations: The new Customizations V3 API manages both options and modifiers:
    1. Customization V3 options type are equivalent to V1 options with managedVariants: true
    2. Customization V3 modifiers type are equivalent to V1 options with managedVariants: false
  7. Custom Text Fields: These have been moved to the Customizations modifier type

Some fields previously accessible via the Catalog V1 Product object are now available through other Catalog V3 APIs. On the other hand, some fields that required separate API calls in V1 are now directly available in the Products V3 API.

Conversion Tables

*Fields marked with an asterisk signify little to no change in semantics or access.

Product Object Conversion

Product V1Product V3Notes
id*id
name*name
slug*slug
visible*visible
productTypeproductTypeEnum values in V3 are in UPPER_CASE
descriptiondescription (recommended) OR plainDescription (if integration with RICOS isn't possible)
skuvariantsInfo.variants[i].skuFor single variant product only. Each variant in V3 can have its own SKU
weightvariantsInfo.variants[i].physicalProperties.weightFor single variant product only. Each variant in V3 can have its own weight
weightRange.minValuephysicalProperties.shippingWeightRange.minValue
weightRange.maxValuephysicalProperties.shippingWeightRange.maxValue
stock.trackInventoryAvailable via Inventory Items APIEach variant in V3 can have its own inventory. Search Inventory Items and filter by productId and/or variantId.
stock.quantityAvailable via Inventory Items APIEach variant in V3 can have its own inventory. Search Inventory Items and filter by productId and/or variantId.
stock.inventoryStatusinventory.availabilityStatus
priceData.currencycurrencyNow a requested field
priceData.pricevariantsInfo.variants[i].price.basePrice.amountSee point (5) in Major Changes section above
priceData.discountedPricevariantsInfo.variants[i].price.salePrice.amountSee point (5) in Major Changes section above
priceData.formatted.pricevariantsInfo.variants[i].price.basePrice.formattedAmountSee point (5) in Major Changes section above
priceData.formatted.discountedPricevariantsInfo.variants[i].price.salePrice.formattedAmountSee point (5) in Major Changes section above
priceData.formatted.pricePerUnitvariantsInfo.variants[i].physicalProperties.pricePerUnit.descriptionSee point (5) in Major Changes section above
priceData.pricePerUnitvariantsInfo.variants[i].physicalProperties.pricePerUnit.valueSee point (5) in Major Changes section above
convertedPriceData.currencycurrencyNow a requested field
convertedPriceData.pricevariantsInfo.variants[i].price.basePrice.amountFor single variant product only. Each variant in V3 can have its own price
convertedPriceData.discountedPricevariantsInfo.variants[i].price.salePrice.amountFor single variant product only. Each variant in V3 can have its own sale price
convertedPriceData.formatted.pricevariantsInfo.variants[i].price.basePrice.formattedAmountFor single variant product only.
convertedPriceData.formatted.discountedPricevariantsInfo.variants[i].price.salePrice.formattedAmountFor single variant product only.
convertedPriceData.formatted.pricePerUnitvariantsInfo.variants[i].physicalProperties.pricePerUnit.descriptionFor single variant product only.
convertedPriceData.pricePerUnitvariantsInfo.variants[i].physicalProperties.pricePerUnit.valueFor single variant product only.
priceRange.minValuebasePriceRange.minValue.amount
priceRange.maxValuebasePriceRange.maxValue.amount
costAndProfitData.itemCostvariantsInfo.variants[i].revenueDetails.cost.amountFor single variant product only.
costAndProfitData.formattedItemCostvariantsInfo.variants[i].revenueDetails.cost.formattedAmountFor single variant product only.
costAndProfitData.profitvariantsInfo.variants[i].revenueDetails.profit.amountFor single variant product only.
costAndProfitData.formattedProfitvariantsInfo.variants[i].revenueDetails.profit.formattedAmountFor single variant product only.
costAndProfitData.profitMarginvariantsInfo.variants[i].revenueDetails.profitMarginFor single variant product only.
costRange.minValuecostRange.minValue.amount
costRange.maxValuecostRange.maxValue.amount
pricePerUnitData.totalQuantityvariantsInfo.variants[i].physicalProperties.pricePerUnit.settings.quantity
pricePerUnitData.totalMeasurementUnitvariantsInfo.variants[i].physicalProperties.pricePerUnit.settings.measurementUnit
pricePerUnitData.baseQuantityphysicalProperties.pricePerUnit.quantity
pricePerUnitData.baseMeasurementUnitphysicalProperties.pricePerUnit.measurementUnit
additionalInfoSections[i].titleinfoSections[i].title
additionalInfoSections[i].descriptioninfoSections[i].description (recommended) OR infoSections[i].plainDescription (if integration with RICOS isn't possible)
media.mainMediamedia.mainSee media table
media.items[i]media.itemsInfo.items[i]
customTextFields[i].titlemodifiers[i].freeTextSettings.titleManage these fields with the Customizations API
customTextFields[i].maxLengthmodifiers[i].freeTextSettings.maxCharCountManage these fields with the Customizations API
customTextFields[i].mandatorymodifiers[i].mandatoryManage these fields with the Customizations API
manageVariants-See point (5) in Major Changes section above
productOptions[i].optionType and manageVariants = trueoptions[i].optionRenderType
productOptions[i].optionType and manageVariants = falsemodifiers[i].modifierRenderType
productOptions[i].name and manageVariants = trueoptions[i].name
productOptions[i].name and manageVariants = falsemodifiers[i].name
productOptions[i].choices[i].value and manageVariants = trueoptions[i].choicesSettings.choices[i]
productOptions[i].choices[i].value and manageVariants = falsemodifiers[i].choicesSettings.choices
productOptions[i].choices[i].description and manageVariants = trueoptions[i].choicesSettings.choices[i].name
productOptions[i].choices[i].description and manageVariants = falsemodifiers[i].choicesSettings.choices[i].name
productOptions[i].choices[i].media and manageVariants = trueoptions[i].choicesSettings.choices[i].linkedMedia[i]See media table
productOptions[i].choices[i].media and manageVariants = falsemodifiers[i].choicesSettings.choices[i].linkedMedia[i]See media table
productOptions[i].choices[i].inStockoptions[i].choicesSettings.choices[i].inStock
productOptions[i].choices[i].visibleoptions[i].choicesSettings.choices[i].visible
productPageUrl.baseurl.urlMust be a full URL
productPageUrl.pathurl.relativePath
numericIdWas used for cursor paging - V3 Query & Search APIs support cursor paging out of the box
inventoryItemIdAvailable via Inventory Items APIMoved to inventory service but it's no longer saved on Product V3. Search Inventory Items and filter by productId and/or variantId.
discount.typevariantsInfo.variants[i].price.salePrice.amountDiscounts now saved on each variant
discount.valuevariantsInfo.variants[i].price.salePrice.amountDiscounts now saved on each variant
collectionIds[i]directCategories[i].id
variants[i].idvariantsInfo.variants[i].id
variants[i].choices[key]variantsInfo.variants[i].choices[i].optionChoiceNames.optionName
variants[i].choices[value]variantsInfo.variants[i].choices[i].optionChoiceNames.choiceName
variants[i].variant.priceData-See point (5) in Major Changes section above
variants[i].variant.convertedPriceData.pricevariantsInfo.variants[i].price.basePrice.amount
variants[i].variant.convertedPriceData.discountedPricevariantsInfo.variants[i].price.salePrice.amount
variants[i].variant.convertedPriceData.formatted.pricevariantsInfo.variants[i].price.basePrice.formattedAmount
variants[i].variant.convertedPriceData.formatted.discountedPricevariantsInfo.variants[i].price.salePrice.formattedAmount
variants[i].variant.convertedPriceData.formatted.pricePerUnitvariantsInfo.variants[i].physicalProperties.pricePerUnit.description
variants[i].variant.convertedPriceData.pricePerUnitvariantsInfo.variants[i].physicalProperties.pricePerUnit.value
variants[i].variant.costAndProfitData.itemCostvariantsInfo.variants[i].revenueDetails.cost.amount
variants[i].variant.costAndProfitData.formattedItemCostvariantsInfo.variants[i].revenueDetails.cost.formattedAmount
variants[i].variant.costAndProfitData.profitvariantsInfo.variants[i].revenueDetails.profit.amount
variants[i].variant.costAndProfitData.formattedProfitvariantsInfo.variants[i].revenueDetails.profit.formattedAmount
variants[i].variant.costAndProfitData.profitMarginvariantsInfo.variants[i].revenueDetails.profitMargin
variants[i].variant.weightvariantsInfo.variants[i].physicalProperties.weight
variants[i].variant.skuvariantsInfo.variants[i].sku
variants[i].variant.visiblevariantsInfo.variants[i].visible
variants[i].stock.trackQuantityAvailable via Inventory Items API
variants[i].stock.quantityAvailable via Inventory Items API
variants[i].stock.inStockvariantsInfo.variants[i].inventoryStatus.inStock
lastUpdatedupdatedDate
createdDatecreatedDate
seoData*seoData
ribbonribbon.nameManage these fields with the Ribbons API
brandbrand.nameManage these fields with the Brands API
taxGroupIdtaxGroupId
digitalFile.idvariantsInfo.variants[i].digitalProperties.digitalFile.idEach variant in V3 can have its own digital file
digitalFile.fileNamevariantsInfo.variants[i].digitalProperties.digitalFile.fileNameEach variant in V3 can have its own digital file
digitalFile.fileTypevariantsInfo.variants[i].digitalProperties.digitalFile.fileTypeEach variant in V3 can have its own digital file

*Fields marked with an asterisk signify little to no change in semantics or access.

Media Conversion Table

Media V1Media V3
thumbnail.url-
thumbnail.width-
thumbnail.height-
thumbnail.format-
thumbnail.altText-
mediaType-
title and mediaType = IMAGEimage.fileName
title and mediaType = VIDEOvideo.filename
id and mediaType = IMAGEimage.id
id and mediaType = VIDEOvideo.id
image.url*image.url
image.width*image.width
image.height*image.height
image.format-
image.altText*image.altText
video.files[i].urlvideo.resolutions[i].url
video.files[i].widthvideo.resolutions[i].width
video.files[i].heightvideo.resolutions[i].height
video.files[i].formatvideo.resolutions[i].format
video.files[i].altText-
video.stillFrameMediaId-

Inventory Conversion Table

Inventory V2Inventory Items V3Notes
id*id
productId*productId
trackQuantitytrackQuantityNow on the variant level
variants[i].variantIdvariantId
variants[i].inStocktrackingMethod.inStock
variants[i].quantitytrackingMethod.quantity
variants[i].availableForPreorderAvailabilityStatus = PREORDER
lastUpdatedupdatedDate
numericId-Was used for cursor paging - V3 Query & Search APIs support cursor paging out of the box
preorderInfo.enabledpreorderInfo.enabled
preorderInfo.messagepreorderInfo.message
preorderInfo.limitpreorderInfo.limit

Subscriptions Conversion Table

In V1 Subscriptions has its own APIs, where in V3 we don't have a dedicated API. Subscriptions exists directly in Product entity.

SubscriptionOption V1Product V3
idsubscriptionDetails.subscriptions[i].id
titlesubscriptionDetails.subscriptions[i].title
descriptionsubscriptionDetails.subscriptions[i].description
subscriptionSettings.frequencysubscriptionDetails.subscriptions[i].frequency
subscriptionSettings.intervalsubscriptionDetails.subscriptions[i].interval
subscriptionSettings.autoRenewalsubscriptionDetails.subscriptions[i].autoRenewal
subscriptionSettings.billingCyclessubscriptionDetails.subscriptions[i].billingCycles
discount.typesubscriptionDetails.subscriptions[i].discount.type
discount.valuesubscriptionDetails.subscriptions[i].discount.amountOff OR subscriptionDetails.subscriptions[i].discount.percentOff
SubscriptionOptionInProduct V1Product V3
idsubscriptionDetails.subscriptions[i].id
hiddensubscriptionDetails.subscriptions[i].visible
titlesubscriptionDetails.subscriptions[i].title
descriptionsubscriptionDetails.subscriptions[i].description
subscriptionSettings.frequencysubscriptionDetails.subscriptions[i].frequency
subscriptionSettings.intervalsubscriptionDetails.subscriptions[i].interval
subscriptionSettings.autoRenewalsubscriptionDetails.subscriptions[i].autoRenewal
subscriptionSettings.billingCyclessubscriptionDetails.subscriptions[i].billingCycles
discount.typesubscriptionDetails.subscriptions[i].discount.type
discount.valuesubscriptionDetails.subscriptions[i].discount.amountOff OR subscriptionDetails.subscriptions[i].discount.percentOff

Webhook Conversion Table

The following table shows Catalog V1 webhooks and their equivalents in Catalog V3 that are triggered at the same time:

Catalog V1Catalog V3
Product CreatedProduct Created
Product ChangedProduct Updated
Product DeletedProduct Deleted
Product Variants Changed-

We've updated the structure of the webhook/event payload. The table below describes where to find the entity ID or entity object in the new webhook payloads:

Catalog V1 WebhooksCatalog V3 Webhooks
productId, collectionId, variants.variantIdAll webhook payloads - metadata.entityId
Product/Collection Created entity dataAll webhook payloads - handler.event.entity

For more detailed information on specific field changes and how to access data in the new API structure, please refer to our API documentation.

Did this help?