Appearance
API integration
The API integration allows vendors without a supported e-commerce platform to connect with a Garnet marketplace via a REST API. Vendors can push products, update prices and stock, submit tracking information, and receive orders via webhook.
Integration scope
- ✅ Product synchronization (push from vendor)
- ✅ Price and stock updates
- ✅ Order synchronization (webhook to vendor)
- ✅ Tracking synchronization (push from vendor)
Authentication
All API requests must include a Bearer token in the Authorization header. The API key is provided when the marketplace admin creates the integration in Garnet > Settings > Integrations > API.
Authorization: Bearer your_api_keyBase URL: https://api.garnetmarketplace.com
Quick start
Here is a full example: create a pineapple product, then update its stock.
Step 1 — Create the product:
Full curl command
bash
curl -X POST https://api.garnetmarketplace.com/products \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{
"externalId": "pineapple-001",
"title": "Fresh Pineapple",
"descriptionHtml": "<p>Sweet and juicy tropical pineapple, hand-picked at peak ripeness.</p>",
"productType": "Fruits",
"tags": ["tropical", "fresh", "fruit"],
"variants": [
{
"sku": "PINE-SINGLE",
"price": 4.99,
"inventoryQuantity": 120,
"weight": { "value": 900, "unit": "GRAMS" }
}
],
"images": [
{ "src": "https://images.unsplash.com/photo-1550258987-190a2d41a8ba?w=800", "alt": "Fresh pineapple" }
]
}'Response:
json
{ "productId": "gid://shopify/Product/123456789" }Step 2 — Update stock and price:
Full curl command
bash
curl -X PATCH https://api.garnetmarketplace.com/products \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '[
{ "sku": "PINE-SINGLE", "price": 3.99, "stock": 85 }
]'Response:
json
{ "updated": 1, "unknownSkus": [] }Endpoints
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": [] }POST /tracking
Submit a tracking number for an order. This will fulfill the order on the marketplace and notify the customer.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
orderId | integer | yes | Numeric Shopify order ID (received in the order webhook) |
trackingNumber | string | yes | Tracking number |
trackingCompany | string | no | Carrier name (e.g. "UPS") |
trackingUrl | string | no | Tracking URL |
Example request:
bash
curl -X POST https://api.garnetmarketplace.com/tracking \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{
"orderId": 5538456789012,
"trackingNumber": "1Z999AA10123456784",
"trackingCompany": "UPS",
"trackingUrl": "https://www.ups.com/track?tracknum=1Z999AA10123456784"
}'Response:
json
{ "fulfilled": true }Receiving orders (webhook)
When a customer places an order on the marketplace, Garnet sends a POST request to the vendor's registered webhook URL. The payload follows the exact same format as the Shopify Order resource.
WARNING
The order webhook URL must be configured separately by the Garnet team. Contact us to set it up.
Order sample
json
{
"id": 6902490759457,
"admin_graphql_api_id": "gid://shopify/Order/6902490759457",
"app_id": 1354745,
"browser_ip": "24.132.136.18",
"buyer_accepts_marketing": false,
"cancel_reason": null,
"cancelled_at": null,
"cart_token": null,
"checkout_id": 40647032832289,
"checkout_token": "e11a0a03bf6395931c8df943a2efe8cc",
"client_details": {
"accept_language": null,
"browser_height": null,
"browser_ip": "24.132.136.18",
"browser_width": null,
"session_hash": null,
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:146.0) Gecko/20100101 Firefox/146.0"
},
"closed_at": null,
"company": null,
"confirmation_number": "C0VW5VQUF",
"confirmed": true,
"contact_email": null,
"created_at": "2025-12-17T02:42:56-05:00",
"currency": "USD",
"current_subtotal_price": "107.80",
"current_subtotal_price_set": {
"shop_money": {
"amount": "107.80",
"currency_code": "USD"
},
"presentment_money": {
"amount": "107.80",
"currency_code": "USD"
}
},
"current_total_additional_fees_set": null,
"current_total_discounts": "2.20",
"current_total_discounts_set": {
"shop_money": {
"amount": "2.20",
"currency_code": "USD"
},
"presentment_money": {
"amount": "2.20",
"currency_code": "USD"
}
},
"current_total_duties_set": null,
"current_total_price": "121.43",
"current_total_price_set": {
"shop_money": {
"amount": "121.43",
"currency_code": "USD"
},
"presentment_money": {
"amount": "121.43",
"currency_code": "USD"
}
},
"current_total_tax": "8.63",
"current_total_tax_set": {
"shop_money": {
"amount": "8.63",
"currency_code": "USD"
},
"presentment_money": {
"amount": "8.63",
"currency_code": "USD"
}
},
"customer_locale": "en",
"device_id": null,
"discount_codes": [
{
"code": "78ZSKTG699J3",
"amount": "4.40",
"type": "percentage"
}
],
"duties_included": false,
"email": "",
"estimated_taxes": false,
"financial_status": "partially_refunded",
"fulfillment_status": null,
"landing_site": null,
"landing_site_ref": null,
"location_id": 83306807585,
"merchant_business_entity_id": "MTc2MTk4MDUyMTI5",
"merchant_of_record_app_id": null,
"name": "#1239",
"note": null,
"note_attributes": [],
"number": 239,
"order_number": 1239,
"order_status_url": "https://ananature.com/76198052129/orders/c747e5e61ded045655e363f0e67314d0/authenticate?key=74674d94ab8a0517b3fbb1e5388260e6",
"original_total_additional_fees_set": null,
"original_total_duties_set": null,
"payment_gateway_names": [
"manual"
],
"phone": null,
"po_number": null,
"presentment_currency": "USD",
"processed_at": "2025-12-17T02:42:55-05:00",
"reference": null,
"referring_site": null,
"source_identifier": null,
"source_name": "shopify_draft_order",
"source_url": null,
"subtotal_price": "215.60",
"subtotal_price_set": {
"shop_money": {
"amount": "215.60",
"currency_code": "USD"
},
"presentment_money": {
"amount": "215.60",
"currency_code": "USD"
}
},
"tags": "",
"tax_exempt": false,
"tax_lines": [
{
"price": "17.25",
"rate": 0.08,
"title": "Tax",
"price_set": {
"shop_money": {
"amount": "17.25",
"currency_code": "USD"
},
"presentment_money": {
"amount": "17.25",
"currency_code": "USD"
}
},
"channel_liable": false
}
],
"taxes_included": false,
"test": false,
"token": "c747e5e61ded045655e363f0e67314d0",
"total_cash_rounding_payment_adjustment_set": {
"shop_money": {
"amount": "0.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "0.00",
"currency_code": "USD"
}
},
"total_cash_rounding_refund_adjustment_set": {
"shop_money": {
"amount": "0.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "0.00",
"currency_code": "USD"
}
},
"total_discounts": "4.40",
"total_discounts_set": {
"shop_money": {
"amount": "4.40",
"currency_code": "USD"
},
"presentment_money": {
"amount": "4.40",
"currency_code": "USD"
}
},
"total_line_items_price": "220.00",
"total_line_items_price_set": {
"shop_money": {
"amount": "220.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "220.00",
"currency_code": "USD"
}
},
"total_outstanding": "0.00",
"total_price": "242.85",
"total_price_set": {
"shop_money": {
"amount": "242.85",
"currency_code": "USD"
},
"presentment_money": {
"amount": "242.85",
"currency_code": "USD"
}
},
"total_shipping_price_set": {
"shop_money": {
"amount": "10.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "10.00",
"currency_code": "USD"
}
},
"total_tax": "17.25",
"total_tax_set": {
"shop_money": {
"amount": "17.25",
"currency_code": "USD"
},
"presentment_money": {
"amount": "17.25",
"currency_code": "USD"
}
},
"total_tip_received": "0.00",
"total_weight": 0,
"updated_at": "2026-01-15T11:29:09-05:00",
"user_id": 122335035681,
"billing_address": null,
"customer": null,
"discount_applications": [
{
"target_type": "line_item",
"type": "discount_code",
"value": "2.0",
"value_type": "percentage",
"allocation_method": "across",
"target_selection": "all",
"code": "78ZSKTG699J3"
}
],
"fulfillments": [],
"line_items": [
{
"id": 16636086157601,
"admin_graphql_api_id": "gid://shopify/LineItem/16636086157601",
"attributed_staffs": [],
"current_quantity": 1,
"fulfillable_quantity": 1,
"fulfillment_service": "manual",
"fulfillment_status": null,
"gift_card": false,
"grams": 0,
"name": "My Groovy 2",
"price": "110.00",
"price_set": {
"shop_money": {
"amount": "110.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "110.00",
"currency_code": "USD"
}
},
"product_exists": false,
"product_id": null,
"properties": [],
"quantity": 2,
"requires_shipping": true,
"sku": null,
"taxable": true,
"title": "My Groovy 2",
"total_discount": "0.00",
"total_discount_set": {
"shop_money": {
"amount": "0.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "0.00",
"currency_code": "USD"
}
},
"variant_id": null,
"variant_inventory_management": null,
"variant_title": null,
"vendor": "Pineapple Groovy",
"tax_lines": [
{
"channel_liable": false,
"price": "17.25",
"price_set": {
"shop_money": {
"amount": "17.25",
"currency_code": "USD"
},
"presentment_money": {
"amount": "17.25",
"currency_code": "USD"
}
},
"rate": 0.08,
"title": "Tax"
}
],
"duties": [],
"discount_allocations": [
{
"amount": "4.40",
"amount_set": {
"shop_money": {
"amount": "4.40",
"currency_code": "USD"
},
"presentment_money": {
"amount": "4.40",
"currency_code": "USD"
}
},
"discount_application_index": 0
}
]
}
],
"payment_terms": null,
"refunds": [
{
"id": 1225821389089,
"admin_graphql_api_id": "gid://shopify/Refund/1225821389089",
"created_at": "2025-12-17T06:02:16-05:00",
"note": "",
"order_id": 6902490759457,
"processed_at": "2025-12-17T06:02:16-05:00",
"restock": true,
"total_duties_set": {
"shop_money": {
"amount": "0.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "0.00",
"currency_code": "USD"
}
},
"user_id": 122335035681,
"order_adjustments": [
{
"id": 349704061217,
"amount": "-5.00",
"amount_set": {
"shop_money": {
"amount": "-5.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "-5.00",
"currency_code": "USD"
}
},
"kind": "shipping_refund",
"order_id": 6902490759457,
"reason": "Shipping refund",
"refund_id": 1225821389089,
"tax_amount": "0.00",
"tax_amount_set": {
"shop_money": {
"amount": "0.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "0.00",
"currency_code": "USD"
}
}
},
{
"id": 349704093985,
"amount": "41.42",
"amount_set": {
"shop_money": {
"amount": "41.42",
"currency_code": "USD"
},
"presentment_money": {
"amount": "41.42",
"currency_code": "USD"
}
},
"kind": "refund_discrepancy",
"order_id": 6902490759457,
"reason": "Refund discrepancy",
"refund_id": 1225821389089,
"tax_amount": "0.00",
"tax_amount_set": {
"shop_money": {
"amount": "0.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "0.00",
"currency_code": "USD"
}
}
}
],
"transactions": [
{
"id": 8492102615329,
"admin_graphql_api_id": "gid://shopify/OrderTransaction/8492102615329",
"amount": "80.00",
"authorization": null,
"created_at": "2025-12-17T06:02:16-05:00",
"currency": "USD",
"device_id": null,
"error_code": null,
"gateway": "manual",
"kind": "refund",
"location_id": null,
"message": "Refunded 80.00 USD from manual gateway",
"order_id": 6902490759457,
"parent_id": 8491800002849,
"payment_id": "#1239.1",
"processed_at": "2025-12-17T06:02:16-05:00",
"receipt": {},
"source_name": "1830279",
"status": "success",
"test": false,
"user_id": 122335035681
}
],
"refund_line_items": [
{
"id": 638025335073,
"line_item_id": 16636086157601,
"location_id": 83306807585,
"quantity": 1,
"restock_type": "cancel",
"subtotal": 107.8,
"subtotal_set": {
"shop_money": {
"amount": "107.80",
"currency_code": "USD"
},
"presentment_money": {
"amount": "107.80",
"currency_code": "USD"
}
},
"total_tax": 8.62,
"total_tax_set": {
"shop_money": {
"amount": "8.62",
"currency_code": "USD"
},
"presentment_money": {
"amount": "8.62",
"currency_code": "USD"
}
},
"line_item": {
"id": 16636086157601,
"admin_graphql_api_id": "gid://shopify/LineItem/16636086157601",
"attributed_staffs": [],
"current_quantity": 1,
"fulfillable_quantity": 1,
"fulfillment_service": "manual",
"fulfillment_status": null,
"gift_card": false,
"grams": 0,
"name": "My Groovy 2",
"price": "110.00",
"price_set": {
"shop_money": {
"amount": "110.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "110.00",
"currency_code": "USD"
}
},
"product_exists": false,
"product_id": null,
"properties": [],
"quantity": 2,
"requires_shipping": true,
"sku": null,
"taxable": true,
"title": "My Groovy 2",
"total_discount": "0.00",
"total_discount_set": {
"shop_money": {
"amount": "0.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "0.00",
"currency_code": "USD"
}
},
"variant_id": null,
"variant_inventory_management": null,
"variant_title": null,
"vendor": "Pineapple Groovy",
"tax_lines": [
{
"channel_liable": false,
"price": "17.25",
"price_set": {
"shop_money": {
"amount": "17.25",
"currency_code": "USD"
},
"presentment_money": {
"amount": "17.25",
"currency_code": "USD"
}
},
"rate": 0.08,
"title": "Tax"
}
],
"duties": [],
"discount_allocations": [
{
"amount": "4.40",
"amount_set": {
"shop_money": {
"amount": "4.40",
"currency_code": "USD"
},
"presentment_money": {
"amount": "4.40",
"currency_code": "USD"
}
},
"discount_application_index": 0
}
]
}
}
],
"duties": []
}
],
"shipping_address": null,
"shipping_lines": [
{
"id": 5304825053473,
"carrier_identifier": null,
"code": "custom",
"discounted_price": "10.00",
"discounted_price_set": {
"shop_money": {
"amount": "10.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "10.00",
"currency_code": "USD"
}
},
"is_removed": false,
"phone": null,
"price": "10.00",
"price_set": {
"shop_money": {
"amount": "10.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "10.00",
"currency_code": "USD"
}
},
"requested_fulfillment_service_id": null,
"source": "shopify",
"title": "Standard shipping",
"tax_lines": [],
"discount_allocations": []
}
]
}Error responses
All endpoints return JSON errors in the following format:
json
{ "error": "Error message describing what went wrong" }| Status | Description |
|---|---|
| 400 | Invalid request (validation error) |
| 401 | Invalid or missing API key |
| 404 | Resource not found |
| 500 | Server error |