Variants
Variants represent the purchasable units of a product. A product with Size and Color options might have variants like “S / Red”, “M / Blue”, etc. Each variant has its own price, SKU, inventory count, and shipping details. A product can have up to 250 variants.
Base URL: https://api.hydrajs.dev
Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v1/products/{id}/variants |
Publishable | List variants for a product |
POST |
/v1/products/{id}/variants |
Secret | Create a variant |
POST |
/v1/products/{id}/variants/generate |
Secret | Generate variants from option combinations |
PATCH |
/v1/variants/{id} |
Secret | Update a variant |
DELETE |
/v1/variants/{id} |
Secret | Delete a variant |
List variants
GET /v1/products/{id}/variants
Returns all variants for a product, ordered by position.
Request
curl https://api.hydrajs.dev/v1/products/prod_abc123/variants \
-H "Authorization: Bearer pk_live_YOUR_KEY"
Response 200
{
"data": [
{
"id": "var_def456",
"product_id": "prod_abc123",
"title": "S",
"sku": "TSH-S",
"barcode": null,
"price": 2999,
"sale_price": null,
"cost": 800,
"taxable": true,
"tax_code": null,
"hs_code": null,
"country_of_origin": null,
"inventory_quantity": 50,
"low_stock_threshold": null,
"qty_step": null,
"weight": 180,
"weight_unit": "g",
"image_id": null,
"options": { "Size": "S" },
"currency_prices": {},
"currency_sale_prices": {},
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-08-01T14:22:00Z"
},
{
"id": "var_ghi789",
"product_id": "prod_abc123",
"title": "M",
"sku": "TSH-M",
"barcode": null,
"price": 2999,
"sale_price": null,
"cost": 800,
"taxable": true,
"tax_code": null,
"hs_code": null,
"country_of_origin": null,
"inventory_quantity": 35,
"low_stock_threshold": 10,
"qty_step": null,
"weight": 190,
"weight_unit": "g",
"image_id": null,
"options": { "Size": "M" },
"currency_prices": {},
"currency_sale_prices": {},
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-08-01T14:22:00Z"
}
]
}
Create a variant
POST /v1/products/{id}/variants
Adds a new variant to a product. The variant is appended to the end of the variant list (highest position).
Request body
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | Variant title (1-255 chars) |
sku |
string | No | Stock keeping unit (max 100 chars) |
barcode |
string | No | Barcode / UPC (max 100 chars) |
price |
integer | Yes | Price in cents (e.g. 2999 = $29.99). Min 0 |
sale_price |
integer | No | Original price in cents for sale display. Min 0 |
cost |
integer | No | Cost per item in cents. Min 0 |
taxable |
boolean | No | Whether the variant is taxable (default: true) |
tax_code |
string | No | Tax code for tax calculation (max 50 chars) |
hs_code |
string | No | Legacy — use product-level hs_code instead (max 20 chars) |
country_of_origin |
string | No | Legacy — use product-level country_of_origin instead |
inventory_quantity |
integer | No | Stock count (default: 0) |
low_stock_threshold |
integer | No | Threshold for inventory.low webhook. Min 0 |
qty_step |
integer | No | Minimum quantity increment. Min 1 |
weight |
integer | No | Weight in weight_unit units. Min 0 |
weight_unit |
string | No | g (default), kg, oz, lb |
image_id |
string | No | ID of an image belonging to the same product |
options |
object | No | Option values: { "Size": "M", "Color": "Blue" } |
currency_prices |
object | No | Multi-currency prices: { "EUR": 2799, "GBP": 2499 } |
currency_sale_prices |
object | No | Multi-currency sale prices |
ℹPrices are integers
All price fields (price, sale_price, cost, currency_prices, currency_sale_prices) are
integers representing the smallest currency unit (e.g. cents for USD). 2999 means $29.99.
Request
curl -X POST https://api.hydrajs.dev/v1/products/prod_abc123/variants \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "L",
"sku": "TSH-L",
"price": 2999,
"sale_price": 3999,
"cost": 800,
"inventory_quantity": 75,
"weight": 200,
"weight_unit": "g",
"options": { "Size": "L" },
"currency_prices": { "EUR": 2799, "GBP": 2499 }
}'
Response 201
{
"data": {
"id": "var_jkl012",
"product_id": "prod_abc123",
"title": "L",
"sku": "TSH-L",
"barcode": null,
"price": 2999,
"sale_price": 3999,
"cost": 800,
"taxable": true,
"tax_code": null,
"hs_code": null,
"country_of_origin": null,
"inventory_quantity": 75,
"low_stock_threshold": null,
"qty_step": null,
"weight": 200,
"weight_unit": "g",
"image_id": null,
"options": { "Size": "L" },
"currency_prices": { "EUR": 2799, "GBP": 2499 },
"currency_sale_prices": {},
"created_at": "2026-08-17T09:15:00Z",
"updated_at": "2026-08-17T09:15:00Z"
}
}
Generate variants
POST /v1/products/{id}/variants/generate
Bulk-creates variants from option combinations. Each combination becomes a variant with a title built from the option values joined by /. Maximum 250 variants per product.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
combinations |
object[] | Yes | Array of option maps (max 250). Each object has option names as keys and values as strings |
Request
curl -X POST https://api.hydrajs.dev/v1/products/prod_abc123/variants/generate \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"combinations": [
{ "Size": "S", "Color": "Red" },
{ "Size": "S", "Color": "Blue" },
{ "Size": "M", "Color": "Red" },
{ "Size": "M", "Color": "Blue" }
]
}'
Response 201
{
"data": {
"variants": [
{
"id": "var_mno345",
"title": "S / Red",
"price": 0,
"options": { "Size": "S", "Color": "Red" }
},
{
"id": "var_pqr678",
"title": "S / Blue",
"price": 0,
"options": { "Size": "S", "Color": "Blue" }
},
{
"id": "var_stu901",
"title": "M / Red",
"price": 0,
"options": { "Size": "M", "Color": "Red" }
},
{
"id": "var_vwx234",
"title": "M / Blue",
"price": 0,
"options": { "Size": "M", "Color": "Blue" }
}
]
}
}
⚠Generated variants have zero price
Variants created via /generate start with price: 0. You must update each variant’s price
individually using PATCH /v1/variants/{id}.
Update a variant
PATCH /v1/variants/{id}
Partially updates a variant. Send only the fields you want to change. Returns the updated variant.
Request body
All fields are optional:
| Field | Type | Description |
|---|---|---|
title |
string | Variant title (1-255 chars) |
sku |
string | Stock keeping unit (max 100 chars) |
barcode |
string | Barcode / UPC (max 100 chars) |
price |
integer | Price in cents. Min 0 |
sale_price |
integer | null | Original price in cents. Set null to clear |
cost |
integer | null | Cost per item in cents. Set null to clear |
taxable |
boolean | Whether the variant is taxable |
tax_code |
string | null | Tax code. Set null to clear (max 50 chars) |
hs_code |
string | null | Legacy — use product-level hs_code instead |
country_of_origin |
string | null | Legacy — use product-level country_of_origin instead |
inventory_quantity |
integer | Stock count |
low_stock_threshold |
integer | null | Low-stock webhook threshold. Set null to disable |
qty_step |
integer | null | Minimum quantity increment. Set null to clear |
weight |
integer | null | Weight in weight_unit units. Set null to clear |
weight_unit |
string | g, kg, oz, lb |
image_id |
string | null | Image ID. Set null to unlink |
options |
object | Option values map |
currency_prices |
object | Multi-currency prices |
currency_sale_prices |
object | Multi-currency sale prices |
Request
curl -X PATCH https://api.hydrajs.dev/v1/variants/var_def456 \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"price": 3499,
"sale_price": 3999,
"sku": "TSH-S-V2",
"inventory_quantity": 100,
"low_stock_threshold": 10,
"hs_code": "6109.10.0040",
"country_of_origin": "US"
}'
Response 200
{
"data": {
"id": "var_def456",
"product_id": "prod_abc123",
"title": "S",
"sku": "TSH-S-V2",
"barcode": null,
"price": 3499,
"sale_price": 3999,
"cost": 800,
"taxable": true,
"tax_code": null,
"hs_code": "6109.10.0040",
"country_of_origin": "US",
"inventory_quantity": 100,
"low_stock_threshold": 10,
"qty_step": null,
"weight": 180,
"weight_unit": "g",
"image_id": null,
"options": { "Size": "S" },
"currency_prices": {},
"currency_sale_prices": {},
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-08-17T09:30:00Z"
}
}
Delete a variant
DELETE /v1/variants/{id}
Permanently deletes a variant. This action cannot be undone.
Request
curl -X DELETE https://api.hydrajs.dev/v1/variants/var_def456 \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 204
Empty body.
⚠Hard delete
Unlike products and customers, variants are permanently deleted, not soft-deleted. Ensure the variant is no longer referenced in active carts or orders before deleting.
The variant object
| Field | Type | Description |
|---|---|---|
id |
string | Unique ID (prefix: var_) |
product_id |
string | Parent product ID |
title |
string | Variant title |
sku |
string | null | Stock keeping unit |
barcode |
string | null | Barcode / UPC |
price |
integer | Price in cents |
sale_price |
integer | null | Original price for sale display |
cost |
integer | null | Cost per item in cents |
taxable |
boolean | Whether the variant is taxable |
tax_code |
string | null | Tax code for tax calculation |
hs_code |
string | null | Legacy — canonical value is on the product |
country_of_origin |
string | null | Legacy — canonical value is on the product |
inventory_quantity |
integer | Current stock count |
low_stock_threshold |
integer | null | Threshold for low-stock webhook |
qty_step |
integer | null | Minimum quantity increment |
weight |
integer | null | Weight value |
weight_unit |
string | Weight unit: g, kg, oz, lb |
image_id |
string | null | Associated image ID |
options |
object | Option name-value pairs (e.g. { "Size": "M" }) |
currency_prices |
object | Multi-currency price overrides (e.g. { "EUR": 2799 }) |
currency_sale_prices |
object | Multi-currency sale price overrides |
created_at |
string | ISO 8601 timestamp |
updated_at |
string | ISO 8601 timestamp |