releases.shpreview
Shopify/Developer Changelog

Developer Changelog

Mon
Wed
Fri
JunJulAugSepOctNovDecJanFebMarAprMayJun
Less
More
Releases90Avg28/moVersionsv4.0 to v11.5

Starting with GraphQL Admin API version 2026-07, the [GiftCardCashOutTransaction](https://shopify.dev/docs/api/admin-graphql/2026-07/objects/GiftCardCashOutTransaction type is introduced as a new variant of the GiftCardTransaction interface. This type specifically represents transactions where a gift card balance is paid out through a point of sale (POS) system.

In previous API versions, such as 2026-04 and earlier, these transactions were classified as GiftCardDebitTransaction. From version 2026-07 onwards, they are identified as GiftCardCashOutTransaction. To accurately differentiate cash-out transactions from credit and debit transactions, use the __typename field when querying giftCard.transactions.

Below is an example query:

giftCard(id: "...") {
  transactions(first: 10) {
    nodes {
      __typename
      ... on GiftCardCashOutTransaction {
        id
        amount { amount currencyCode }
      }
    }
  }
}

You can now identify cart lines by their view_key when calling the cartLinesUpdate and cartLinesRemove mutations, as an alternative to the cart line id.

What's new

  • cartLinesUpdate accepts a viewKey on each CartLineUpdateInput, mutually exclusive with id.
  • cartLinesRemove accepts a viewKeys list, mutually exclusive with lineIds.

How to use

Provide exactly one identifier per line. Existing integrations that use id or lineIds keep working with no changes.

mutation RemoveLineByViewKey($cartId: ID!) {
  cartLinesRemove(cartId: $cartId, viewKeys: ["794864053:7c2a9f..."]) {
    cart { id }
    userErrors { field message }
  }
}

The end-to-end review management experience previously launched for new app submissions in the Partner Dashboard now also applies to app audits.

When a published app undergoes a quality check and requires changes, that feedback appears in the Partner Dashboard under App > Distribution. You’ll see the same requirement-level tracking, a structured fix workflow, and direct messaging used for app submissions.

What to do if your app has an active audit

If your published app currently has an open audit with outstanding issues, review and manage all feedback in the Partner Dashboard under App > Distribution. Use your app’s status page there to see required changes, update your app, and respond to the review team, instead of checking your email inbox.

Your store includes a default agents.md file accessible at /agents.md. The paths /llms.txt and /llms-full.txt also point to this content by default.

Add any of the following templates under Online Store > Themes > Edit code to serve different content per path:

  • templates/agents.md.liquid — controls /agents.md (and the default for the other two paths)
  • templates/llms.txt.liquid — controls /llms.txt only
  • templates/llms-full.txt.liquid — controls /llms-full.txt only

If no template is present for a given path, it falls back to your agents.md template, then to the Shopify-generated default.

Starting in API version 2026-07, the GraphQL Admin API supports local currency gift cards. You can create gift card products that are issued in a specific currency, and control whether buyers can redeem those gift cards across currencies. If your app creates gift cards directly, migrate from the deprecated initialValue field to initialAmount.

What changed

Use the new giftCardProductSet mutation to create and update gift card products. The input includes issuanceCurrency and crossCurrencyRedeemable, and automatically applies the product’s gift card settings to its variants. You can set issuanceCurrency and crossCurrencyRedeemable only when you create the product; you can’t change either field afterward.

Inspect a product’s settings through Product.giftCardSettings. If issuanceCurrency is null, Shopify issues gift cards from the product in the shop’s currency. If issuanceCurrency is set, Shopify issues gift cards in the specified currency, and buyers can purchase the product only in that currency. Publish these products only in markets where that currency is supported.

crossCurrencyRedeemable controls redemption behavior across currencies:

  • If crossCurrencyRedeemable is false, issued gift cards use a crossCurrencyRedemptionStrategy of NONE.
  • If crossCurrencyRedeemable is true and the product has no issuance currency, gift cards use MARKET_FX.
  • If crossCurrencyRedeemable is true and the product has an issuance currency, gift cards use SPOT_FX.

Gift card creation now accepts initialAmount, which replaces the deprecated initialValue field. initialAmount includes both the amount and currency. Query GiftCard.isRedeemable and GiftCard.crossCurrencyRedemptionStrategy to check whether a gift card can be redeemed and how cross-currency conversion is handled.

What to do

  1. If you create gift cards using giftCardCreate, replace initialValue with initialAmount before you upgrade to 2026-07.
  2. If you offer multi-currency stores, decide whether new gift card products should be pinned to a single issuance currency. Configure issuanceCurrency and crossCurrencyRedeemable when you create the product; you can’t change either field afterward.
  3. Update redemption flows to read GiftCard.crossCurrencyRedemptionStrategy so you can surface accurate cross-currency conversion behavior to merchants and buyers.

Related docs

We’ve updated our headless checkout authentication docs to refer to the silent single sign-on query parameter as sso=silent instead of logged_in=true.

This is a terminology and documentation update only. Existing checkout URLs that use logged_in=true will continue to work. Going forward, Shopify docs and examples will use sso=silent when describing the silent SSO flow from a headless storefront to checkout.

Use sso=silent when you want checkout to verify the buyer’s active session on the customer accounts domain through an OIDC-compliant flow. For most headless storefronts using the Customer Account API, we continue to recommend continuous cart authentication by setting the cart’s customerAccessToken and redirecting buyers to the cart’s checkoutUrl.

Learn more about authenticating buyers in checkout.

Next Generation Events are now available in developer preview, with field-level control over when events fire, what data they carry, and what triggered each delivery.

  • Subscribe to exactly what you care about. Field-level triggers pre-qualify deliveries before they reach your endpoint. A subscription scoped to product.variants.price won't fire on title edits, tag updates, or status changes. Only when the price changes.
  • Get the payload your app needs, not a fixed schema. You define the delivery payload with a standard Admin GraphQL query. No over-fetching fields you'll discard. No extra API call to get the data you actually wanted after the webhook lands.
  • Know what fired for each delivery. Every delivery includes fields_changed: an explicit list of the fields that triggered the event, with full entity paths and IDs. That means you don't need to infer, or diff against prior state.
  • Filter on current state. query_filter narrows deliveries based on the current state of your query output. Use it to skip events that don't meet your conditions, like only delivering for active products.
  • Configure in code. Subscriptions live in shopify.app.toml alongside your other app configuration. Version-controlled, reviewable, and deployable.

As a developer preview, Events are available in the unstable API version and APIs may change. Product and Customer topics are live today.

Configuration and payload
[events]
api_version = "unstable"

[[events.subscription]]
handle = "price_sync"
topic = "Product"
actions = ["update"]
triggers = ["product.variants.price", "product.variants.compareAtPrice"]

uri = "/api/events"

query = """
	query priceSync($productId: ID!, $variantsId: ID!) {
		productVariant(id: $variantsId) {
			id
			price
			compareAtPrice
			sku
		}
		product(id: $productId) {
			id
			title
			status
		}
	}
"""
query_filter = "product.status:'ACTIVE'"

Every delivery includes fields_changed, data from your query, and query_variables used to fetch it:

{
  "topic": "Product",
  "action": "update",
  "handle": "price_sync",
  "data": {
    "productVariant": {
      "id": "gid://shopify/ProductVariant/456",
      "price": "24.99",
      "compareAtPrice": "34.99",
      "sku": "SIGNAL-NOT-NOISE"
    },
    "product": {
      "id": "gid://shopify/Product/123",
      "title": "Peace & Quiet Tee",
      "status": "ACTIVE"
    }
  },
  "fields_changed": [
    "product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456'].price"
  ],
  "query_variables": {
    "productId": "gid://shopify/Product/123",
    "variantsId": "gid://shopify/ProductVariant/456"
  }
}
Learn more

Learn more about how Events relate to Webhooks: https://shopify.dev/docs/apps/build/events-webhooks Get started by Creating an Events subscription.

v4.0

The release of Shopify CLI 4.0 today brings clarity to CLI versioning, the introduction of automatic updates, and the announced removal of the deprecated --force flag from shopify app deploy.

Semantic Versioning

Shopify CLI is now following semantic versioning practices. Releases with new features will be minor versions, and bug fixes will be patch versions. When required, major version releases will be used to communicate breaking changes to CLI command structure or behavior.

For more information, see our announcement of the move to SemVer.

Automatic Upgrades

Starting with Shopify CLI 4.0, Shopify CLI upgrades itself automatically using the package manager you installed it with. Auto-upgrade is skipped in CI, project-local installs, and for major version releases. Automatic upgrades can be disabled with the shopify config autoupgrade off command.

For more information, see Shopify CLI documentation.

Removal of the --force flag for app releases

The --force flag on the app deploy and app release commands didn’t distinguish between low-risk operations (adding or updating extensions) and high-risk ones (deleting them). This flag has been removed in Shopify CLI 4.0. The previously released --allow-updates and --allow-deletes flags give you granular control, so your CI/CD pipelines can run unattended without the risk of accidental, irreversible deletions.

For more information, see the March 2026 changelog.

Other removed commands and flags

The following deprecated commands and flags have also been removed in Shopify CLI 4.0:

  • shopify webhook trigger (use shopify app webhook trigger)
  • shopify theme serve (use shopify theme dev)
  • shopify app generate schema (use shopify app function schema)
  • shopify app webhook trigger --shared-secret (use --client-secret)
  • shopify app generate extension --type (use --template)

You can now create your app's landing page in App Home as a Preact-based admin UI extension using the new admin.app.home.render target. This means your App Home UI extensions are bundled with your other admin UI extensions, eliminating the need for a separate web server to render your app's primary workspace.

Use this extension type when you want:

  • A persistent, full-page app workspace that's integrated into your extension bundle, rather than a separate iframe-hosted web app.
  • A unified source of truth for your app's primary UI, alongside your other admin UI extensions.
  • The performance and design-system advantages of Polaris web components without the need for hosting a web server for the App Home experience.
Availability

App Home UI extensions are available starting from API version 2026-07 and are intended for custom-distribution apps. If you're developing a public app for the Shopify App Store, you should continue using the iframe-based App Home solution.

Get started

To begin, scaffold a new extension-only app by selecting Build an extension-only app when prompted:

shopify app init

Alternatively, add an App Home UI extension to an existing app by selecting App home when prompted:

shopify app generate extension

For a comprehensive list of target APIs, web components, and configuration options, refer to the App Home UI extension reference.

New Features

Optional Consent

Users can now reject scopes and continue using your Mini. Consent is no longer all-or-nothing — if a user declines a scope, your Mini should gracefully degrade rather than block the experience. If your Mini hard-fails when a scope is rejected, please update it using the new hooks below.

useCheckScopesConsent Hook

Check at runtime which scopes a user has granted. Use this to conditionally render features that depend on a particular scope.

Usage:

import {useCheckScopesConsent} from '@shopify/shop-minis-react'

function MyMini() {
  const {scopes} = useCheckScopesConsent()

  if (scopes.includes('product_lists:write')) {
    return <SaveToListButton />
  }
  return <SignInPrompt />
}
useRequestScopesConsent Hook

Re-request consent after a user has previously declined. The hook must be invoked from a user interaction — you cannot re-prompt automatically. Use this for flows where granting consent unlocks a clear, user-initiated action.

Usage:

import {useRequestScopesConsent} from '@shopify/shop-minis-react'

function GrantAccessButton() {
  const {requestScopesConsent} = useRequestScopesConsent()

  return (
    <button onClick={() => requestScopesConsent(['product_lists:write'])}>
      Enable saving products
    </button>
  )
}
useCheckPermissions Hook

Separate from scopes, useCheckPermissions lets your Mini check OS-level permissions (camera, photo library, and so on) before invoking an action that requires them.

Usage:

import {useCheckPermissions} from '@shopify/shop-minis-react'

function CameraFeature() {
  const {permissions} = useCheckPermissions(['camera'])

  if (permissions.camera === 'granted') {
    return <CameraView />
  }
  return <RequestCameraButton />
}
request_blocked Sentinel

When a user has declined a scope or permission and the platform will not re-prompt, the relevant hooks now return a request_blocked sentinel value instead of null. This lets you distinguish "not asked yet" from "asked and blocked" and tailor your UI accordingly. See the Scopes Consent docs on shopify.dev for the full state machine.

Intents

Intents are a new communication layer between the Shop app and Shop Minis. The Shop app launches your Mini from contextually relevant moments — such as a product detail page — and passes along the context (typically a product). For partners, this opens a new path to distribution: instead of relying on the Explore tab alone, your Mini can be surfaced where buyer intent is highest.

Two intents are supported today:

| Intent | What it's for | | :

You can query the shippingLine field on FulfillmentOrderLineItem.

This field returns the ShippingLine associated with a fulfillment order line item, if available. This feature simplifies the process for order management and fulfillment apps to identify the shipping method for each line item. It is particularly useful in scenarios where fulfillment orders are merged across different delivery profiles, and the original per-line shipping service is not identified by the fulfillment order's delivery method.

For example, apps can use properties such as shippingLine.code, shippingLine.title, and shippingLine.source to accurately map line items to the correct carrier service or shipping method.

For more information, refer to the FulfillmentOrderLineItem reference.

We’ve published new migration guides to help you upgrade Checkout and Customer Account UI extensions to the latest API version and Polaris web components.

The new guides include:

  • Guidance for moving from React or JavaScript extension APIs to Preact, Polaris web components, and the global shopify object.
  • More than 60 component-specific migration pages, covering components such as Button, Checkbox, TextField, Banner and View for Checkout and Customer Account UI extensions.
  • Instructions for migrating checkout metafields to cart metafields

If your extension uses an API version earlier than 2025-10, use these guides to adopt Polaris web components, which are the default in API version 2025-10 and later.

Start with:

You no longer need to ask merchants to share function run logs with you. These logs are now automatically available in the Dev Dashboard for any function your app has the necessary access scopes to view.

What's Changed

Function run logs in the Dev Dashboard are now accessible based on the access scopes granted to your app by the merchant. The required scopes to view a log are determined by the function's input query. If your app has the necessary scopes to read these fields via the GraphQL Admin API, you will automatically see the run details without needing any additional action from the merchant.

What You Need to Do

If you expect to see function run details but don't, ensure your app has the scopes required by the input query. Here's how you can check:

  1. Request the scopes during your app's installation/authentication process: This is ideal for scopes your app consistently needs. Refer to Access scopes for instructions on declaring and requesting access scopes.

  2. Request protected customer data scopes when accessing customer data: Some fields, like customer details and addresses, require additional protected customer data access. Consult Protected customer data for the approval process and necessary data-level scopes.

  3. Use optional scopes for temporary or debugging access: If a scope is needed occasionally, such as for debugging, request it as an optional scope. Merchants can grant or revoke it without reinstalling the app.

Once the required scopes are granted, the run details will automatically be visible the next time you access the log.

Starting with the 2026-07 version of the Storefront API, the Cart emits a PRODUCT_UNAVAILABLE_IN_BUYER_LOCATION warning when a cart line contains a product that isn't available in the buyer's location.

Each affected cart line returns its own warning. The warning's target is set to the CartLine ID so you can map it back to the line in your UI.

For background on cart warnings and an example of handling them, refer to our docs on cart warnings.

The App Events API lets you send any event from your app to Shopify. App event data appears in your Dev Dashboard Logs alongside webhooks, Function executions, and API calls.

How it works:

1. Send app events to a single API endpoint: Define the event_handle and attributes you want to track and send them to the App Events API, including:

  • Feature usage: bulk_edit_completed, report_generated, automation_created
  • Workflows: onboarding_completed, campaign_sent, export_finished
  • Performance: sync_failed, api_timeout, rate_limit_hit
  • Conversion signals: limit_hit, premium_viewed, milestone_achieved
  • Billable activities: order_processed, email_sent, label_printed

2. View events in Dev Dashboard: All app events flow into Dev Dashboard Logs automatically for monitoring, alongside data Shopify provides about your app, i.e: Webhooks, Functions executions, and API calls.

3. Optional: Turn app events into billing: On Shopify App Pricing, any app event can become a usage-based charge. Define a meter in the Partner Dashboard, match it to an event_handle, and Shopify handles metering and invoicing. No additional code required.

App Events is available now for all apps, regardless of billing method. Learn more

Shopify App Pricing supports subscriptions, usage-based charges, or combined models, configured in the Partner Dashboard.

What's new:

Managed Pricing is now Shopify App Pricing Shopify App Pricing replaces Managed Pricing as Shopify’s default billing solution that gets configured during app submission in the Partner Dashboard. Apps previously on Managed Pricing will now see “Shopify App Pricing” as their selected billing solution.

Usage-based billing now possible with App Events API Charge based on merchant usage using the App Events API. Send events from your app, define meters in the Partner Dashboard, and Shopify handles aggregation, calculation, and invoicing. Three pricing structures supported: fixed, graduated, and volume. Supports negative reporting for automatic charge corrections.

New APIs make billing data more accurate Active Subscription API: Real-time subscription status (active, pending, cancelled, frozen) that persists beyond uninstall [Historical API:](https://shopify.dev/docs/apps/launch/billing/shopify-app-pricing#app

We're changing how public apps handle offline access tokens to enhance merchant data protection. Starting January 1, 2027, all public apps must use expiring offline access tokens when calling the Admin API. After that date, public apps still using non-expiring tokens will receive authentication errors.

This extends the April 1, 2026 change, which applied only to newly created public apps, to all public apps, including those created before April 1, 2026.

What apps are affected

Public apps making Admin API requests using non-expiring offline access tokens, including apps created before April 1, 2026

What apps are unaffected

  • Custom apps
  • Apps created by merchants either in the Dev Dashboard or in the admin

Why we're making this change

Non-expiring tokens, if leaked, remain valid indefinitely. Expiring tokens close that window in 60 minutes and rotate automatically, dramatically reducing the impact of a credential leak. This aligns with modern OAuth best practices, and as a developer it gives your app a predictable refresh flow.

Action required

Existing public apps: Migrate from non-expiring to expiring offline access tokens.

Merchants don't need to reinstall, as your app exchanges existing tokens through code. Follow the migration guide for the step-by-step path. If you use Shopify's app templates and official API libraries, refresh handling is already implemented; you only need to handle the token exchange and storage updates.

Need help? Engage with the dev platform community for support and questions.

Seven new Settings intents let apps open editors for notifications, payment capture, gift cards, delivery profiles, and business details. This builds on the initial Settings intents release from March.

With a single API call, your app opens the relevant Settings section as a contextual overlay and scrolls the merchant directly to the field they need to edit.

New intents

Notifications
  • edit:settings/NotificationsSenderEmail
  • edit:settings/NotificationsStaff
Payments and gift cards
  • edit:settings/PaymentCaptureMethod
  • edit:settings/GiftCardExpiration
Delivery
  • create:shopify/DeliveryProfile
  • edit:shopify/DeliveryProfile
Business
  • edit:settings/BusinessDetails

Each intent opens the relevant Settings page in a page stack and scrolls the merchant directly to the targeted card, following the pattern established in the initial release.

Resources

We've introduced markets as a new option in DiscountContextInput, enabling you to target discounts to specific regional markets, retail locations, or B2B company locations. This option can be used alongside existing eligibility options such as all, customerSegments, and customers.

You can now set market eligibility for all discount types, including:

  • Basic, BXGY, App, and Free Shipping discounts (both automatic and code-based).
  • Note that eligibility types are mutually exclusive—you can target either markets OR customer segments, but not both simultaneously.

What you can do:

  • Assign market eligibility to a discount by using markets in DiscountContextInput when creating or updating a discount.
  • Query the discounts and discountsCount fields on a Market to view the list of discount customizations for that market.
  • Filter discounts by any market eligibility using context:market or by specific markets using market_ids in discountNodes.

What you need to know:

  • Discounts do not inherit across different market types (e.g., from regional to B2B or retail). When you assign a discount to a regional market, it automatically applies to sub-markets of the same type (e.g., from "North America" to "Canada").
  • If you are using API versions prior to 2026-07, discounts with market eligibility will be filtered out, as these versions cannot represent them (both in node queries and specific discounts by ID).

For more information, refer to the Admin GraphQL API documentation.

What's changing

Shopify now applies stricter rate limits to bots and agents that access the Storefront API and Shopify-hosted online store pages. Bots and agents that don't sign their requests are subject to the strictest limits. To qualify for higher rate limits, operators should sign their requests with Web Bot Auth. For more details, see Storefront rate limits.

What you should do

If you operate a bot or agent accessing Shopify storefronts, sign your requests using Web Bot Auth. To get started, review the Web Bot Auth architecture and Cloudflare's implementation guide — for context only, you do not need to enroll with Cloudflare.

Higher access tiers

If you require higher rate limits than those provided to Web Bot Auth traffic, please contact us through this form.

Shopify Merchants

Shopify merchants who want to crawl their own stores can find ready-to-use Web Bot Auth signatures in the Shopify admin.

Last Checked
4h ago
Latest
Jun 2, 2026
Tracking since Oct 9, 2025