Shopify Community AMA with Shopify Developers: The New GraphQL Product APIs

Topic summary

Shopify hosted a live AMA on August 20th, 2024, addressing questions about new GraphQL Product APIs that support up to 2,000 variants per product (released in 2024-04 stable API). The APIs come with deprecations of REST product APIs and several GraphQL fields.

Major Developer Concerns:

  • Scope re-authorization issues: Multiple developers expressed worry about requiring existing users to re-authorize with write_publications scope, fearing low adoption rates (potentially only 10%). They requested automatic backfilling similar to the 2018 multi-location rollout. Shopify later confirmed a backfill option is available via form submission.

  • API efficiency complaints: Developers noted GraphQL requires multiple mutations for tasks REST handled in one call (product creation + publishing + inventory now needs 3+ separate calls). Concerns raised about atomic operations and increased complexity.

  • productSet limitations: The mutation doesn’t support inventory or publishing fields, forcing developers to use additional mutations. Shopify acknowledged they’re working to extend capabilities.

  • Bulk operation issues: Reports of errors when products have 40+ variants, missing variants in responses, and inconsistent file size limits (sometimes 20MB, sometimes less).

  • Missing features: No variantsCount for entire shop, productsCount limited to 10,000, no easy way to bulk activate inventory items across locations.

Shopify Responses:

The team acknowledged most concerns as “something we are considering” and confirmed they’re actively working on performance improvements, extending mutation capabilities, and addressing bugs as they move toward full 2,000-variant support.

Summarized with AI on November 3. AI used: claude-sonnet-4-5-20250929.

We’ll be hosting a live AMA on Tuesday, August 20th from 11 am to 1 pm ET that will answer questions on the new GraphQL Product APIs announced in the 2024-04 stable API release.

Hit reply now to post any questions here on this thread before August 20th, 2024 and we’ll answer them live. You can also bring your questions to be answered the day of.

What to know:

The new GraphQL product APIs that support up to 2,000 variants per product were recently launched in the 2024-04 stable API release, enabling developers to build support for larger and more complex catalogs. Alongside the release of the new GraphQL product APIs, we also announced deprecations of the REST product APIs, as well as several fields within the existing GraphQL product APIs.

This AMA is an opportunity to interact with the developers who built these APIs to get any questions on both the new APIs and associated deprecations answered.

In advance of the session, please review the API documentation on the new GraphQL product APIs, our FAQ and our relevant community discussions.

Rules of engagement:

We’ll do our best to follow up on every question during the event.

  • You must be logged into your account on Community to participate.
  • Assume positive intent with one another and be kind. Some users may be new and learning how to engage with the Community.
  • Be authentic and honest with your questions and answers.
  • Do not ask for or share store admin login details or passwords.
  • Like posts and threads that are of interest or helpful to you.
  • Be constructive with criticism, not offensive.
  • Share your experiences and insights whenever you can to support others.
  • Abuse, harassment, and spam content won’t be tolerated.
8 Likes
  1. When implementing a data import flow /integration from external systems, is it realistic that a single productSet mutation will be sufficient or would it generally be a safer option (in terms of performance, retry mechanisms, observability, reliability) to use separate APIs to first create the product, then attach variants, then attached medias and metafields, rather than trying to set everything in one go?

  2. Will productSet be fully transactional, i.e. either the entire request succeeds or none if it does? In both sync and async mode?

  3. Since market APIs can be used to set a fixed price of an item in the default market to a different value than item’s price in the store currency, are there plans to deprecate product variant price field at some point? What use cases have you seen where a merchant would want the default market price to be different from product variant price?

4 Likes

Hello!

We already made the switch to support the 2,000 variants with GraphQL and it’s working well.

However, on stores we are doing calls to Shopify Ajax API to get the variants of a product (The prices of the variants are already converted with Market when doing it)

But even with the new version, we receive only 100 variants with no pagination system.

So for the 100 first variants we have the prices converted (for example we have the exact price someone applied to a product for France)

But for the other variants we don’t have it so we can’t get real time prices.

We’re not a sales channel so we can’t use the Storefront API.

When will you update it so we can actually get all the variants?

Thank you!

6 Likes

There are many existing stores that allow you to order things like custom t-shirts that leak customer information via the /collections JSON endpoint, where every product is always visible. I’ve seen examples of stores that leak photos, addresses, personal messages, etc in this way.

For our use case we need customers to be able to create their own products based on a file they upload.
Can the variant system be used for this in a way that keeps all custom data private?

3 Likes

Hi
We currently use REST API’s published_at field on the Product to hide sold-out products from online store channel and publish back-in-stock products to the online store channel.

Since the REST API product endpoint is being deprecated we are rewriting our app logic using GraphQL.

But in the GraphQL productUpdate mutation (2024-10), it says publishedAt field is deprecated and asks us to Use PublishablePublish instead. This means we have to re-authorize all existing customers with the write_publications scope

We are extremely worried that we will not be able to re-authorize 100% of our customers. Because most customers have our app on auto-pilot trusting it to do its job. Likely scenario is only 10% re-authorize which will be a disaster for our app that has been around for over 10 years.

Back in 2018, when multi-location was rolled-out by Shopify, app developers were given the ability to backfill the new scopes : read_inventory, write_inventory and read_locations. See screenshot attached showing how it was done.

As you are taking away the publish ability by deprecating the REST endpoints, it would only be fair to give automatic access to its equivalent in GraphQL to ensure smooth migration. Since our existing customers have already given us “publish” permission by installing our app, can you please enable back-population of the new access scopes necessitated by this deprecation similar to what was done for the multi-location roll-out in 2018. This is a practical solution that works for all stakeholders.

This issue has been raised by other developers as well in the previous AMA.

4 Likes

Question 1:

For retrieving the total number of products, we previously used the products/count endpoint in the REST API. What is the recommended alternative in the new GraphQL product APIs for fetching the total product count?

Question 2:

In our current implementation, we rely on the REST API’s Product object within Webhooks. Will the new GraphQL product APIs accommodate similar functionality with the Product object? Additionally, will updated documentation be provided, particularly since the current documentation for the product/update webhook (Webhooks Documentation) still references the REST API?

Question 3:

We currently use the REST API’s Product object in Bulk Operations. As we transition to the new GraphQL product APIs, how will the Product object be supported in Bulk Operations? Will there be comprehensive documentation available to guide this transition? Currently, some fields from the GraphQL Product object do not work in Bulk Operations as they do with the REST API’s Product object.

Here is an example of our current GraphQL query used in Bulk Operations:

mutation {
  bulkOperationRunQuery(
   query: """
    {
      products {
        edges {
          node {
            id
            title
            handle
            publishedAt
            media(first: 1) {
              edges {
                node {
                  preview {
                    image {
                      originalSrc
                    }
                  }
                }
              }
            }
            variants(first:100) {
              edges {
               node {
                 sku
                 barcode
               }
             }
            }
          }
        }
      }
    }
    """
  ) {
    bulkOperation {
      id
      status
    }
userErrors {
    field
      message
    }
  }
}

Specifically, can we expect all fields from the GraphQL Product object to be functional in Bulk Operations?

4 Likes

Question about product and variant counts:

  1. productsCount is returning only upto 10,000 count. We need to know the exact number of products in a shop like the REST api endpoint currently does. This also goes for other counts that are limited to 10,000.

  2. we need variantsCount ie. the total number of variants in a shop. the unified Count object does not have this presently. Note that Product.variantsCount gives only the variant count for a given product. I’m referring to the the “total” variantsCount of the entire shop. the variants/count.json REST endpoint returns the total variant count of a shop but that is being deprecated.

4 Likes

I’d recommend not creating unique products based on customer inputs, since product creation is not storefront activity. Any apps that do this are likely to cause leaking of sensitive data, and I’d recommend against using them.
Ideally the customizations a customer make to a product land on the line item properties and metafields.
Is there any more information that make the above not workable?

3 Likes

Hello,
For creating a product with multiple variants, is it possible to do it using a single mutation?

What’s the exact use case for productSet and productCreate/productVariantsBulkCreate mutations?
I am trying to create a product with more than 100 variants using productSet, but can’t find inventoryItem in prodctSet.variants (ProductVariantSetInput)

So for creating a new product with variant fields like tracking, weight etc, do I have to use productCreate and then create variants using productVariantsBulkCreate?
I see inventoryItem in productVariantsBulkCreate though (ProductVariantInput)

Thanks,
Lily

2 Likes

Hello Team,

I share the same concern as @Naren1 and regarding the need to re-authorize all existing customers with the write_publications scope.

We manage 4 public apps that use automations and webhooks for creating and updating products based on our app functionalities. The issue is that if users don’t access the app, we can’t update the app scopes & it will stope & break the app automations. Therefore, I strongly request that publishing products be allowed under the existing write_products scope.

Please avoid introducing a new scope like write_publications. If it’s unavoidable, could you provide a workaround so that existing access tokens can continue publishing products using the write_products scope? For new app users, we will of course request the write_publications scope.

Additionally, I’m concerned about the efficiency of the GraphQL API compared to REST. In REST, we could add and publish a product with a single HTTP request. However, in GraphQL, the same process requires 3 HTTP calls:

  • productCreate mutation
  • publishablePublish mutation
  • Fetching publicationId with another mutation

While REST handled this with fewer requests and less complexity, GraphQL seems to make the process longer and more complicated.

Moreover, adding tags and creating or updating variants also require separate mutations. Could we have a single master mutation that allows us to create a product with basic parameters, all in one HTTP call?

Could you please look into this? Many other developers share these concerns as well. Any assistance would be appreciated.

Thank you.

3 Likes

I’ve been experiencing an issue with the productVariantsBulkCreate mutation, specifically when using the REMOVE_STANDALONE_VARIANT strategy. Despite this setting, the default variant is still being created (using the first option and value defined for the product) and not removed as expected. When I contacted your API team, they mentioned they couldn’t replicate the issue. However, I’ve seen multiple discussions in forums where others have encountered the same problem. The current workaround—allowing Shopify to create the default variant, then renaming and removing it manually before adding the desired variants—seems far from ideal. Is this a known issue, or am I overlooking something?

Additionally, could this issue be avoided by using the productSet mutation to immediately create the product with the respective options and variants? If productSet doesn’t create the default variant, this might be a better approach for me. What I would like is more freedom with productSet like setting the inventory location id as this is not an option for now…

2 Likes

In the Admin REST API we had the field presentment_prices in Variant which used to return price of product with different currencies. In the graphql API this has been replaced with contextualPricing in ProductVariant but earlier this was a list and now it is just a Object.
How can I get presentment_prices for all currencies using graphql API given that I don’t know all the currencies beforehand ?

2 Likes

Why does productSet mutation not have the ProductSetInput.variants.inventoryItem field, just like ProductVariantsBulkCreateInput? It makes the mutation unusable for me. Let us at least set the location it should be stocked at. Otherwise I need to fire off 4 extra mutations per variant just to:

  1. set tracked: true for the variant using inventoryItemUpdate mutation
  2. use inventoryActivate to activate the variant for my Fulfillment Service
  3. use inventorySetQuantities to set the initial quantity from my Fulfillment Service
  4. use inventoryDeactivate to deactivate the variant from the default location

This just seems incredibly convoluted to me :disappointed_face:

5 Likes

Hey team,

We have been using the productVariantsBulkUpdate mutation since the beginning of the year and for the majority of that time things have worked great. More recently though (seemingly in correlation with the variant limit increase) we have noticed the following issues:

  1. When a product has more than roughly 40 variants, the following error appears on random variants for that product in the .jsonl response - ‘This product is currently being modified. Please try again later.’
  2. Likely associated with the previous issue, the .jsonl file is missing variants entirely from the response. We cannot reproduce this consistently but it impacts our merchants on occasion. It seems most likely to happen when we are mutating more than 100 products. For example, a mutation targeting 1000 variants only returns 700 are yet the highest lineNumber of a variant in the file is greater than 700 implying the other 300 were at least received in the request. Of the 300 missing, some are mutated but some are not.

Given that productUpdate.variants has been deprecated in favour of using the productVariantsBulkUpdate mutation, and considering the 2000 variants limit means both of these issues are more likely to be encountered, are these issues something that can be addressed? Alternatively, in what ways could we work around these limitations when mutating a large number of products with a large number of variants?

2 Likes

We have an app block that takes a customer’s file and sends it over to our server for analysis (we’re a manufacturing company creating physical objects based on clients’ designs). After this we need to store the file and analysis, so we save them into a meta object (as it contains too much info for a line item, and also includes some files our server generates).

When adding to the cart we create a new product and link the the meta object to it, so we have access to the data without exposing it to others (as meta objects are private).

This all works, but it’s so convoluted, and we can’t use things like the product image in the cart, because that image will get exposed to the public endpoints (and the image would contain our clients’ design which we want to keep private).

Still hoping Shopify will implement a ‘private’ flag on products at some point, hiding them from all the public endpoints and only allowing access via a direct product ID in the API. That would solve so many issues. Really don’t understand why all products should be visible on the JSON endpoints.

2 Likes

Great work on the ProductSet mutation. We’re also using the productVariantsBulk****Update mutation to upload a catalog from a csv. However, we have run into some challenges. For context, on ocassion, we have to update upto 200k variants each upload.

When a variant needs to be added to a new inventory location, we cant simply add the availableQuantity and locationId. Instead, we need to first run inventoryBulkToggle****Activation to activate this variant’s inventory item in a particular location and then continue with the above mutation. This would be alright if it was available in the Bulk Mutation API but unfortuntaly this only works as regular mutation which means for catalogs with 1000s of variants, we need to run a queue just to activate these inventoryItems in a location only to be able update the availableQuantity in the productVariantsBulkUpdate mutation. Is there a better way to manage this? It would be really nice to activate this automatically in the above productVariantsBulkUpdate mutation on passing of availableQuantity and locationId.

This is a similar challenge for inventorySetAdjustments too

Feature request: The current Bulk Mutation Query which currently offers an incrementing objectCount in the operation status api. It would be nice to get a totalObjectCount as well to allow us to estimate the progress or atleast show the progress to the end user.

The current file size that is accepted in the mutation is not consistent, sometimes, it is 20mb, sometimes even lesser. Is there a guideline for this? We’re now simply sending 100 products at a time to be on the safe side but it would be great to know a better way to manage this do reduce the number of bulk mutations in queue.

3 Likes

Hey folks!

Thank you for joining our AMA for the new GraphQL Product APIs. Our developer team will be working through each question and will do their best to reply within the 2 hour time.

If you haven’t posted your question yet, make sure to get it in before 1pm EDT today!

3 Likes

Hi @evaldas_92

  1. We have introduced productSet to our APIS for this specific scenario and are working to make it as performant as possible. That said, it currently does not support inventory & publishing - for those you would need to do additional calls. Media will be supported as of 2024-10 , but will download the files async.
  2. Yes, fully transaction sync and async
  3. will get back to you on this
1 Like

Where is the link for the live AMA?

Hi @Naren1

Thanks for this feedback, this is something we are considering.