Create Storefront
Create a new storefront (Creator page) as a draft.
The path is collection-level — not nested under a storefront UUID. There are
no path or query parameters (include, currency, and status are not
accepted). The body is { "name" } only. Extra keys, including slug,
status, and section JSON, return 422.
The slug is generated from name, and duplicate names are allowed. This call
does not require an active Easytools plan. See
Active plan required.
The new page copies this store's profile (name, description, website) and
default branding onto header and styles at create time. Later branding
edits in the dashboard do not rewrite this draft. Widgets start empty — no
products or newsletter are added. Inspect with
Get Storefront
?include=styles,header,settings,blocks (blocks is []).
Open preview_url to see the page. It stays a draft until
Publish Storefront.
Request
POST /storefronts
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name (the Creator page name in the dashboard; max 255 characters). |
name is the only accepted key. slug is not accepted — it is generated
from name. If that slug would be empty, it is storefront. A collision
on this store becomes {slug}-{6-char} and is still 201.
Example Request
curl -X POST "https://cart.easy.tools/api/v1/storefronts" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Print Shop"
}'
Response
Success Response (201)
Returns the same lean identity as a Get Storefronts
list item, plus a required preview_url — the same keys as
Publish Storefront and
Unpublish Storefront. status is always draft,
public_url is null, published_at is null, and domains is [].
There are no styles, header, settings, or blocks keys on this
response.
{
"id": "ec28afe5-0008-4048-840b-68dac0c66817",
"slug": "print-shop",
"name": "Print Shop",
"status": "draft",
"public_url": null,
"preview_url": "https://cart.easy.tools/storefront-preview/ec28afe5-0008-4048-840b-68dac0c66817?expires=1788359609&signature=5325650496f9d1d3582bea5e4b2714673c6bca35be9374458d63554e3ac58373",
"domains": [],
"created_at": "2026-09-02T13:33:29+00:00",
"updated_at": "2026-09-02T13:33:29+00:00",
"published_at": null
}
preview_url is a fresh signature. The expires / signature query in
this example will already be stale; the shape is what matters. See
Draft preview.
Creating a second storefront named Print Shop also returns 201, with a
new id (39cf79d7-7bf4-4f93-941d-9747eb96306c) and a suffixed slug
(print-shop-jklogl).
Response Fields
Same lean projection as a Get Storefronts list item, plus:
| Field | Type | Nullable | Description |
|---|---|---|---|
preview_url | string | No | Temporary signed URL of the saved draft. Expires after about one hour. See Draft preview. |
Error Responses
Validation Error (422 Unprocessable Entity)
Returned when name is missing or empty ({}), longer than 255 characters,
or when extra keys are sent (slug, status, and section JSON among them).
Extra keys return The {key} field is not allowed.
{
"message": "The slug field is not allowed.",
"errors": {
"slug": [
"The slug field is not allowed."
]
}
}
Unauthorized (401)
{
"message": "Unauthenticated."
}
Forbidden (403)
Returned when your API key has not been granted access to the requested store.
{
"message": "You do not have API access to the requested store."
}
Too Many Requests (429)
Returned when you exceed the rate limit. The Retry-After response header gives
the number of seconds to wait.
{
"message": "Too many requests. Please retry after 60 seconds."
}