Skip to main content

Managed mode for Shopify Tax

Shopify Tax managed mode helps Shopify apply the correct tax behavior for US sales by managing some store settings and API behavior directly. To keep those settings consistent, some Admin API writes now validate against the requirements of managed mode.

Managed mode sets requirements that Shopify uses to keep tax behavior consistent across a store. In some cases, the API now prevents apps from writing settings that would conflict with those requirements. In other cases, tax behavior now depends on more specific product or store data instead of simple boolean settings.

For app developers, the main pattern is:

  • Requests that already use the required settings, or that omit settings the app doesn't need to manage, continue to work.
  • Requests that try to override managed-mode requirements might now return validation errors.

These changes affect apps that configure markets, publish products, create custom line items, or preview checkout branding for stores that use Shopify Tax managed mode. The changes fall into four categories:

  • Breaking changes: Markets API writes and product publishing writes can now fail when they conflict with Shopify Tax managed mode requirements.
  • Deprecation: The taxable input on custom line items is deprecated in favor of productCategoryId.
  • New capability: Apps can assign product categories to custom line items in draft orders and order edits.
  • Behavior clarification: Checkout footer visibility controls merchant-configurable content only, not Shopify-provided transaction information.

Breaking: Markets API writes require fixed US defaults

For stores that use Shopify Tax in managed mode for US sales, the marketCreate and marketUpdate mutations now reject attempts to override required currency and tax-display defaults for affected markets. The validation applies only to merchant-managed, non-retail markets that include the United States. Markets without the United States, retail markets, and third-party-managed markets are excluded.

Stores that don't use Shopify Tax managed mode are unaffected even if they sell to US customers.

Affected requests

This change applies across all supported API versions, including unstable. The validation only applies when a request supplies currencySettings or priceInclusions, so requests that omit these inputs are unchanged. When one of these inputs is submitted, Shopify validates the resulting setting, including retained values and defaults for omitted subfields.

If your app sets these fields, use the required defaults or omit fields that your app doesn't need to manage.

For a US-only market, the following optional inputs use the required defaults:

{
"currencySettings": {
"baseCurrency": "USD",
"localCurrencies": false
},
"priceInclusions": {
"taxPricingStrategy": "ADD_TAXES_AT_CHECKOUT"
}
}

For a market that includes the United States and another country, such as Canada, the following optional inputs use the required defaults:

{
"currencySettings": {
"localCurrencies": true
},
"priceInclusions": {
"taxPricingStrategy": "INCLUDES_TAXES_IN_PRICE_BASED_ON_COUNTRY"
}
}

Handle validation errors through userErrors.code, userErrors.field, and userErrors.message. Currency violations return UNSUPPORTED_CURRENCY. Tax-display violations return INCOMPATIBLE_CONFIGURATION on API version 2026-07 and later, or GENERIC_ERROR on earlier versions.

Related docs



Breaking: Product publishing requires the Shop channel

For stores that use Shopify Tax managed mode, products published to Online Store, Headless, Hydrogen, or Buy Button must also be published to Shop. These channels depend on Shop, so requests that would leave a product on one of these channels without Shop are handled differently by API version. In unstable, the request fails. In dated versions, Shopify adds the missing Shop or dependent-channel changes to the request and saves it. Shopify doesn't save any part of a failed request.

The failures described below apply to the unstable API version. Dated versions apply the same rules, but change the request instead of failing it. Refer to Dated API versions. Stores that don't use Shopify Tax managed mode are unaffected, and requests that only change other sales channels, collections, or product variants are unchanged. The change is rolling out gradually to stores that use managed mode, with no schema changes.

Affected requests

A product counts as being on a channel when it's published there, scheduled to publish there, or, for draft products, added to that channel. A request that includes both Shop and a dependent channel is checked as a whole, in any order.

The validation applies to publishablePublish, publishableUnpublish, and publicationUpdate. It also applies to deprecated GraphQL publishing APIs, including productPublish, productUnpublish, and the publishing fields on productCreate and productUpdate. For the REST Admin API, product create and update requests fail when they would put a product on Online Store while the product isn't on Shop or is blocked by Shop.

Additional validation rules apply:

  • Shop blocks a product when it rejects the product or flags it as needing action. publishablePublish fails if Shop blocks the product and the resulting state leaves it on a dependent channel, even if the request publishes only to Shop. productUpdate also fails if Shop blocks the product and the resulting state leaves it on a dependent channel.

  • Removing a product from Shop requires removing its dependent-channel publications, in any state. This applies to publishableUnpublish and to publicationUpdate removals from Shop.

  • For publicationUpdate:

    • Adding a product to a dependent channel fails if the product isn’t on Shop or Shop blocks it. Adding a blocked product to Shop also fails if it remains on a dependent channel. Products already in the target publication aren’t checked when included in publishablesToAdd.
    • publicationUpdate rejects autoPublish: true on a dependent channel when Shop’s publication doesn’t auto-publish. It also rejects autoPublish: false on Shop when a dependent channel still auto-publishes.
  • On productUpdate, publications replace the product’s entire publication list. Include Shop whenever the replacement list includes a dependent channel, even if the product is already on Shop. When the request also changes status, validation uses the new status.

The deprecated productPublish and productUnpublish mutations follow the same failure conditions as publishablePublish and publishableUnpublish.

Dated API versions

On dated API versions, Shopify changes a request that breaks these rules so that it follows them, then saves it:

  • Publishing a product to a dependent channel also publishes it to Shop. Shop doesn't support scheduled publishing, so Shopify publishes to Shop immediately, even when the dependent channel is scheduled.
  • Removing a product from Shop also removes it from its dependent channels.
  • On productCreate and productUpdate, including the product-level publishing fields, Shop is added when the request puts the product on Online Store or another dependent channel. On productUpdate, a publications list that leaves out Shop keeps the product on Shop.
  • For publicationUpdate, adding products to a dependent channel also adds them to Shop, and removing products from Shop also removes them from dependent channels. Turning on autoPublish for a dependent channel also turns it on for Shop. Turning off autoPublish for Shop also turns it off for dependent channels.
  • A Shop rejection or a "needs action" flag doesn't block the request.
  • REST Admin API product, product listing, and product publication requests behave the same way.

If the request still breaks the rules after these changes, it fails with the same error as in unstable. For example, this happens when a draft product is scheduled on a dependent channel without Shop.

Keep in mind:

  • If your app publishes products to Online Store, Headless, Hydrogen, or Buy Button, publish the product to Shop first or include Shop in the same request. If your app unpublishes a product from Shop, unpublish it from dependent channels first or include those removals in the same request.
  • If your app creates active products with the REST Admin API, send "published": false, then publish the product to Shop and Online Store with publishablePublish.
  • On dated versions, Shopify can publish a product to Shop, or remove it from dependent channels, even when your request didn't name those channels. To control the result, send Shop and its dependent channels together.

Handle these failures as validation errors. Retrying the same request returns the same error. Publishing requests fail with For the store setup, Shop publication is a prerequisite. Unpublishing requests fail with For the store setup, unpublishing from dependent publications is a prerequisite.

Related docs





Deprecated: taxable on custom line items

The taxable input for custom line items in draft orders and order edits is deprecated in favor of productCategoryId, which assigns a category from Shopify's Standard Product Taxonomy and lets Shopify determine the item's tax treatment.

On GraphQL Admin API version 2027-01 and later, DraftOrderLineItemInput.taxable and the taxable argument on orderEditAddCustomItem are marked as deprecated. Apps on API version 2026-10 or earlier don't see a schema change.

  • Reading the taxable state isn't deprecated, so fields that return whether a line item is taxable, and webhook payloads that include taxable state, are unchanged.
  • For stores using Shopify Tax managed mode, taxable is ignored on custom line items in every API version. The product category sets tax treatment, and a custom line item with no category is taxed at the standard rate. For all other stores, taxable works as before.

If your app sets taxable when creating or editing custom line items, replace it with productCategoryId on GraphQL Admin API version 2027-01 or later. To exempt an entire draft order on a store that uses Shopify Tax managed mode, mark the customer, company, or company location as tax-exempt. Use a category to exempt a single item.

Related docs



New: Set product categories on custom line items in draft orders and order edits

You can now assign a category from Shopify's Standard Product Taxonomy to custom line items in draft orders and order edits. The category controls the item's tax treatment in the same way it does for products.

For stores using Shopify Tax managed mode, productCategoryId is the input that sets a custom line item's tax treatment. The taxable input is ignored. A custom line item with no category is treated as Uncategorized and taxed at the standard rate.

For stores that don't use Shopify Tax managed mode, taxable: false continues to mean that the custom line item isn't taxed. When the item is taxed, Shopify can use its category to calculate tax.

Affected requests

In draft orders, DraftOrderLineItemInput.productCategoryId sets the product category for a custom line item in draftOrderCreate, draftOrderUpdate, and draftOrderCalculate. It's ignored when variantId is provided. You can read the saved category from DraftOrderLineItem.productCategory and CalculatedDraftOrderLineItem.productCategory; these fields return null for product variant line items.

In order edits, orderEditAddCustomItem accepts a new productCategoryId argument. You can read the category from CalculatedLineItem.productCategory.

If productCategoryId doesn't match a category in the current taxonomy, the mutation returns a user error.

A product category can express reduced rates, exemptions, and category-specific tax rules that a yes-or-no taxable value can't. To use it, look up a category ID with the taxonomy query, pass the ID as productCategoryId, and read the saved category from the relevant productCategory field.

query {
taxonomy {
categories(search: "t-shirts", first: 5) {
nodes {
id
fullName
}
}
}
}

Related docs



Clarification: Checkout footer visibility controls merchant-configurable content only

The visibility fields on CheckoutBrandingFooterContent and CheckoutAndAccountsConfigurationBrandingFooterContent now control only merchant-configurable footer content. All checkout and Thank you pages can display the additional Shopify-provided transaction information in the footer when visibility is set to HIDDEN.

Merchant-configurable footer content includes merchant policy links and copyright copy. Shopify-provided transaction information is part of checkout, isn't controlled by checkout branding, and isn't configurable through these visibility settings.

This affects apps that customize checkout branding for Shopify Plus stores through the legacy Checkout Branding API or the Checkout and Accounts Configuration API, especially apps that manage footer visibility, render branding previews, or run visual tests. Apps that don't manage checkout footer visibility are unaffected.

No fields, input types, enum values, access scopes, or mutations have changed. The clarification applies to every GraphQL Admin API version where the corresponding branding type exists; it isn't tied to a new API version.

Existing mutations and stored branding configurations continue to work without changes. If your app previews or tests checkout branding, update it so Shopify-provided transaction information can remain visible when merchant-configurable footer content is hidden.

Related docs

Was this page helpful?