Product Options API
Manage product options and their values. Options describe the choices a
customer makes, for example Size or Color. Each option has an ordered list of
values such as Small, Medium, and Large.
Options and values make, rename and merge a product's
variants as the dashboard does. A product can also
start with its options and every combination of their values; see
Options.
Endpoints
Options:
- List Product Options -
GET /api/v1/products/{product_id}/options/ - Create Product Option -
POST /api/v1/products/{product_id}/options/ - Update Product Option -
PUT /api/v1/products/{product_id}/options/{option_id}/ - Delete Product Option -
DELETE /api/v1/products/{product_id}/options/{option_id}/
Values:
- Create Product Option Value -
POST /api/v1/products/{product_id}/options/{option_id}/values/ - Update Product Option Value -
PUT /api/v1/products/{product_id}/options/{option_id}/values/{value_id}/ - Move Product Option Value Up -
POST /api/v1/products/{product_id}/options/{option_id}/values/{value_id}/move-up/ - Delete Product Option Value -
DELETE /api/v1/products/{product_id}/options/{option_id}/values/{value_id}/
List Product Options
Retrieve all options for a product, including each option's values. This
endpoint is not paginated.
Endpoint: GET /api/v1/products/{product_id}/options/
Scope Required: products:read
Request
curl -X GET "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/options/" \
-H "Authorization: Bearer your_api_key_here"
Response
Status: 200 OK
{
"data": [
{
"id": "pop_d0b6fmv28q6vn14peun0",
"name": "Color",
"type": "color",
"values": [
{
"id": "pov_d0b6fmv28q6vn14peun0",
"value": "Red",
"position": 0,
"hex": "#ff0000"
},
{
"id": "pov_xk3mq7r41p8nt26zv9w0",
"value": "Blue",
"position": 1,
"hex": "#0000ff"
}
],
"created_at": "2023-01-01T10:00:00Z",
"updated_at": "2023-01-01T10:15:00Z"
}
]
}
Create Product Option
Create an option for a product. Every variant has one value of each option, so
when the product already has variants, send a default_value: the option is
created with that value, and each variant gets it and is renamed to include
it. A product without variants yet needs no default; add values with
Create Product Option Value.
Endpoint: POST /api/v1/products/{product_id}/options/
Scope Required: products:write
Request Body
{
"name": "Size",
"type": "text"
}
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Option name |
type |
string | Yes | text or color |
default_value |
string | When the product has variants | Value given to every existing variant |
default_hex |
string | No | Hex color of default_value, for color options (e.g. #ff0000) |
Request
curl -X POST "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/options/" \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-12345" \
-d '{"name": "Size", "type": "text"}'
Response
Status: 201 Created
{
"id": "pop_d0b6fmv28q6vn14peun0",
"name": "Size",
"type": "text",
"values": [],
"created_at": "2023-01-01T10:00:00Z",
"updated_at": "2023-01-01T10:00:00Z"
}
Error Responses
Missing required field
Status: 400 Bad Request
{
"error": "Name is required",
"code": "MISSING_FIELD"
}
Invalid option type
Status: 400 Bad Request
{
"error": "Type is required",
"code": "MISSING_FIELD"
}
Default value missing
The product has variants, but no default_value was sent.
Status: 400 Bad Request
{
"error": "Invalid 'default_value' parameter: required when the product has variants",
"code": "INVALID_REQUEST_ERROR"
}
Update Product Option
Rename an option.
Endpoint: PUT /api/v1/products/{product_id}/options/{option_id}/
Scope Required: products:write
Request Body
{
"name": "Sizing"
}
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Option name |
Request
curl -X PUT "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/options/pop_d0b6fmv28q6vn14peun0/" \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-67890" \
-d '{"name": "Sizing"}'
Response
Status: 200 OK
{
"id": "pop_d0b6fmv28q6vn14peun0",
"name": "Sizing",
"type": "text",
"values": [],
"created_at": "2023-01-01T10:00:00Z",
"updated_at": "2023-01-01T10:30:00Z"
}
Delete Product Option
Delete an option and its values, as the dashboard does. Variants that then
have the same values are merged into one, the oldest, and every variant is
renamed without the option's value: deleting Color from "Red, S" and
"Blue, S" leaves one variant, "S". Shoppers' carts lose the product's
variants. Nothing changes once any of the product's variants has been
ordered.
Endpoint: DELETE /api/v1/products/{product_id}/options/{option_id}/
Scope Required: products:write
Request
curl -X DELETE "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/options/pop_d0b6fmv28q6vn14peun0/" \
-H "Authorization: Bearer your_api_key_here"
Response
Status: 204 No Content
Error Responses
A variant of the product has been ordered
Status: 409 Conflict
{
"error": "Variants someone has ordered can't be deleted or merged",
"code": "CONFLICT"
}
Create Product Option Value
Add a value to an option. Values are ordered by position, starting at 0, and
a new one goes last. An option has at most 30 values; adding another fails
with 400 Bad Request and INVALID_FIELD.
Values make variants as they do in the dashboard:
- An option's first value is given to every variant the product has, and each
is renamed to include it. It makes no variants. - Another value makes one variant for each combination with the other
options' values, all at once. Adding "L" to Size, beside Color's "Red" and
"Blue", makes "Red, L" and "Blue, L": values are named in the order the
options were created, joined by ", ". Each new variant costs what the
product's first variant does and starts with no stock, SKU or barcode. - A value makes no variants while another option has no values yet, or while
the product has no variants at all (one made through the API without
options): there is no first variant to price them like.
A value whose combinations would take the product past 100 variants is
refused with 409 Conflict and TOO_MANY_VARIANTS, and neither the value nor
any variant is made.
Endpoint: POST /api/v1/products/{product_id}/options/{option_id}/values/
Scope Required: products:write
Request Body
{
"value": "L",
"hex": null
}
| Field | Type | Required | Description |
|---|---|---|---|
value |
string | Yes | Value text |
hex |
string | No | Hex color for color options (e.g. #ff0000) |
Request
curl -X POST "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/options/pop_d0b6fmv28q6vn14peun0/values/" \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-13579" \
-d '{"value": "L"}'
Response
Status: 201 Created
The new value and the variants it made, in the order made. variants is
always present, and empty when the value made none.
{
"value": {
"id": "pov_d0b6fmv28q6vn14peun0",
"value": "L",
"position": 2
},
"variants": [
{
"id": "prv_d0b6fmv28q6vn14peun0",
"name": "Red, L",
"price": 2500,
"sale": null,
"total_inventory": 0,
"delivery": "physical",
"created_at": "2023-01-01T10:00:00Z",
"updated_at": "2023-01-01T10:00:00Z",
"external_source": null,
"external_id": null,
"weight_grams": null,
"sku": null,
"barcode": null
},
{
"id": "prv_xk3mq7r41p8nt26zv9w0",
"name": "Blue, L",
"price": 2500,
"sale": null,
"total_inventory": 0,
"delivery": "physical",
"created_at": "2023-01-01T10:00:00Z",
"updated_at": "2023-01-01T10:00:00Z",
"external_source": null,
"external_id": null,
"weight_grams": null,
"sku": null,
"barcode": null
}
]
}
Each variant is a Product Variant Object.
Error Responses
Missing value
Status: 400 Bad Request
{
"error": "Value is required",
"code": "MISSING_FIELD"
}
The variants would pass the cap
Status: 409 Conflict
{
"error": "A product can have at most 100 variants",
"code": "TOO_MANY_VARIANTS"
}
Update Product Option Value
Update a value's text and color. Every variant using the value is renamed to
match.
Endpoint: PUT /api/v1/products/{product_id}/options/{option_id}/values/{value_id}/
Scope Required: products:write
Request Body
{
"value": "Extra Small",
"hex": null
}
Request
curl -X PUT "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/options/pop_d0b6fmv28q6vn14peun0/values/pov_d0b6fmv28q6vn14peun0/" \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-24680" \
-d '{"value": "Extra Small"}'
Response
Status: 200 OK
{
"id": "pov_d0b6fmv28q6vn14peun0",
"value": "Extra Small",
"position": 0
}
Move Product Option Value Up
Move a value one position earlier in the option's list.
Endpoint: POST /api/v1/products/{product_id}/options/{option_id}/values/{value_id}/move-up/
Scope Required: products:write
Request
curl -X POST "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/options/pop_d0b6fmv28q6vn14peun0/values/pov_d0b6fmv28q6vn14peun0/move-up/" \
-H "Authorization: Bearer your_api_key_here" \
-H "Idempotency-Key: unique-request-id-11223"
Response
Status: 204 No Content
There is no move-down endpoint. To reorder downward, move the other values up.
Delete Product Option Value
Delete a value from an option, as the dashboard does. Every variant has a
value of each option, so when variants use the value and the option has
others, name one to take its place with replacement_id. The variants are
given it and renamed, and any that then match another variant's values are
merged into the oldest: deleting "Red" in favor of "Blue" turns "Red, S" into
"Blue, S", merged with the existing "Blue, S". Shoppers' carts lose the
variants that used the deleted value. Nothing changes once any of the
variants involved has been ordered.
A value no variant uses, or an option's only value, needs no replacement;
deleting an option's only value takes it off its variants.
Endpoint: DELETE /api/v1/products/{product_id}/options/{option_id}/values/{value_id}/
Scope Required: products:write
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
replacement_id |
string | When variants use the value and the option has other values | Another value of the same option, given to the variants in its place |
Request
curl -X DELETE "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/options/pop_d0b6fmv28q6vn14peun0/values/pov_d0b6fmv28q6vn14peun0/?replacement_id=pov_xk3mq7r41p8nt26zv9w0" \
-H "Authorization: Bearer your_api_key_here"
Response
Status: 204 No Content
Error Responses
Replacement missing
Status: 400 Bad Request
{
"error": "Invalid 'replacement_id' parameter: required when variants use the value and the option has others",
"code": "INVALID_REQUEST_ERROR"
}
Replacement is the value deleted
Status: 400 Bad Request
{
"error": "Invalid input",
"code": "INVALID_FIELD"
}
A variant involved has been ordered
Status: 409 Conflict
{
"error": "Variants someone has ordered can't be deleted or merged",
"code": "CONFLICT"
}
Value or replacement not found
Status: 404 Not Found
{
"error": "Resource not found",
"code": "NOT_FOUND"
}
Product Option Object
Fields
| Field | Type | Description |
|---|---|---|
id |
string | Option public ID |
name |
string | Option name |
type |
string | text or color |
values |
array | Option values |
created_at |
string | ISO 8601 timestamp |
updated_at |
string | ISO 8601 timestamp |
Product Option Value Object
Fields
| Field | Type | Description |
|---|---|---|
id |
string | Value public ID |
value |
string | Value text |
position |
integer | Sort position, starting at 0 |
hex |
string|null | Hex color for color options |