Sites API
Manage the storefront sites in your store. A site has a name, a copyright name,
a slug, a status, a currency, a language, the set of countries you ship to,
whether it sends wishlist sale alerts, and the
handling time its product pages and checkout estimate delivery dates from.
What it charges to ship is set by its
shipping rates.
A site's language is its main language, used for its storefront and for the
email it sends buyers, such as order confirmations, so it should match the
language your products are written in. A site can also be offered in other
languages, each under its own path prefix such as
/fr/. Buyers see the storefront in the language of the URL they visit,
whatever their browser asks for.
Related resources:
- Pages for the home page and info page content
- Collections for product groupings
- Discount Codes for site-scoped codes
- Wishlists for the wishlists alerts are sent for
- Gift Options for gift wrapping and the like
- Shipping Rates for what the site charges to ship
Endpoints
- List Sites -
GET /api/v1/sites/ - Create Site -
POST /api/v1/sites/ - Get Site -
GET /api/v1/sites/{site_id}/ - Update Site -
PUT /api/v1/sites/{site_id}/
List Sites
Retrieve the sites for your store. This endpoint is not paginated. The list
does not include allowed shipping countries, so allowed_shipping_countries is empty.
Fetch a single site to see them.
Endpoint: GET /api/v1/sites/
Scope Required: sites:read
Request
curl -X GET "https://studio.easel.engineering/api/v1/sites/" \
-H "Authorization: Bearer your_api_key_here"
Response
Status: 200 OK
{
"data": [
{
"id": "sit_d0b6fmv28q6vn14peun0",
"name": "My Store",
"copyright_name": "My Store",
"slug": "my-store",
"status": "active",
"currency": "USD",
"language": "en",
"languages": [],
"domain_host": null,
"allowed_shipping_countries": [],
"cancel_window_minutes": 15,
"gift_notes_enabled": true,
"gift_note_max_length": 200,
"created_at": "2023-01-01T10:00:00Z",
"updated_at": "2023-01-01T10:00:00Z",
"wishlist_sale_alerts": true,
"delivery_times": {
"handling_days": 1
}
}
]
}
Create Site
Create a new storefront site.
Endpoint: POST /api/v1/sites/
Scope Required: sites:write
Request Body
{
"name": "My Store",
"copyright_name": "My Store",
"allowed_shipping_countries": ["CA", "US"],
"language": "en"
}
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Site name |
copyright_name |
string | Yes | Name shown in the footer copyright notice |
allowed_shipping_countries |
array | No | ISO 3166-1 alpha-2 codes of the countries you ship to, such as ["CA", "US"]. See Country Codes |
language |
string | No | Language code such as en or de. Defaults to en |
all_products |
boolean | No | Show every product the store has on the new site (default false). A store's first site always does. See Product Sites |
A store's first site shows all of its products. Any later site starts with
none unless you send "all_products": true; add products to it with
Add Product Site.
A new site starts with wishlist sale alerts on. Use
Update Site to turn them off. It also starts with one free
"Standard" shipping rate per zone, which you can
price or replace.
Request
curl -X POST "https://studio.easel.engineering/api/v1/sites/" \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-12345" \
-d '{
"name": "My Store",
"copyright_name": "My Store",
"allowed_shipping_countries": ["CA", "US"],
"language": "en",
"languages": [],
"wishlist_sale_alerts": false
}'
Response
Status: 201 Created
{
"id": "sit_d0b6fmv28q6vn14peun0"
}
Error Responses
Missing required field
Status: 400 Bad Request
{
"error": "Name is required",
"code": "MISSING_FIELD"
}
Unknown country
A code in allowed_shipping_countries names no country Easel knows.
Status: 400 Bad Request
{
"error": "Countries must be ISO 3166-1 alpha-2 codes, such as \"US\"",
"code": "INVALID_FIELD"
}
Get Site
Retrieve a single site, including its allowed shipping countries.
Endpoint: GET /api/v1/sites/{site_id}/
Scope Required: sites:read
Request
curl -X GET "https://studio.easel.engineering/api/v1/sites/sit_d0b6fmv28q6vn14peun0/" \
-H "Authorization: Bearer your_api_key_here"
Response
Status: 200 OK
{
"id": "sit_d0b6fmv28q6vn14peun0",
"name": "My Store",
"copyright_name": "My Store",
"slug": "my-store",
"status": "active",
"currency": "USD",
"language": "en",
"languages": [],
"domain_host": "shop.example.com",
"allowed_shipping_countries": ["CA", "US"],
"reviews_enabled": true,
"cancel_window_minutes": 15,
"gift_notes_enabled": true,
"gift_note_max_length": 200,
"created_at": "2023-01-01T10:00:00Z",
"updated_at": "2023-01-01T10:00:00Z",
"wishlist_sale_alerts": true,
"delivery_times": {
"handling_days": 1
}
}
Error Responses
Site not found
Status: 404 Not Found
{
"error": "Resource not found",
"code": "NOT_FOUND"
}
Update Site
Update a site's name, copyright name, status, domain, allowed countries, language, reviews setting, wishlist sale alerts, cancel window,
and delivery times. All fields except language, reviews_enabled,
wishlist_sale_alerts, cancel_window_minutes, and delivery_times are
required. An empty domain_host clears the custom domain. The site logo is
preserved.
Endpoint: PUT /api/v1/sites/{site_id}/
Scope Required: sites:write
Request Body
{
"name": "My Store",
"copyright_name": "My Store",
"status": "active",
"domain_host": "shop.example.com",
"allowed_shipping_countries": ["CA", "US"],
"language": "en",
"reviews_enabled": true,
"wishlist_sale_alerts": false,
"cancel_window_minutes": 15,
"gift_notes_enabled": true,
"gift_note_max_length": 200
}
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Site name |
copyright_name |
string | Yes | Name shown in the footer copyright notice |
status |
string | Yes | active or draft |
domain_host |
string | Yes | Custom domain host, or an empty string |
allowed_shipping_countries |
array | Yes | ISO 3166-1 alpha-2 codes of the countries you ship to |
language |
string | No | Language code such as en or de. Omit it to keep the current language |
wishlist_sale_alerts |
boolean | No | Whether the site emails opted-in customers when wishlist items go on sale. Omit it to keep the current setting. See Wishlist Sale Alerts |
reviews_enabled |
boolean | No | Turn product reviews on or off for the site. Omit it to keep the current setting |
cancel_window_minutes |
integer | No | Minutes after paying that a buyer with an account may cancel their own order for a full refund, from 0 (off) to 1440. Omit it to keep the current setting |
delivery_times |
object | No | Replaces the site's delivery times. Omit it to keep the current ones |
gift_notes_enabled |
boolean | No | Whether buyers can write a gift note at checkout. Omit it to keep the current setting |
gift_note_max_length |
integer | No | Longest gift note, in characters, from 1 to 1000. Omit it to keep the current limit |
Request
curl -X PUT "https://studio.easel.engineering/api/v1/sites/sit_d0b6fmv28q6vn14peun0/" \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-67890" \
-d '{
"name": "My Store",
"copyright_name": "My Store",
"status": "active",
"domain_host": "shop.example.com",
"allowed_shipping_countries": ["CA", "US"],
"language": "en",
"languages": [],
"wishlist_sale_alerts": false,
"cancel_window_minutes": 15
}'
Response
Status: 204 No Content
Error Responses
Invalid status
Status: 400 Bad Request
{
"error": "Status must be 'active' or 'draft'",
"code": "INVALID_FIELD"
}
Unknown country
A code in allowed_shipping_countries names no country Easel knows.
Status: 400 Bad Request
{
"error": "Countries must be ISO 3166-1 alpha-2 codes, such as \"US\"",
"code": "INVALID_FIELD"
}
Invalid language
Status: 400 Bad Request
{
"error": "language must be a language code such as en or de",
"code": "INVALID_FIELD"
}
Invalid cancel window
Status: 400 Bad Request
{
"error": "cancel_window_minutes must be from 0 to 1440",
"code": "INVALID_FIELD"
}
Invalid delivery times
Status: 400 Bad Request
{
"error": "Days must be between 0 and 60",
"code": "INVALID_FIELD"
}
Site Object
Fields
| Field | Type | Description |
|---|---|---|
id |
string | Site public ID |
name |
string | Site name |
copyright_name |
string | Name shown in the footer copyright notice |
slug |
string | Storefront slug, made from the name when the site is created. Renaming the site keeps it, so its address on Easel's domain never moves |
status |
string | active or draft |
currency |
string | The store's currency code, such as USD, which all its sites price in |
language |
string | Main language code of the storefront and buyer email, such as en |
languages |
array | Other languages the storefront is offered in, sorted, such as ["de", "fr"]. Set them with Set Site Languages |
domain_host |
string|null | Custom domain host |
allowed_shipping_countries |
array | ISO 3166-1 alpha-2 codes of the countries you ship to, in order of their English names |
reviews_enabled |
boolean | Whether the storefront shows product reviews and takes new ones |
cancel_window_minutes |
integer | Minutes after paying that a buyer with an account may cancel their own order for a full refund, as long as nothing has shipped or been downloaded. 0 turns it off; new sites start at 15 |
gift_notes_enabled |
boolean | Whether buyers can write a gift note at checkout |
gift_note_max_length |
integer | Longest gift note, in characters. A new site takes 200 |
created_at |
string | ISO 8601 timestamp |
updated_at |
string | ISO 8601 timestamp |
wishlist_sale_alerts |
boolean | Whether the site emails opted-in customers when items on their wishlist go on sale. New sites start with it on. See Wishlist Sale Alerts |
delivery_times |
object | The handling time product pages and checkout estimate delivery dates from. See Delivery Times Object |
price_mode |
string | added when checkout adds tax on top of prices, as in the US; included when prices already include it, as in the EU, UK, and Australia, whose law requires it. Read-only: it follows the site's home country, set in the dashboard's Tax settings, and is added only for the US and Canada |
Reviews
Product reviews are on for a new site. With reviews_enabled set to
false, the storefront shows no reviews, ratings, or review structured
data, offers no review form, and hides customers' review pages. No review is
deleted: the dashboard and the Reviews API still list and
moderate them, and setting it back to true shows them again. A server run
with EASEL_REVIEWS=false has no reviews whatever this setting says.
Wishlist Sale Alerts
A site can email customers when items on their account wishlist go on sale.
wishlist_sale_alerts turns this on or off for the whole site. It starts on,
because only customers who opted in ever get an alert: a customer opts in
themselves, at registration or on their email preferences page, and neither the
store nor the API can opt anyone in. Turning it off stops every alert from the
site, including ones already waiting to be sent. Guests, whose wishlist lives
only in a browser cookie, never get alerts.
- What triggers one. Saving a variant so it is on sale for less than its
regular price, from the dashboard or with
Update Product Variant,
starts a sale. Each opted-in customer with that variant on their account
wishlist is queued an alert. Changing the price of a running sale, even
lowering it, is not a new sale and alerts no one again. Ending a sale and
starting another is a new sale. - One a day. Alerts go out hourly. Everything waiting for a customer is
grouped into one email, and a customer gets at most one alert email a day;
anything that goes on sale in between waits for the next one. - Checked at send time. If the customer withdrew consent, was banned, or was
erased, or the item left their wishlist, the product is no longer active, or
the sale ended, the alert is dropped instead of sent. - Postal address required. Marketing email must show the sender's physical
postal address (CAN-SPAM in the US, and similar rules elsewhere), so alerts
pause until the store has one. A merchant sets it under Postal Address in the
dashboard; it is shown, with the site's name, in the footer of every alert.
While it is missing, alerts stay queued rather than being dropped, and the
site edit page and the dashboard say so. Once it is added, sending resumes
on the next hourly run, after the checks above drop anything that went
stale. The API can't read or set the address. - Unsubscribe. Every alert has a one-click unsubscribe link that works
without logging in, andList-Unsubscribeheaders so mail clients can offer
their own unsubscribe button. Unsubscribing withdraws the customer's
marketing consent.
The email is in the site's language and shows each product's regular and sale
price in the store's currency. Merchants can't send alerts by hand; a
customer's page in the dashboard shows when they were last sent one.
Delivery Times Object
A physical product's page shows an estimated delivery date range, such as
"Thu, Oct 23 – Tue, Oct 28", and checkout shows one beside each shipping
rate. The shop ships handling_days business days after the order, or a
product's own handling_days when it sets one (see
Products), and the carrier delivers
within the shipping rate's transit range after
that. A product page estimates by the cheapest rate to the buyer's zone and
names a faster one when there is one, as in "or faster with 2-day air".
Business days skip weekends and the nationwide public holidays of the US,
Canada, the UK, Ireland, Australia, Germany, Austria, France, Belgium, the
Netherlands, Spain, Italy, Portugal, Poland, Denmark, Sweden, and Finland.
Handling counts on the calendar of the site's default country and transit on
the buyer's. Other countries close only on weekends.
Buyers see the estimate for the site's default country until they pick
another country the site ships to, which they do from the estimate itself.
Only countries whose zone has a rate are offered.
| Field | Type | Description |
|---|---|---|
handling_days |
integer | Business days the shop takes to ship an order, from 0 to 60. New sites start at 1 |
{
"handling_days": 1
}