Templates

Customize storefront templates and preview changes

GET /admin/api/templates

List all storefront template names with their override status for the active theme.

GET /admin/api/templates/{name}

Get the content of a template. Returns the custom override if one exists, otherwise the built-in default.

GET /admin/api/templates/{name}/default

Get the built-in default content for a template, ignoring any custom override.

PUT /admin/api/templates/{name}

Create or update a custom template override. Validates Tera syntax before saving. Invalidates the template cache for the active theme.

DELETE /admin/api/templates/{name}

Delete a custom template override, reverting to the built-in default. Returns 404 if no custom override exists.

POST /admin/api/templates/{name}/preview

Render a template with sample data and return the HTML preview. Validates Tera syntax and reports render errors.

GET /admin/api/email-templates

List all email template names with their override status for the active theme.

GET /admin/api/email-templates/{name}

Get the content of an email template. Returns the custom override if one exists, otherwise the built-in default.

GET /admin/api/email-templates/{name}/default

Get the built-in default content for an email template, ignoring any custom override.

PUT /admin/api/email-templates/{name}

Create or update a custom email template override. Validates Tera syntax before saving. Email templates are standalone HTML and do not extend the storefront base layout.

DELETE /admin/api/email-templates/{name}

Delete a custom email template override, reverting to the built-in default. Returns 404 if no custom override exists.

POST /admin/api/email-templates/{name}/preview

Render an email template with sample order data and return the HTML preview. Sample context includes shop_name, order_id, customer_name, customer_email, items, subtotal, tax_total, total, and shipping address fields.

POST /admin/api/email-templates/{name}/send-preview

Send a real preview email rendered from the supplied draft (or, when `content` is omitted, the active theme's saved override / built-in default). The body uses the same per-template sample context as the in-browser preview, so what the admin sees on screen matches what lands in the inbox. The subject is the production subject prefixed with `[TEST]`.

GET /admin/api/template-variants

List every distinct template-variant slug of the requested kind across all themes, annotated with which themes define each slug and whether the currently active theme is one of them. Used to populate the Template dropdown on product and category edit forms. Results are sorted by slug ascending; the themes array within each entry is sorted by name ascending.

GET /admin/api/templates

List all storefront template names with their override status for the active theme.

Response 200

[
  {
    "name": "base",
    "has_custom": false,
    "updated_at": null
  },
  {
    "name": "home",
    "has_custom": true,
    "updated_at": "2025-12-01T10:00:00Z"
  },
  {
    "name": "product",
    "has_custom": false,
    "updated_at": null
  },
  {
    "name": "browse",
    "has_custom": false,
    "updated_at": null
  },
  {
    "name": "cart",
    "has_custom": false,
    "updated_at": null
  },
  {
    "name": "checkout",
    "has_custom": false,
    "updated_at": null
  }
]

Example

curl "https://yourshop.zeroshop.io/admin/api/templates" \
  -H "Authorization: Bearer zspat_..."
GET /admin/api/templates/{name}

Get the content of a template. Returns the custom override if one exists, otherwise the built-in default.

Response 200

{
  "name": "home",
  "content": "<h1>{{ t.home_hero_title | default(value='Welcome') }}</h1>\n<p>{{ t.home_hero_subtitle | default(value='Browse our products') }}</p>",
  "is_custom": true
}

Example

curl "https://yourshop.zeroshop.io/admin/api/templates/home" \
  -H "Authorization: Bearer zspat_..."
GET /admin/api/templates/{name}/default

Get the built-in default content for a template, ignoring any custom override.

Response 200

{
  "name": "home",
  "content": "{% extends \"base\" %}...",
  "is_custom": false
}

Example

curl "https://yourshop.zeroshop.io/admin/api/templates/home/default" \
  -H "Authorization: Bearer zspat_..."
PUT /admin/api/templates/{name}

Create or update a custom template override. Validates Tera syntax before saving. Invalidates the template cache for the active theme.

Request Body

{
  "content": "<h1>{{ t.home_hero_title | default(value='Welcome to our shop') }}</h1>"
}

Response 204

Example

curl -X PUT "https://yourshop.zeroshop.io/admin/api/templates/home" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"content": "<h1>{{ t.home_hero_title | default(value='"'"'Welcome'"'"') }}</h1>"}'
DELETE /admin/api/templates/{name}

Delete a custom template override, reverting to the built-in default. Returns 404 if no custom override exists.

Response 204

Example

curl -X DELETE "https://yourshop.zeroshop.io/admin/api/templates/home" \
  -H "Authorization: Bearer zspat_..."
POST /admin/api/templates/{name}/preview

Render a template with sample data and return the HTML preview. Validates Tera syntax and reports render errors.

Request Body

{
  "content": "<h1>Welcome to {{ shop_name }}</h1>"
}

Response 200

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/templates/home/preview" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"content": "<h1>Welcome to {{ shop_name }}</h1>"}'
GET /admin/api/email-templates

List all email template names with their override status for the active theme.

Response 200

[
  {
    "name": "order_confirmation",
    "description": "Order Confirmation",
    "has_custom": false,
    "updated_at": null
  },
  {
    "name": "shipping_notification",
    "description": "Shipping Notification",
    "has_custom": true,
    "updated_at": "2025-12-05T09:30:00Z"
  }
]

Example

curl "https://yourshop.zeroshop.io/admin/api/email-templates" \
  -H "Authorization: Bearer zspat_..."
GET /admin/api/email-templates/{name}

Get the content of an email template. Returns the custom override if one exists, otherwise the built-in default.

Response 200

{
  "name": "order_confirmation",
  "description": "Order Confirmation",
  "content": "<html><body><h1>Thank you for your order, {{ customer_name }}!</h1></body></html>",
  "is_custom": false
}

Example

curl "https://yourshop.zeroshop.io/admin/api/email-templates/order_confirmation" \
  -H "Authorization: Bearer zspat_..."
GET /admin/api/email-templates/{name}/default

Get the built-in default content for an email template, ignoring any custom override.

Response 200

{
  "name": "order_confirmation",
  "description": "Order Confirmation",
  "content": "<html><body>...</body></html>",
  "is_custom": false
}

Example

curl "https://yourshop.zeroshop.io/admin/api/email-templates/order_confirmation/default" \
  -H "Authorization: Bearer zspat_..."
PUT /admin/api/email-templates/{name}

Create or update a custom email template override. Validates Tera syntax before saving. Email templates are standalone HTML and do not extend the storefront base layout.

Request Body

{
  "content": "<html><body><h1>Order #{{ order_id }} confirmed</h1><p>Thank you, {{ customer_name }}!</p></body></html>"
}

Response 204

Example

curl -X PUT "https://yourshop.zeroshop.io/admin/api/email-templates/order_confirmation" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"content": "<html><body><h1>Order confirmed</h1></body></html>"}'
DELETE /admin/api/email-templates/{name}

Delete a custom email template override, reverting to the built-in default. Returns 404 if no custom override exists.

Response 204

Example

curl -X DELETE "https://yourshop.zeroshop.io/admin/api/email-templates/order_confirmation" \
  -H "Authorization: Bearer zspat_..."
POST /admin/api/email-templates/{name}/preview

Render an email template with sample order data and return the HTML preview. Sample context includes shop_name, order_id, customer_name, customer_email, items, subtotal, tax_total, total, and shipping address fields.

Request Body

{
  "content": "<html><body><h1>Order #{{ order_id }}</h1><p>Dear {{ customer_name }},</p></body></html>"
}

Response 200

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/email-templates/order_confirmation/preview" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"content": "<html><body><h1>Order #{{ order_id }}</h1></body></html>"}'
POST /admin/api/email-templates/{name}/send-preview

Send a real preview email rendered from the supplied draft (or, when `content` is omitted, the active theme's saved override / built-in default). The body uses the same per-template sample context as the in-browser preview, so what the admin sees on screen matches what lands in the inbox. The subject is the production subject prefixed with `[TEST]`.

Request Body

{
  "recipient_email": "owner@example.com",
  "content": "<html><body><h1>Order #{{ order_id }}</h1></body></html>"
}

Response 200

{
  "ok": true
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/email-templates/order_confirmation/send-preview" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"recipient_email": "owner@example.com"}'
GET /admin/api/template-variants

List every distinct template-variant slug of the requested kind across all themes, annotated with which themes define each slug and whether the currently active theme is one of them. Used to populate the Template dropdown on product and category edit forms. Results are sorted by slug ascending; the themes array within each entry is sorted by name ascending.

Parameters

Name Type Required Description
kind string required Which variant kind to list. `product` lists product/<slug> templates; `category` lists browse/<slug> templates. Any other value is rejected with 400.

Response 200

[
  {
    "slug": "bundle",
    "themes": [
      "Default",
      "Holiday"
    ],
    "in_active_theme": true
  },
  {
    "slug": "limited-edition",
    "themes": [
      "Holiday"
    ],
    "in_active_theme": false
  }
]

Example

curl "https://yourshop.zeroshop.io/admin/api/template-variants?kind=product" \
  -H "Authorization: Bearer zspat_..."

We value your privacy

We use cookies for essential site functionality and, with your consent, analytics to understand how our platform is used. No personal data is shared with third parties. See our Privacy Policy for details.