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

Easel

← API Documentation

Products API

Manage products in your store. A product has a name, a status, an optional
description, and one or more variants that hold the price and inventory.

Related resources:

Endpoints


List Products

Retrieve a paginated list of products for your store.

Endpoint: GET /api/v1/products/

Permission Required: Read

Query Parameters

Parameter Type Description
after string Return products after this public ID
before string Return products before this public ID
limit integer Number of products to return (default 10, max 100)
search string Search products by name or description
status string Filter by product status (draft, active, archived)

after and before cannot be used together.

Request

curl -X GET "https://studio.easel.engineering/api/v1/products/?status=active&limit=20" \
  -H "Authorization: Bearer your_api_key_here"

Response

Status: 200 OK

{
  "data": [
    {
      "id": "pro_d0b6fmv28q6vn14peun0",
      "name": "Premium T-Shirt",
      "status": "active",
      "description": "High-quality cotton t-shirt",
      "created_at": "2023-01-01T10:00:00Z",
      "updated_at": "2023-01-01T10:15:00Z"
    }
  ],
  "has_more": true
}

Error Responses

Invalid query parameter

Status: 400 Bad Request

{
  "error": "Invalid 'after' parameter",
  "code": "INVALID_FIELD"
}

Failed to list products

Status: 500 Internal Server Error

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

Create Product

Create a new product in your store. New products are created with the draft
status, physical fulfillment, and no variants.

Endpoint: POST /api/v1/products/

Permission Required: Write

Request Body

{
  "name": "Premium T-Shirt",
  "description": "High-quality cotton t-shirt"
}

Fields

Field Type Required Description
name string Yes Product name
description string No Product description

Request

curl -X POST "https://studio.easel.engineering/api/v1/products/" \
  -H "Authorization: Bearer your_api_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-12345" \
  -d '{
    "name": "Premium T-Shirt",
    "description": "High-quality cotton t-shirt"
  }'

Optional Headers:

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

Response

Returns the created product.

Status: 201 Created

{
  "id": "pro_d0b6fmv28q6vn14peun0",
  "name": "Premium T-Shirt",
  "status": "draft",
  "description": "High-quality cotton t-shirt",
  "created_at": "2023-01-01T10:00:00Z",
  "updated_at": "2023-01-01T10: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": "Product name is required",
  "code": "MISSING_FIELD"
}

Failed to create product

Status: 500 Internal Server Error

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

Get Product

Retrieve a single product by its public ID.

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

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/" \
  -H "Authorization: Bearer your_api_key_here"

Response

Status: 200 OK

{
  "id": "pro_d0b6fmv28q6vn14peun0",
  "name": "Premium T-Shirt",
  "status": "active",
  "description": "High-quality cotton t-shirt",
  "created_at": "2023-01-01T10:00:00Z",
  "updated_at": "2023-01-01T10:15:00Z"
}

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"
}

Update Product

Update an existing product's name, description, or status.

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

Permission Required: Write

Path Parameters

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

Request Body

{
  "name": "Premium T-Shirt - Updated",
  "status": "active",
  "description": "Updated high-quality cotton t-shirt"
}

Fields

Field Type Required Description
name string Yes Product name
status string Yes Product status: draft, active, or archived
description string No Product description

Request

curl -X PUT "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/" \
  -H "Authorization: Bearer your_api_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-67890" \
  -d '{
    "name": "Premium T-Shirt - Updated",
    "status": "active",
    "description": "Updated high-quality cotton t-shirt"
  }'

Optional Headers:

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

Response

Returns the updated product.

Status: 200 OK

{
  "id": "pro_d0b6fmv28q6vn14peun0",
  "name": "Premium T-Shirt - Updated",
  "status": "active",
  "description": "Updated high-quality cotton t-shirt",
  "created_at": "2023-01-01T10:00:00Z",
  "updated_at": "2023-01-01T11:30: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": "Product name is required",
  "code": "MISSING_FIELD"
}

Invalid status

Status: 400 Bad Request

{
  "error": "Status must be 'draft', 'active', or 'archived'",
  "code": "INVALID_FIELD"
}

Product not found

Status: 404 Not Found

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

Failed to update product

Status: 500 Internal Server Error

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

Duplicate Product

Copy a product and its variants into a new draft product.

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

Permission Required: Write

Path Parameters

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

Request

curl -X POST "https://studio.easel.engineering/api/v1/products/pro_d0b6fmv28q6vn14peun0/duplicate/" \
  -H "Authorization: Bearer your_api_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-13579"

Response

Status: 201 Created

{
  "id": "pro_new1fmv28q6vn14peun0"
}

Error Responses

Product not found

Status: 404 Not Found

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

Too many copies

Status: 400 Bad Request

{
  "error": "Invalid input",
  "code": "INVALID_FIELD"
}

Failed to duplicate product

Status: 500 Internal Server Error

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

Product Object

Fields

Field Type Description
id string Product public ID
name string Product name
status string Product status: draft, active, archived
description string|null Product description
created_at string ISO 8601 timestamp
updated_at string ISO 8601 timestamp

Product Status Values

  • draft - Product is being configured, not visible to customers
  • active - Product is available for purchase
  • archived - Product is no longer available but preserved for historical data

Fulfillment Type

The fulfillment type is set on the product and shown on its variants. Products
created through the API are physical. Digital variants carry a downloadable
file, which you manage with the Digital Files endpoints.