Create and manage Shopify products via the Admin API. Workflow: gather product data, choose method (API or CSV), execute, verify. Use when adding products, bulk importing, updating variants, managing inventory, uploading product images, or assigning products to collections.
Creates and manages Shopify products via API or CSV import for adding, updating, and bulk importing inventory.
npx claudepluginhub jezweb/claude-skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/product-csv-template.csvreferences/csv-format.mdreferences/graphql-mutations.mdCreate, update, and bulk-import Shopify products. Produces live products in the store via the GraphQL Admin API or CSV import.
shopify.config.json or .dev.varsDetermine what the user wants to create or update:
Accept data from:
| Scenario | Method |
|---|---|
| 1-5 products | GraphQL mutations |
| 6-20 products | GraphQL with batching |
| 20+ products | CSV import via admin |
| Updates to existing | GraphQL mutations |
| Inventory adjustments | inventorySetQuantities mutation |
Single product with variants:
curl -s https://{store}/admin/api/2025-01/graphql.json \
-H "Content-Type: application/json" \
-H "X-Shopify-Access-Token: {token}" \
-d '{
"query": "mutation productCreate($product: ProductCreateInput!) { productCreate(product: $product) { product { id title } userErrors { field message } } }",
"variables": {
"product": {
"title": "Example T-Shirt",
"descriptionHtml": "<p>Premium cotton tee</p>",
"vendor": "My Brand",
"productType": "T-Shirts",
"tags": ["summer", "cotton"],
"options": ["Size", "Colour"],
"variants": [
{"optionValues": [{"optionName": "Size", "name": "S"}, {"optionName": "Colour", "name": "Black"}], "price": "29.95"},
{"optionValues": [{"optionName": "Size", "name": "M"}, {"optionName": "Colour", "name": "Black"}], "price": "29.95"},
{"optionValues": [{"optionName": "Size", "name": "L"}, {"optionName": "Colour", "name": "Black"}], "price": "29.95"}
]
}
}
}'
See references/graphql-mutations.md for all mutation patterns.
Batching multiple products: Create products sequentially with a short delay between each to respect rate limits (1,000 cost points/second).
For 20+ products, generate a CSV and import through Shopify admin:
references/csv-format.mdassets/product-csv-template.csvhttps://{store}.myshopify.com/admin/products/importUse browser automation to assist with the upload if needed.
Images require a two-step process — staged upload then attach:
mutation {
stagedUploadsCreate(input: [{
filename: "product-image.jpg"
mimeType: "image/jpeg"
httpMethod: POST
resource: IMAGE
}]) {
stagedTargets {
url
resourceUrl
parameters { name value }
}
}
}
Then upload to the staged URL, and attach with productCreateMedia.
Shortcut: If images are already hosted at a public URL, pass src directly in the product creation:
{
"images": [
{ "src": "https://example.com/image.jpg", "alt": "Product front view" }
]
}
After creation, add products to collections:
mutation {
collectionAddProducts(
id: "gid://shopify/Collection/123456"
productIds: ["gid://shopify/Product/789"]
) {
collection { title productsCount }
userErrors { field message }
}
}
To find collection IDs:
{
collections(first: 50) {
edges {
node { id title handle }
}
}
}
Query back the created products to confirm:
{
products(first: 10, reverse: true) {
edges {
node {
id title status
variants(first: 5) { edges { node { title price inventoryQuantity } } }
images(first: 3) { edges { node { url altText } } }
}
}
}
}
Provide the admin URL for the user to review: https://{store}.myshopify.com/admin/products
New products default to DRAFT. To make them visible:
{ "status": "ACTIVE" }
Always confirm with the user before setting status to ACTIVE.
Shopify allows max 100 variants per product and 3 options (e.g. Size, Colour, Material). If you need more, split into separate products.
To set inventory quantities, use inventorySetQuantities after product creation:
mutation {
inventorySetQuantities(input: {
reason: "correction"
name: "available"
quantities: [{
inventoryItemId: "gid://shopify/InventoryItem/123"
locationId: "gid://shopify/Location/456"
quantity: 50
}]
}) {
inventoryAdjustmentGroup { reason }
userErrors { field message }
}
}
Prices are strings, not numbers. Always quote them: "price": "29.95" not "price": 29.95.
Product descriptions accept HTML. Keep it simple — Shopify's editor handles basic tags:
<p>, <strong>, <em>, <ul>, <ol>, <li>, <h2>-<h6><a href="..."> for links<img> is stripped — use product images insteadFor 50+ products via API, use Shopify's bulk operation:
mutation {
bulkOperationRunMutation(
mutation: "mutation ($input: ProductInput!) { productCreate(input: $input) { product { id } userErrors { message } } }"
stagedUploadPath: "tmp/bulk-products.jsonl"
) {
bulkOperation { id status }
userErrors { message }
}
}
This accepts a JSONL file with one product per line, processed asynchronously.
assets/product-csv-template.csv — Blank CSV template with Shopify import headersreferences/graphql-mutations.md — Key GraphQL mutations for product CRUDreferences/csv-format.md — Shopify CSV import column format and examplesUse when working with Payload CMS projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.