# Shopify in Python

Call the Shopify GraphQL Admin API from Python services, receive webhooks with HMAC verification and deduplication, run bulk operations on a schedule, and sync products and inventory with your ERP.

[Get started ▶](https://zato.io/docs/admin/guide/install/index.html) [Read the docs](https://zato.io/docs/index.html)

GraphQL

Admin API client

HMAC

webhook verification

24/7

scheduled syncs

7

guides and docs

Code examples

## Both directions, one platform

Call the Admin API from Python or receive Shopify webhooks through a REST channel, all with the same services.

**Call the Admin API**

```python
# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class GetProducts(Service):
    name = 'shopify.get-products'

    def handle(self) -> 'None':

        # Get a connection to Shopify ..
        conn = self.out.graphql['Shopify']

        # .. run a query ..
        result = conn.execute('{ products(first: 10) { edges { node { id title } } } }')

        # .. and log what we received.
        self.logger.info('Products: %s', result)
```

**Receive a webhook**

```python
# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class OrderCreated(Service):
    name = 'shopify.order-created'

    def handle(self) -> 'None':

        # Shopify delivers at-least-once, so deduplicate ..
        event_id = self.request.http.headers['X-Shopify-Event-Id']

        # .. skip events that were already handled ..
        if self.cache.get(event_id):
            return

        # .. remember this one ..
        self.cache.set(event_id, True, expiry=86400)

        # .. and acknowledge now, processing in the background.
        self.invoke_async('shopify.order-process', self.request.input)
```

Features

## Everything for Shopify integrations

The Admin API, webhooks and scheduled syncs, with the reliability primitives Shopify leaves to you.

[GraphQL Admin API](https://zato.io/docs/dev/shopify/graphql-admin-api-python.html)

Call Shopify's GraphQL Admin API with self.out.graphql - queries, mutations and variables, with the access token attached to every request for you.

```python
conn = self.out.graphql['Shopify']

# Variables are passed as a dict
params = {'sku': 'HAT-001'}

result = conn.execute(query, params=params)
```

[Webhook channels](https://zato.io/docs/dev/shopify/webhooks-python.html)

Receive orders/create, products/update and any other topic through REST channels, with HMAC verification and cache-based deduplication.

[Rate-limit aware](https://zato.io/docs/dev/shopify/rate-limits-and-backoff.html)

Back off on THROTTLED errors and stay under the cost-based leaky bucket without hand-rolling a limiter in every service.

[Scheduled syncs](https://zato.io/docs/dev/shopify/bulk-operations.html)

Run bulk operations, nightly reconciliation and catalog imports from the built-in scheduler - no cron jobs or external workers.

```python
# Invoked by a scheduler job, e.g. nightly at 02:00
class ReconcileInventory(Service):
    name = 'shopify.reconcile-inventory'

    def handle(self) -> 'None':
        erp_counts = self.get_erp_counts()
        self.publish_to_shopify(erp_counts)
```

[Security definitions](https://zato.io/docs/dev/shopify/graphql-admin-api-python.html)

Keep the X-Shopify-Access-Token header in an API-key security definition, never in code.

[Configuration as YAML](https://zato.io/docs/admin/enmasse-reference.html)

Define Shopify connections declaratively with enmasse and deploy them across environments.

Tutorials

## Learn by building

Step-by-step guides for building API integrations in Python.

[API In-depth API integration tutorial Learn how to design and build scalable, real-world, production-ready API integrations in Python. Start tutorial](https://zato.io/tutorials/main/01.html) [REST REST APIs in Python Build REST channels and outgoing connections - the same building blocks Shopify webhooks use. Start tutorial](https://zato.io/tutorials/rest-api/python.html) [GraphQL GraphQL usage examples Queries, mutations, variables and the DSL - everything self.out.graphql can do. Read the examples](https://zato.io/docs/dev/examples/graphql.html)

Guides

## Shopify integration guides

Each guide covers one part of a Shopify integration, with complete Python services you can copy and run.

[GraphQL The GraphQL Admin API from Python Connections, access tokens, API versions, queries and mutations](https://zato.io/docs/dev/shopify/graphql-admin-api-python.html) [Products Products and variants productSet, productVariantsBulkUpdate and the 2048-variant model](https://zato.io/docs/dev/shopify/products-and-variants.html) [Rate limits Rate limits and backoff The cost-based leaky bucket, the 1,000-point ceiling and THROTTLED](https://zato.io/docs/dev/shopify/rate-limits-and-backoff.html) [Webhooks Reliable Shopify webhooks HMAC verification, fast acknowledgments and deduplication](https://zato.io/docs/dev/shopify/webhooks-python.html) [Errors GraphQL error handling Why 200 OK does not mean success - errors and userErrors](https://zato.io/docs/dev/shopify/graphql-error-handling.html) [Bulk Bulk operations Full-catalog reads and writes, polled by the scheduler](https://zato.io/docs/dev/shopify/bulk-operations.html) [ERP ERP and inventory sync Source of truth, idempotent publishing and nightly reconciliation](https://zato.io/docs/dev/shopify/erp-inventory-sync.html)

FAQ

## Frequently asked questions

The GraphQL Admin API - Shopify marked the REST Admin API legacy in October 2024 and new public apps have been GraphQL-only since April 2025. The [Admin API guide](https://zato.io/docs/dev/shopify/graphql-admin-api-python.html) shows how to call it from Python with self.out.graphql.

Create a custom app in your Shopify admin, take its Admin API access token and store it in an API-key security definition that sends the X-Shopify-Access-Token header. The token never appears in your code - the connection attaches it to every request.

No. A Zato integration is a standalone backend that talks to Shopify with a custom app's access token - there is no App Bridge, no session tokens and no app-store review involved.

Shopify delivers webhooks at-least-once, so duplicates are guaranteed. Deduplicate on the X-Shopify-Event-Id header with [the built-in cache](https://zato.io/docs/dev/examples/cache.html), as shown in the [webhooks guide](https://zato.io/docs/dev/shopify/webhooks-python.html).

Shopify's GraphQL API returns HTTP 200 OK even for many failures, with the details nested in errors and userErrors fields. The [error handling guide](https://zato.io/docs/dev/shopify/graphql-error-handling.html) shows the pattern that catches both.

The Admin API uses a cost-based leaky bucket with a 1,000-point single-query ceiling. Keep queries small, read the cost feedback and back off on THROTTLED - the [rate limits guide](https://zato.io/docs/dev/shopify/rate-limits-and-backoff.html) has a ready-to-use retry pattern.

Use [bulk operations](https://zato.io/docs/dev/shopify/bulk-operations.html) - Shopify runs the query on its side and returns the results as a JSONL file. A scheduler job polls for completion, and only one bulk operation can run at a time per shop.

Make the ERP the source of truth, publish quantities to Shopify idempotently and reconcile nightly with the scheduler. The [ERP sync guide](https://zato.io/docs/dev/shopify/erp-inventory-sync.html) covers the architecture, SKU-matching pitfalls and the 50,000 inventory-quantities mutation limit.

Yes - define connections and security definitions in YAML with [enmasse](https://zato.io/docs/admin/enmasse-reference.html) and import them per environment, with secrets read from environment variables.

## Ready to build Shopify integrations?

Get started with Zato and connect Shopify to your enterprise systems in minutes.

[Get started ▶](https://zato.io/docs/admin/guide/install/index.html) [Read the docs](https://zato.io/docs/index.html)

Open source In Python
