Documentation

Shopify

Store domain handshake, GID-style product IDs, and location-based inventory.

Shopify is one of the cleaner integrations — well-documented REST and GraphQL APIs, predictable rate limits, native webhooks. The quirks come from its data model: every Shopify object has a globally unique GID, inventory is split across locations, and the auth flow needs the shop's myshopify.com domain up front.

Shop domain

Every Shopify store has a permanent domain like acme-store.myshopify.com. Even if the store uses a custom domain on the storefront, the API hostname is always <shop>.myshopify.com. Pass shop when starting the OAuth flow:

curl "https://appengine.appmint.io/connect/shopify/auth-url?shop=acme-store.myshopify.com" \
  -H "Authorization: Bearer $JWT" -H "orgid: $ORG"

The channel stores shop and uses it to build the API base URL: https://acme-store.myshopify.com/admin/api/2024-10/....

GIDs and numeric IDs

Shopify's GraphQL API exposes Global IDs like gid://shopify/Product/1234567890. The REST API uses bare numeric IDs (1234567890). The provider deals in GIDs internally, since GraphQL is the path forward for new features (Bulk Operations, Storefront API).

When mapping Shopify products in POST /sales-channel/mappings/categories or referencing locations, always use the GID form:

{
  "channel": "shopify",
  "sku": "SKU-100",
  "channelSku": "gid://shopify/ProductVariant/9876543210",
  "metadata": { "productGid": "gid://shopify/Product/1234567890" }
}

Location-based inventory

A Shopify shop has one or more locations (physical warehouses, retail stores, third-party fulfillment). Inventory levels are tracked per (variant, location). The default location is set in admin; multi-location shops require explicit decisions about which location each push affects.

During channel enable, set defaultLocationId:

{
  "shop": "acme-store.myshopify.com",
  "defaultLocationId": "gid://shopify/Location/123"
}

Inventory pushes go to the default location unless overridden. To split master across locations, use the channel mapping per-SKU:

{
  "sku": "SKU-100",
  "locationSplit": {
    "gid://shopify/Location/123": 0.7,
    "gid://shopify/Location/456": 0.3
  }
}

The push allocates 70/30 between the two locations.

Rate limits

Shopify's REST API uses a leaky bucket — 40 requests for the bucket, leaks at 2/s. The GraphQL API uses a points-based cost model: 1,000 points per query, restored at 50/s. Bulk Operations API runs queries asynchronously without blocking the regular budget.

The module config caps Shopify at 40 req/min, 40,000/day. For large catalog pushes, the provider switches to Bulk Operations automatically.

Webhooks

Shopify supports HMAC-signed webhooks. The provider auto-registers these on enable:

  • orders/create, orders/updated, orders/cancelled
  • products/create, products/update, products/delete
  • inventory_levels/update
  • app/uninstalled (drives credential invalidation)

The receiver verifies the HMAC against the shared secret, then writes the event into the unified order list or fires a sync.

Variants and options

A Shopify product has up to three options (Size, Color, Material) and multiple variants — each with its own SKU, price, and inventory. The provider treats Storefront variants and Shopify variants 1:1 by SKU. Shopify enforces:

  • Maximum 100 variants per product (default; can be raised to 2000 with the GraphQL productOptionsCreate).
  • Maximum 3 options per product. More requires multiple products.
  • Unique SKUs within a shop are not enforced by Shopify but are by the provider — duplicate SKU pushes return mapping_conflict.

Currency and markets

Shopify Markets lets a shop sell in multiple currencies and regions. Pricing rules can target a specific market via:

{
  "channel": "shopify",
  "scope": { "type": "all" },
  "adjustment": { "type": "set_price", "value": 24.99, "currency": "EUR", "marketId": "gid://shopify/Market/55" }
}

Without marketId, the rule applies to the shop's primary market.

Common failure modes

SymptomLikely cause
401 on every callAccess token revoked (app uninstalled). Re-OAuth.
429 burst on bulk pushHit the leaky bucket. Switch to Bulk Operations.
Inventory drift on multi-location shopsWrong defaultLocationId. Set per-SKU locationSplit.
Variants missing after syncProduct hit 100-variant cap. Split into multiple products.
Webhook not receivedWrong app URL or signing-secret rotation. Re-register webhooks.

The Shopify Admin API version is pinned (e.g. 2024-10) per provider release. Major Shopify API versions are released quarterly and supported for 12 months — the provider auto-upgrades on each release.