Developer Changelog / Shopify Tax · Admin API

Shopify Tax"managed mode"
Admin API writes are now validated to protect US sales tax settings

On stores using managed mode, Shopify manages market currency and tax display, product sales channel publishing, and how custom line items are taxed. API writes that conflict with these requirements return validation errors.

On this page
  1. What's changing? (30-second overview)
  2. The 4 change categories at a glance
  3. Breaking: Markets API is locked to US defaults
  4. Breaking: Product publishing requires the Shop channel
  5. Deprecated / New: Custom line items move from taxable to productCategoryId
  6. Clarification: Checkout footer display
  7. 5 key points for developers
  8. 3 practical use cases
  9. One-line summary for client proposals

1What's changing?

Shopify Tax's managed mode is a mode in which, to apply the correct tax treatment to US sales, Shopifydirectly manages certain store settings and API behavior.
To keep settings consistent, some Admin API writes are now validated against managed mode requirements.

Requests that keep working as before

Requests that already send settings matching the requirements, or that leave settings the app doesn't need to manageomitted.

Requests that may return errors

Requests that conflict with managed mode requirements andtry to override them. These may return validation errors.

This affects apps thatconfigure markets, publish products, create custom line items, or preview checkout branding.
In some cases, tax treatment will also be determined not by a simple true/false setting but bymore specific product and store data.

2The 4 change categories at a glance

Shopify Tax managed mode (US sales) BREAKING Markets API marketCreate / marketUpdate Currency and tax display locked to US defaults BREAKING Product publishing publishablePublish, etc. Online Store and others require publishing to Shop DEPRECATED + NEW Custom line items taxable → productCategoryId Product category determines tax treatment CLARIFICATION Checkout footer visibility: HIDDEN Only merchant-configured content can be hidden
The breaking changes to the Markets API and product publishingdo not affect stores that don't use managed mode(even if they sell to US customers).

3Breaking: Markets API is locked to US defaults

For stores using managed mode for US sales,marketCreate and marketUpdate reject requests that attempt to override the target market'srequired currency and tax display defaults.

Markets subject to validation

In scope
Includes the US
Merchant-managed, non-retail markets
Out of scope
Excludes the US
markets
Out of scope
Retail
markets
Out of scope
Third-party-managed
markets
All supported API versions, including unstableare affected.
Validation runs only when you send currencySettings or priceInclusions . If you omit them, behavior is unchanged. If you send them,the result, including retained values and defaults for omitted subfields,is used for validation.

Required default (use this value if sending it as an optional input)

US-only market
{
 "currencySettings": {
 "baseCurrency": "USD",
 "localCurrencies": false
 },
 "priceInclusions": {
 "taxPricingStrategy": "ADD_TAXES_AT_CHECKOUT"
 }
}
US + other countries (e.g., Canada)
{
 "currencySettings": {
 "localCurrencies": true
 },
 "priceInclusions": {
 "taxPricingStrategy": "INCLUDES_TAXES_IN_PRICE_BASED_ON_COUNTRY"
 }
}

How to identify the error

Violation typeuserErrors.codeNotes
CurrencyUNSUPPORTED_CURRENCY—
Tax displayINCOMPATIBLE_CONFIGURATIONAPI 2026-07 and later
Tax displayGENERIC_ERROREarlier versions

Errors are handled via userErrors.code/userErrors.field/userErrors.message .

4Breaking: Publishing products requires the Shop channel

In managed mode stores, products published toOnline Store/Headless/Hydrogen/Buy Button must also be published toShop . These are treated as channels that depend on Shop (dependent channels).

Shop Prerequisite channel Online Store Headless Hydrogen Buy Button When publishing Publish to Shop first or include it in the same request When removing from Shop Remove dependent channels first or include them in the same request

Behavior differs between unstable and dated versions

Request that violates the rulesunstableDated versions
Publish to a dependent channel(without Shop) Fails Auto-corrected Also publishes to Shop. Shop doesn't support scheduled publishing, so even if the dependent channel is scheduled,Shop is published immediately
Unpublish from Shop(dependent channels remain) Fails Auto-corrected Also removes it from dependent channels
productCreate / productUpdate Fails Auto-correct Adds Shop when publishing to a dependent channel.productUpdate 's publications don't include Shop, Shop is retained
autoPublish in publicationUpdate Fails Auto-correct ON for a dependent channel → Shop also ON. OFF for Shop → dependent channels also OFF
Shop rejected / action-required flag Fails Does not block
Still violates the rules after correction(e.g., scheduling a draft product on a dependent channel without Shop) Fails Fails Same error as unstable

Failed requests are not partially saved. This is rolling out gradually, with no schema changes. The REST Admin API product, product listing, and product publication endpoints behave the same way.

Affected APIs and detailed rules

Affected APIs

GraphQL / REST

publishablePublish·publishableUnpublish·publicationUpdate. Publishing fields on the deprecated productPublish·productUnpublish,productCreate/productUpdate are also covered. REST product create and update fail when a product that isn't on Shop (or is blocked by Shop) is added to the Online Store.

What "on a channel" means

Published, scheduled, or added as a draft

A product counts as added to a channel if it's published, scheduled for publishing, or a draft. Requests that include both Shop and dependent channels arevalidated together, regardless of order.

Blocking by Shop

Rejected / action-required flag

If the result would leave a Shop-blocked product on a dependent channel, even a request that publishes only to Shop publishablePublish fails.productUpdate behaves the same way.

productUpdate caveats

publications is fully replaced

If the new list includes a dependent channel, even if the product is already on Shop, you must include Shop. If you also change status, validation uses the new status.

Error messages (retrying returns the same error)

RequestMessage
PublishFor the store setup, Shop publication is a prerequisite.
UnpublishFor the store setup, unpublishing from dependent publications is a prerequisite.

App-side steps (when creating active products via REST)

1
REST

Create with "published": false

Don't publish the product when creating it via the REST Admin API.

2

Call publishablePublish

Target Shop and Online Store.

3

Send Shop together with its dependent channels

Avoids unintended auto-corrections on dated versions.

5Deprecated / New: custom line items move from taxable to productCategoryId

DEPRECATED (2027-01 and later) taxable: true / false Only a binary taxable / not taxable choice Ignored in managed mode NEW : productCategoryId Assign a Standard Product Taxonomy category Reduced rates Exemptions Category-specific tax rules Expresses treatments a yes/no taxable flag can't
StoreHow taxable is handledHow productCategoryId is handled
With managed mode Ignored In all API versions The input that determines tax treatment No category: treated as Uncategorized, withstandard ratetax applied
Without managed mode As before taxable: false means not taxed If taxed, Shopify can use the category for tax calculation

Schema changes

Deprecation

2027-01 and later

DraftOrderLineItemInput.taxable and orderEditAddCustomItem 's taxable argument is deprecated. No schema changes in 2026-10 and earlier.

Unchanged

Read side

Fields that return tax status and webhook payloads that include tax status are unchanged.Reads are not deprecated.

New

Input and read

Draft orders: draftOrderCreate/Update/Calculate 's productCategoryIdOrder editing: orderEditAddCustomItem gets a new argument.

Implementation flow

1

Look up the ID with the taxonomy query

Search by category name to get the id and fullName.

2
ID

Pass it to productCategoryId

IDs not in the current taxonomy return a user error.variantId is ignored when provided.

3

Read it back with productCategory

DraftOrderLineItem/CalculatedDraftOrderLineItem/CalculatedLineItem. Null for variant line items.

query {
 taxonomy {
 categories(search: "t-shirts", first: 5) {
 nodes {
 id
 fullName
 }
 }
 }
}
In stores using managed mode, tomake an entire draft order tax-exempt, set the customer, company, or company location to tax-exempt.To exempt just one line item, use a category.

6Clarification: Checkout footer display

Checkout / Thank you page Body Merchant-configured content Policy links and copyright notice → hidden with HIDDEN Shopify-provided transaction information May still appear with HIDDEN (not controllable)

CheckoutBrandingFooterContent and CheckoutAndAccountsConfigurationBrandingFooterContent visibility controlsonly the footer content merchants can configure.

Even when visibility is HIDDEN , every checkout and Thank you page may showShopify-provided transaction informationin the footer. This is part of checkout and can't be controlled through branding.

No changes to fields, input types, enums, scopes, or mutations. Not tied to a new API version. Existing settings keep working as-is.

Impact: Apps that use the legacy Checkout Branding API or the Checkout and Accounts Configuration API to manage branding for Shopify Plus stores and that manage footer visibility, render previews, or run visual tests. Apps that don't manage footer visibility are unaffected.

75 key points for engineers

1. Default rule: if you don't manage it, don't send it

In Markets, currencySettings/priceInclusions is not validated if you omit it. If you send it, validation also covers the defaults for any omitted subfields, so match the required defaults when you send it.

unstable dated

2. Publishing behavior depends on the API version

On unstable, the request fails. On dated versions, Shopify adds Shop or removes dependent channels andsaves the corrected result automatically. Channels you didn't name can change, so always send Shop and its dependent channels together.

3. Retrying won't fix it

Publishing errors are validation errors, so retrying the same request returns the same error. Don't put these requests in a retry queue. Route them to a branch that fixes the request instead.

2026-07

4. Error codes depend on the API version

Tax display violations: from 2026-07 onward, INCOMPATIBLE_CONFIGURATION; before that, GENERIC_ERROR. Currency violations: UNSUPPORTED_CURRENCY. Check code and field, not just the message string.

5. taxable: reading is fine, but writes need a replacement

In managed mode, writes to taxable areignored in all API versions, and custom line items with no category are taxed at the standard rate. Apps that relied ontaxable: false to make items tax-exempt may unintentionally charge tax on managed-mode stores. From 2027-01, migrate to productCategoryId . Reading tax status and webhooks are unchanged.

83 practical use cases

Shop Online
USE CASE 1

Update publishing in product sync and PIM integration apps to support managed mode

Challenge
You sync products from an external PIM or core system and publish them only to Online Store or Headless. On managed-mode stores, this fails on unstable, and on dated versions the products get published to Shop automatically.
Approach
Always send Shop and its dependent channels together in publish requests. To unpublish, remove the dependent channels first or include them in the same request. When creating via REST, use "published": false → publishablePublish.
Impact
Prevents unintended channel states caused by auto-correction on dated versions, and keeps working if dated versions later adopt unstable's behavior.
Tech notes
productUpdate replaces publications entirely, so always include Shop, even for products already on Shop. Treat these errors as non-retryable.
Category Category Category Draft orders
USE CASE 2

Set the correct tax classification on custom line items in B2B and phone-order draft orders

Challenge
A quoting or phone-order app used taxable: false to make custom line items tax-exempt, but managed-mode stores ignore this and tax them at the standard rate.
Approach
taxonomy Look up the category ID with a query and pass it toDraftOrderLineItemInput.productCategoryId/orderEditAddCustomItem . For order-wide exemptions, use tax-exempt on the customer, company, or company location.
Impact
Reduced rates, exemptions, and category-specific rules can be expressed per line item, producing more accurate tax calculations than the binary taxable flag.
Technical notes
variantId is ignored on line items that specify it. Read the saved result back with productCategory to verify. The taxable input is deprecated from 2027-01 onward.
USD
USE CASE 3

Add validation to settings pushed by market configuration tools and cross-border e-commerce builds

Problem
Tools and build templates that bulk-apply market currency and tax-inclusive pricing write their own values to markets that include the US on managed mode stores, which causes errors.
Approach
US only: USD /localCurrencies: false/ADD_TAXES_AT_CHECKOUT. US + other countries: localCurrencies: true/INCLUDES_TAXES_IN_PRICE_BASED_ON_COUNTRY. If you don't need to manage it, omit the input entirely.
Impact
Prevents push failures up front and reduces rework during setup.
Technical notes
UNSUPPORTED_CURRENCY and INCOMPATIBLE_CONFIGURATION(before 2026-07: GENERIC_ERROR) are captured to show which field violates the requirements via userErrors.field .
For apps with checkout branding previews or visual tests, assume that even with the footer set to HIDDEN, Shopify-provided transaction information may still be displayed, and update expected values (snapshots) accordingly.

9One-line summary for proposals

"In stores using Shopify Tax managed mode,US market currency and tax display, product publishing that requires Shop, and category-based tax on custom line itemsare enforced by Shopify.
Apps can adapt with three changes: don't send settings you don't manage, publish together with Shop, and replace taxable with productCategoryId."