Search Documentation

Search for a documentation page...

Products API

REST API endpoints for browsing, creating, updating, and deleting products.

List Products

GET /api/v1/products

Returns a paginated list of products with variants, categories, and translations.

Query Parameters

ParameterTypeDefaultDescription
limitnumber10Products per page (1-100)
offsetnumber0Number of products to skip
cursorstringProduct UUID for keyset pagination
categorystringFilter by category slug
brandstringFilter by brand slug
querystringSearch term for product name
activebooleanFilter by published status
excludeBundlesbooleanfalseExclude bundle products
includeEventsbooleanfalseInclude event-products (excluded by default — see the Events API)
orderBystringSort field: price, name, or createdAt
orderDirectionstringdescSort direction: asc or desc
currencystringCurrency code for price display (e.g. EUR)
langstringLocale code for translations (e.g. pl-PL)

Response

{
"data": [
{
"id": "0191abc0-1234-7def-8000-000000000001",
"name": "Classic Tee",
"slug": "classic-tee",
"summary": "A comfortable everyday tee",
"images": ["https://cdn.example.com/tee.jpg"],
"status": "published",
"categoryId": "0191abc0-0000-7000-8000-000000000010",
"variants": [
{
"id": "0191abc0-0000-7000-8000-000000000100",
"sku": "CT-SM-BLK",
"price": "2500",
"stock": 42
}
],
"translations": []
}
],
"meta": {
"count": 1
}
}

Get Product

GET /api/v1/products/:idOrSlug

Returns a single product by UUID or URL slug, with full variant details, category, collections, and translations.

ParameterTypeDescription
currencystringCurrency code for variant price resolution
langstringLocale code for translated slug lookup

Supports ?lang= query parameter for translated slug lookup when translations are enabled.

Response

{
"id": "0191abc0-1234-7def-8000-000000000001",
"name": "Classic Tee",
"slug": "classic-tee",
"summary": "A comfortable everyday tee",
"images": ["https://cdn.example.com/tee.jpg"],
"status": "published",
"category": { "id": "...", "name": "Shirts", "slug": "shirts" },
"variants": [
{
"id": "0191abc0-0000-7000-8000-000000000100",
"sku": "CT-SM-BLK",
"price": "2500",
"stock": 42,
"combinations": { "size": "Small", "color": "Black" }
}
],
"collections": [],
"translations": []
}

Create Product

POST /api/v1/products

Creates a product in one call. Image URLs are downloaded and re-uploaded to the store's CDN. Categories and collections are found or created automatically when referenced by name.

By default a single default variant is created at the given price. To create a product with multiple variants (e.g. Size × Color), pass the variants array — see the multi-variant example below.

Request Body

FieldTypeRequiredDescription
namestringYesProduct display name
slugstringYesURL-friendly identifier (^[a-z0-9-]+$)
descriptionstringNoPlain text product description
contentobjectNoRich TipTap JSON document ({ "type": "doc", ... }) for the product body
pricenumberYesPrice as a decimal (e.g. 29.99)
imagesstring[]NoArray of image URLs to upload
categoryIdstringNoCategory UUID — takes priority over category when both are provided
categorystringNoCategory name — created automatically if it doesn't exist
brandIdstringNoBrand UUID — must reference an existing brand (pre-create via the admin)
collectionIdsstring[]NoCollection UUIDs to attach the product to (unioned with collectionNames)
collectionNamesstring[]NoCollection names — created automatically if missing
stocknumberNoInitial inventory quantity (default: 0)
quantitynumberNoDeprecated — use stock instead
pricesobjectNoMulti-currency prices (e.g. { "EUR": 25.99, "GBP": 22.50 })
variantsobject[]NoStructured variants — see Multi-Variant Products below

Simple product

curl -X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Classic Tee",
"slug": "classic-tee",
"price": 25.00,
"images": ["https://example.com/tee.jpg"],
"category": "Shirts",
"stock": 100,
"prices": { "EUR": 23.00 }
}' \
https://your-store.yns.store/api/v1/products

Response (201)

{
"message": "Product created successfully",
"product": {
"id": "0191abc0-1234-7def-8000-000000000001",
"name": "Classic Tee",
"slug": "classic-tee",
"description": null,
"category": "Shirts",
"collectionIds": [],
"images": ["https://cdn.store.com/tee-abc123.jpg"],
"variant": {
"id": "0191abc0-0000-7000-8000-000000000100",
"price": "2500",
"stock": 100
}
}
}

Multi-Variant Products

Pass the variants array to create a product with real variant types, values, and combinations (e.g. Size × Color). Every variant must define the same set of option keys. The top-level price is used as the default when a variant omits its own price.

Variant object fields

FieldTypeRequiredDescription
optionsobjectYesOption label → value map, e.g. { "Size": "L", "Color": "Red" }
skustringNoVariant SKU (required to sync stock and per-variant prices)
pricenumberNoVariant price as a decimal — defaults to the product price
stocknumberNoVariant inventory quantity
imagesstring[]NoVariant-specific image URLs
shippablebooleanNoWhether the variant ships physically (default: true)
weightnumberNoWeight for shipping calculation
widthnumberNoWidth dimension
heightnumberNoHeight dimension
depthnumberNoDepth dimension
pricesobjectNoPer-variant multi-currency prices (e.g. { "EUR": 28.00 })

Example

curl -X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Classic Tee",
"slug": "classic-tee",
"price": 25.00,
"category": "Shirts",
"images": ["https://example.com/tee.jpg"],
"variants": [
{ "options": { "Size": "S", "Color": "Black" }, "sku": "CT-S-BLK", "stock": 20 },
{ "options": { "Size": "S", "Color": "White" }, "sku": "CT-S-WHT", "stock": 15 },
{ "options": { "Size": "M", "Color": "Black" }, "sku": "CT-M-BLK", "price": 27.00, "stock": 30 },
{ "options": { "Size": "M", "Color": "White" }, "sku": "CT-M-WHT", "price": 27.00, "stock": 25 }
]
}' \
https://your-store.yns.store/api/v1/products

Multi-variant response (201)

{
"message": "Product created successfully",
"product": {
"id": "0191abc0-1234-7def-8000-000000000001",
"name": "Classic Tee",
"slug": "classic-tee",
"description": null,
"content": null,
"category": "Shirts",
"collectionIds": [],
"images": ["https://cdn.store.com/tee-abc123.jpg"],
"variantCount": 4
}
}

Update Product

PATCH /api/v1/products/:idOrSlug

Partially updates a product. Only the provided fields are changed.

Request Body

FieldTypeDescription
titlestringNew product name
descriptionstringNew plain text description
imagesstring[]Replace the product's images. External URLs are uploaded to the store's CDN; URLs already on the CDN pass through. [] removes all images.
statusstringactive (published) or draft
curl -X PATCH \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{"title": "Premium Tee", "status": "active"}' \
https://your-store.yns.store/api/v1/products/classic-tee

Delete Product

DELETE /api/v1/products/:idOrSlug

Deletes a product if it has no order history. Products with orders are archived (status set to hidden) instead of deleted.

{ "message": "Product deleted" }
// or
{ "message": "Product archived (has order history)" }

Create Variant

POST /api/v1/products/:idOrSlug/variants

Adds a new variant to an existing product.

Request Body

FieldTypeRequiredDescription
skustringYesSKU code
titlestringYesVariant display name (e.g. Large / Red)
priceCentsnumberYesPrice in cents (e.g. 2999 = $29.99)
imageUrlstringNoVariant image URL
stocknumberNoInventory quantity (default: 0)
curl -X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{"sku": "CT-LG-RED", "title": "Large / Red", "priceCents": 2500, "stock": 50}' \
https://your-store.yns.store/api/v1/products/classic-tee/variants

Batch Create Products

POST /api/v1/products/batch

Creates up to 100 products in a single request. Each product gets a default variant. Partial failures are reported in the errors array.

Request Body

JSON array of product objects:

FieldTypeRequiredDescription
namestringYesProduct name
slugstringNoURL slug (auto-generated from name)
summarystringNoShort description
pricenumberYesPrice as decimal
imagesstring[]NoImage URLs
statusstringNodraft, published, or hidden (default: draft)
category_namestringNoCategory name
collection_namesstring[]NoCollection names to add to
skustringNoStock keeping unit
stocknumberNoInventory quantity
shippablebooleanNoRequires shipping (default: true)
curl -X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '[
{"name": "Soap A", "price": 12.99, "sku": "SOAP-A", "stock": 50},
{"name": "Soap B", "price": 14.99, "status": "published"}
]' \
https://your-store.yns.store/api/v1/products/batch

Response

{
"message": "Import completed",
"totalProducts": 2,
"imported": 2,
"errors": []
}

Import Products (CSV)

POST /api/v1/products/import
Content-Type: text/plain

Import products from CSV. Supports multi-variant products (multiple rows with the same slug) and updates via product_id. Categories and collections are created or matched automatically.

curl -X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: text/plain" \
--data-binary @products.csv \
https://your-store.yns.store/api/v1/products/import

Response

{
"message": "Import completed",
"totalProducts": 10,
"imported": 10,
"errors": []
}

Product Reviews

List Reviews

GET /api/v1/products/:idOrSlug/reviews

Returns approved reviews with summary statistics.

ParameterTypeDefaultDescription
limitnumber10Reviews per page (1-100)
offsetnumber0Reviews to skip
langstringLocale code for translated slug lookup
{
"data": [
{
"id": "0191abc0-0000-7000-8000-000000000200",
"author": "Jane",
"content": "Love this product!",
"rating": 5,
"createdAt": "2024-06-15T10:30:00.000Z"
}
],
"meta": { "count": 1, "offset": 0, "limit": 10 },
"summary": { "averageRating": 5, "reviewCount": 1 }
}

Create Review

POST /api/v1/products/:idOrSlug/reviews

Submits a review (pending approval by store owner).

FieldTypeRequiredDescription
authorstringYesReviewer name (1-100 chars)
emailstringYesReviewer email (not returned in responses)
contentstringYesReview text (1-5000 chars)
ratingnumberYesStar rating (1-5)