Use the [`productSet`](/docs/api/admin-graphql/unstable/mutations/productSet) mutation to sync the desired state of a product with data from an external source in a single operation This mutation is suited for apps and use cases where the state of the product model is managed outside of Shopify, for example with an Enterprise Resource Planning (ERP) system or Worksheet, and you want to update Shopify's product model to reflect your external state. The mutation is available in both [asynchronous](#create-a-product-with-variants-and-options-asynchronously) and [synchronous](#create-a-product-with-variants-and-options-synchronously) modes. The default is asynchronous. The [`productSet`](/docs/api/admin-graphql/latest/mutations/productSet) mutation has an input limit of 2K variants when run asynchronously and only 100 variants when run synchronously. This guide provides examples of how to create and update products asynchronously and synchronously, with data from an external source. ## Create a product with variants and options asynchronously The following [`productSet`](/docs/api/admin-graphql/unstable/mutations/productSet) mutation initiates an asynchronous operation to create a product with an option named `Color`. The option has three possible values: `Red`, `Green`, and `Blue`. The mutation also sets up product variants, each associated with one of the color options. The response to the mutation indicates that the operation has been successfully initiated with the status `CREATED`.
Products, variants, and options
Variant GID Option name Option value name
gid://shopify/ProductVariant/1 Color Red
gid://shopify/ProductVariant/2 Color Green
gid://shopify/ProductVariant/3 Color Blue
```graphql mutation setProduct { productSet( input: { id: "gid://shopify/Product/1", title: "My Cool Product", productOptions: [ { name: "Color", values: [ { name: "Red" }, { name: "Green" }, { name: "Blue" } ] } ], variants: [ { optionValues: [{ optionName: "Color", name: "Red" }] }, { optionValues: [{ optionName: "Color", name: "Green" }] }, { optionValues: [{ optionName: "Color", name: "Blue" }] } ] } ) { productSetOperation { id status userErrors { code field message } } userErrors { field message } } } ``` ```json { "data": { "productSet": { "productSetOperation": { "id": "gid://shopify/ProductSetOperation/1", "status": "CREATED", "userErrors": [] }, "userErrors": [] } } } ``` ### Check the status of the operation Use the [`productOperation`](/docs/api/admin-graphql/unstable/queries/productOperation) query to check the status of the operation, using the ID that was returned [when the product was created](#create-a-product-with-variants-and-options-asynchronously). The query response indicates that the operation is `COMPLETE` and provides the details of the created product. ```graphql query productSetOperation { productOperation(id: "gid://shopify/ProductSetOperation/1") { ... on ProductSetOperation { id status product { id title options { id name optionValues { id name } } variants(first: 100) { edges { node { id selectedOptions { name value } } } } } userErrors { code field message } } } } ``` ```json { "data": { "productOperation": { "id": "gid://shopify/ProductSetOperation/1", "status": "COMPLETE", "product": { "id": "gid://shopify/Product/1", "title": "My Cool Product", "options": [ { "id": "gid://shopify/ProductOption/1", "name": "Color", "optionValues": [ { "id": "gid://shopify/ProductOptionValue/1", "name": "Red" }, { "id": "gid://shopify/ProductOptionValue/2", "name": "Green" }, { "id": "gid://shopify/ProductOptionValue/3", "name": "Blue" } ] } ], "variants": { "edges": [ { "node": { "id": "gid://shopify/ProductVariant/1", "selectedOptions": [ { "name": "Color", "value": "Red" } ] } }, { "node": { "id": "gid://shopify/ProductVariant/2", "selectedOptions": [ { "name": "Color", "value": "Green" } ] } }, { "node": { "id": "gid://shopify/ProductVariant/3", "selectedOptions": [ { "name": "Color", "value": "Blue" } ] } } ] } }, "userErrors": [] } } } ``` ## Update the product data asynchronously The following [`productSet`](/docs/api/admin-graphql/unstable/mutations/productSet) mutation initiates an asynchronous operation to update an existing product's `Color` option. The original color values of `Red`, `Green`, and `Blue` are replaced with new values of `Maroon`, `Forest Green`, and `Deep Sea Blue`. The mutation also updates the product variants from the old color values to the new ones. Each variant retains its original GID.
Updated products, variants, and options
Variant GID Option name Option value name
gid://shopify/ProductVariant/1 Color Deep Sea Blue
gid://shopify/ProductVariant/2 Color Forest Green
gid://shopify/ProductVariant/3 Color Maroon
The response to the mutation indicates that the operation has been successfully initiated with the status `CREATED`. ```graphql mutation setProduct { productSet( input: { id: "gid://shopify/Product/1", title: "My Extra Cool Product", productOptions: [ { name: "Color", values: [ { name: "Maroon" }, { name: "Forest Green" }, { name: "Deep Sea Blue" } ] } ], variants: [ { optionValues: [{ optionName: "Color", name: "Deep Sea Blue" }] }, { optionValues: [{ optionName: "Color", name: "Forest Green" }] }, { optionValues: [{ optionName: "Color", name: "Maroon" }] } ] } ) { productSetOperation { id status userErrors { code field message } } userErrors { field message } } } ``` ```json { "data": { "productSet": { "productSetOperation": { "id": "gid://shopify/ProductSetOperation/2", "status": "CREATED", "userErrors": [] }, "userErrors": [] } }, "extensions": { "cost": { "requestedQueryCost": 11, "actualQueryCost": 11 } } } ``` ### Query the updated product asynchronously After the product has been updated asynchronously, use the [`productOperation`](/docs/api/admin-graphql/unstable/queries/productOperation) query to retrieve the updated product data. This query uses the [`ProductSetOperation`](/docs/api/admin-graphql/unstable/objects/ProductSetOperation) object to check the status of the operation and to retrieve the details of the updated product and its variants. The response to this query indicates that the operation is `COMPLETE`, and indicates that the product's title has been updated, and the color options have been updated to `Deep Sea Blue`, `Forest Green`, and `Maroon`. ```graphql query productSetOperation { productOperation(id: "gid://shopify/ProductSetOperation/2") { ... on ProductSetOperation { id status product { id title options { id name optionValues { id name } } variants(first: 100) { edges { node { id selectedOptions { name value } } } } } userErrors { code field message } } } } ``` ```json { "data": { "productOperation": { "id": "gid://shopify/ProductSetOperation/2", "status": "COMPLETE", "product": { "id": "gid://shopify/Product/1", "title": "My Extra Cool Product", "options": [ { "id": "gid://shopify/ProductOption/1", "name": "Color", "optionValues": [ { "id": "gid://shopify/ProductOptionValue/1", "name": "Deep Sea Blue" }, { "id": "gid://shopify/ProductOptionValue/2", "name": "Forest Green" }, { "id": "gid://shopify/ProductOptionValue/3", "name": "Maroon" } ] } ], "variants": { "edges": [ { "node": { "id": "gid://shopify/ProductVariant/1", "selectedOptions": [ { "name": "Color", "value": "Deep Sea Blue" } ] } }, { "node": { "id": "gid://shopify/ProductVariant/2", "selectedOptions": [ { "name": "Color", "value": "Forest Green" } ] } }, { "node": { "id": "gid://shopify/ProductVariant/3", "selectedOptions": [ { "name": "Color", "value": "Maroon" } ] } } ] } }, "userErrors": [] } } } ``` ## Create a product with variants and options synchronously The following [`productSet`](/docs/api/admin-graphql/unstable/mutations/productSet) mutation creates a product with an option named `Color`. The option has three possible values, `Red`, `Green`, and `Blue`. The mutation creates product variants where each is associated with one of the color options. Each variant is identified by a globally-unique ID. The mutation runs synchronously because the [`synchronous`](/docs/api/admin-graphql/unstable/mutations/productSet#argument-synchronous) field is set.
Products, variants, and options
Variant GID Option name Option value name
gid://shopify/ProductVariant/1 Color Red
gid://shopify/ProductVariant/2 Color Green
gid://shopify/ProductVariant/3 Color Blue
> Note: > `synchronous: true` executes the mutation in synchronous mode. ```graphql mutation setProductSync { productSet( synchronous: true, input: { title: "My Cool Product", productOptions: [ { name: "Color", values: [ { name: "Red" }, { name: "Green" }, { name: "Blue" } ] } ], variants: [ { optionValues: [{ optionName: "Color", name: "Red" }] }, { optionValues: [{ optionName: "Color", name: "Green" }] }, { optionValues: [{ optionName: "Color", name: "Blue" }] } ] } ) { product { id title description options { id name position values optionValues { id name hasVariants } } variants(first: 100) { edges { node { id selectedOptions { name value } } } } } userErrors { field message } } } ``` ```json { "data": { "productSet": { "product": { "id": "gid://shopify/Product/1", "title": "My Cool Product", "description": "", "options": [ { "id": "gid://shopify/ProductOption/1", "name": "Color", "position": 1, "values": [ "Red", "Green", "Blue" ], "optionValues": [ { "id": "gid://shopify/ProductOptionValue/1", "name": "Red", "hasVariants": true }, { "id": "gid://shopify/ProductOptionValue/2", "name": "Green", "hasVariants": true }, { "id": "gid://shopify/ProductOptionValue/3", "name": "Blue", "hasVariants": true } ] } ], "variants": { "edges": [ { "node": { "id": "gid://shopify/ProductVariant/1", "selectedOptions": [ { "name": "Color", "value": "Red" } ] } }, { "node": { "id": "gid://shopify/ProductVariant/2", "selectedOptions": [ { "name": "Color", "value": "Green" } ] } }, { "node": { "id": "gid://shopify/ProductVariant/3", "selectedOptions": [ { "name": "Color", "value": "Blue" } ] } } ] } }, "userErrors": [] } } } ``` ## Update the product data synchronously > Note: > Because this mutation encapsulates many domain entities and their relationships, forming valid product inputs requires more care and attention and the mutations will take longer to execute. The following [`productSet`](/docs/api/admin-graphql/unstable/mutations/productSet) mutation updates the existing product's `Color` option. The original color values `Red`, `Green`, and `Blue` are replaced with new values of `Maroon`, `Forest Green`, and `Deep Sea Blue`. The mutation also updates the product variants from the old color values to the new ones. Each variant retains its original GID. The mutation runs synchronously because the [`synchronous`](/docs/api/admin-graphql/unstable/mutations/productSet#argument-synchronous) field is set.
Updated products, variants, and options
Variant GID Option name Option value name
gid://shopify/ProductVariant/1 Color Deep Sea Blue
gid://shopify/ProductVariant/2 Color Forest Green
gid://shopify/ProductVariant/3 Color Maroon
```graphql mutation setProductSync { productSet( synchronous: true, input: { id: "gid://shopify/Product/1", title: "My Extra Cool Product", productOptions: [ { name: "Color", values: [ { name: "Maroon" }, { name: "Forest Green" }, { name: "Deep Sea Blue" } ] } ], variants: [ { optionValues: [{ optionName: "Color", name: "Deep Sea Blue" }] }, { optionValues: [{ optionName: "Color", name: "Forest Green" }] }, { optionValues: [{ optionName: "Color", name: "Maroon" }] } ] } ) { product { id title description options { id name position values optionValues { id name hasVariants } } variants(first: 100) { edges { node { id selectedOptions { name value } } } } } userErrors { field message } } } ``` ```json { "data": { "productSet": { "product": { "id": "gid://shopify/Product/1", "title": "My Extra Cool Product", "description": "", "options": [ { "id": "gid://shopify/ProductOption/1", "name": "Color", "position": 1, "values": [ "Deep Sea Blue", "Forest Green", "Maroon" ], "optionValues": [ { "id": "gid://shopify/ProductOptionValue/1", "name": "Deep Sea Blue", "hasVariants": true }, { "id": "gid://shopify/ProductOptionValue/2", "name": "Forest Green", "hasVariants": true }, { "id": "gid://shopify/ProductOptionValue/3", "name": "Maroon", "hasVariants": true } ] } ], "variants": { "edges": [ { "node": { "id": "gid://shopify/ProductVariant/1", "selectedOptions": [ { "name": "Color", "value": "Deep Sea Blue" } ] } }, { "node": { "id": "gid://shopify/ProductVariant/2", "selectedOptions": [ { "name": "Color", "value": "Forest Green" } ] } }, { "node": { "id": "gid://shopify/ProductVariant/3", "selectedOptions": [ { "name": "Color", "value": "Maroon" } ] } } ] } }, "userErrors": [] } } } ``` ## Next steps

Product management in GraphQL versus REST

Learn about the differences between using GraphQL and REST to interact with products, variants, and related API components.

Migrate to GraphQL

If you're new to using GraphQL at Shopify, review guides and resources for migrating your app to the GraphQL Admin API from the REST Admin API.

GraphQL basics

Learn about the basics of GraphQL, including its benefits over REST.