Products API
Push products from the vendor's system to the marketplace, then keep their price and stock up to date. All requests need the API key of the integration, see authentication. Errors follow the common format.
POST /products
Create or update a product in the marketplace. If a product with the same externalId already exists, it will be updated. On first creation, the product is created as DRAFT. The marketplace admin can then approve and publish it.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
externalId | string | yes | Unique product identifier in the vendor's system |
title | string | yes | Product title |
descriptionHtml | string | no | Product description in HTML |
vendor | string | no | Brand name (defaults to the vendor name) |
productType | string | no | Product type (e.g. "Bags") |
tags | string[] | no | Product tags |
productOptions | object[] | no | Product options (see below) |
variants | object[] | yes | At least one variant (see below) |
images | object[] | no | Product images (see below) |
metafields | object[] | no | Custom metafields (see below) |
Product option
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Option name (e.g. "Size") |
values | string[] | yes | Option values (e.g. ["S", "M", "L"]) |
Variant
| Field | Type | Required | Description |
|---|---|---|---|
sku | string | yes | SKU identifier |
barcode | string | no | Barcode (EAN, UPC, etc.) |
price | number | yes | Sale price |
compareAtPrice | number | no | Original price before discount |
inventoryQuantity | integer | no | Available stock quantity |
tracked | boolean | no | Whether inventory is tracked (default: true) |
requiresShipping | boolean | no | Whether shipping is required (default: true) |
weight | object | no | { value: number, unit: "GRAMS" | "KILOGRAMS" | "OUNCES" | "POUNDS" } |
optionValues | object[] | no | [{ optionName: "Size", name: "M" }] — must match productOptions |
externalVariantId | string | no | Unique variant identifier in the vendor's system |
Image
| Field | Type | Required | Description |
|---|---|---|---|
src | string | yes | Public URL of the image |
alt | string | no | Alt text for accessibility |
externalId | string | no | Unique image ID to avoid re-uploading on updates |
Metafield
| Field | Type | Required | Description |
|---|---|---|---|
key | string | yes | Metafield key (e.g. "material") |
value | string | yes | Metafield value (e.g. "leather") |
Example request:
bash
curl -X POST https://api.garnetmarketplace.com/products \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{
"externalId": "vendor-product-123",
"title": "Premium Leather Bag",
"descriptionHtml": "<p>A beautiful leather bag</p>",
"productType": "Bags",
"tags": ["leather", "premium"],
"productOptions": [
{ "name": "Size", "values": ["S", "M", "L"] }
],
"variants": [
{
"sku": "BAG-001-S",
"price": 129.99,
"inventoryQuantity": 50,
"optionValues": [{ "optionName": "Size", "name": "S" }]
},
{
"sku": "BAG-001-M",
"price": 129.99,
"inventoryQuantity": 30,
"optionValues": [{ "optionName": "Size", "name": "M" }]
}
],
"images": [
{ "src": "https://example.com/bag-front.jpg", "alt": "Front view" }
],
"metafields": [
{ "key": "material", "value": "leather" },
{ "key": "country_of_origin", "value": "Italy" }
]
}'Response:
json
{ "productId": "gid://shopify/Product/123456789" }PATCH /products
Bulk update price and stock for existing products by SKU. Maximum 250 items per request. Only updates variants that match existing SKUs in the marketplace.
Request body: Array of objects:
| Field | Type | Required | Description |
|---|---|---|---|
sku | string | yes | SKU identifier |
price | number | yes | New price |
stock | integer | yes | New stock quantity |
Example request:
bash
curl -X PATCH https://api.garnetmarketplace.com/products \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '[
{ "sku": "BAG-001-S", "price": 119.99, "stock": 45 },
{ "sku": "BAG-001-M", "price": 119.99, "stock": 28 }
]'Response:
json
{ "updated": 1, "unknownSkus": [] }