Skip to main content

AI Edit Brand Layout (stream)

POST 

/api/store-email-layouts/:storeId/ai-edit/stream

Server-Sent Events: one AI assistant turn on a brand layout document. :storeId is a store id, or default for the tenant default layout; layout_id in the body names the layout explicitly. An empty current_html uses the saved layout HTML.

Required scope: settings:write

Grant this scope to your token under Settings → Developer → Personal Access Tokens.

Authentication: Requires Bearer token and the email_templates.update permission.

Body: layout_id (int|null), store_id (int|null), instruction (required, max 5000), current_html (max 200000), history, target, reference_images, provider, model (as for AI Edit Email Template).

The proposal is checked in layout mode ({{content}} exactly once, only layout tokens, no unsafe content) and trial-rendered around the order confirmation with sample data. complete has the same shape as the template stream with proposal.subject / proposal.preheader always null; status steps start with "Reading layout".

Errors arrive as an error event {type: "error", message, status?} on a 200 stream: the template editor switched off in AI settings (503), no API key for the provider (503), the hourly limit (AiSettings::max_requests_per_user_per_hour, default 60, per user per tenant; 429 — "You've hit the hourly AI limit; try again at 15:40."), provider failures mapped to friendly copy (quota, rate limit, bad key, timeout). Request validation failures are a normal 422 JSON response.

Nothing is saved: the editor applies the proposal to its buffer and the user saves (with version_source: ai). A proposal that fails the content checks is retried once with the errors fed back; still invalid → success: false, validation.ok: false, no rendered_preview_html.

reference_images (max 3; {mime_type, data (base64, no prefix), name} objects or data:image/...;base64, URIs; png/jpeg/webp/gif) are sent as vision input and stored as email assets so the proposal can embed them by URL; images the proposal does not embed are deleted again.

Request​

Responses​

OK

Response Headers
    Content-Type