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
minimumRequirement
field for both theDiscountAutomaticBasic
andDiscountAutomaticFreeShipping
objects is now nullable, making minimum purchase conditions optional for automatic discounts. -
Bulk query operations: The
BulkOperationUserError
object has been updated with a newUserError
GraphQL object type, which includes an additionalcode
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 thefulfillmentServiceCreate
mutation 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_body
for function external calls. Use this field when thebody
is in JSON format to reduce function instruction consumption and to ensure thebody
is formatted in logs. Don't use theJSON_body
field together with thebody
field in theHttpResponse
object. If both are provided, then theHttpResponse
'sbody
field takes precedence. If theJSON_body
field is specified and noContent-Type
header is included, then the header will automatically be set toapplication/json
. -
Metafield admin access: The
admin
field on theMetafieldAccessInput
andMetafieldAccessUpdateInput
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 theMetafieldDefinition
object instead. -
Multi-location shop feature: The deprecated
multiLocation
field has been removed from theShopFeatures
object. Use thelocationsCount
query to determine the number of shop locations. -
New metafieldsDelete mutation: We've replaced the
metafieldDelete
mutation with themetafieldsDelete
mutation. 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
handle
field on theProductInput
input 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
tags
field. Use theCUSTOMER_TAGS_ADDED
andCUSTOMER_TAGS_REMOVED
webhook topics instead. -
Removed the
email_marketing_consent
field. Use theCUSTOMERS_EMAIL_MARKETING_CONSENT_UPDATE
webhook topic instead. -
Removed the
sms_marketing_consent
field. Use theCUSTOMERS_MARKETING_CONSENT_UPDATE
webhook topic instead. -
Removed the
last_order_id
,last_order_name
,total_spent
, andorders_count
fields. Use theCUSTOMERS_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 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_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:
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
PrivateMetafield
was removed from the public GraphQL Admin API. Useapp-data
metafields instead. -
If the
metafield
is needed per resource, refer to the migration guide for usingapp-reserved
namespaces.
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
VerificationSessionResolve
andVerificationSessionReject
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 theVerificationSessionResolve
orVerificationSessionReject
mutation. -
We're also deprecating the following
VerificationSessionStateReason
:REQUIRED_3DS_CHALLENGE
. Use the newVerificationSessionRedirect
mutation 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_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.
Anchor to Shop fieldsShop fields
We've removed the following unused fields on the Shop
object:
collectionSavedSearches
. UseQueryRoot.collectionSavedSearches
instead.draftOrderSavedSearches
. UseQueryRoot.draftOrderSavedSearches
instead.marketingEvents
. UseQueryRoot.marketingEvents
instead.orderSavedSearches
. UseQueryRoot.orderSavedSearches
instead.productByHandle
. UseQueryRoot.productByHandle
instead.productSavedSearches
. UseQueryRoot.productSavedSearches
instead.uploadedImagesByIds
. Use thefiles
query 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 theAbandonedCheckoutLineItem
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
andmerchandiseThumbnail.badge.background
, to theCheckoutBrandingInput
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 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:
CompanyLocationAssignTaxExemptions
CompanyLocationCreateTaxRegistration
CompanyLocationRevokeTaxExemptions
CompanyLocationRevokeTaxRegistration
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.customId
for details about defining the metafield definitionid
and thekey
,namespace
, andvalue
input 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
productSet
and 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
tags
field. Use theCUSTOMER_TAGS_ADDED
andCUSTOMER_TAGS_REMOVED
webhook topics instead. -
Removed the
email_marketing_consent
field. Use theCUSTOMERS_EMAIL_MARKETING_CONSENT_UPDATE
webhook topic instead. -
Removed the
sms_marketing_consent
field. Use theCUSTOMERS_MARKETING_CONSENT_UPDATE
webhook topic instead. -
Removed the
last_order_id
,last_order_name
,total_spent
, andorders_count
fields. Use theCUSTOMERS_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
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
customerPaymentMethodRemoteCreditCardCreate
mutation after January 2026, following the deprecation of the 2025-01 API version. You should transition away from using thecustomerPaymentMethodRemoteCreditCardCreate
mutation by January 2026. - The
stripePaymentMethodId
argument, 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
deliveryPromiseSettings
query to retrieve delivery promise settings for a shop. -
You can make updates using the
deliveryPromiseParticipantsUpdate
mutation.We’ve also added the
delivery_promise_settings/update
webhook 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
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 tobundles
or 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
PrivateMetafield
was removed from the public GraphQL Admin API. Useapp-data
metafields instead. -
If the
metafield
is needed per resource, refer to the migration guide for usingapp-reserved
namespaces.
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_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
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_field
number_integer
url
id
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_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
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_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
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.collectionSavedSearches
instead.draftOrderSavedSearches
. UseQueryRoot.draftOrderSavedSearches
instead.marketingEvents
. UseQueryRoot.marketingEvents
instead.orderSavedSearches
. UseQueryRoot.orderSavedSearches
instead.productByHandle
. UseQueryRoot.productByHandle
instead.productSavedSearches
. UseQueryRoot.productSavedSearches
instead.uploadedImagesByIds
. Use thefiles
query 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
VerificationSessionResolve
andVerificationSessionReject
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 theVerificationSessionResolve
orVerificationSessionReject
mutation. -
We're also deprecating the following
VerificationSessionStateReason
:REQUIRED_3DS_CHALLENGE
. Use the newVerificationSessionRedirect
mutation 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_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:
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.