--- title: productSet - GraphQL Admin description: |- Performs multiple operations to create or update products in a single request. Use the `productSet` mutation to sync information from an external data source into Shopify, manage large product catalogs, and perform batch updates. The mutation is helpful for bulk product management, including price adjustments, inventory updates, and product lifecycle management. The behavior of `productSet` depends on the type of field it's modifying: - **For list fields**: Creates new entries, updates existing entries, and deletes existing entries that aren't included in the mutation's input. Common examples of list fields include [`collections`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productSet#arguments-input.fields.collections), [`metafields`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productSet#arguments-input.fields.metafields), and [`variants`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productSet#arguments-input.fields.variants). - **For all other field types**: Updates only the included fields. Any omitted fields will remain unchanged. > Note: > By default, stores have a limit of 100 product variants for each product. You can create a development store and > [enable the **Extended Variants** developer preview](https://shopify.dev/docs/apps/build/graphql/migrate/new-product-model/migrate-and-test#create-a-development-store-that-allows-2-048-variants-per-product) > to create or update a maximum of 2,048 product variants in a single operation. You can run `productSet` in one of the following modes: - **Synchronously**: Returns the updated product in the response. - **Asynchronously**: Returns a [`ProductSetOperation`](https://shopify.dev/docs/api/admin-graphql/latest/objects/ProductSetOperation) object. Use the [`productOperation`](https://shopify.dev/api/admin-graphql/latest/queries/productOperation) query to check the status of the operation and retrieve details of the updated product and its product variants. If you need to only manage product variants, then use one of the following mutations: - [`productVariantsBulkCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productVariantsBulkCreate) - [`productVariantsBulkUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productVariantsBulkUpdate) - [`productVariantsBulkDelete`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productVariantsBulkDelete) If you need to only manage product options, then use one of the following mutations: - [`productOptionsCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productOptionsCreate) - [`productOptionUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productOptionUpdate) - [`productOptionsReorder`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productOptionsReorder) - [`productOptionsDelete`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productOptionsDelete) Learn more about [syncing product data from an external source](https://shopify.dev/docs/apps/build/graphql/migrate/new-product-model/sync-data). api_version: 2025-01 api_name: admin type: mutation api_type: graphql source_url: html: https://shopify.dev/docs/api/admin-graphql/2025-01/mutations/productSet md: https://shopify.dev/docs/api/admin-graphql/2025-01/mutations/productSet.md --- # product​Set mutation Requires `write_products` access scope. Also: The user must have a permission to create products. Performs multiple operations to create or update products in a single request. Use the `productSet` mutation to sync information from an external data source into Shopify, manage large product catalogs, and perform batch updates. The mutation is helpful for bulk product management, including price adjustments, inventory updates, and product lifecycle management. The behavior of `productSet` depends on the type of field it's modifying: * **For list fields**: Creates new entries, updates existing entries, and deletes existing entries that aren't included in the mutation's input. Common examples of list fields include [`collections`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productSet#arguments-input.fields.collections), [`metafields`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productSet#arguments-input.fields.metafields), and [`variants`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productSet#arguments-input.fields.variants). * **For all other field types**: Updates only the included fields. Any omitted fields will remain unchanged. *** Note By default, stores have a limit of 100 product variants for each product. You can create a development store and [enable the **Extended Variants** developer preview](https://shopify.dev/docs/apps/build/graphql/migrate/new-product-model/migrate-and-test#create-a-development-store-that-allows-2-048-variants-per-product) to create or update a maximum of 2,048 product variants in a single operation. *** You can run `productSet` in one of the following modes: * **Synchronously**: Returns the updated product in the response. * **Asynchronously**: Returns a [`ProductSetOperation`](https://shopify.dev/docs/api/admin-graphql/latest/objects/ProductSetOperation) object. Use the [`productOperation`](https://shopify.dev/api/admin-graphql/latest/queries/productOperation) query to check the status of the operation and retrieve details of the updated product and its product variants. If you need to only manage product variants, then use one of the following mutations: * [`productVariantsBulkCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productVariantsBulkCreate) * [`productVariantsBulkUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productVariantsBulkUpdate) * [`productVariantsBulkDelete`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productVariantsBulkDelete) If you need to only manage product options, then use one of the following mutations: * [`productOptionsCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productOptionsCreate) * [`productOptionUpdate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productOptionUpdate) * [`productOptionsReorder`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productOptionsReorder) * [`productOptionsDelete`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productOptionsDelete) Learn more about [syncing product data from an external source](https://shopify.dev/docs/apps/build/graphql/migrate/new-product-model/sync-data). ## Arguments * input [Product​Set​Input!](https://shopify.dev/docs/api/admin-graphql/2025-01/input-objects/ProductSetInput) required The properties of the newly created or updated product. * synchronous [Boolean](https://shopify.dev/docs/api/admin-graphql/2025-01/scalars/Boolean) Default:true Whether the mutation should be run synchronously or asynchronously. If `true`, the mutation will return the updated `product`. If `false`, the mutation will return a `productSetOperation`. Defaults to `true`. Setting `synchronous: false` may be desirable depending on the input complexity/size, and should be used if you are experiencing timeouts. **Note**: When run in the context of a [bulk operation](https://shopify.dev/api/usage/bulk-operations/imports), the mutation will always run synchronously and this argument will be ignored. *** ## Product​Set​Payload returns * product [Product](https://shopify.dev/docs/api/admin-graphql/2025-01/objects/Product) The product object. * product​Set​Operation [Product​Set​Operation](https://shopify.dev/docs/api/admin-graphql/2025-01/objects/ProductSetOperation) The product set operation, returned when run in asynchronous mode. * user​Errors [\[Product​Set​User​Error!\]!](https://shopify.dev/docs/api/admin-graphql/2025-01/objects/ProductSetUserError) non-null The list of errors that occurred from executing the mutation. *** ## Examples * ### Asynchronously create a product with two variants #### Description Create a product with two variants asynchronously using different \[option values]\(https\://shopify.dev/docs/api/admin-graphql/latest/objects/ProductOptionValue). This example returns a \[\`productSetOperation\`]\(https\://shopify.dev/docs/api/admin-graphql/latest/objects/ProductSetOperation) with the status \`CREATED\`. #### Query ```graphql mutation createProductAsynchronous($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id } productSetOperation { id status userErrors { code field message } } userErrors { code field message } } } ``` #### Variables ```json { "synchronous": false, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "price": 69.99 } ] } } ``` #### cURL ```bash curl -X POST \ https://your-development-store.myshopify.com/admin/api/2025-01/graphql.json \ -H 'Content-Type: application/json' \ -H 'X-Shopify-Access-Token: {access_token}' \ -d '{ "query": "mutation createProductAsynchronous($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id } productSetOperation { id status userErrors { code field message } } userErrors { code field message } } }", "variables": { "synchronous": false, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "price": 69.99 } ] } } }' ``` #### React Router ```javascript import { authenticate } from "../shopify.server"; export const loader = async ({request}) => { const { admin } = await authenticate.admin(request); const response = await admin.graphql( `#graphql mutation createProductAsynchronous($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id } productSetOperation { id status userErrors { code field message } } userErrors { code field message } } }`, { variables: { "synchronous": false, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "price": 69.99 } ] } }, }, ); const json = await response.json(); return json.data; } ``` #### Ruby ```ruby session = ShopifyAPI::Auth::Session.new( shop: "your-development-store.myshopify.com", access_token: access_token ) client = ShopifyAPI::Clients::Graphql::Admin.new( session: session ) query = <<~QUERY mutation createProductAsynchronous($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id } productSetOperation { id status userErrors { code field message } } userErrors { code field message } } } QUERY variables = { "synchronous": false, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "price": 69.99 } ] } } response = client.query(query: query, variables: variables) ``` #### Node.js ```javascript const client = new shopify.clients.Graphql({session}); const data = await client.query({ data: { "query": `mutation createProductAsynchronous($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id } productSetOperation { id status userErrors { code field message } } userErrors { code field message } } }`, "variables": { "synchronous": false, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "price": 69.99 } ] } }, }, }); ``` #### Response ```json { "productSet": { "product": null, "productSetOperation": { "id": "gid://shopify/ProductSetOperation/1010603851", "status": "CREATED", "userErrors": [] }, "userErrors": [] } } ``` * ### Create a product and associate files #### Description Create a product and associate file attachments (like images or videos). This example returns the product and its associated image files. #### Query ```graphql mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id media(first: 5) { nodes { id alt mediaContentType status } } variants(first: 5) { nodes { title price media(first: 5) { nodes { id alt mediaContentType status } } } } } userErrors { field message } } } ``` #### Variables ```json { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "files": [ { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "file": { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "file": { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 } ] } } ``` #### cURL ```bash curl -X POST \ https://your-development-store.myshopify.com/admin/api/2025-01/graphql.json \ -H 'Content-Type: application/json' \ -H 'X-Shopify-Access-Token: {access_token}' \ -d '{ "query": "mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id media(first: 5) { nodes { id alt mediaContentType status } } variants(first: 5) { nodes { title price media(first: 5) { nodes { id alt mediaContentType status } } } } } userErrors { field message } } }", "variables": { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "files": [ { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "file": { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "file": { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 } ] } } }' ``` #### React Router ```javascript import { authenticate } from "../shopify.server"; export const loader = async ({request}) => { const { admin } = await authenticate.admin(request); const response = await admin.graphql( `#graphql mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id media(first: 5) { nodes { id alt mediaContentType status } } variants(first: 5) { nodes { title price media(first: 5) { nodes { id alt mediaContentType status } } } } } userErrors { field message } } }`, { variables: { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "files": [ { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "file": { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "file": { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 } ] } }, }, ); const json = await response.json(); return json.data; } ``` #### Ruby ```ruby session = ShopifyAPI::Auth::Session.new( shop: "your-development-store.myshopify.com", access_token: access_token ) client = ShopifyAPI::Clients::Graphql::Admin.new( session: session ) query = <<~QUERY mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id media(first: 5) { nodes { id alt mediaContentType status } } variants(first: 5) { nodes { title price media(first: 5) { nodes { id alt mediaContentType status } } } } } userErrors { field message } } } QUERY variables = { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "files": [ { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "file": { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "file": { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 } ] } } response = client.query(query: query, variables: variables) ``` #### Node.js ```javascript const client = new shopify.clients.Graphql({session}); const data = await client.query({ data: { "query": `mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id media(first: 5) { nodes { id alt mediaContentType status } } variants(first: 5) { nodes { title price media(first: 5) { nodes { id alt mediaContentType status } } } } } userErrors { field message } } }`, "variables": { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "files": [ { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "file": { "originalSource": "https://example.com/hats/grey-hat.jpg", "alt": "An elegant grey hat", "filename": "grey-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "file": { "originalSource": "https://example.com/hats/black-hat.jpg", "alt": "An elegant black hat", "filename": "black-hat.jpg", "contentType": "IMAGE" }, "price": 11.99 } ] } }, }, }); ``` #### Response ```json { "productSet": { "product": { "id": "gid://shopify/Product/1072481957", "media": { "nodes": [ { "alt": "An elegant grey hat", "mediaContentType": "IMAGE", "status": "UPLOADED" }, { "alt": "An elegant black hat", "mediaContentType": "IMAGE", "status": "UPLOADED" } ] }, "variants": { "nodes": [ { "title": "Grey", "price": "11.99", "media": { "nodes": [ { "alt": "An elegant grey hat", "mediaContentType": "IMAGE", "status": "UPLOADED" } ] } }, { "title": "Black", "price": "11.99", "media": { "nodes": [ { "alt": "An elegant black hat", "mediaContentType": "IMAGE", "status": "UPLOADED" } ] } } ] } }, "userErrors": [] } } ``` * ### Create a product with customized inventory quantities #### Description Create a product with \[inventory quantities]\(https\://shopify.dev/docs/apps/build/orders-fulfillment/inventory-management-apps/manage-quantities-states). This example returns the product with the specified inventory quantities configured for the variants. #### Query ```graphql mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id variants(first: 5) { nodes { title price inventoryQuantity inventoryItem { inventoryLevels(first: 5) { nodes { location { id name } } } } } } } userErrors { field message } } } ``` #### Variables ```json { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 12 }, { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 19 } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 976 }, { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 844 } ], "price": 11.99 } ] } } ``` #### cURL ```bash curl -X POST \ https://your-development-store.myshopify.com/admin/api/2025-01/graphql.json \ -H 'Content-Type: application/json' \ -H 'X-Shopify-Access-Token: {access_token}' \ -d '{ "query": "mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id variants(first: 5) { nodes { title price inventoryQuantity inventoryItem { inventoryLevels(first: 5) { nodes { location { id name } } } } } } } userErrors { field message } } }", "variables": { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 12 }, { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 19 } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 976 }, { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 844 } ], "price": 11.99 } ] } } }' ``` #### React Router ```javascript import { authenticate } from "../shopify.server"; export const loader = async ({request}) => { const { admin } = await authenticate.admin(request); const response = await admin.graphql( `#graphql mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id variants(first: 5) { nodes { title price inventoryQuantity inventoryItem { inventoryLevels(first: 5) { nodes { location { id name } } } } } } } userErrors { field message } } }`, { variables: { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 12 }, { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 19 } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 976 }, { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 844 } ], "price": 11.99 } ] } }, }, ); const json = await response.json(); return json.data; } ``` #### Ruby ```ruby session = ShopifyAPI::Auth::Session.new( shop: "your-development-store.myshopify.com", access_token: access_token ) client = ShopifyAPI::Clients::Graphql::Admin.new( session: session ) query = <<~QUERY mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id variants(first: 5) { nodes { title price inventoryQuantity inventoryItem { inventoryLevels(first: 5) { nodes { location { id name } } } } } } } userErrors { field message } } } QUERY variables = { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 12 }, { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 19 } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 976 }, { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 844 } ], "price": 11.99 } ] } } response = client.query(query: query, variables: variables) ``` #### Node.js ```javascript const client = new shopify.clients.Graphql({session}); const data = await client.query({ data: { "query": `mutation createProduct($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id variants(first: 5) { nodes { title price inventoryQuantity inventoryItem { inventoryLevels(first: 5) { nodes { location { id name } } } } } } } userErrors { field message } } }`, "variables": { "synchronous": true, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 12 }, { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 19 } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "inventoryQuantities": [ { "locationId": "gid://shopify/Location/346779380", "name": "available", "quantity": 976 }, { "locationId": "gid://shopify/Location/415211365", "name": "available", "quantity": 844 } ], "price": 11.99 } ] } }, }, }); ``` #### Response ```json { "productSet": { "product": { "id": "gid://shopify/Product/1072481937", "variants": { "nodes": [ { "title": "Grey", "price": "79.99", "inventoryQuantity": 31, "inventoryItem": { "inventoryLevels": { "nodes": [ { "location": { "id": "gid://shopify/Location/346779380", "name": "Ottawa Store" } }, { "location": { "id": "gid://shopify/Location/415211365", "name": "US Store" } } ] } } }, { "title": "Black", "price": "11.99", "inventoryQuantity": 1820, "inventoryItem": { "inventoryLevels": { "nodes": [ { "location": { "id": "gid://shopify/Location/346779380", "name": "Ottawa Store" } }, { "location": { "id": "gid://shopify/Location/415211365", "name": "US Store" } } ] } } } ] } }, "userErrors": [] } } ``` * ### Create a product with two options and four variants #### Description Create a product with \[multiple options]\(https\://shopify.dev/docs/api/admin-graphql/latest/objects/ProductOption) and all possible \[variant]\(https\://shopify.dev/docs/api/admin-graphql/latest/objects/ProductVariant) combinations. This example returns a product with two options and four variants, representing all \[option value]\(https\://shopify.dev/docs/api/admin-graphql/latest/objects/ProductOptionValue) combinations. #### Query ```graphql mutation createProductWithTwoOptionsAndVariants($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id title options(first: 5) { name position optionValues { name } } variants(first: 5) { nodes { price selectedOptions { name optionValue { id name } } } } } userErrors { field message } } } ``` #### Variables ```json { "synchronous": true, "productSet": { "title": "A humble tie", "productOptions": [ { "name": "Pattern", "position": 1, "values": [ { "name": "Plain" }, { "name": "Stripes" } ] }, { "name": "Width", "position": 2, "values": [ { "name": "Slim" }, { "name": "Classic" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 } ] } } ``` #### cURL ```bash curl -X POST \ https://your-development-store.myshopify.com/admin/api/2025-01/graphql.json \ -H 'Content-Type: application/json' \ -H 'X-Shopify-Access-Token: {access_token}' \ -d '{ "query": "mutation createProductWithTwoOptionsAndVariants($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id title options(first: 5) { name position optionValues { name } } variants(first: 5) { nodes { price selectedOptions { name optionValue { id name } } } } } userErrors { field message } } }", "variables": { "synchronous": true, "productSet": { "title": "A humble tie", "productOptions": [ { "name": "Pattern", "position": 1, "values": [ { "name": "Plain" }, { "name": "Stripes" } ] }, { "name": "Width", "position": 2, "values": [ { "name": "Slim" }, { "name": "Classic" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 } ] } } }' ``` #### React Router ```javascript import { authenticate } from "../shopify.server"; export const loader = async ({request}) => { const { admin } = await authenticate.admin(request); const response = await admin.graphql( `#graphql mutation createProductWithTwoOptionsAndVariants($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id title options(first: 5) { name position optionValues { name } } variants(first: 5) { nodes { price selectedOptions { name optionValue { id name } } } } } userErrors { field message } } }`, { variables: { "synchronous": true, "productSet": { "title": "A humble tie", "productOptions": [ { "name": "Pattern", "position": 1, "values": [ { "name": "Plain" }, { "name": "Stripes" } ] }, { "name": "Width", "position": 2, "values": [ { "name": "Slim" }, { "name": "Classic" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 } ] } }, }, ); const json = await response.json(); return json.data; } ``` #### Ruby ```ruby session = ShopifyAPI::Auth::Session.new( shop: "your-development-store.myshopify.com", access_token: access_token ) client = ShopifyAPI::Clients::Graphql::Admin.new( session: session ) query = <<~QUERY mutation createProductWithTwoOptionsAndVariants($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id title options(first: 5) { name position optionValues { name } } variants(first: 5) { nodes { price selectedOptions { name optionValue { id name } } } } } userErrors { field message } } } QUERY variables = { "synchronous": true, "productSet": { "title": "A humble tie", "productOptions": [ { "name": "Pattern", "position": 1, "values": [ { "name": "Plain" }, { "name": "Stripes" } ] }, { "name": "Width", "position": 2, "values": [ { "name": "Slim" }, { "name": "Classic" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 } ] } } response = client.query(query: query, variables: variables) ``` #### Node.js ```javascript const client = new shopify.clients.Graphql({session}); const data = await client.query({ data: { "query": `mutation createProductWithTwoOptionsAndVariants($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id title options(first: 5) { name position optionValues { name } } variants(first: 5) { nodes { price selectedOptions { name optionValue { id name } } } } } userErrors { field message } } }`, "variables": { "synchronous": true, "productSet": { "title": "A humble tie", "productOptions": [ { "name": "Pattern", "position": 1, "values": [ { "name": "Plain" }, { "name": "Stripes" } ] }, { "name": "Width", "position": 2, "values": [ { "name": "Slim" }, { "name": "Classic" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Plain" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Slim" } ], "price": 15 }, { "optionValues": [ { "optionName": "Pattern", "name": "Stripes" }, { "optionName": "Width", "name": "Classic" } ], "price": 15 } ] } }, }, }); ``` #### Response ```json { "productSet": { "product": { "id": "gid://shopify/Product/1072481953", "title": "A humble tie", "options": [ { "name": "Pattern", "position": 1, "optionValues": [ { "name": "Plain" }, { "name": "Stripes" } ] }, { "name": "Width", "position": 2, "optionValues": [ { "name": "Slim" }, { "name": "Classic" } ] } ], "variants": { "nodes": [ { "price": "15.00", "selectedOptions": [ { "name": "Pattern", "optionValue": { "id": "gid://shopify/ProductOptionValue/1054677147", "name": "Plain" } }, { "name": "Width", "optionValue": { "id": "gid://shopify/ProductOptionValue/1054677149", "name": "Slim" } } ] }, { "price": "15.00", "selectedOptions": [ { "name": "Pattern", "optionValue": { "id": "gid://shopify/ProductOptionValue/1054677147", "name": "Plain" } }, { "name": "Width", "optionValue": { "id": "gid://shopify/ProductOptionValue/1054677150", "name": "Classic" } } ] }, { "price": "15.00", "selectedOptions": [ { "name": "Pattern", "optionValue": { "id": "gid://shopify/ProductOptionValue/1054677148", "name": "Stripes" } }, { "name": "Width", "optionValue": { "id": "gid://shopify/ProductOptionValue/1054677149", "name": "Slim" } } ] }, { "price": "15.00", "selectedOptions": [ { "name": "Pattern", "optionValue": { "id": "gid://shopify/ProductOptionValue/1054677148", "name": "Stripes" } }, { "name": "Width", "optionValue": { "id": "gid://shopify/ProductOptionValue/1054677150", "name": "Classic" } } ] } ] } }, "userErrors": [] } } ``` * ### productSet reference [Open in GraphiQL](http://localhost:3457/graphiql?query=mutation%20createProductAsynchronous\(%24productSet%3A%20ProductSetInput!%2C%20%24synchronous%3A%20Boolean!\)%20%7B%0A%20%20productSet\(synchronous%3A%20%24synchronous%2C%20input%3A%20%24productSet\)%20%7B%0A%20%20%20%20product%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%20%20productSetOperation%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20status%0A%20%20%20%20%20%20userErrors%20%7B%0A%20%20%20%20%20%20%20%20code%0A%20%20%20%20%20%20%20%20field%0A%20%20%20%20%20%20%20%20message%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20userErrors%20%7B%0A%20%20%20%20%20%20code%0A%20%20%20%20%20%20field%0A%20%20%20%20%20%20message%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D\&variables=%7B%0A%20%20%22synchronous%22%3A%20false%2C%0A%20%20%22productSet%22%3A%20%7B%0A%20%20%20%20%22title%22%3A%20%22Winter%20hat%22%2C%0A%20%20%20%20%22productOptions%22%3A%20%5B%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%22name%22%3A%20%22Color%22%2C%0A%20%20%20%20%20%20%20%20%22position%22%3A%201%2C%0A%20%20%20%20%20%20%20%20%22values%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%20%22Grey%22%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%20%22Black%22%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%2C%0A%20%20%20%20%22variants%22%3A%20%5B%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%22optionValues%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22optionName%22%3A%20%22Color%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%20%22Grey%22%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22price%22%3A%2079.99%0A%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%22optionValues%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22optionName%22%3A%20%22Color%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%20%22Black%22%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22price%22%3A%2069.99%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%0A%20%20%7D%0A%7D) ```javascript import { authenticate } from "../shopify.server"; export const loader = async ({request}) => { const { admin } = await authenticate.admin(request); const response = await admin.graphql( `#graphql mutation createProductAsynchronous($productSet: ProductSetInput!, $synchronous: Boolean!) { productSet(synchronous: $synchronous, input: $productSet) { product { id } productSetOperation { id status userErrors { code field message } } userErrors { code field message } } }`, { variables: { "synchronous": false, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "price": 69.99 } ] } }, }, ); const json = await response.json(); return json.data; } ``` ## Input variables JSON ```json { "synchronous": false, "productSet": { "title": "Winter hat", "productOptions": [ { "name": "Color", "position": 1, "values": [ { "name": "Grey" }, { "name": "Black" } ] } ], "variants": [ { "optionValues": [ { "optionName": "Color", "name": "Grey" } ], "price": 79.99 }, { "optionValues": [ { "optionName": "Color", "name": "Black" } ], "price": 69.99 } ] } } ``` ## Response JSON ```json { "productSet": { "product": null, "productSetOperation": { "id": "gid://shopify/ProductSetOperation/1010603851", "status": "CREATED", "userErrors": [] }, "userErrors": [] } } ```