Free tool by Meridian

API Upgrade Planner for Shopify apps

Pick the API version your app runs on and the one you are moving to. Get every change that needs action between the two, sorted by deadline, with what to do and what to search for in your code.

Source: Shopify developer changelog. Not affiliated with Shopify.

Surfaces you build on

All surfaces are shown. Platform changes that every app gets are always included.

14 changes to handle to move from 2025-10 to 2026-10.

2025-10 stopped being served on Oct 16, 2026. Shopify already answers your app with the oldest supported version, so the changes below may already apply.

Sorted by deadline, then severity. Covers the changes Shopify announced since Aug 18, 2025. Meridian last added a change from the changelog on Nov 6, 2026.

Get this checklist by email

The full list of changes for this upgrade, in your inbox.

Deadline passedApr 1, 2026
criticalBreaking changeAction requiredLands in 2026-04

JSON metafield values limited to 128KB

Starting in API version 2026-04, writes to JSON-type metafields will be capped at 128KB (down from the current 2MB limit), which will break write operations for apps that store larger JSON payloads unless they were already using JSON metafields before April 1, 2026 (grandfathered at 2MB) or granted an exception.

What to do: Audit all metafield writes (via metafieldsSet, REST /metafields.json endpoints, or Customer Account/Storefront API mutations) that use the 'json' type and ensure values stay under 128KB for any app not already using JSON metafields before April 1, 2026. Apps with existing JSON metafields will be grandfathered at the current 2MB limit, but new apps needing larger values must request an exception via Shopify's provided form before relying on values >128KB.

Search your code formetafieldsSetMetafieldsSetInputMetafieldsSetPayloadmetafieldDefinitionCreateMetafield.type/admin/api/2026-04/metafields.json/admin/api/2026-04/.../metafields/{metafield_id}.json

GraphQL Admin API · Admin REST API · Customer Account API · Storefront API

Deadline passedApr 1, 2026
criticalAction requiredLands in 2026-01

Concurrency protection features for inventory and refund mutations

Shopify is adding compare-and-swap (changeFromQuantity) and idempotency (@idempotent directive) protections to core inventory and refund mutations; these become mandatory in the 2026-04 API version, breaking any client that doesn't supply them.

What to do: Update all calls to inventoryAdjustQuantities, inventoryMoveQuantities, inventorySetQuantities, inventorySetOnHandQuantities, and refundCreate to pass the changeFromQuantity field (or explicitly null to opt out of the compare-and-swap check) and wrap them with the @idempotent(key: ...) directive before the 2026-04 release, since the old compareQuantity/compareAndSetQuantity fields on inventorySetQuantities will be removed and changeFromQuantity plus @idempotent will become mandatory.

Search your code forinventoryAdjustQuantitiesinventoryMoveQuantitiesinventorySetQuantitiesinventorySetOnHandQuantitiesrefundCreateInventoryChangeInput.changeFromQuantityInventoryQuantityInput.changeFromQuantityInventorySetQuantitiesInput.compareQuantityInventorySetQuantitiesInput.ignoreCompareQuantity@idempotent

GraphQL Admin API

BeforeOct 16, 2026when 2025-10 stops being served
criticalBreaking changeAction requiredLands in 2026-10

Cart mutations reject unconfirmed writes in POS UI extensions 2026-10

Starting in POS UI extensions API version 2026-10, Cart API write mutations (e.g. shopify.cart.bulkCartUpdate, removeLineItem, applyCartDiscount, etc.) now reject their returned promise when POS does not confirm the cart was actually changed, instead of always resolving as in 2026-07 and earlier; apps must add rejection handling or they will silently fail to detect dropped cart writes.

What to do: For any POS UI extension targeting api_version 2026-10 or later, wrap all shopify.cart.* mutation calls (bulkCartUpdate, removeLineItem, applyCartDiscount, addCartCodeDiscount, removeAllDiscounts, setCustomer, removeCustomer, addLineItemProperties, bulkAddLineItemProperties, removeLineItemProperties, setLineItemDiscount, bulkSetLineItemDiscounts, removeLineItemDiscount, addLineItemSellingPlan, removeLineItemSellingPlan, updateLineItemQuantity) in try/catch logic that handles promise rejection, distinguishing the 'POS refused the cart update...' and 'POS could not confirm the cart update...' messages from other validation errors, and re-reading cart state before retrying on an unconfirmed-outcome rejection. Apps remaining on 2026-07 or earlier are unaffected and can defer this change.

Search your code forshopify.cart.bulkCartUpdateshopify.cart.removeLineItemshopify.cart.applyCartDiscountshopify.cart.addCartCodeDiscountshopify.cart.removeAllDiscountsshopify.cart.setCustomershopify.cart.removeCustomershopify.cart.addLineItemPropertiesshopify.cart.bulkAddLineItemPropertiesshopify.cart.removeLineItemPropertiesshopify.cart.setLineItemDiscountshopify.cart.bulkSetLineItemDiscountsshopify.cart.removeLineItemDiscountshopify.cart.addLineItemSellingPlanshopify.cart.removeLineItemSellingPlanshopify.cart.updateLineItemQuantity

POS Extensions

BeforeOct 16, 2026when 2025-10 stops being served
criticalBreaking changeAction requiredLands in 2026-10

Updated function syntax on the segment query language

Starting in API version 2026-10, the ShopifyQL segment query syntax changes breaking existing segment query strings that use function syntax like .opened() = true or products_purchased(quantity: 5) = true, as well as deprecating named date literals (12_months_ago, 90_days_ago, 30_days_ago, 7_days_ago); any app that builds, stores, or submits segment query strings via segmentCreate/segmentUpdate or parses them from the Segment.query field will break or behave unexpectedly unless updated to the new MATCHES syntax and date offsets.

What to do: Update any code that constructs or parses ShopifyQL segment query strings (e.g. passed to segmentCreate/segmentUpdate mutations or read from Segment.query) to use the new MATCHES/NOT MATCHES function syntax (e.g. shopify_email.opened MATCHES () and products_purchased MATCHES (quantity = 5)) instead of = true/= false, and replace deprecated named dates (12_months_ago, 90_days_ago, 30_days_ago, 7_days_ago) with equivalent date offsets (e.g. -12m) before targeting API version 2026-10.

Search your code forsegmentCreatesegmentUpdateSegment.querysegmentssegmentsegmentFilterssegmentFilterSuggestionsMATCHESNOT MATCHES12_months_ago90_days_ago30_days_ago7_days_ago

GraphQL Admin API

BeforeOct 16, 2026when 2025-10 stops being served
criticalBreaking changeAction requiredLands in 2026-10

Removed session.currentSession.staffMemberId from POS UI Extensions (2026-10)

The static field session.currentSession.staffMemberId has been removed in POS UI Extensions API version 2026-10; any extension code reading this field will break when targeting 2026-10, since the field no longer exists on the Session API.

What to do: Replace all reads of session.currentSession.staffMemberId with session.staffMember.value?.id before targeting API version 2026-10. For extensions that need to react to staff changes while running, subscribe via session.staffMember.subscribe((staffMember) => { ... }), or import @shopify/ui-extensions/preact and read session.staffMember.value during render to get automatic re-rendering. Extensions still targeting 2026-07 or earlier are unaffected, and the separate BaseData session.staffMemberId used by receipt targets does not need changes.

Search your code forsession.currentSession.staffMemberIdsession.staffMembersession.staffMember.valuesession.staffMember.subscribe

POS Extensions

BeforeOct 16, 2026when 2025-10 stops being served
criticalAction requiredLands in 2026-01

The cartDiscountCodeUpdate mutation now requires the discountCodes field

Starting with API version 2026-01, calls to the cartDiscountCodesUpdate mutation without the discountCodes argument will now fail (previously they silently no-op'd), so any client code that omits this argument must be updated to avoid breaking cart discount workflows.

What to do: Audit all calls to the cartDiscountCodesUpdate mutation and ensure the discountCodes argument (a [String!]! array) is always explicitly provided — pass an empty array to remove all codes rather than omitting the argument — before adopting or being migrated to Storefront API version 2026-01.

Search your code forcartDiscountCodesUpdatediscountCodesCartDiscountCodesUpdatePayload

Storefront API

BeforeOct 16, 2026when 2025-10 stops being served
warningAction requiredLands in 2026-10

Discounts can now be included in Rollouts

Discounts can now be part of merchant-configured Rollouts, which can change a discount's effective availability and buyer reach without altering its own startsAt/endsAt fields; apps that read discounts and infer availability purely from discount status/dates may show inaccurate information to merchants or miscalculate eligibility.

What to do: Request and add the read_rollouts access scope (existing installs may need merchant reauthorization), then query Discount.rollouts alongside existing startsAt/endsAt fields to read each Rollout's schedule, trafficAllocation, effectiveTrafficAllocation, and treatment status before determining a discount's true availability and buyer reach; subscribe to the new rollouts/* webhook topics if real-time updates are needed, and re-query the rollouts connection rather than relying on webhook payloads for treatment/change details.

Search your code forDiscount.rolloutsRolloutStatusRolloutTreatmenttrafficAllocationeffectiveTrafficAllocationread_rolloutsrollouts/createrollouts/updaterollouts/deleterollouts/resource_change_addedrollouts/resource_change_removedrollouts/resource_change_updated

GraphQL Admin API

BeforeOct 16, 2026when 2025-10 stops being served
warningAction requiredLands in 2026-10

SMS marketing consent now available on the CustomerPhoneNumber object

The flat SMS marketing consent fields on CustomerPhoneNumber (marketingState, marketingOptInLevel, marketingUpdatedAt, marketingCollectedFrom, sourceLocation) are now deprecated in favor of a new structured smsMarketingConsent field, aligning with the WhatsApp consent model; existing integrations continue to work but should migrate.

What to do: Update GraphQL queries/mutations that read the deprecated flat fields on CustomerPhoneNumber (marketingState, marketingOptInLevel, marketingUpdatedAt, marketingCollectedFrom, sourceLocation) to instead read the new CustomerPhoneNumber.smsMarketingConsent field (type CustomerSmsMarketingConsent, exposing state, optInLevel, updatedAt, collectedFrom, sourceLocation), matching the structure already used for WhatsApp consent; continue using the customerSmsMarketingConsentUpdate mutation to write consent changes.

Search your code forCustomerPhoneNumber.marketingStateCustomerPhoneNumber.marketingOptInLevelCustomerPhoneNumber.marketingUpdatedAtCustomerPhoneNumber.marketingCollectedFromCustomerPhoneNumber.sourceLocationCustomerPhoneNumber.smsMarketingConsentCustomerSmsMarketingConsentcustomerSmsMarketingConsentUpdate

GraphQL Admin API · Customer Account API

BeforeOct 16, 2026when 2025-10 stops being served
warningAction requiredLands in 2026-10

New SubscriptionContractCalculation API for subscription management

Shopify has introduced a new SubscriptionContractCalculation API that replaces SubscriptionDraft for managing subscription contract edits, routing changes through the checkout engine and adding support for Shopify Functions (cart transforms, delivery customizations); SubscriptionDraft continues to work but will not receive these new capabilities, so apps should migrate to stay aligned with checkout behavior and gain function support.

What to do: Plan migration from SubscriptionDraft mutations (subscriptionContractCreate/subscriptionDraftCommit/subscriptionDraftLineAdd/subscriptionDraftDiscountAdd/etc.) to the new asynchronous SubscriptionContractCalculation flow: call subscriptionContractCreateCalculate or subscriptionContractUpdateCalculate, poll the subscriptionContractCalculation query (or subscribe to the subscription_contract_calculations/succeed and /fail webhook topics), review calculatedContract/projectedOrderTotals/warnings, then finalize with subscriptionContractCalculationCommit; enable withMerchandiseCustomizations/withDeliveryCustomizations if you need cart transform or delivery customization Function support, and follow Shopify's migration guide at docs/apps/build/purchase-options/subscriptions/contracts/migrate-to-subscription-calculation-api.

Search your code forSubscriptionDraftsubscriptionDraftCommitsubscriptionDraftLineAddsubscriptionDraftLineRemovesubscriptionDraftDiscountAddsubscriptionDraftDiscountCodeApplysubscriptionDraftFreeShippingDiscountAddsubscriptionDraftFreeShippingDiscountUpdatesubscriptionContractUpdateSubscriptionContractCalculationSubscriptionContractCalculationPendingSubscriptionContractCalculationSuccessSubscriptionContractCalculationFailuresubscriptionContractCreateCalculatesubscriptionContractUpdateCalculatesubscriptionContractCalculationCommitsubscriptionContractCalculationsubscription_contract_calculations/succeedsubscription_contract_calculations/fail

GraphQL Admin API · Functions

BeforeOct 16, 2026when 2025-10 stops being served
warningAction requiredDeprecationLands in 2026-10

Variants now support multiple barcodes

ProductVariant.barcode is deprecated in favor of a new barcodes connection/input that supports multiple typed barcodes (UPC, EAN, ISBN, GTIN, ASIN); existing single-barcode reads/writes keep working today, but apps should migrate to the new field to support multiple identifiers and avoid relying on deprecated behavior.

What to do: Update product/variant creation and update flows to use the new barcodes input (with optional type: UPC, EAN, ISBN, GTIN, ASIN) on productSet, productVariantsBulkCreate, and productVariantsBulkUpdate instead of the deprecated barcode field, and switch reads to the new barcodes connection on ProductVariant while ensuring no single variant input sets both barcode and barcodes.

Search your code forProductVariant.barcodeProductVariant.barcodesProductVariantBarcodeConnectionBarcodeInputProductVariantsBulkInput.barcodesProductVariantSetInput.barcodesGiftCardProductVariantSetInput.barcodesproductSetproductVariantsBulkCreateproductVariantsBulkUpdatebarcode (products/productVariants query filter)

GraphQL Admin API

BeforeOct 16, 2026when 2025-10 stops being served
warningDeprecationLands in 2026-10

Customer Address APIs now support countryCode

Customer Account API version 2026-10 adds a strongly-typed countryCode field to CustomerAddress and CustomerAddressInput, deprecating territoryCode; existing territoryCode usage continues to work with no removal date announced, so there is no breaking change yet but developers adopting 2026-10 should migrate.

What to do: When upgrading to Customer Account API version 2026-10 or later, replace territoryCode with countryCode in CustomerAddressInput mutations and CustomerAddress queries, supplying ISO 3166-1 alpha-2 values (e.g., US) via the CountryCode enum, while noting territoryCode remains functional for now with no announced removal version.

Search your code forCustomerAddress.countryCodeCustomerAddress.territoryCodeCustomerAddressInput.countryCodeCustomerAddressInput.territoryCodeCountryCode

Checkout UI · Customer Account API · Customer Accounts

BeforeOct 16, 2026when 2025-10 stops being served
warningBreaking changeAction requiredLands in 2026-10

OrderDisplayFulfillmentStatus now returns FULFILLMENT_NOT_REQUIRED for orders with no items to fulfill

The OrderDisplayFulfillmentStatus enum gains a new value, FULFILLMENT_NOT_REQUIRED, returned in place of UNFULFILLED for orders with zero remaining fulfillable quantity (e.g., fully cancelled/refunded before fulfillment) starting in API version 2026-10, which can break exhaustive switch statements or filters keyed on UNFULFILLED.

What to do: When adopting API version 2026-10, update any exhaustive switch statements, status-to-label/badge mappings, or generated types that branch on OrderDisplayFulfillmentStatus to explicitly handle the new FULFILLMENT_NOT_REQUIRED value, and review any logic filtering on UNFULFILLED since orders with no fulfillable items will now report FULFILLMENT_NOT_REQUIRED instead.

Search your code forOrder.displayFulfillmentStatusOrderDisplayFulfillmentStatus

GraphQL Admin API

DeadlineJan 1, 2027
warningAction requiredLands in 2026-10

New owner_type field for metafield declarations in Checkout and Customer Account UI extensions, required in 2027-01

Checkout and Customer Account UI extensions that declare metafields in shopify.extension.toml must add an owner_type to each metafield declaration before upgrading to API version 2027-01, or deployments will be blocked.

What to do: Update every [[extensions.metafields]] and [[extensions.targeting.metafields]] entry in shopify.extension.toml to include an owner_type value (e.g. PRODUCT, CUSTOMER, ORDER, SHOP, CART, COMPANY, COMPANY_LOCATION, PRODUCTVARIANT as applicable) now while on API version 2026-10, then redeploy and verify no validation errors before moving to API version 2027-01.

Search your code forextensions.metafieldsextensions.targeting.metafieldsowner_typeshopify.extension.toml

Checkout UI · Customer Accounts

DeadlineMar 1, 2027
criticalAction requiredDeprecationEvery version

Script tags are deprecated and will stop running on March 1, 2027

scriptTagCreate and scriptTagUpdate (GraphQL) and the ScriptTag REST resource's POST/PUT endpoints will start returning errors on October 1, 2026 across all API versions, and Shopify will stop injecting any existing script tags into storefronts on March 1, 2027, breaking any app functionality that relies on script tags for online_store display scope.

What to do: Audit existing script tags with the scriptTags query, migrate any storefront JavaScript injection (display_scope=online_store) to a theme app extension using app embed blocks, or to a Web Pixel if the script only collects analytics/conversion data, and delete obsolete script tags via scriptTagDelete once replacements are confirmed active before October 1, 2026 (when scriptTagCreate/scriptTagUpdate and REST POST/PUT start failing) and definitely before March 1, 2027 (when Shopify stops injecting script tags into storefronts).

Search your code forscriptTagCreatescriptTagUpdatescriptTagDeletescriptTagsScriptTag/admin/api/*/script_tags.json/admin/api/*/script_tags/{script_tag_id}.json/admin/api/*/script_tags/count.json

GraphQL Admin API · Admin REST API

Already in effect on every version (4)

Recent breaking changes with no API version and no deadline. They apply to your app today, whatever version it runs on.

In effectsince Oct 7, 2026
criticalBreaking changeAction requiredEvery version

POS UI extensions now return percentage values for percentage discounts

Starting with POS 11.15, the Cart API's Discount.amount for Percentage-type discounts now returns the percentage value (e.g., 25) instead of the previously returned monetary amount (e.g., 50), breaking any extension logic that treated this value as money for display, savings calculations, or integrations.

What to do: Update all logic consuming Discount.amount to first check Discount.type: treat 'Percentage' amounts as raw percentage numbers (not currency) and only treat 'FixedAmount' or 'Code' amounts as monetary values. Audit and fix currency displays, savings calculations, loyalty point logic, and any bulkCartUpdate round-tripping of cart state, then test on POS 11.15+. If supporting POS 11.14 or earlier, implement version-detection branching to preserve old behavior until those devices are upgraded, since the fix is not gated by api_version.

Search your code forDiscount.amountDiscount.typecart.currentcart.subscribelineItems[].discountscartDiscountcartDiscountscartLineItembulkCartUpdateapplyCartDiscountsetLineItemDiscountbulkSetLineItemDiscounts

POS Extensions

In effectsince Sep 16, 2026
criticalAction requiredEvery version

Updates to Events payloads and subscription configuration

The new Events system (shopify.app.toml [[events.subscription]]) changes the fields_changed payload shape from a flat array to an object with added/updated/removed arrays, requires parent triggers to use an explicit .* wildcard, and drops the shopify-event-id and shopify-resource-id delivery headers; apps using Events (not Classic Webhooks) will break if they parse the old payload shape, use old parent trigger syntax, or rely on the removed headers.

What to do: Update webhook/event handler code to read fields_changed.added, fields_changed.updated, and fields_changed.removed instead of a flat fields_changed array; update any parent-level entries in shopify.app.toml [[events.subscription]].triggers to use the terminal wildcard syntax (e.g. 'product.variants.*') on the next deploy; stop reading the now-removed shopify-event-id and shopify-resource-id headers and instead rely on shopify-webhook-id for deduplication, upgrading your Shopify API client libraries to versions that handle this automatically.

Search your code forfields_changedfields_changed.addedfields_changed.updatedfields_changed.removedtriggers[[events.subscription]]shopify-event-idshopify-resource-id

Events & webhooks

In effectsince Sep 10, 2026
criticalAction requiredEvery version

Discounts Allocator Function API developer preview has ended

The Discounts Allocator Function API developer preview has ended and its mutations are being removed from the unstable Admin GraphQL API; apps that still declare the purchase.discounts-allocator.run extension target will fail shopify app deploy for their entire app until the extension is removed.

What to do: Remove the purchase.discounts-allocator.run extension target from your app's configuration (shopify.app.toml / extension TOML) and any code calling discountsAllocatorFunctionRegister or discountsAllocatorFunctionUnregister. Migrate discount allocation logic to the Discount Function API (https://shopify.dev/docs/apps/build/discounts) to retain custom discount behavior, since Shopify now unregisters preview functions automatically but leaving the extension target declared will block shopify app deploy for the whole app.

Search your code fordiscountsAllocatorFunctionRegisterdiscountsAllocatorFunctionUnregisterpurchase.discounts-allocator.run

GraphQL Admin API · Functions

In effectsince Sep 25, 2026
warningAction requiredEvery version

AI Toolkit skills have been consolidated to shopify

This change affects local AI agent tooling configuration (npx skills / agent plugins), not the Shopify GraphQL or REST API surface; developers using individual shopify- skills must reinstall the consolidated shopify skill or their AI agent may lose access to Shopify-specific context.

What to do: If using npx skills or agent plugins that installed individual shopify- skills, run npx skills remove -y shopify-admin shopify-app-pricing shopify-app-store-review shopify-custom-data shopify-customer shopify-dev shopify-functions shopify-hydrogen shopify-liquid shopify-onboarding-dev shopify-onboarding-merchant shopify-partner shopify-payments-apps shopify-polaris-admin-extensions shopify-polaris-app-home shopify-polaris-checkout-extensions shopify-polaris-customer-account-extensions shopify-pos-ui shopify-shopifyql shopify-storefront-graphql shopify-use-shopify-cli followed by npx skills add Shopify/shopify-ai-toolkit --skill shopify to migrate to the consolidated shopify skill; for agent environments with automatic plugin updates, verify the plugin updates or manually trigger an update via the agent's plugin manager.

Search your code forshopify-adminshopify-app-pricingshopify-app-store-reviewshopify-custom-datashopify-customershopify-devshopify-functionsshopify-hydrogenshopify-liquidshopify-onboarding-devshopify-onboarding-merchantshopify-partnershopify-payments-appsshopify-polaris-admin-extensionsshopify-polaris-app-homeshopify-polaris-checkout-extensionsshopify-polaris-customer-account-extensionsshopify-pos-uishopify-shopifyqlshopify-storefront-graphqlshopify-use-shopify-clinpx skills removenpx skills add Shopify/shopify-ai-toolkit --skill shopify

AI Toolkit

Which of these hit your code?

Meridian scans your repository against every change in this list and shows the files and lines to fix, with the fix written for your code.

Admin API versions

When each version stops being served, and until when UI extensions on it can be deployed.

VersionReleasedServed untilUI extensions deployable untilStatus
2025-07Jul 1, 2025Jul 16, 2026Jul 1, 2026No longer served
2025-10your versionOct 1, 2025Oct 16, 2026Oct 1, 2026No longer served
2026-01Jan 1, 2026Jan 16, 2027Jan 1, 2027Supported
2026-04Apr 1, 2026Apr 16, 2027Apr 1, 2027Supported
2026-07Jul 1, 2026Jul 16, 2027Jul 1, 2027Supported
2026-10targetOct 1, 2026Oct 16, 2027Oct 1, 2027Latest
2027-01Jan 1, 2027Jan 16, 2028Jan 1, 2028Release candidate