Skip to main content
POST
/
v2
/
products
Create Product
curl --request POST \
  --url https://api.puppetvendors.com/v2/products \
  --header 'Content-Type: application/json' \
  --header 'x-access-token: <api-key>' \
  --data '
{
  "title": "<string>",
  "vendorId": "<string>",
  "descriptionHtml": "<string>",
  "productType": "<string>",
  "status": "<string>",
  "tags": [
    "<string>"
  ],
  "handle": "<string>",
  "options": [
    {}
  ],
  "variants": [
    {}
  ],
  "metafields": [
    {}
  ],
  "media": [
    {}
  ],
  "seo": {}
}
'
V2 Alpha — This endpoint is part of the V2 API preview. Breaking changes may occur.

Overview

Create a new product via Shopify’s productSet mutation. Includes variants, options, metafields, and media in a single synchronous call. Maximum 100 variants per product. Vendor tokens can only create products for their own vendor. Merchant tokens must specify a vendorId.

Use Cases

  • Automated product creation — Import products from external sources
  • Vendor product submission — Let vendors create products via API
  • Catalogue management — Programmatically build product catalogues

Request Body

title
string
required
Product title (max 255 characters).
vendorId
string
required
Vendor ObjectId. Required for merchant tokens; auto-filled for vendor tokens.
descriptionHtml
string
HTML product description.
productType
string
Product type (max 255 characters).
status
string
default:"DRAFT"
Initial product status. One of: ACTIVE, DRAFT, ARCHIVED.
tags
string[]
Product tags (max 250 tags).
handle
string
URL handle (max 255 characters). Auto-generated from title if not provided.
options
object[]
Product options (max 3). Each option has name (string) and values (string array).
variants
object[]
Product variants (max 100). Each variant can include:
  • optionValues — Array of { name, value } matching product options
  • price — Decimal string (e.g. "29.99")
  • compareAtPrice — Decimal string
  • sku — SKU string
  • barcode — Barcode string
  • inventoryQuantity — Integer (requires locationId)
  • weight — Object with value (number) and optional unit (POUNDS, OUNCES, KILOGRAMS, GRAMS)
  • requiresShipping — Boolean
  • taxable — Boolean
metafields
object[]
Product metafields. Each has namespace, key, value, and optional type.
media
object[]
Product media (max 250). Each has originalSource (URL), optional mediaContentType (IMAGE, VIDEO, MODEL_3D, EXTERNAL_VIDEO), and optional alt.
seo
object
SEO settings with optional title (max 255) and description (max 320).

Response

201
{
  "success": true,
  "data": {
    "_id": "507f1f77bcf86cd799439013",
    "title": "Widget Pro",
    "handle": "widget-pro",
    "status": "DRAFT",
    "vendorId": "507f1f77bcf86cd799439011",
    "productId": 7654321098765,
    "graphqlProductId": "gid://shopify/Product/7654321098765",
    "createdAt": "2024-06-15T10:30:00.000Z"
  }
}

Error Responses

400
{
  "success": false,
  "error": {
    "message": "Title is required",
    "code": "VALIDATION_ERROR"
  }
}
409
{
  "success": false,
  "error": {
    "message": "Product creation failed in Shopify",
    "code": "CONFLICT"
  }
}

Example

curl -X POST https://api.puppetvendors.com/v2/products \
  -H "Content-Type: application/json" \
  -H "x-access-token: YOUR_JWT_TOKEN" \
  -d '{
    "title": "Widget Pro",
    "vendorId": "507f1f77bcf86cd799439011",
    "descriptionHtml": "<p>Premium widget</p>",
    "status": "DRAFT",
    "options": [
      { "name": "Size", "values": ["Small", "Medium", "Large"] }
    ],
    "variants": [
      {
        "optionValues": [{ "name": "Size", "value": "Small" }],
        "price": "19.99",
        "sku": "WP-SM"
      },
      {
        "optionValues": [{ "name": "Size", "value": "Medium" }],
        "price": "24.99",
        "sku": "WP-MD"
      },
      {
        "optionValues": [{ "name": "Size", "value": "Large" }],
        "price": "29.99",
        "sku": "WP-LG"
      }
    ]
  }'