AI Edit Email Template (stream)
POST/api/store-email-templates/ai-edit/stream
Server-Sent Events: one AI assistant turn on an email template's subject, preheader and body (or a first draft when template_id is null — an empty current_html then starts from SKU's built-in default for the context + event).
settings:writeGrant this scope to your token under Settings → Developer → Personal Access Tokens.
Authentication: Requires Bearer token and the email_templates.update permission.
Body: template_id (int|type string|null), context + event (required when template_id is null), store_id (int|null — whose brand layout and sample data), instruction (required, max 5000), current_subject (max 255), current_preheader (max 255), current_html (max 200000), history (max 10 × {instruction, summary}; the last 6 are replayed), target ({label ≤120, html ≤2000} — the preview element the user pointed at; changes are confined to it), reference_images, provider (anthropic|openai|google|deepseek|null), model.
Events: status {message} — Reading template → Writing changes → Checking variables → (Fixing problems the checks found) → Rendering preview; complete {success, proposal {subject|null, preheader|null, html, summary, unresolved[]}, validation {ok, errors[], warnings[], error_details[], warning_details[]}, usage {input_tokens, output_tokens}, rendered_preview_html, provider, model, error}; error {message, status?}. subject / preheader are null when the model kept the current value.
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
- 200
- 401
- 403
- 422
- 429
OK
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden
Response Headers
Validation failed — the body is a field → messages map (Laravel shape) or the platform envelope with a stable machine-readable code. Fix the payload and resubmit.
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.