Skip to main content

2025-01 release notes

Note

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.

The API version release date and the date that the version is no longer supported
Release dateDate version is no longer supported
January 1, 2025January 1, 2026

Here are some highlights of version 2025-01 of Shopify's APIs:

  • Automatic discounts: The minimumRequirement field for both the DiscountAutomaticBasic and DiscountAutomaticFreeShipping objects is now nullable, making minimum purchase conditions optional for automatic discounts.

  • Bulk query operations: The BulkOperationUserError object has been updated with a new UserError GraphQL object type, which includes an additional code field.

  • 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 permitsSkuSharing field on the fulfillmentServiceCreate mutation is now set to true, 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_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.

  • Metafield 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.

  • Metafield storefront visibility: Several related objects, mutations, queries, and fields have been removed. Use the access field on the MetafieldDefinition object instead.

  • Multi-location shop feature: The deprecated multiLocation field has been removed from the ShopFeatures object. Use the locationsCount query to determine the number of shop locations.

  • New metafieldsDelete mutation: We've replaced the metafieldDelete mutation with the metafieldsDelete mutation. This change provides a fundamental update in how you delete metafields. By using metafieldsDelete, you need to adjust your code to accommodate for a new identifier format.

  • Product handle uniqueness validation: The handle field on the ProductInput input object is now validated for uniqueness, preventing collisions when creating or updating product handles.


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.

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 tags field. Use the CUSTOMER_TAGS_ADDED and CUSTOMER_TAGS_REMOVED webhook topics instead.

  • Removed the email_marketing_consent field. Use the CUSTOMERS_EMAIL_MARKETING_CONSENT_UPDATE webhook topic instead.

  • Removed the sms_marketing_consent field. Use the CUSTOMERS_MARKETING_CONSENT_UPDATE webhook topic instead.

  • Removed the last_order_id, last_order_name, total_spent, and orders_count fields. Use the CUSTOMERS_PURCHASING_SUMMARY webhook 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 stripePaymentMethodId argument is now required. Update your code to accommodate this change.
  • Transition away from using the customerPaymentMethodRemoteCreditCardCreate mutation 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 scopeWhat you can access
read_merchant_managed_fulfillment_ordersHolds on fulfillment orders assigned to a merchant-managed location
read_assigned_fulfillment_ordersHolds on fulfillment orders assigned to locations owned by your app
read_third_party_fulfillment_ordersHolds on fulfillment orders assigned to a third-party location
read_marketplace_fulfillment_ordersHolds 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.

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.

Note

The PaymentCustomizationPaymentMethodPlacement enum contains the PAYMENT_METHOD values.

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, and PUBLIC_READ_WRITE values from app-reserved metafield and metaobject enums.

  • Removed the LEGACY_LIQUID_ONLY value 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:

Additions to metafield definition capabilities
NameType/fieldChange
useAsCollectionConditionFieldRemoved. Use the capabilities.smartCollectionCondition field instead. For more information, refer to the developer changelog.
capabilitiesFieldAdded to standardMetafieldDefinitionEnable mutation
capabilitiesFieldAdded to standardMetafieldDefinitionsEnable mutation
INVALID_CAPABILITYError codeAdded to the MetafieldDefinitionCreateUserErrorCode and MetafieldDefinitionUpdateUserErrorCode enums.
TYPE_NOT_ALLOWED_FOR_CONDITIONSError codeAdded to the MetafieldDefinitionCreateUserErrorCode and MetafieldDefinitionUpdateUserErrorCode enums.

Anchor to Metafield storefront visibilityMetafield storefront visibility

We've removed several MetafieldStorefrontVisibility related objects, mutations, queries, and fields:

Removals of MetafieldStorefrontVisibility-related types
NameTypeChange
MetafieldStorefrontVisibilityObjectRemoved. Use the access field on the MetafieldDefinition object instead.
metafieldStorefrontVisibilityCreateMutationRemoved. Use the metafieldDefinitionUpdate mutation instead.
metafieldStorefrontVisibilityDeleteMutationRemoved. Use the metafieldDefinitionUpdate mutation instead.
metafieldStorefrontVisibilitiesQueryRemoved. Use the access field on the MetafieldDefinition object instead.
metafieldStorefrontVisibilityQueryRemoved. Use the access field on the MetafieldDefinition object instead.
visibleToStorefrontApiField on MetafieldDefinition objectRemoved. Use the access field on the MetafieldDefinition object instead.
visibleToStorefrontApiField on MetafieldDefinitionInput input objectRemoved. Use the access field on the MetafieldDefinitionInput input object instead.
visibleToStorefrontApiField on MetafieldDefinitionUpdateInput input objectRemoved. 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

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:

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 VerificationSessionResolve and VerificationSessionReject mutations.

    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 VerificationSessionRedirect mutation.

  • When resolving or rejecting a verification that required 3DS, pass the authentication argument to either the VerificationSessionResolve or VerificationSessionReject mutation.

  • We're also deprecating the following VerificationSessionStateReason: REQUIRED_3DS_CHALLENGE. Use the new VerificationSessionRedirect mutation instead.

We've removed the following values on the PriceListUserErrorCode enum that aren't currently returned by the GraphQL Admin API:

  • CONTEXT_RULE_COUNTRIES_LIMIT
  • CONTEXT_RULE_COUNTRY_TAKEN
  • CONTEXT_RULE_LIMIT_REACHED
  • CONTEXT_RULE_MARKET_NOT_FOUND
  • CONTEXT_RULE_MARKET_TAKEN
  • COUNTRY_CURRENCY_MISMATCH
  • CURRENCY_COUNTRY_MISMATCH
  • MARKET_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_orders access scope.

  • The order is older than 60 days.

  • The order no longer exists.

    In API versions prior to 2025-01, the order field returns a GraphQL error when the order isn't available.

We've removed the following unused fields on the Shop object:

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:

Script tag display scope usage and recommended alternatives
If you use......Then use this instead
UI customizationsUpgrade to Shopify Extensions in Checkout
Analytics and conversion trackingUpgrade to web pixels
Online storeUpdate the displayScope value to ONLINE_STORE

Anchor to GraphQL Admin API changesGraphQL 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.

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

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 the AbandonedCheckoutLineItem object. Use this field to define the component products within a product bundle, ensuring a grouped view in Abandoned Checkout Emails.

  • The group field 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.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.

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.

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:

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:

New types and fields for managing conditional metafield definitions
NameTypeChange
MetafieldDefinitionConstraintsInputInput objectAdded
MetafieldDefinitionConstraintsUpdatesInputInput objectAdded
constraintsFieldAdded to MetafieldDefinitionInput input object
constraintsUpdatesFieldAdded to MetafieldDefinitionUpdateInput input object
deleteConflictingConstrainedMetafields deleteConflictingConstrainedMetafieldsFieldAdded to ProductUpdateInput input object
linkedMetafieldValueFieldAdded to VariantOptionValueInput input object
INVALID_CONSTRAINTSError codeAdded to MetafieldDefinitionCreateUserErrorCode enum
INVALID_CONSTRAINTSError codeAdded to MetafieldDefinitionUpdateUserErrorCode enum

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.customId for details about defining the metafield definition id and the key, namespace, and value input fields used in creating a metafield ID.
Note

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 productSet and for customers use customerSet. You cannot yet use a custom ID as a matching key for upserting.
Note

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

We've changed how a customer is represented in webhooks:

  • Removed the tags field. Use the CUSTOMER_TAGS_ADDED and CUSTOMER_TAGS_REMOVED webhook topics instead.

  • Removed the email_marketing_consent field. Use the CUSTOMERS_EMAIL_MARKETING_CONSENT_UPDATE webhook topic instead.

  • Removed the sms_marketing_consent field. Use the CUSTOMERS_MARKETING_CONSENT_UPDATE webhook topic instead.

  • Removed the last_order_id, last_order_name, total_spent, and orders_count fields. Use the CUSTOMERS_PURCHASING_SUMMARY webhook 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

Note

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:

We've added the following new fields and error messages for managing discounts:

New fields and error messages for managing discounts
NameTypeChange
appliesOnOneTimeSubscriptionFieldAdded to DiscountAutomaticAppInput input object
appliesOnOneTimePurchaseFieldAdded to DiscountAutomaticApp input object
appliesOnOneTimePurchaseFieldAdded to DiscountCodeApp object
appliesOnOneTimePurchaseFieldAdded to DiscountCodeAppInput input object
appliesOnSubscriptionFieldAdded to DiscountCodeAppInput input object
appliesOnSubscriptionFieldAdded to DiscountCodeApp object
APPLIES_ON_ONE_TIME_PURCHASE_AND_SUBSCRIPTION_BOTH_FALSEError codeAdded to DiscountErrorCode enum
MULTIPLE_RECURRING_CYCLE_LIMIT_FOR_NON_SUBSCRIPTION_ITEMS_CONSTRAINTSError codeAdded to DiscountErrorCode enum
recurringCycleLimitFieldAdded to DiscountCodeAppInput input object
RECURRING_CYCLE_LIMIT_NOT_A_VALID_INTEGERError codeAdded to PriceRuleErrorCode enum
RECURRING_CYCLE_LIMIT_NOT_A_VALID_INTEGERError codeAdded 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.

Note

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 priceOverride field 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 to bundles or their components. If a line item is included in a bundle, 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.

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

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 scopeWhat you can access
read_merchant_managed_fulfillment_ordersHolds on fulfillment orders assigned to a merchant-managed location
read_assigned_fulfillment_ordersHolds on fulfillment orders assigned to locations owned by your app
read_third_party_fulfillment_ordersHolds on fulfillment orders assigned to a third-party location
read_marketplace_fulfillment_ordersHolds on fulfillment orders that belong to one of your marketplace's orders

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 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.

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 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.

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:

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

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

We've removed the PrivateMetafield from the public GraphQL Admin API, changing how metafields are implemented and used across stores.

Developer action required

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, and PUBLIC_READ_WRITE values from app-reserved metafield and metaobject enums.

  • Removed the LEGACY_LIQUID_ONLY value 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 work with custom data.

Additions to metafield definition capabilities
NameType/fieldChange
useAsCollectionConditionFieldRemoved. Use the capabilities.smartCollectionCondition field instead. For more information, refer to the developer changelog.
capabilitiesFieldAdded to standardMetafieldDefinitionEnable mutation
capabilitiesFieldAdded to standardMetafieldDefinitionsEnable mutation
INVALID_CAPABILITYError codeAdded to the MetafieldDefinitionCreateUserErrorCode and MetafieldDefinitionUpdateUserErrorCode enums.
TYPE_NOT_ALLOWED_FOR_CONDITIONSError codeAdded 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_field
  • number_integer
  • url
  • id

Anchor to New metafieldsDelete mutationNew metafieldsDelete mutation

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.

Note

The metafield gid isn't an option in the metafieldsDelete mutation.

Anchor to Metafield storefront visibilityMetafield storefront visibility

We've removed several MetafieldStorefrontVisibility-related objects, mutations, queries, and fields:

Removals of MetafieldStorefrontVisibility-related types
NameTypeChange
MetafieldStorefrontVisibilityObjectRemoved. Use the access field on the MetafieldDefinition object instead.
metafieldStorefrontVisibilityCreateMutationRemoved. Use the metafieldDefinitionUpdate mutation instead.
metafieldStorefrontVisibilityDeleteMutationRemoved. Use the metafieldDefinitionUpdate mutation instead.
metafieldStorefrontVisibilitiesQueryRemoved. Use the access field on the MetafieldDefinition object instead.
metafieldStorefrontVisibilityQueryRemoved. Use the access field on the MetafieldDefinition object instead.
visibleToStorefrontApiField on MetafieldDefinition objectRemoved. Use the access field on the MetafieldDefinition object instead.
visibleToStorefrontApiField on MetafieldDefinitionInput input objectRemoved. Use the access field on the MetafieldDefinitionInput input object instead.
visibleToStorefrontApiField on MetafieldDefinitionUpdateInput input objectRemoved. Use the access field on the MetafieldDefinitionUpdateInput input object instead.

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 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.

You can now use the pickupAddress field in both the SubscriptionDeliveryMethodPickupOption and SubscriptionPickupOption objects to query for a customer pickup address.

We've removed the following values on the PriceListUserErrorCode enum that aren't currently returned by the GraphQL Admin API:

  • CONTEXT_RULE_COUNTRIES_LIMIT
  • CONTEXT_RULE_COUNTRY_TAKEN
  • CONTEXT_RULE_LIMIT_REACHED
  • CONTEXT_RULE_MARKET_NOT_FOUND
  • CONTEXT_RULE_MARKET_TAKEN
  • COUNTRY_CURRENCY_MISMATCH
  • CURRENCY_COUNTRY_MISMATCH
  • MARKET_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 metadata queriesProduct metadata queries

We've moved the following product metadata queries from the Shop type to QueryRoot and added pagination support:

Product metadata query changes
NameTypeChange
productTagsQueryMoved to QueryRoot with pagination support
productTypesQueryMoved to QueryRoot with pagination support
productVendorsQueryMoved 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

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_orders access scope.

  • The order is older than 60 days.

  • The order no longer exists.

    In API versions prior to 2025-01, the order field 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

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

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.

Script tag display scope usage and recommended alternatives
If you use......Then use this instead
UI customizationsUpgrade to Shopify Extensions in Checkout
Analytics and conversion trackingUpgrade to web pixels
Online storeUpdate the displayScope value to ONLINE_STORE

We've removed the following unused fields on the Shop object:

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:

Product metadata query changes
NameTypeChange
productTagsQueryMoved to QueryRoot with pagination support
productTypesQueryMoved to QueryRoot with pagination support
productVendorsQueryMoved 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.

Caution

The replaced headers field remains available but is deprecated. We recommend that you use the 'header' field instead.

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.

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 VerificationSessionResolve and VerificationSessionReject mutations.

    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 VerificationSessionRedirect mutation.

  • When resolving or rejecting a verification that required 3DS, pass the authentication argument to either the VerificationSessionResolve or VerificationSessionReject mutation.

  • We're also deprecating the following VerificationSessionStateReason: REQUIRED_3DS_CHALLENGE. Use the new VerificationSessionRedirect mutation instead.

Anchor to Product image resourceProduct image resource

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_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 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

  • totalTaxAmountEstimated

    Tax 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:

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.


Was this page helpful?