For AI agents: the complete documentation index is available at https://docs.dataplatform.ovh.net/llms.txt, the full documentation bundle is available at https://docs.dataplatform.ovh.net/llms-full.txt, and this page is available as Markdown at https://docs.dataplatform.ovh.net/connectors-sources-shopify-technical-reference.md.
  • 🇬🇧 English
  • Shopify: Technical Reference

    This is the technical companion to the main Shopify connector documentation

    Objective

    This is the technical companion to the main Shopify connector documentation. It covers authentication internals, the full endpoint reference, pagination, rate limits, output format, and limitations, everything needed to integrate the connector into a data pipeline.

    Authentication

    Supported Modes

    The connector supports two interchangeable authentication modes that both end up sending an X-Shopify-Access-Token header on every API request.

    ModeFields filled in the UIWhat the connector does
    Direct tokenshop + access_tokenSends the token as-is.
    OAuth client_credentialsshop + client_id + client_secretExchanges the credentials at the Shopify OAuth endpoint, then uses the resulting offline access token.

    If access_token is filled, it takes priority. The OAuth exchange is skipped.

    Token Formats

    PrefixSourceNotes
    shpat_…Legacy "Develop apps" flow in the Shopify adminToken revealed once in the UI
    shpua_…Output of the client_credentials OAuth grantOffline access token, non-expiring while the app is installed

    Both prefixes are valid in the Access Token field and are used identically by the connector.

    Deprecated authentication methods

    MethodWhy
    API key (?key=… query string)Removed by Shopify
    Storefront access tokenDifferent audience (customer browsing); not accepted by the Admin API
    OAuth authorization_code flow with redirectDesigned for distributed public apps, not for a server-to-server data pipeline

    Custom App Approval

    For Customer / Order / DraftOrder / AbandonedCheckout / FulfillmentOrder data, Shopify requires Protected Customer Data approval at the app level. On a development store this is granted instantly when the merchant ticks the relevant boxes in the Dev Dashboard. On production stores distributed via the App Store, Shopify reviews the request manually.

    When the approval is missing, the API returns ACCESS_DENIED errors on the affected fields. The connector treats these as expected and returns whatever data was successfully fetched (with the restricted fields blanked out).

    Architecture

    The connector returns raw JSON from the Shopify GraphQL API. The platform takes over from there. It auto-discovers the schema from the JSON payload, flattens nested objects into dot-notation columns (slugified to lowercase with underscores), and stores the result in the lakehouse, queryable via Trino. Any new field Shopify adds to a node appears automatically on the next extraction.

    The connector itself is responsible for:

    ResponsibilityBehavior
    AuthBuilds the X-Shopify-Access-Token header from either the direct token or an OAuth exchange
    Endpoint routingMaps the selected endpoint type to a built-in GraphQL query
    PaginationLoops first: N, after: cursor while pageInfo.hasNextPage is true
    Cost-based back-offReads extensions.cost.throttleStatus, sleeps if the next request would exceed available budget
    ThrottlingCatches THROTTLED GraphQL errors and HTTP 429, retries with Retry-After
    Field-level access denialsReturns the partial data with restricted fields removed (instead of failing)

    API Version

    All requests target the 2026-04 version of the Shopify Admin GraphQL API. Update Shopify's release notes before pinning to a newer version, schema changes can rename fields or change types.

    Endpoint Reference

    Every paginated endpoint shares the same call shape:

    POST https://{shop}.myshopify.com/admin/api/2026-04/graphql.json
    { "query": "...", "variables": { "first": 100, "after": null } }

    The connector iterates pages until pageInfo.hasNextPage == false or the user-specified max_items cap is reached.

    For each endpoint below, "Output" is Raw JSON: the full GraphQL node object, with nested fields preserved. The platform flattens it downstream.

    products

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: products(first, after, sortKey: CREATED_AT)

    Default fields: id, handle, title, description, vendor, productType, status, tags, timestamps, totalInventory, tracksInventory, featuredImage, options, seo, onlineStoreUrl, priceRangeV2.

    product_variants

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: productVariants(first, after): top-level since API 2022-07; no parent product ID required.

    Default fields: id, sku, title, position, price, compareAtPrice, barcode, taxable, inventoryQuantity, availableForSale, timestamps, selectedOptions, parent product ref, image.

    collections

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: collections(first, after): unified view of manual + smart collections.

    Default fields: id, handle, title, description, updatedAt, sortOrder, productsCount, seo, image.

    customers

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: customers(first, after)

    Default fields: id, firstName, lastName, email, phone, state, note, tags, timestamps, verifiedEmail, numberOfOrders, amountSpent, defaultAddress, lifetimeDuration.

    PII fields (firstName, lastName, email, phone, defaultAddress.zip) require Protected Customer Data approval. Without it the rows still come through with those fields blanked out.

    customer_segment_members

    ParameterTypeRequired
    segment_idtextYes: Shopify GID, e.g. gid://shopify/Segment/12345
    max_itemsnumberNo

    Root field: customerSegmentMembers(first, after, segmentId: $segment_id)

    Use the segments endpoint first to discover segment IDs.

    orders

    ParameterTypeRequired
    query_filtertextNo (default status:any)
    max_itemsnumberNo

    Root field: orders(first, after, query: $query_filter, sortKey: CREATED_AT)

    query_filter accepts Shopify search syntax (e.g. created_at:>=2026-01-01, financial_status:paid).

    Default fields: id, name, legacyResourceId, lifecycle timestamps, displayFinancialStatus, displayFulfillmentStatus, money sets (totalPrice, subtotalPrice, totalTax, totalDiscounts, totalRefunded, totalShippingPrice), customer, addresses, channelInformation.

    draft_orders

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: draftOrders(first, after)

    Default fields: id, name, status, email, note2, timestamps, money sets, customer, shippingAddress.

    abandoned_checkouts

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: abandonedCheckouts(first, after)

    Default fields: id, name, abandonedCheckoutUrl, timestamps, money sets, customer.

    fulfillment_orders

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: fulfillmentOrders(first, after)

    Default fields: id, status, requestStatus, timestamps, destination (address fields), assignedLocation, parent order.

    tender_transactions

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: tenderTransactions(first, after)

    Default fields: id, paymentMethod, processedAt, remoteReference, test, amount, parent order, user.

    locations

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: locations(first, after)

    Default fields: id, name, isActive, timestamps, fulfillsOnlineOrders, shipsInventory, legacyResourceId, address.

    inventory_items

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: inventoryItems(first, after)

    Default fields: id, sku, tracked, requiresShipping, timestamps, countryCodeOfOrigin, harmonizedSystemCode, unitCost, parent variant + product.

    segments

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: segments(first, after)

    Default fields: id, name, query (segment definition expression), creationDate, lastEditDate.

    companies

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: companies(first, after): B2B only; returns empty if B2B is not enabled on the store.

    Default fields: id, name, externalId, note, timestamps, locationsCount, ordersCount, totalSpent.

    company_locations

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: companyLocations(first, after): B2B only.

    Default fields: id, name, externalId, note, timestamps, addresses, parent company.

    price_lists

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: priceLists(first, after): B2B / wholesale.

    Default fields: id, name, currency, parent.adjustment, linked catalog.

    catalogs

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: catalogs(first, after): B2B catalog assignments.

    Default fields: id, title, status, linked priceList.

    markets

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: markets(first, after): multi-region configuration.

    Default fields: id, name, handle, enabled, primary, webPresence.rootUrls, currencySettings.baseCurrency.

    discount_nodes

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: discountNodes(first, after): union of automatic + code + manual discounts.

    Default fields: id, plus a typed discount payload using inline fragments for DiscountAutomaticBasic, DiscountAutomaticBxgy, DiscountCodeBasic, DiscountCodeBxgy, DiscountCodeFreeShipping, DiscountAutomaticFreeShipping. Each variant exposes title, status, startsAt, endsAt, usage counts.

    code_discount_nodes

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: codeDiscountNodes(first, after): code discounts only.

    Same field shape as discount_nodes, restricted to the DiscountCode* types.

    gift_cards

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: giftCards(first, after): Shopify Plus only.

    Default fields: id, enabled, expiresOn, timestamps, lastCharacters, note, balance, initialValue, owning customer.

    selling_plan_groups

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: sellingPlanGroups(first, after): subscription plans.

    Default fields: id, name, description, createdAt, merchantCode, appId, summary, productsCount, options.

    marketing_events

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: marketingEvents(first, after): campaign tracking.

    Default fields: id, type, remoteId, startedAt, endedAt, manageUrl, previewUrl, UTM fields, owning app.

    publications

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: publications(first, after): sales-channel publications.

    Default fields: id, name, supportsFuturePublishing, owning app.

    payouts / disputes / balance_transactions

    ParameterTypeRequired
    max_itemsnumberNo

    Root path: shopifyPaymentsAccount.{payouts | disputes | balanceTransactions}(first, after). Shopify Payments must be enabled on the store. The connector returns an empty list (with a warning) when shopifyPaymentsAccount is null.

    Default fields (payouts): id, status, issuedAt, net, summary breakdown. Default fields (disputes): id, status, initiatedAt, amount, reasonDetails. Default fields (balance_transactions): id, type, transactionDate, test, amount, fee, net.

    metaobjects

    ParameterTypeRequired
    metaobject_typetextYes: the metaobject definition's type (e.g. recipe)
    max_itemsnumberNo

    Root field: metaobjects(first, after, type: $metaobject_type)

    Use the metaobject_definitions endpoint first to list the available types.

    Default fields: id, handle, type, displayName, updatedAt, capabilities.publishable.status, fields[].{key, value, type, jsonValue}.

    metaobject_definitions

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: metaobjectDefinitions(first, after)

    Default fields: id, type, name, displayNameKey, description, nested fieldDefinitions.

    metafield_definitions

    ParameterTypeRequired
    owner_typeselectYes: one of PRODUCT, PRODUCTVARIANT, CUSTOMER, ORDER, COLLECTION, ARTICLE, BLOG, PAGE, SHOP, LOCATION, COMPANY, COMPANY_LOCATION, MARKET
    max_itemsnumberNo

    Root field: metafieldDefinitions(first, after, ownerType: $owner_type)

    Default fields: id, namespace, key, name, description, ownerType, type.name, pinnedPosition.

    articles / blogs / pages / url_redirects / files

    ParameterTypeRequired
    max_itemsnumberNo

    Standard paginated content endpoints. Each returns the typed node object, see the Shopify GraphQL reference for the exact field shape per type. The connector requests a sensible default field subset per endpoint (handle, title, body/summary, timestamps, publication status, ..).

    For files, the query uses inline fragments for MediaImage, Video, and GenericFile, so the output includes a media-type-specific payload alongside id, alt, createdAt, fileStatus.

    events

    ParameterTypeRequired
    max_itemsnumberNo

    Root field: events(first, after, sortKey: CREATED_AT, reverse: true): shop audit log.

    Default fields: id, message, createdAt, appTitle, attributeToApp, attributeToUser, criticalAlert.

    staff_members / delivery_profiles / fulfillment_services

    Standard endpoints with a max_items parameter. fulfillment_services is unusual. The data is nested under shop.fulfillmentServices and is returned as a list (not paginated). The connector handles the special path automatically.

    shop

    No parameters. Returns a one-element list with the store's metadata, id, name, domain, currency, timezone, plan, billing address, primary domain, feature flags, timestamps. Useful as a small reference table.

    custom_query

    ParameterTypeRequired
    querytextareaYes
    variablesjsonNo (default {})
    connection_pathtextNo (default = auto-detect)
    max_itemsnumberNo

    Run any GraphQL query against the Admin API. Constraints:

    1. The query must declare $first: Int! and $after: String as variables.
    2. It must paginate one connection with pageInfo { hasNextPage endCursor }.
    3. Either provide connection_path (dot-path to the connection from the data root, e.g. products, shop.metafields) or let the connector auto-detect the first edges/pageInfo connection in the response.

    The connector substitutes $first (defaults to 250 or max_items when set) and $after (cursor from the previous page), then loops until pageInfo.hasNextPage is false.

    variables lets you pass additional parameters used by your query (e.g. {"query": "tag:vip"} for a customer search filter). $first / $after are reserved.

    Validation runs at extract time, invalid queries (missing variables) raise a clear error before the first HTTP call.

    Pagination

    All paginated endpoints use cursor-based pagination (Relay-style connections). The connector loops:

    {
      edges { node { ... } }
      pageInfo { hasNextPage endCursor }
    }

    With first: 100 (default page size, capped at 250) and after: <previous endCursor>. The loop ends when hasNextPage == false or the user-specified max_items is reached.

    Single-object endpoints (shop) and the nested list fulfillment_services skip pagination. The connector wraps the response in a one-element list.

    Rate Limits

    The Shopify Admin GraphQL API uses cost-based rate limiting (not requests-per-second). Every query has a point cost computed from its connection sizes; each store has a per-app bucket that refills at a fixed rate.

    PlanBucketRestore rate
    Standard / Shopify / Advanced100 pts100 pts/s
    Shopify Plus1,000 pts1,000 pts/s
    Enterprise2,000 pts2,000 pts/s

    Refer to Shopify's official rate-limit documentation for current details.

    Throttle Handling

    The connector handles throttling in three ways:

    1. Pre-emptive sleep: after every response, it inspects extensions.cost.throttleStatus. If the next page's cost would exceed the currently available budget, it sleeps for the time needed to refill.
    2. GraphQL THROTTLED errors: Shopify sometimes returns HTTP 200 with a THROTTLED error in the body. The connector retries after a short back-off.
    3. HTTP 429: rare, but handled with Retry-After. The connector retries up to 5 times before raising.

    Output Format

    Raw JSON

    The connector returns the contents of edges[].node as a list of dicts, exactly as Shopify GraphQL returned them. Nested objects (addresses, money sets, child arrays) are preserved.

    Example product node (truncated):

    {
      "id": "gid://shopify/Product/123",
      "handle": "snowboard",
      "title": "All-mountain snowboard",
      "vendor": "Acme",
      "productType": "Snowboard",
      "status": "ACTIVE",
      "createdAt": "2024-01-15T10:30:00Z",
      "totalInventory": 42,
      "featuredImage": {
        "url": "https://cdn.shopify.com/.../snowboard.jpg",
        "altText": "Snowboard front view"
      },
      "priceRangeV2": {
        "minVariantPrice": { "amount": "299.00", "currencyCode": "EUR" }
      }
    }

    Flattened in the lakehouse

    The platform automatically flattens nested objects into dot-notation columns, then slugifies them:

    Raw JSON pathLakehouse column
    idid
    featuredImage.urlfeaturedimage_url
    priceRangeV2.minVariantPrice.amountpricerangev2_minvariantprice_amount

    List-of-object fields (e.g. tags, options) are exploded automatically, one row per list element.

    Limitations

    • GIDs are strings, not integers. Shopify identifiers come as gid://shopify/Resource/12345: keep them as strings in your downstream queries.
    • No bulk operations. Very large extractions (millions of records) page synchronously through the GraphQL API. For multi-million-row stores, write a custom_query against bulkOperationRunQuery instead, or extract incrementally with a date filter (query_filter).
    • Shopify Payments endpoints require enrollment. payouts, disputes, balance_transactions return empty lists if Shopify Payments isn't activated on the store.
    • Protected Customer Data field-level approval. Without it, customer / order rows return with PII fields (firstName, lastName, email, phone, zip) blanked out, but the rows themselves are returned. Approve the relevant data categories in the Dev Dashboard to get full PII.
    • Sub-resources require custom_query. Per-order transactions / refunds / fulfillments and per-product metafields aren't dedicated endpoints. They are accessible via custom_query if you write a nested GraphQL.
    • B2B endpoints return empty without B2B. companies, company_locations, catalogs, price_lists return [] on stores without B2B enabled. No error, just empty.
    • gift_cards is Shopify Plus only. Lower plans receive ACCESS_DENIED and the connector returns an empty list.
    • Field set is fixed per endpoint. Each built-in endpoint has a default field selection. To customize fields (more or fewer), use custom_query.
    • Shopify GraphQL changelog. The connector is pinned to API version 2026-04. Field renames or removals in newer versions are not picked up automatically, review Shopify's release notes before bumping the version.

    Go further

    If you need training or technical assistance to implement our solutions, contact your sales representative or click on this link to get a quote and ask our Professional Services experts for a custom analysis of your project.

    Ask questions, give your feedback and interact directly with the team building the Data Platform on the dedicated Discord channel.

    If you need support with your OVHcloud services, create a request in our Help Centre.

    Join our community of users.