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

Easel

← API Documentation

API Documentation

PRE-RELEASE WARNING: This API is currently in pre-release and undergoing rapid development. Breaking changes are occurring frequently as we work toward a stable v1 release. Please use caution when building production systems against this API during the pre-release period.

The Easel API is a RESTful HTTP API for your ecommerce store. Use it to keep inventory in sync, or to pull orders and customer data into your own tools.

What can you do with the API?

  • Manage your catalog: Create and update products, variants, options, images, and tags
  • Process orders: Update order status, record shipments and refunds, and manage digital downloads
  • Manage customers: Store customer information and their addresses
  • Configure storefronts: Manage sites, pages, collections, discount codes, and more

Base URL

/api/v1/

Authentication

All API endpoints require authentication using Bearer tokens. See the Authentication documentation for details.

Response Format

All API responses use JSON format. Single resources are returned as a JSON object:

{
  "id": "pro_d0b6fmv28q6vn14peun0",
  "name": "Example Product",
  "status": "active",
  "created_at": "2023-01-01T00:00:00Z"
}

List endpoints wrap results in a data array:

{
  "data": [
    {
      "id": "pro_d0b6fmv28q6vn14peun0",
      "name": "Example Product"
    }
  ],
  "has_more": true
}

Some list endpoints are not paginated and return only data.

Error responses include a descriptive message and an error code:

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

Common error codes include INVALID_JSON, MISSING_FIELD, INVALID_FIELD, INVALID_REQUEST_ERROR, REQUEST_TOO_LARGE, NOT_FOUND, DUPLICATE, CONFLICT, ORDER_CANCELED, TOO_MANY_VARIANTS, and INTERNAL_ERROR.

Request bodies are limited to 1 MiB, except on the file upload endpoints,
which document their own limits. A larger body returns
413 Request Entity Too Large:

{
  "error": "Request body is too large",
  "code": "REQUEST_TOO_LARGE"
}

Query parameter validation failures use the INVALID_REQUEST_ERROR code. The
error message names the offending parameter, for example:

{
  "error": "Invalid 'limit' parameter: cannot exceed 100",
  "code": "INVALID_REQUEST_ERROR"
}

Pagination

Lists support cursor-based pagination using the after and before query
parameters, plus limit:

  • after: Return results after this public ID
  • before: Return results before this public ID
  • limit: Number of results to return (default 10, max 100)
  • after and before cannot be used together

A list keeps one order whichever way you page: a page from before comes in
the same order as a page from after, and holds the results nearest the
cursor. Products, orders, and customers come oldest first; each list's docs
give its order. Searches and filters page with after and before like the
plain list.

Gift card lists also accept a status filter. Order lists also accept
status and refund_status filters, and customer lists accept email and
search filters. The product and customer lists also accept external_source
and external_id to find an imported
record
. The waitlisted products
list
accepts search and ranks by waiting count, as
does the wishlisted products list. The review
list
accepts product, customer, and status filters,
newest first. The translation
list
pages by each translation's
cursor, and accepts status, language, and product filters.
The activity log accepts entity_type, entity_id,
and actor filters, newest first.
Paginated responses include a has_more boolean.

Example:

GET /api/v1/products/?after=pro_d0b6fmv28q6vn14peun0&limit=20

Idempotency

To ensure safe retries of write operations (POST and PUT requests), you can provide an Idempotency-Key header. This prevents duplicate operations if a request is retried due to network issues or timeouts.

How it Works

  1. Include an Idempotency-Key header with a unique string (1 to 256 characters) in your POST or PUT request
  2. If the request succeeds, the response is cached for 24 hours
  3. Subsequent requests with the same key return the cached response without executing the operation again
  4. The X-Idempotency-Replayed header indicates whether the response was replayed from cache

File uploads (product images, digital files, and gift option images) ignore the Idempotency-Key header: a file is too large to buffer and hash, so uploading it twice stores it twice.

Example

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

Response Headers

When a request includes an Idempotency-Key, the response includes:

  • X-Idempotency-Replayed: false - Request was processed normally
  • X-Idempotency-Replayed: true - Response was returned from cache

Important Notes

  • Idempotency keys are scoped to your store: a key is shared by every API key in the store, so each key must be unique for the whole store
  • Only successful responses (2xx status codes) are cached. Failed requests release the key so it can be retried
  • The request body must match exactly for the cached response to be returned. Reusing a key with a different method, path, or body returns 400 Bad Request
  • Different request methods or paths require different idempotency keys
  • Retrying a key while the original request is still in flight returns 409 Conflict; retry after a short delay
  • Keys are optional. Without a key, requests are processed normally

Imports and External References

Products, product variants, product images, collections, and customers can
record the ID they had in the system they were imported from, such as Shopify
or Etsy. An importer uses this to find what an earlier run created, so it can
run again after a partial failure without making duplicates.

Set both fields when creating the record:

  • external_source: the system's name, up to 32 lowercase letters, digits,
    -, or _ (for example shopify)
  • external_id: the record's ID in that system, up to 256 characters

Both must be set together, and they can only be set on create; updates ignore
them. Every resource returns both fields, which are null for records made in
Easel.

A reference is unique per store and resource type. Creating a record with a
reference that's already taken returns 409 Conflict with the existing
record's ID, so the importer can update it instead:

{
  "error": "A record with this external reference already exists",
  "code": "DUPLICATE",
  "id": "pro_d0b6fmv28q6vn14peun0"
}

To look a record up before creating it, filter the product or customer list by
both fields. The response's data holds the one matching record, or nothing,
and the other filters and cursor are ignored:

GET /api/v1/products/?external_source=shopify&external_id=632910392

Variants, images, and collections are listed by their product or site, and
each item includes its reference, so match on those fields. When a merchant
deletes a customer, its reference is cleared, so a later import creates the
customer again.

An external reference makes a create safe to repeat across runs, while an
Idempotency-Key makes a single request safe to retry. An importer can use
both.

HTTP Status Codes

  • 200 OK - Request successful
  • 201 Created - Resource created
  • 204 No Content - Request successful, no response body
  • 400 Bad Request - Invalid request data
  • 401 Unauthorized - Authentication required or invalid
  • 403 Forbidden - The API key's scopes don't allow the request
  • 404 Not Found - Resource not found
  • 405 Method Not Allowed - Unsupported HTTP method
  • 409 Conflict - Resource already exists (a DUPLICATE error for an
    external reference includes the existing record's id), or the
    resource's state doesn't allow the change: CONFLICT, such as canceling
    a shipment whose label hasn't been voided, ORDER_CANCELED, which
    refuses to ship an order the customer canceled, SYSTEM_COLLECTION,
    which refuses to change New Arrivals or Best Sellers, or
    TOO_MANY_VARIANTS, which refuses a variant, options or an option value
    that would take a product past 100 variants
  • 413 Request Entity Too Large - Request body or uploaded file exceeds the size limit
  • 429 Too Many Requests - Rate limit exceeded
  • 500 Internal Server Error - Server error

Rate Limiting

API requests are rate limited per store at 60 requests per minute. Rate limit information is returned in response headers:

  • X-Ratelimit-Limit: Total requests allowed per window
  • X-Ratelimit-Remaining: Requests remaining in the current window
  • X-Ratelimit-Reset: Unix timestamp when the rate limit resets

When the limit is exceeded, the API returns 429 Too Many Requests.

Data Types

Timestamps

All timestamps are returned in RFC3339 format (ISO 8601):

2023-01-01T00:00:00Z

IDs

Public IDs are used for all external-facing identifiers:

  • Products: pro_d0b6fmv28q6vn14peun0
  • Orders: ord_d0b6fmv28q6vn14peun0
  • Customers: cus_d0b6fmv28q6vn14peun0
  • Variants: prv_d0b6fmv28q6vn14peun0
  • Sites: sit_d0b6fmv28q6vn14peun0

Paginated list cursors use these public IDs.

Monetary Values

All monetary values are integers in the smallest currency unit for your store's currency (for example, cents for USD and yen for JPY):

{
  "price": 1999,
  "total": 2599
}

API Reference

Resource Description
Activity Log Read who changed which product or setting, and when
Authentication API key authentication and scopes
Carriers Look up carrier IDs
Collections Group products on a site
Customer Addresses Manage customer addresses
Customers Store and manage customer information
Digital Files Manage downloadable variant files
Discount Codes Manage site discount codes
Gift Options Manage gift wrapping and other gift options
Gift Cards Issue gift cards and manage their balances
Shipments Record shipments and tracking
Order Downloads Manage digital download links
Locations Choose where the store sells in person
Orders Process and manage customer orders
Pages Manage home and info page content
Product Images Upload and manage product photos
Product Options Manage option choices such as size and color
Product Variants Handle prices, inventory, and sales
Products Manage your product catalog
Refunds List and create refunds
Restock Waitlist Track shoppers waiting for a restock
Reviews Read and moderate product reviews
Shipping Rates Set what each site charges to ship
Sites Manage storefront sites
Store Filters Promote product options to storefront filters
Tax Registrations Choose where the store collects tax
Tags Organize products with tags
Translations Offer a site in other languages and translate its content
Wishlists Track products shoppers have saved