Building Shopify API integration using GraphQL mutations

I started working on a Shopify integration project recently and I’m having trouble with GraphQL. I built everything using REST API first but now I need to switch to GraphQL since that’s what Shopify recommends.

I’m using N8N to handle the workflow and I can create basic products but I can’t add important details like pricing, inventory, SKU, or weight. Every time I try to add these fields I get errors about needing variants first, then options, then inventory settings. It’s like a chain of requirements that never ends.

This basic mutation works fine:

mutation AddNewProduct {
  productCreate(product: {
    title: "Smart Bulb Pro",
    descriptionHtml: "<p>Advanced smart lighting solution</p>",
    productType: "Electronics",
    vendor: "TechCorp",
    tags: ["smart", "wireless"]
  }) {
    product {
      id
      title
      vendor
      tags
    }
    shop {
      id
    }
    userErrors {
      field
      message
    }
  }
}

But I can’t figure out how to add price, weight, dimensions, SKU and other product details. I need to set prices per unit like $15 per item or $8 per 100g. Has anyone dealt with this before?

Most people get stuck on inventory management after setting up variants. When you’re configuring variant fields, set inventoryManagement to SHOPIFY for automatic tracking, or BLANK if you don’t want it. The inventoryPolicy controls what happens when you’re out of stock - CONTINUE lets people keep buying, DENY stops them. I learned this the hard way when my client’s store kept taking orders for out-of-stock items because I messed up the policy. For weight-based products like your 100g example, set requiresSellingPlan to true and handle it through selling plans instead of basic variants. The weight field needs grams as an integer, so 100g = weight: 100. Pro tip: always include inventoryItem in your response queries to double-check the inventory settings actually worked.

Yeah, the variant requirement totally caught me off guard coming from REST too. I ended up treating every product like it has at least one variant right from the start. Here’s what finally worked for me:

mutation AddNewProduct {
  productCreate(product: {
    title: "Smart Bulb Pro",
    descriptionHtml: "<p>Advanced smart lighting solution</p>",
    productType: "Electronics",
    vendor: "TechCorp",
    tags: ["smart", "wireless"],
    variants: [{
      price: "15.00",
      weight: 250,
      sku: "SBP-001",
      inventoryQuantity: 50,
      inventoryPolicy: CONTINUE,
      inventoryManagement: SHOPIFY
    }]
  }) {
    product {
      id
      title
      variants(first: 1) {
        edges {
          node {
            id
            price
            sku
            weight
          }
        }
      }
    }
    userErrors {
      field
      message
    }
  }
}

Shopify basically forces you to think variants first, then products. Weight’s in grams, price as a decimal string. For per-unit pricing, just set the price directly on the variant.

the variants thing is annoying at first, but it’s manageable once you figure it out. I just copy a working mutation and swap out the values. keep your price as a string (“15.00”) instead of a number - otherwise you’ll get errors. and handle userErrors in your n8n workflow because shopify returns those instead of real errors half the time.

shopify’s graphql is weird about this. you have to wrap everything in a variants array, even for single products. add variants: [{price: “15.00”, weight: 500, sku: “smartbulb-001”, inventoryQuantity: 10}] inside your product object. the variant structure is required even though it feels redundant if you’re coming from rest.

You’re hitting Shopify’s annoying requirement that every product needs variants, even single items. Price, SKU, weight, and inventory aren’t product-level fields - they’re variant properties. Hit the same wall when I switched from REST to GraphQL last year. You’ve got to include a variants array in your productCreate mutation, even for just one variant. Stick price, weight, inventoryQuantity, and sku inside the variant object, not the main product. For your $15 item or $8 per 100g examples, just set the price field to “15.00” or “8.00” in the variant. Inventory gets messy because you’ll need inventoryPolicy and tracking settings too. I usually create the product with basic variant info first, then handle complex inventory stuff with separate mutations. The GraphQL docs show all the nested fields, but it’s pretty unintuitive coming from REST where you could set everything directly on the product.