Public Alpha. Easel is in early development, so expect rough edges.

Easel

← API Documentation

Product Variants API

Manage product variants for your products. A variant is a specific version of
a product, for example a size or color, with its own price and inventory.

Endpoints

Digital files have their own endpoints. See
Digital Files.


List Product Variants

Retrieve all variants for a specific product. Variant lists are not paginated,
so has_more is always false.

Endpoint: GET /api/v1/products/{id}/variants/

Permission Required: Read

Path Parameters

Parameter Type Description
id string Product public ID (e.g., pro_d0b6fmv28q6vn14peun0)

Request

curl -X GET "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/variants/" \
  -H "Authorization: Bearer your_api_key_here"

Response

Status: 200 OK

{
  "data": [
    {
      "id": "prv_d0b6fmv28q6vn14peun0",
      "name": "Small Red",
      "price": 1999,
      "sale": null,
      "total_inventory": 50,
      "fulfillment_type": "physical",
      "created_at": "2023-01-01T10:00:00Z",
      "updated_at": "2023-01-01T10:15:00Z"
    },
    {
      "id": "prv_xk3mq7r41p8nt26zv9w0",
      "name": "Large Blue",
      "price": 2499,
      "sale": {
        "price": 1999
      },
      "total_inventory": 25,
      "fulfillment_type": "physical",
      "created_at": "2023-01-01T10:30:00Z",
      "updated_at": "2023-01-01T11:00:00Z"
    }
  ],
  "has_more": false
}

Error Responses

Product not found

Status: 404 Not Found

{
  "error": "Resource not found",
  "code": "NOT_FOUND"
}

Failed to get product

Status: 500 Internal Server Error

{
  "error": "Internal server error",
  "code": "INTERNAL_ERROR"
}

Create Product Variant

Create a new variant for a specific product.

Endpoint: POST /api/v1/products/{id}/variants/

Permission Required: Write

Path Parameters

Parameter Type Description
id string Product public ID (e.g., pro_d0b6fmv28q6vn14peun0)

Request Body

{
  "name": "Medium Green",
  "price": 2199,
  "inventory": 10
}

Fields

Field Type Required Description
name string Yes Variant name
price integer Yes Price in the store's smallest currency unit (must be non-negative)
inventory integer No Stock count (defaults to 0, must be non-negative)

Request

curl -X POST "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/variants/" \
  -H "Authorization: Bearer your_api_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-12345" \
  -d '{
    "name": "Medium Green",
    "price": 2199,
    "inventory": 10
  }'

Optional Headers:

  • Idempotency-Key: Unique string to prevent duplicate variant creation (see Idempotency)

Response

Returns the created variant.

Status: 201 Created

{
  "id": "prv_j2k5n8p1q4r7t0w3x6z9",
  "name": "Medium Green",
  "price": 2199,
  "sale": null,
  "total_inventory": 10,
  "fulfillment_type": "physical",
  "created_at": "2023-01-01T12:00:00Z",
  "updated_at": "2023-01-01T12:00:00Z"
}

Error Responses

Invalid JSON body

Status: 400 Bad Request

{
  "error": "Invalid JSON body",
  "code": "INVALID_JSON"
}

Missing required field

Status: 400 Bad Request

{
  "error": "Variant name is required",
  "code": "MISSING_FIELD"
}

Invalid price or inventory

Status: 400 Bad Request

{
  "error": "Price must be non-negative",
  "code": "INVALID_FIELD"
}

Failed to create variant

Status: 500 Internal Server Error

{
  "error": "Internal server error",
  "code": "INTERNAL_ERROR"
}

Get Product Variant

Retrieve a single product variant by its ID.

Endpoint: GET /api/v1/products/{id}/variants/{variant_id}/

Permission Required: Read

Path Parameters

Parameter Type Description
id string Product public ID (e.g., pro_d0b6fmv28q6vn14peun0)
variant_id string Variant public ID (e.g., prv_d0b6fmv28q6vn14peun0)

Request

curl -X GET "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/variants/prv_d0b6fmv28q6vn14peun0/" \
  -H "Authorization: Bearer your_api_key_here"

Response

Status: 200 OK

{
  "id": "prv_d0b6fmv28q6vn14peun0",
  "name": "Small Red",
  "price": 1999,
  "sale": null,
  "total_inventory": 50,
  "fulfillment_type": "physical",
  "created_at": "2023-01-01T10:00:00Z",
  "updated_at": "2023-01-01T10:15:00Z"
}

Error Responses

Variant not found

Status: 404 Not Found

{
  "error": "Resource not found",
  "code": "NOT_FOUND"
}

Failed to get variant

Status: 500 Internal Server Error

{
  "error": "Internal server error",
  "code": "INTERNAL_ERROR"
}

Update Product Variant

Update an existing product variant's price, inventory, or sale.

Endpoint: PUT /api/v1/products/{id}/variants/{variant_id}/

Permission Required: Write

Path Parameters

Parameter Type Description
id string Product public ID (e.g., pro_d0b6fmv28q6vn14peun0)
variant_id string Variant public ID (e.g., prv_d0b6fmv28q6vn14peun0)

Request Body

{
  "price": 2299,
  "inventory": 45,
  "sale": {
    "price": 1999
  }
}

Fields

Field Type Required Description
price integer Yes Price in the store's smallest currency unit (must be non-negative)
inventory integer Yes Stock count (must be non-negative)
sale object|null No Sale price. Omit or set to null to end the sale

Omit sale or set it to null to remove an existing sale. Supplying a
sale.price sets or updates the sale.

Request

curl -X PUT "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/variants/prv_d0b6fmv28q6vn14peun0/" \
  -H "Authorization: Bearer your_api_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-67890" \
  -d '{
    "price": 2299,
    "inventory": 45,
    "sale": {
      "price": 1999
    }
  }'

Optional Headers:

  • Idempotency-Key: Unique string to prevent duplicate variant updates (see Idempotency)

Response

Returns the updated variant.

Status: 200 OK

{
  "id": "prv_d0b6fmv28q6vn14peun0",
  "name": "Small Red",
  "price": 2299,
  "sale": {
    "price": 1999
  },
  "total_inventory": 45,
  "fulfillment_type": "physical",
  "created_at": "2023-01-01T10:00:00Z",
  "updated_at": "2023-01-01T13:30:00Z"
}

Error Responses

Invalid JSON body

Status: 400 Bad Request

{
  "error": "Invalid JSON body",
  "code": "INVALID_JSON"
}

Invalid price, inventory, or sale price

Status: 400 Bad Request

{
  "error": "Price must be non-negative",
  "code": "INVALID_FIELD"
}

Variant not found

Status: 404 Not Found

{
  "error": "Resource not found",
  "code": "NOT_FOUND"
}

Failed to update variant

Status: 500 Internal Server Error

{
  "error": "Internal server error",
  "code": "INTERNAL_ERROR"
}

Product Variant Object

Fields

Field Type Description
id string Variant public ID
name string Variant name
price integer Regular price in the store's smallest currency unit
sale object|null Sale information if the variant is on sale
total_inventory integer Current stock count
fulfillment_type string physical or digital
created_at string ISO 8601 timestamp
updated_at string ISO 8601 timestamp

Sale Object

When a variant is on sale, the sale field contains:

Field Type Description
price integer Sale price in the store's smallest currency unit

Fulfillment Type

The fulfillment type comes from the product. Physical variants are shipped and
carry inventory. Digital variants are delivered as a download and do not need
stock.