Skip to main content

Manage Events subscriptions

Developer preview

Events is in developer preview on the unstable API version, available today for a subset of topics. Use it for early testing ahead of a stable release and broader topic coverage. For topics not yet supported, use webhooks alongside Events in the same shopify.app.toml. As Events expands topic coverage, it will become the primary subscription mechanism.

An Events subscription tells Shopify which resources your app wants to track, which changes on those resources matter, and where to send the delivery.

This page covers subscription configuration and the concepts that determine what qualifies a delivery. To narrow which changes trigger a delivery or shape what each delivery returns, see Filter Events deliveries and Events delivery structure.

Illustration of Events pipeline and how configuration gates deliveries.

You need Shopify CLI 3.92 or higher to configure Events in shopify.app.toml. Run shopify version to check your version, and upgrade Shopify CLI if needed.

Each topic you subscribe to has a required access scope. See the Events reference for a full list of supported topics and their required scopes.


The api_version field in [events] controls the GraphQL Admin API version used to validate and run subscription query operations:

shopify.app.toml

[events]
api_version = "unstable"
Note

Events is available only on the unstable API version. Use it for early testing ahead of a stable release and broader topic coverage. For all production use cases continue to use webhooks.


Each Events subscription is defined by an [[events.subscription]] entry in your shopify.app.toml file. Every subscription requires the following fields:

FieldPurpose
handleUnique ID for this subscription (alphanumeric, _, -, max 50 characters). Included in the delivery payload and headers.
topicCapitalized resource name (for example Product). See Topic boundaries.
actionsOne or more of create, update, delete. See Actions.
uriDelivery destination. HTTPS URL, AWS EventBridge ARN, or Google Pub/Sub URI.

Additional optional fields are available for filtering deliveries and defining their response structure:

FieldPurpose
triggersField paths that narrow update deliveries. If omitted, every change to the topic fires. See Delivery filtering.
queryGraphQL operation whose result appears in data. See Delivery structure.
query_filterExpression evaluated on the query result after query runs. See Delivery filtering.

A topic names the GraphQL Admin resource your subscription listens to. For example, Events subscriptions on the Product topic listen for changes to Product GraphQL Admin objects.

Some objects don't have their own topic because they only exist as part of another resource. For example, ProductVariant doesn't have a separate Events topic. Shopify surfaces ProductVariant changes on the Product topic. If you need to listen to changes to ProductVariant, you would subscribe to Product, not a standalone ProductVariant topic.

Use the Events reference for the current list of topics and validation behavior when you deploy.


actions lists which lifecycle transitions on the subscribed topic can produce a delivery.

  • create and delete apply to the topic entity itself. There's no field-path narrowing for those actions at the subscription level. Shopify matches these actions at the resource create/delete boundary for that topic.

  • update covers changes on the topic entity and, where the model routes them there, on owned children (for example ProductVariant fields under Product). Optional triggers restricts which field paths can qualify an update. That mechanism applies only to update. See Delivery filtering.

You can list any combination of create, update, and delete. A subscription that includes update alongside create or delete still uses triggers only when deciding which update changes qualify.


The following subscription listens for any create, update, or delete on the Product topic and delivers to a single endpoint. It uses no triggers, query, or query_filter, so every qualifying change fires a delivery with the base payload.

Product subscription

[events]
api_version = "unstable"

[[events.subscription]]
handle = "product-updates"

topic = "Product"
actions = ["create", "update", "delete"]

uri = "https://your-app.example.com/events/product"
{
"topic": "Product",
"action": "update",
"handle": "product-updates",
"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"
}
}

  • Delivery filtering: Narrow update deliveries with triggers and gate sends with query_filter.
  • Delivery structure: Shape data with query and understand what each delivery contains.

Was this page helpful?