2025-01 release notes
We're no longer publishing API release notes. Instead, you can find the latest updates on Shopify APIs in our developer changelog. You can filter updates by area. For example, you can filter API updates by the API name and version, such as GraphQL Admin API changes in version 2025-04.
| Release date | Date version is no longer supported |
|---|---|
| January 1, 2025 | January 1, 2026 |
Anchor to HighlightsHighlights
Here are some highlights of version 2025-01 of Shopify's APIs:
-
Automatic discounts: The
minimumRequirementfield for both theDiscountAutomaticBasicandDiscountAutomaticFreeShippingobjects is now nullable, making minimum purchase conditions optional for automatic discounts. -
Bulk query operations: The
BulkOperationUserErrorobject has been updated with a newUserErrorGraphQL object type, which includes an additionalcodefield. -
Fulfillment holds: You can now place multiple holds on a fulfillment order. Each hold captures a specific issue independently, allowing you to release holds individually while maintaining other active holds. For detailed information on the changes, and how to upgrade to the 2025-01 version of the GraphQL Admin API, consult the developer changelog.
-
Fulfillment services: The default value for the
permitsSkuSharingfield on thefulfillmentServiceCreatemutation is now set totrue, allowing fulfillment services to stock inventory across multiple locations. -
JSON body support: We now provide native support of a HTTP request body as a
JSON_bodyfor function external calls. Use this field when thebodyis in JSON format to reduce function instruction consumption and to ensure thebodyis formatted in logs. Don't use theJSON_bodyfield together with thebodyfield in theHttpResponseobject. If both are provided, then theHttpResponse'sbodyfield takes precedence. If theJSON_bodyfield is specified and noContent-Typeheader is included, then the header will automatically be set toapplication/json. -
Metafield admin access: The
adminfield on theMetafieldAccessInputandMetafieldAccessUpdateInputobjects is now optional. In API version 2024-10 and prior, this field was required. -
Metafield storefront visibility: Several related objects, mutations, queries, and fields have been removed. Use the
accessfield on theMetafieldDefinitionobject instead. -
Multi-location shop feature: The deprecated
multiLocationfield has been removed from theShopFeaturesobject. Use thelocationsCountquery to determine the number of shop locations. -
New metafieldsDelete mutation: We've replaced the
metafieldDeletemutation with themetafieldsDeletemutation. This change provides a fundamental update in how you delete metafields. By usingmetafieldsDelete, you need to adjust your code to accommodate for a new identifier format. -
Product handle uniqueness validation: The
handlefield on theProductInputinput object is now validated for uniqueness, preventing collisions when creating or updating product handles.
Anchor to Breaking changesBreaking changes
These changes require special attention. If your app uses these API resources, and you don’t adjust your usage of the resources according to the following instructions, then your app might break when you update to this API version.
Anchor to Automatic discountsAutomatic discounts
We've changed the minimumRequirement field for both the DiscountAutomaticBasic object and DiscountAutomaticFreeShipping object to be nullable. Previously, merchants were required to specify minimum purchase conditions on product, order, and free shipping automatic discounts. We're now making these conditions optional, so the minimumRequirement field can return a null value.
Anchor to Bulk query operationsBulk query operations
In the Admin API, we have improved the BulkOperationUserError object by introducing a new code field for the userErrors returned by the bulkOperationRunQuery mutation. The new code field allows for improved error handling while retaining all the previous fields. We have also made the BulkOperationUserError type public, enabling developers to access this updated error information.
Anchor to Customer payloads in webhook topicsCustomer payloads in webhook topics
We've changed how a customer is represented in webhooks:
-
Removed the
tagsfield. Use theCUSTOMER_TAGS_ADDEDandCUSTOMER_TAGS_REMOVEDwebhook topics instead. -
Removed the
email_marketing_consentfield. Use theCUSTOMERS_EMAIL_MARKETING_CONSENT_UPDATEwebhook topic instead. -
Removed the
sms_marketing_consentfield. Use theCUSTOMERS_MARKETING_CONSENT_UPDATEwebhook topic instead. -
Removed the
last_order_id,last_order_name,total_spent, andorders_countfields. Use theCUSTOMERS_PURCHASING_SUMMARYwebhook topic instead.The following webhook topics contain a customer payload:
-
CHECKOUTS_CREATE -
CHECKOUTS_UPDATE -
CUSTOMERS_CREATE -
CUSTOMERS_DELETE -
CUSTOMERS_DISABLE -
CUSTOMERS_ENABLE -
CUSTOMERS_UPDATE -
DRAFT_ORDERS_CREATE -
DRAFT_ORDERS_UPDATE -
ORDERS_CANCELLED -
ORDERS_CREATE -
ORDERS_FULFILLED -
ORDERS_PAID -
ORDERS_PARTIALLY_FULFILLED -
ORDERS_UPDATED
Anchor to Customer payment methodsCustomer payment methods
We've hidden the customerPaymentMethodRemoteCreditCardCreate mutation, as it has been deprecated for more than three years. You can use the customerPaymentMethodRemoteCreate mutation instead to manage customer payment methods.
Learn more about payment processing.
Developer action required
- The
stripePaymentMethodIdargument is now required. Update your code to accommodate this change. - Transition away from using the
customerPaymentMethodRemoteCreditCardCreatemutation by January 2026. We'll fully remove this mutation after January 2026, following its complete deprecation in the 2025-01 API version. This mutation was primarily intended for creating payment methods using credit cards stored by Stripe. If the customer IDs you request are invalid, then the method returns a user error.
Anchor to Fulfillment hold accessFulfillment hold access
We've introduced validation for fulfillment hold access in node queries. This change only affects apps which fetch fulfillment holds using a node or nodes GraphQL query. If your app doesn't currently have sufficient access scopes as defined below then you need to request the correct access scopes before migrating to the 2025-01 API version.
When using a node or nodes query to fetch holds, if your app doesn't have sufficient access, then a null value is returned for any fulfillment holds that you don't have access to. Refer to the API access scopes section of the FulfillmentOrder object for more information about access scopes.
Developer action required
Apps using the node or nodes GraphQL queries to fetch fulfillment holds will only retrieve those associated with fulfillment orders for which they have access:
| Access scope | What you can access |
|---|---|
read_merchant_managed_fulfillment_orders | Holds on fulfillment orders assigned to a merchant-managed location |
read_assigned_fulfillment_orders | Holds on fulfillment orders assigned to locations owned by your app |
read_third_party_fulfillment_orders | Holds on fulfillment orders assigned to a third-party location |
read_marketplace_fulfillment_orders | Holds on fulfillment orders that belong to one of your marketplace's orders |
For more information, refer to the changelog.
Anchor to Fulfillment hold field replacementFulfillment hold field replacement
We've added the new heldByApp object field on the FulfillmentHold object, replacing the heldBy string field.
Developer action required
The heldByApp field provides access to all attributes of the App object, in contrast to the deprecated heldBy field, which only indicated the app's title.
If you currently query fulfillmentHold.heldBy, then transition to querying fulfillmentHold.heldByApp.title.
Anchor to Fulfillment holdsFulfillment holds
You can now place multiple holds on a fulfillment order. Each hold captures a specific issue independently, allowing you to release holds individually while maintaining other active holds. For detailed information on the changes, and how to upgrade to the 2025-01 version of the GraphQL Admin API, consult the developer changelog.
Anchor to Fulfillment servicesFulfillment services
The default value of the permitsSkuSharing field on the fulfillmentServiceCreate mutation is now true. If permitsSkuSharing is true, then a fulfillment service can stock inventory at multiple fulfillment services or merchant-managed locations.
Anchor to Gift card visibilityGift card visibility
We've changed the paymentMethods field within the Input object of the PaymentCustomizationApi. This feature enhances the flexibility of payment processing by enabling merchants to configure the visibility of gift cards based on specific conditions.
The PaymentCustomizationPaymentMethodPlacement enum contains the PAYMENT_METHOD values.
Anchor to Localized fieldsLocalized fields
You can now use localized fields in checkout UI extensions and Shopify Functions to implement custom validation for tax fields in checkout. You can apply checkout error targets to custom tax fields for precise error messages.
We've added the HasLocalizedFields interface. We've also renamed the localizationExtensions field to localizedFields on the following types:
Anchor to Metafield admin accessMetafield admin access
The admin field on the MetafieldAccessInput and MetafieldAccessUpdateInput objects is now optional. In API version 2024-10 and prior, this field was required.
The admin field governs access to metafields. If you don't explicitly set the field, then the behavior works the same as if the field was omitted.
Learn more about metafield access controls.
Anchor to Metafield and metaobject permissionsMetafield and metaobject permissions
We're simplifying how metafield and metaobject permissions work to improve API response times.
We've removed private and public permissions for app-reserved metafields and metaobjects from all mutations:
-
Removed
PRIVATE,PUBLIC_READ, andPUBLIC_READ_WRITEvalues from app-reserved metafield and metaobject enums. -
Removed the
LEGACY_LIQUID_ONLYvalue from app-reserved metafield and metaobject enums.For more information on upcoming changes to metafields and metaobjects, refer to the developer changelog.
Anchor to Metafield definition capabilitiesMetafield definition capabilities
We're sharing a consistent configuration pattern for capabilities between metafield and metaobject definitions, to unify and simplify how you enable optional features across custom data.
To implement metafield definition capabilities, we've made the following changes:
| Name | Type/field | Change |
|---|---|---|
useAsCollectionCondition | Field | Removed. Use the capabilities.smartCollectionCondition field instead. For more information, refer to the developer changelog. |
capabilities | Field | Added to standardMetafieldDefinitionEnable mutation |
capabilities | Field | Added to standardMetafieldDefinitionsEnable mutation |
INVALID_CAPABILITY | Error code | Added to the MetafieldDefinitionCreateUserErrorCode and MetafieldDefinitionUpdateUserErrorCode enums. |
TYPE_NOT_ALLOWED_FOR_CONDITIONS | Error code | Added to the MetafieldDefinitionCreateUserErrorCode and MetafieldDefinitionUpdateUserErrorCode enums. |
Anchor to Metafield storefront visibilityMetafield storefront visibility
We've removed several MetafieldStorefrontVisibility related objects, mutations, queries, and fields:
| Name | Type | Change |
|---|---|---|
MetafieldStorefrontVisibility | Object | Removed. Use the access field on the MetafieldDefinition object instead. |
metafieldStorefrontVisibilityCreate | Mutation | Removed. Use the metafieldDefinitionUpdate mutation instead. |
metafieldStorefrontVisibilityDelete | Mutation | Removed. Use the metafieldDefinitionUpdate mutation instead. |
metafieldStorefrontVisibilities | Query | Removed. Use the access field on the MetafieldDefinition object instead. |
metafieldStorefrontVisibility | Query | Removed. Use the access field on the MetafieldDefinition object instead. |
visibleToStorefrontApi | Field on MetafieldDefinition object | Removed. Use the access field on the MetafieldDefinition object instead. |
visibleToStorefrontApi | Field on MetafieldDefinitionInput input object | Removed. Use the access field on the MetafieldDefinitionInput input object instead. |
visibleToStorefrontApi | Field on MetafieldDefinitionUpdateInput input object | Removed. Use the access field on the MetafieldDefinitionUpdateInput input object instead. |
Anchor to Metafields remove privateMetafields remove private
We've removed the PrivateMetafield from the public GraphQL Admin API, changing how metafields are implemented and used across stores.
Developer action required
-
The
PrivateMetafieldwas removed from the public GraphQL Admin API. Useapp-datametafields instead. -
If the
metafieldis needed per resource, refer to the migration guide for usingapp-reservednamespaces.
Anchor to Multi-location shop featureMulti-location shop feature
We've removed the deprecated multiLocation field from the ShopFeatures object. Use the locationsCount query instead to determine the number of shop locations.
Anchor to Payments bank account remove fieldsPayments bank account remove fields
We've cleaned up the GraphQL Admin API ShopifyPaymentsBankAccount object and removed the following fields that weren't being used by third-party apps:
Anchor to Payment extensionsPayment extensions
Payments extensions that support vaulting have been improved to enable the processing of Three-Domain Secure (3DS) challenges for verifications.
-
A new mutation,
VerificationSessionRedirect, is introduced. -
New arguments have been added to the existing
VerificationSessionResolveandVerificationSessionRejectmutations.Developer action required
For payments extensions that support vaulting, we strongly recommend that you update to the 2025-01 version as soon as possible. You also need to consider the following actions:
-
If 3DS is required for a verification, you must use the
VerificationSessionRedirectmutation. -
When resolving or rejecting a verification that required 3DS, pass the
authenticationargument to either theVerificationSessionResolveorVerificationSessionRejectmutation. -
We're also deprecating the following
VerificationSessionStateReason:REQUIRED_3DS_CHALLENGE. Use the newVerificationSessionRedirectmutation instead.
Anchor to Price listsPrice lists
We've removed the following values on the PriceListUserErrorCode enum that aren't currently returned by the GraphQL Admin API:
CONTEXT_RULE_COUNTRIES_LIMITCONTEXT_RULE_COUNTRY_TAKENCONTEXT_RULE_LIMIT_REACHEDCONTEXT_RULE_MARKET_NOT_FOUNDCONTEXT_RULE_MARKET_TAKENCOUNTRY_CURRENCY_MISMATCHCURRENCY_COUNTRY_MISMATCHMARKET_CURRENCY_MISMATCH
Anchor to Product handle uniqueness validationProduct handle uniqueness validation
The handle field on the ProductInput input object is now validated for uniqueness.
This enhancement ensures that there are no collisions when creating or updating product handles. The change doesn't affect existing behavior when a handle isn't provided as input.
Anchor to Product image deprecateProduct image deprecate
We have changed the REST Admin API for the product image resource so that it returns a media image id instead of a product image GID. This is designed to make it easier to migrate to GraphQL from REST when interfacing with product images that were created before the introduction of a unified media ID.
Developer action required
Use medias.id instead of medias.legacy_id/product_images.id for the admin_graphql_api_id.
Previously, the admin_graphql_api_id returned a product image ID:
"gid://shopify/ProductImage/43701248884792"
Now, the admin_graphql_api_id returns a media image ID:
"gid://shopify/MediaImage/12379812379123"
This change will only affect clients using the latest 2025-01 API version. Older versions will continue to return the ProductImage GID, ensuring backward compatibility. It's strongly recommended that you upgrade to using GraphQL, as REST is nearing deprecation.
Anchor to Reverse fulfillment ordersReverse fulfillment orders
The order field on the ReverseFulfillmentOrder object is now nullable. An order can be nullable if the app meets any of the following conditions:
-
The app doesn't have the
read_all_ordersaccess scope. -
The order is older than 60 days.
-
The order no longer exists.
In API versions prior to 2025-01, the
orderfield returns a GraphQL error when the order isn't available.
Anchor to Shop fieldsShop fields
We've removed the following unused fields on the Shop object:
collectionSavedSearches. UseQueryRoot.collectionSavedSearchesinstead.draftOrderSavedSearches. UseQueryRoot.draftOrderSavedSearchesinstead.marketingEvents. UseQueryRoot.marketingEventsinstead.orderSavedSearches. UseQueryRoot.orderSavedSearchesinstead.productByHandle. UseQueryRoot.productByHandleinstead.productSavedSearches. UseQueryRoot.productSavedSearchesinstead.uploadedImagesByIds. Use thefilesquery instead.
Anchor to Script tag display scopesScript tag display scopes
We've reduced the available options for where a script is included when you create or update script tags. This change is related to the upcoming deprecation of script tags for the Thank you and Order status pages on August 28, 2025. Learn more about upcoming changes, key dates, and actions that you're required to take related to the deprecation of script tags.
The only valid value for the displayScope field on the ScriptTagInput input object is now ONLINE_STORE.
The displayScope field remains optional. When you omit this field from the scriptTagCreate mutation, the value defaults to ONLINE_STORE.
Review the following next steps based on how you currently use script tags:
| If you use... | ...Then use this instead |
|---|---|
| UI customizations | Upgrade to Shopify Extensions in Checkout |
| Analytics and conversion tracking | Upgrade to web pixels |
| Online store | Update the displayScope value to ONLINE_STORE |
Anchor to GraphQL Admin API changesGraph QL Admin API changes
Version 2025-01 of the GraphQL Admin API introduces the following changes:
Anchor to Add checkout branding customizationsAdd checkout branding customizations
We've added the customizations fields, merchandiseThumbnail.fit and merchandiseThumbnail.badge.background, to the CheckoutBrandingInput input object. You can now adjust the aspect ratio and image fit for product thumbnails, as well as the quantity badge background colors to align with your brand.
Anchor to Associating customers and ordersAssociating customers and orders
We've added the OrderCreateUpsertCustomerAttributesInput input object that contains the input fields for creating a new customer object or for identifying an existing customer to update and associate with the order. We also added the toUpsert input field to the orderCreate mutation, at order.customer.toUpsert. You can now create a new customer or update an existing customer when you create an order.
Anchor to Automatic discountsAutomatic discounts
Anchor to BreakingBreaking
We've changed the minimumRequirement field for both the DiscountAutomaticBasic object and DiscountAutomaticFreeShipping object to be nullable. Previously, merchants were required to specify minimum purchase conditions on product, order, and free shipping automatic discounts. We're now making these conditions optional, so the minimumRequirement field can return a null value.
Anchor to Bulk query operationsBulk query operations
Anchor to BreakingBreaking
We've improved the BulkOperationUserError object by introducing a new code field for the userErrors returned by the bulkOperationRunQuery mutation. The new code field allows for improved error handling while retaining all the previous fields. We have also made the BulkOperationUserError type public, enabling developers to access this updated error information.
Anchor to Bundles grouped viewBundles grouped view
We've added two new fields to represent product bundles, allowing you to accurately nest component products under the parent product in a grouped view.
-
The
[components](/docs/api/admin-graphql/2025-01/objects/AbandonedCheckoutLineItem#field-components)field has been added to theAbandonedCheckoutLineItemobject. Use this field to define the component products within a product bundle, ensuring a grouped view in Abandoned Checkout Emails. -
The
groupfield has been added to the [LineItem] object. Use this field to indicate that line item products are a part of a product bundle, ensuring a grouped view in Orders Detail Pages.In addition, these fields can help you display product bundles in a grouped view in transactional emails, such as order confirmations and shipping updates. Learn how you can implement a grouped view by following this tutorial.
We've added the customizations fields,
merchandiseThumbnail.fitandmerchandiseThumbnail.badge.background, to theCheckoutBrandingInputinput object. You can now adjust the aspect ratio and image fit for product thumbnails, as well as the quantity badge background colors to align with your brand.
Anchor to Business entitiesBusiness entities
We've added the BusinessEntity object, which represents the formal and legal structure under which a merchant operates their business.
You can use the businessEntities query to retrieve information about business entities that are enabled on a merchant's shop.
Anchor to Combined listingsCombined listings
The MISSING_OPTIONS_VALUE error code value has been added to the CombinedListingUpdateUserErrorCode enum. This error code is returned when the optionsAndValues field is empty.
Anchor to Company location tax settingsCompany location tax settings
We've added the taxExemptions and taxRegistrationId fields on the CompanyLocationTaxSettings object. As a result, we've deprecated these fields from the root of the CompanyLocation object.
Additionally, we've introduced a companyLocationTaxSettingsUpdate mutation for updating tax_exempt, taxExemptions, and taxRegistrationId for a company location. You should use this mutation in place of the following deprecated fields:
CompanyLocationAssignTaxExemptionsCompanyLocationCreateTaxRegistrationCompanyLocationRevokeTaxExemptionsCompanyLocationRevokeTaxRegistration
Anchor to Conditional metafield definitionsConditional metafield definitions
You can now use the metafieldDefinitionCreate and metafieldDefinitionUpdate mutations to create and edit conditional metafield definitions.
Conditional metafield definitions are definitions with constraints, which allow metafield definitions to be applied to a subset of resources. For example, each category metafield comes with a set of constraints that determine what product categories the metafield applies to. Currently, Shopify supports only product category constraints on product metafield definitions.
To implement conditional metafield definitions, the following types and fields have been added:
| Name | Type | Change | |
|---|---|---|---|
MetafieldDefinitionConstraintsInput | Input object | Added | |
MetafieldDefinitionConstraintsUpdatesInput | Input object | Added | |
constraints | Field | Added to MetafieldDefinitionInput input object | |
constraintsUpdates | Field | Added to MetafieldDefinitionUpdateInput input object | |
deleteConflictingConstrainedMetafields | deleteConflictingConstrainedMetafields | Field | Added to ProductUpdateInput input object |
linkedMetafieldValue | Field | Added to VariantOptionValueInput input object | |
INVALID_CONSTRAINTS | Error code | Added to MetafieldDefinitionCreateUserErrorCode enum | |
INVALID_CONSTRAINTS | Error code | Added to MetafieldDefinitionUpdateUserErrorCode enum |
Anchor to Custom idsCustom ids
We've added custom ID and upsert support to enhance data management across platforms. Use the custom ID support to assign unique identifiers to resources and look up the resource by the custom ID. This simplifies the synchronization process and reduces data inconsistencies. Concurrently, you can use the upsert to either create or update a resource based on a matching key, reducing the number of API calls required.
- For custom IDs: You can create and manage custom IDs for any data type that has metafield support. Refer to metafieldDefinitionCreate and
identifier.customIdfor details about defining the metafield definitionidand thekey,namespace, andvalueinput fields used in creating a metafield ID.
You can look up custom IDs only for products and customers.
- For upserts - We've made two APIs available that allow upserting by a matching key. For products, use
productSetand for customers usecustomerSet. You cannot yet use a custom ID as a matching key for upserting.
Custom IDs and external keys are the same; external keys were renamed custom IDs.
Anchor to Customer payloads in webhook topicsCustomer payloads in webhook topics
Anchor to BreakingBreaking
We've changed how a customer is represented in webhooks:
-
Removed the
tagsfield. Use theCUSTOMER_TAGS_ADDEDandCUSTOMER_TAGS_REMOVEDwebhook topics instead. -
Removed the
email_marketing_consentfield. Use theCUSTOMERS_EMAIL_MARKETING_CONSENT_UPDATEwebhook topic instead. -
Removed the
sms_marketing_consentfield. Use theCUSTOMERS_MARKETING_CONSENT_UPDATEwebhook topic instead. -
Removed the
last_order_id,last_order_name,total_spent, andorders_countfields. Use theCUSTOMERS_PURCHASING_SUMMARYwebhook topic instead.The following webhook topics contain a customer payload:
-
CHECKOUTS_CREATE -
CHECKOUTS_UPDATE -
CUSTOMERS_CREATE -
CUSTOMERS_DELETE -
CUSTOMERS_DISABLE -
CUSTOMERS_ENABLE -
CUSTOMERS_UPDATE -
DRAFT_ORDERS_CREATE -
DRAFT_ORDERS_UPDATE -
ORDERS_CANCELLED -
ORDERS_CREATE -
ORDERS_FULFILLED -
ORDERS_PAID -
ORDERS_PARTIALLY_FULFILLED -
ORDERS_UPDATED
Anchor to Customer payment methodsCustomer payment methods
Anchor to BreakingBreaking
We've hidden the customerPaymentMethodRemoteCreditCardCreate mutation, as it has been deprecated for more than three years. You can use the customerPaymentMethodRemoteCreate mutation instead to manage customer payment methods.
Learn more about payment processing.
Developer action required
- We'll fully remove the
customerPaymentMethodRemoteCreditCardCreatemutation after January 2026, following the deprecation of the 2025-01 API version. You should transition away from using thecustomerPaymentMethodRemoteCreditCardCreatemutation by January 2026. - The
stripePaymentMethodIdargument, which is currently optional, is required in API version 2025-01. Update your code to accommodate this change in anticipation of the transition.
The customerPaymentMethodRemoteCreditCardCreate mutation was primarily intended for creating payment methods using credit cards stored by Stripe. If the customer IDs you request are invalid, then the method returns a user error.
Anchor to Customer subscription contract order connectionCustomer subscription contract order connection
We've added a subscriptionContracts connection to the Order object. This connection lets you query subscription contracts associated with a specific order, making it easier to manage customer subscriptions.
Anchor to Delivery promise settingsDelivery promise settings
We've added the DeliveryPromiseSetting object, which stores information about when customers can expect to receive their orders. With this addition you can do the following:
-
You can use the
deliveryPromiseSettingsquery to retrieve delivery promise settings for a shop. -
You can make updates using the
deliveryPromiseParticipantsUpdatemutation.We’ve also added the
delivery_promise_settings/updatewebhook topic so that your app can be notified when a delivery promise setting is updated.
Anchor to DiscountsDiscounts
We've added the following new fields and error messages for managing discounts:
| Name | Type | Change |
|---|---|---|
appliesOnOneTimeSubscription | Field | Added to DiscountAutomaticAppInput input object |
appliesOnOneTimePurchase | Field | Added to DiscountAutomaticApp input object |
appliesOnOneTimePurchase | Field | Added to DiscountCodeApp object |
appliesOnOneTimePurchase | Field | Added to DiscountCodeAppInput input object |
appliesOnSubscription | Field | Added to DiscountCodeAppInput input object |
appliesOnSubscription | Field | Added to DiscountCodeApp object |
APPLIES_ON_ONE_TIME_PURCHASE_AND_SUBSCRIPTION_BOTH_FALSE | Error code | Added to DiscountErrorCode enum |
MULTIPLE_RECURRING_CYCLE_LIMIT_FOR_NON_SUBSCRIPTION_ITEMS_CONSTRAINTS | Error code | Added to DiscountErrorCode enum |
recurringCycleLimit | Field | Added to DiscountCodeAppInput input object |
RECURRING_CYCLE_LIMIT_NOT_A_VALID_INTEGER | Error code | Added to PriceRuleErrorCode enum |
RECURRING_CYCLE_LIMIT_NOT_A_VALID_INTEGER | Error code | Added to DiscountErrorCode enum |
Anchor to Discount code filter addedDiscount code filter added
We've added a new code filter parameter to the discountNodes query, allowing you to filter discounts by their associated discount codes.
Filtering by the discount code is not supported for bulk discounts.
Anchor to Draft order overridesDraft order overrides
We've added the priceOverride field on the DraftOrderLineItemInput input object. This latest enhancement enables you to use the field to customize pricing at the draft order level. You can specify a price override for the line item, which will replace the product variant's catalog price for that draft order. This functionality allows for greater flexibility in managing pricing directly at the draft order level:
-
Use the
priceOverridefield to customize pricing at the draft order level. -
Specify a price override for the line item, which will replace the product variant's catalog price for that draft order.
You need to handle currency conversion and understand the restrictions concerning
bundles. Price overrides cannot be applied tobundlesor their components. If a line item is included in abundle, any price override will be removed.
Anchor to Error codes for cart submissionError codes for cart submission
We've added new error codes to the SubmissionErrorCode enum. These enhancements provide clearer feedback when issues occur during the cart submission process. The new error codes enhance the detail and clarity of error responses when cart submission fails.
Anchor to ExchangesExchanges
We've added the variantId field to the CalculateExchangeLineItemInput input object. You can use this field to set the ID of the product variant to be added to the order as part of an exchange.
Anchor to Fulfillment hold accessFulfillment hold access
Anchor to BreakingBreaking
We've introduced validation for fulfillment hold access in node queries. This change only affects apps which fetch fulfillment holds using a node or nodes GraphQL query. If your app doesn't currently have sufficient access scopes as defined below then you need to request the correct access scopes before migrating to the 2025-01 API version.
When using a node or nodes query to fetch holds, if your app doesn't have sufficient access, then a null value is returned for any fulfillment holds that you don't have access to. Refer to the API access scopes section of the FulfillmentOrder object for more information about access scopes.
Developer action required
Apps using the node or nodes GraphQL queries to fetch fulfillment holds will only retrieve those associated with fulfillment orders for which they have access:
| Access scope | What you can access |
|---|---|
read_merchant_managed_fulfillment_orders | Holds on fulfillment orders assigned to a merchant-managed location |
read_assigned_fulfillment_orders | Holds on fulfillment orders assigned to locations owned by your app |
read_third_party_fulfillment_orders | Holds on fulfillment orders assigned to a third-party location |
read_marketplace_fulfillment_orders | Holds on fulfillment orders that belong to one of your marketplace's orders |
Anchor to Fulfillment hold field replacementFulfillment hold field replacement
Anchor to BreakingBreaking
We've added the new heldByApp object field on the FulfillmentHold object, replacing the heldBy string field.
Developer action required
The heldByApp object field provides access to all attributes of the App object, in contrast to the deprecated heldBy field, which only indicated the app's title.
If you currently query fulfillmentHold.heldBy, you should transition to querying fulfillmentHold.heldByApp.title.
For more information, refer to the changelog.
Anchor to Fulfillment holdsFulfillment holds
Anchor to BreakingBreaking
You can now place multiple holds on a fulfillment order. Each hold captures a specific issue independently, allowing you to release holds individually while maintaining other active holds. For detailed information on the changes, and how to upgrade to the 2025-01 version of the GraphQL Admin API, consult the developer changelog.
Anchor to Fulfillment servicesFulfillment services
Anchor to BreakingBreaking
The default value of the permitsSkuSharing field on the fulfillmentServiceCreate mutation is now true. If permitsSkuSharing is true, then a fulfillment service can stock inventory at multiple fulfillment services or merchant-managed locations.
Anchor to Localization extension keysLocalization extension keys
We've added the SHIPPING_CREDENTIAL_MX extension key to the LocalizationExtensionKey enum. Use this extension key to retrieve the shipping credentials for cross-border shipments to Mexico.
Anchor to Localized fieldsLocalized fields
Anchor to BreakingBreaking
You can now use localized fields in checkout UI extensions and Shopify Functions to implement custom validation for tax fields in checkout. You can apply checkout error targets to custom tax fields for precise error messages.
We've added the HasLocalizedFields interface. We've also renamed the localizationExtensions field to localizedFields on the following types:
Anchor to Location query idLocation query id
We've added the location_id filter to the locations query. The location ID allows you to specify the location where the physical good resides. If no ID is specified, then the primary location is used.
Anchor to Manual payment gatewayManual payment gateway
We’ve added the manualPaymentGateway field to the OrderTransaction object. The manualPaymentGateway field indicates whether the transaction is processed by a manual payment gateway.
For more information about manual payments, refer to Manual payment methods.
Anchor to Metafield admin accessMetafield admin access
Anchor to BreakingBreaking
The admin field on the MetafieldAccessInput and MetafieldAccessUpdateInput objects is now optional. In API version 2024-10 and prior, this field was required.
The admin field governs access to metafields. If the field isn't explicitly set, then the behavior works the same as if the field was omitted.
Learn more about metafield access controls.
Anchor to Metafields input query variablesMetafields input query variables
Metafields input query variables are now subject to additional validation across all Function APIs. Previously, if these metafields didn't contain properly formatted data, we treated them as empty. This could lead to situations where it was difficult to determine why a function wasn't receiving the expected input data.
Now, an invalid metafield will result in an InvalidVariableValueError when attempting to run the function. For more information, refer to the list of errors. -->
Anchor to Metafields remove privateMetafields remove private
Anchor to BreakingBreaking
We've removed the PrivateMetafield from the public GraphQL Admin API, changing how metafields are implemented and used across stores.
Developer action required
-
The
PrivateMetafieldwas removed from the public GraphQL Admin API. Useapp-datametafields instead. -
If the
metafieldis needed per resource, refer to the migration guide for usingapp-reservednamespaces.
Anchor to Metafield and metaobject permissionsMetafield and metaobject permissions
Anchor to BreakingBreaking
We're simplifying how metafield and metaobject permissions work to improve API response times.
We've removed private and public permissions for app-reserved metafields and metaobjects from all mutations:
-
Removed
PRIVATE,PUBLIC_READ, andPUBLIC_READ_WRITEvalues from app-reserved metafield and metaobject enums. -
Removed the
LEGACY_LIQUID_ONLYvalue from app-reserved metafield and metaobject enums.For more information on upcoming changes to metafields and metaobjects, refer to the developer changelog.
Anchor to Metafield definition capabilitiesMetafield definition capabilities
Anchor to BreakingBreaking
We're sharing a consistent configuration pattern for capabilities between metafield and metaobject definitions, to unify and simplify how you work with custom data.
| Name | Type/field | Change |
|---|---|---|
useAsCollectionCondition | Field | Removed. Use the capabilities.smartCollectionCondition field instead. For more information, refer to the developer changelog. |
capabilities | Field | Added to standardMetafieldDefinitionEnable mutation |
capabilities | Field | Added to standardMetafieldDefinitionsEnable mutation |
INVALID_CAPABILITY | Error code | Added to the MetafieldDefinitionCreateUserErrorCode and MetafieldDefinitionUpdateUserErrorCode enums. |
TYPE_NOT_ALLOWED_FOR_CONDITIONS | Error code | Added to the MetafieldDefinitionCreateUserErrorCode and MetafieldDefinitionUpdateUserErrorCode enums. |
Anchor to Metafield definition uniquenessMetafield definition uniqueness
You can now use the MetafieldCapabilityUniqueValues object and MetafieldCapabilityUniqueValuesInput input object to retrieve metafield definitions that enforce uniqueness. You can use this capability to ensure that each metafield has a unique value across all resources. Currently, you can only enforce uniqueness on metafield definitions that don’t yet have associated metafields.
You can enforce uniqueness for the following data types:
single_line_text_fieldnumber_integerurlid
Anchor to New metafieldsDelete mutationNew metafields Delete mutation
Anchor to BreakingBreaking
We've removed the metafieldDelete mutation and replaced it with the metafieldsDelete mutation. The former mutation relies on the Metafield group identifier (gid), while the latter takes an array of MetafieldIdentifier fields composed of key, namespace, and ownerId.
The metafield gid isn't an option in the metafieldsDelete mutation.
Anchor to Metafield storefront visibilityMetafield storefront visibility
Anchor to BreakingBreaking
We've removed several MetafieldStorefrontVisibility-related objects, mutations, queries, and fields:
| Name | Type | Change |
|---|---|---|
MetafieldStorefrontVisibility | Object | Removed. Use the access field on the MetafieldDefinition object instead. |
metafieldStorefrontVisibilityCreate | Mutation | Removed. Use the metafieldDefinitionUpdate mutation instead. |
metafieldStorefrontVisibilityDelete | Mutation | Removed. Use the metafieldDefinitionUpdate mutation instead. |
metafieldStorefrontVisibilities | Query | Removed. Use the access field on the MetafieldDefinition object instead. |
metafieldStorefrontVisibility | Query | Removed. Use the access field on the MetafieldDefinition object instead. |
visibleToStorefrontApi | Field on MetafieldDefinition object | Removed. Use the access field on the MetafieldDefinition object instead. |
visibleToStorefrontApi | Field on MetafieldDefinitionInput input object | Removed. Use the access field on the MetafieldDefinitionInput input object instead. |
visibleToStorefrontApi | Field on MetafieldDefinitionUpdateInput input object | Removed. Use the access field on the MetafieldDefinitionUpdateInput input object instead. |
Anchor to Multi-location shop featureMulti-location shop feature
Anchor to BreakingBreaking
We've removed the deprecated multiLocation field from the ShopFeatures object. Use the locationsCount query instead to determine the number of shop locations.
Anchor to Orders webhook includes product bundles informationOrders webhook includes product bundles information
We've added the sales_line_item_group_id field to the orders/create webhook. This field allows you to determine if a specific line_item is part of a product bundle. When a line_item belongs to a product bundle, it will have an associated sales_line_item_group_id.
Anchor to Pickup addressPickup address
You can now use the pickupAddress field in both the SubscriptionDeliveryMethodPickupOption and SubscriptionPickupOption objects to query for a customer pickup address.
Anchor to Price listsPrice lists
Anchor to BreakingBreaking
We've removed the following values on the PriceListUserErrorCode enum that aren't currently returned by the GraphQL Admin API:
CONTEXT_RULE_COUNTRIES_LIMITCONTEXT_RULE_COUNTRY_TAKENCONTEXT_RULE_LIMIT_REACHEDCONTEXT_RULE_MARKET_NOT_FOUNDCONTEXT_RULE_MARKET_TAKENCOUNTRY_CURRENCY_MISMATCHCURRENCY_COUNTRY_MISMATCHMARKET_CURRENCY_MISMATCH
Anchor to Product handle uniqueness validationProduct handle uniqueness validation
Anchor to BreakingBreaking
The handle field on the ProductInput input object is now validated for uniqueness.
This enhancement ensures that there are no collisions when creating or updating product handles. The change doesn't affect existing behavior when a handle isn't provided as input.
Anchor to Product metadata queriesProduct metadata queries
We've moved the following product metadata queries from the Shop type to QueryRoot and added pagination support:
| Name | Type | Change |
|---|---|---|
productTags | Query | Moved to QueryRoot with pagination support |
productTypes | Query | Moved to QueryRoot with pagination support |
productVendors | Query | Moved to QueryRoot with pagination support |
Previously, these fields were available on the Shop type with a limit of 250 results. The new implementation removes this limitation and supports pagination through standard cursor-based connections.
Anchor to Reverse fulfillment ordersReverse fulfillment orders
Anchor to BreakingBreaking
The order field on the ReverseFulfillmentOrder object is now nullable. An order can be nullable if the app meets any of the following conditions:
-
The app doesn't have the
read_all_ordersaccess scope. -
The order is older than 60 days.
-
The order no longer exists.
In API versions prior to 2025-01, the
orderfield returns a GraphQL error when the order isn't available.
Anchor to Revocation reasons for payment methodsRevocation reasons for payment methods
We've added the PAYMENT_METHOD_VERIFICATION_FAILED and THREE_D_SECURE_FLOW_IN_VERIFICATION_NOT_IMPLEMENTED values to the CustomerPaymentMethodRevocationReason enum to provide more granular information about payment method revocations. This enhancement helps apps handle scenarios where a customer's payment method needs to be revoked.
Anchor to Shopify Payments bank account fields removedShopify Payments bank account fields removed
Anchor to BreakingBreaking
We've removed the following fields from the ShopifyPaymentsBankAccount object that weren't being used by third-party apps:
Anchor to Script tag display scopesScript tag display scopes
Anchor to BreakingBreaking
We've reduced the available options for where a script is included when you create or update script tags. This change is related to the upcoming deprecation of script tags for the Thank you and Order status pages on August 28, 2025. Learn more about upcoming changes, key dates, and actions that you're required to take related to the deprecation of script tags.
The only valid value for the displayScope field on the ScriptTagInput input object is now ONLINE_STORE.
The displayScope field remains optional. When you omit this field from the scriptTagCreate mutation, the value defaults to ONLINE_STORE.
| If you use... | ...Then use this instead |
|---|---|
| UI customizations | Upgrade to Shopify Extensions in Checkout |
| Analytics and conversion tracking | Upgrade to web pixels |
| Online store | Update the displayScope value to ONLINE_STORE |
Anchor to Shop fieldsShop fields
Anchor to BreakingBreaking
We've removed the following unused fields on the Shop object:
collectionSavedSearches. UseQueryRoot.collectionSavedSearchesinstead.draftOrderSavedSearches. UseQueryRoot.draftOrderSavedSearchesinstead.marketingEvents. UseQueryRoot.marketingEventsinstead.orderSavedSearches. UseQueryRoot.orderSavedSearchesinstead.productByHandle. UseQueryRoot.productByHandleinstead.productSavedSearches. UseQueryRoot.productSavedSearchesinstead.uploadedImagesByIds. Use thefilesquery instead.
Anchor to Shopify Payments accountsShopify Payments accounts
We've added the accountOpenerName field to the ShopifyPaymentsAccount object. You can use the field to query the name of the person that opened the Shopify Payments account.
Anchor to Single product variant connectionSingle product variant connection
You can use a limit of up to 2000 variants when running a query on a single product, such as product or productByHandle. This enhanced limit doesn't apply if you make multiple queries in one request, or are accessing the variants any other way except through the ProductVariantConnection.
Anchor to String connection nodesString connection nodes
The StringConnection connection now includes a nodes field, which provides a list of strings within the connection. The nodes field contains a list of nodes contained in StringEdge. This StringEdge contains one String and a cursor. The StringConnection and its associated Edge are cacheable, for improved performance. This addition makes it easier for developers to access the individual elements in a string connection seamlessly.
Anchor to Subscription contractsSubscription contracts
We’ve introduced the concatenatedOriginContract field to the SubscriptionLine object. The concatenatedOriginContract field provides information about the originating contract of the subscription line, and specifically whether it was created by concatenating multiple contracts. The concatenatedOriginContract field returns an instance of SubscriptionContract, which can be null if no concatenation is present.
Anchor to Product metadata queriesProduct metadata queries
We've moved the following product metadata queries from the Shop type to QueryRoot and added pagination support:
| Name | Type | Change |
|---|---|---|
productTags | Query | Moved to QueryRoot with pagination support |
productTypes | Query | Moved to QueryRoot with pagination support |
productVendors | Query | Moved to QueryRoot with pagination support |
We’ve introduced the concatenatedOriginContract field to the SubscriptionLine object. The concatenatedOriginContract field provides information about the originating contract of the subscription line, and specifically whether it was created by concatenating multiple contracts. The concatenatedOriginContract field returns an instance of SubscriptionContract, which can be null if no concatenation is present.
Anchor to Shopify Function APIs changesShopify Function APIs changes
Version 2025-01 of the Shopify Function APIs introduces the following changes:
Anchor to Header selection fieldHeader selection field
We've added the header field to the HttpResponse object. This field allows you to query for a specific HTTP header and add a specific header field to the function's external calls response.
The header field is available across all Shopify Function APIs.
The new header field includes a required name argument. This argument lets you specify a case-insensitive header name to retrieve its value. With this header field, you can access individual HTTP headers on demand. This provides more granular control compared to the previously available headers field, which returned all headers as a list. The header field returns an instance of the HttpResponseHeader type.
The replaced headers field remains available but is deprecated. We recommend that you use the 'header' field instead.
Anchor to JSON body supportJSON body support
We now provide native support of a HTTP request body as a JSON_body for function external calls. Use this field when the body is in JSON format to reduce function instruction consumption and to ensure the body is formatted in logs. Don't use the JSON_body field together with the body field in the HttpResponse object. If both are provided, then the HttpResponse's body field takes precedence. If the JSON_body field is specified and no Content-Type header is included, then the header will automatically be set to application/json.
Anchor to Localized fields for cart and checkout validationLocalized fields for cart and checkout validation
We've added the paymentDetails field on the verificationSessionResolve mutation. This field allows payment providers to send payment details as arguments to a card input field, such as billingAddress and cardHolderName.
Anchor to Payments Apps API changesPayments Apps API changes
Version 2025-01 of the Payments Apps API introduces the following changes:
Anchor to Localized fields for cart and checkout validationLocalized fields for cart and checkout validation
We've added a localizedFields attribute to the Cart object for function inputs. This attribute returns the localized fields available for the cart. Values are only returned for server-side validations using the purchase.validation.run extension target.
Anchor to Payment extensionsPayment extensions
Anchor to BreakingBreaking
Payments extensions that support vaulting have been improved to enable the processing of Three-Domain Secure (3DS) challenges for verifications.
-
A new mutation,
VerificationSessionRedirect, is introduced. -
New arguments have been added to the existing
VerificationSessionResolveandVerificationSessionRejectmutations.Developer action required
For payments extensions that support vaulting, we strongly recommend that you update to the 2025-01 version as soon as possible. You also need to consider the following actions:
-
If 3DS is required for a verification, you must use the
VerificationSessionRedirectmutation. -
When resolving or rejecting a verification that required 3DS, pass the
authenticationargument to either theVerificationSessionResolveorVerificationSessionRejectmutation. -
We're also deprecating the following
VerificationSessionStateReason:REQUIRED_3DS_CHALLENGE. Use the newVerificationSessionRedirectmutation instead.
Anchor to Product image resourceProduct image resource
Anchor to BreakingBreaking
We have changed the product image resource so that it returns a media ID instead of a product image GID. This is designed to make it easier to migrate to GraphQL from REST when interfacing with product images that were created before the introduction of a unified media ID.
Developer action required
Use medias.id instead of medias.legacy_id/product_images.id for the admin_graphql_api_id.
-
Previously, the
admin_graphql_api_idreturned a product image ID:"gid://shopify/ProductImage/43701248884792" -
Now, the
admin_graphql_api_idreturns a media image ID:"gid://shopify/MediaImage/12379812379123"This change will only affect clients using the latest 2025-01 API version. Older versions will continue to return the
ProductImage GID, ensuring backward compatibility. It's strongly recommended that you upgrade to using GraphQL, as REST is nearing deprecation.
Anchor to Verification session payment detailsVerification session payment details
We've added the paymentDetails field on the verificationSessionResolve mutation. This field allows payment providers to send payment details as arguments to its paymentDetails.card input field.
Anchor to Storefront API changesStorefront API changes
Version 2025-01 of the Storefront API introduces the following changes:
Anchor to Cart delivery addressesCart delivery addresses
We've added an addresses field to the CartDelivery object. This field returns a list of addresses that customers can select for their cart delivery, providing more flexible shipping options.
Anchor to Cart tax and duties deprecatedCart tax and duties deprecated
We've deprecated the following tax and duty fields on the Cart object's cost field:
-
totalDutyAmount -
totalDutyAmountEstimated -
totalTaxAmount -
totalTaxAmountEstimatedTax and duties are now calculated at checkout within the complete context of the customer's information, ensuring greater accuracy.
Anchor to String connection nodesString connection nodes
The StringConnection connection now includes a nodes field, which provides a list of strings within the connection. The nodes field contains a list of nodes contained in StringEdge. This StringEdge contains one String and a cursor. The StringConnection and its associated Edge are cacheable, for improved performance. This addition makes it easier for developers to access the individual elements in a string connection.
Anchor to REST Admin API changesREST Admin API changes
Version 2025-01 of the REST Admin API introduces the following changes:
Anchor to Business entitiesBusiness entities
We've added business entity identifiers on the Order resource, as well as on webhook payloads. These identifiers represents the formal and legal structure under which a merchant operates their business.