Passa al contenuto principale

Email-templates API

Auto-generated from the OpenAPI spec. Run node docs-site/scripts/fetch-openapi.js to regenerate.

About the blocks field (Visual Email Builder)

POST/PUT bodies on /api/v1/email/templates accept an optional blocks field, and GET/POST/PUT responses echo it back:

  • null or omitted — the template is in raw HTML mode. html_body is the template as written; there is no canvas structure behind it.
  • A JSON array of block objects — the template is in canvas mode. Each element is { id: string, type: "text" | "image" | "button" | "divider" | "spacer" | "html", props: {...} }, where props is a block-type-specific object (for example, a text block's props has content, align, fontSize, color, bold, italic). The server does not validate props's shape — that's the frontend's responsibility (frontend/src/renderer/src/lib/emailBlocks.ts) — it only requires that blocks be a JSON-serializable list of objects.

html_body is always required and is always the fully-rendered HTML, regardless of mode — when saving a canvas-mode template, the frontend computes html_body from blocks client-side before sending both together, so a client integrating directly with this API in canvas mode must do the same (render blocks to HTML itself) rather than relying on the server to derive one from the other.

GET /api/v1/email/templates

List Templates

Responses

  • 200 — Successful Response

POST /api/v1/email/templates

Create Template

Request body

FieldRequiredTypeDescription
nameYesstring
subjectYesstring
html_bodyYesstring
blocksNoarray

Responses

  • 201 — Successful Response
  • 422 — Validation Error

GET /api/v1/email/templates/{template_id}

Get Template

Parameters

NameInRequiredTypeDescription
template_idpathYesinteger

Responses

  • 200 — Successful Response
  • 422 — Validation Error

PUT /api/v1/email/templates/{template_id}

Update Template

Parameters

NameInRequiredTypeDescription
template_idpathYesinteger

Request body

FieldRequiredTypeDescription
nameNostring
subjectNostring
html_bodyNostring
blocksNoarray

Responses

  • 200 — Successful Response
  • 422 — Validation Error

DELETE /api/v1/email/templates/{template_id}

Delete Template

Parameters

NameInRequiredTypeDescription
template_idpathYesinteger

Responses

  • 200 — Successful Response
  • 422 — Validation Error

POST /api/v1/email-templates/images

Upload Email Template Image

Upload one image for a Visual Email Builder Image block. Manager-only.

Returns an absolute URL (baked in at upload time, not left relative, since the URL must resolve correctly inside an email opened outside the app) built from StudioSettings.tunnel_url — same pattern as app/routers/clients.py's invite_url construction. Falls back to a relative path when tunnel_url isn't set yet (e.g. local dev before named-tunnel provisioning), consistent with clients.py's own fallback behavior of still returning a usable (if not yet externally-resolvable) URL rather than blocking the upload.

Response body (201)

FieldTypeDescription
urlstringAbsolute URL for the uploaded image ({tunnel_url}/api/v1/email-templates/images/{filename}), ready to use as an Image block's source. Relative (no scheme/host) if the studio has not yet set up a tunnel URL.

Responses

  • 201 — Successful Response
  • 422 — Validation Error

GET /api/v1/email-templates/images/{filename}

Get Email Template Image

Serve a previously-uploaded email image. Public — intentionally no auth dependency (see module docstring / §6.20b).

The filename path param is never trusted directly: it is sanitized (basename + allow-list + commonpath containment check, same technique as resolve_safe_photo_path) AND must start with the "email_" prefix this upload endpoint always gives its files (defense in depth, same technique as app/routers/widget.py::get_widget_product_photo) — any mismatch or missing file is a generic 404, never a 500.

Response body (200): the raw image file (binary), not JSON — served with the content type of the uploaded file. No Authorization header required or checked; this is the one deliberately public, no-auth endpoint on this page (see the module docstring above) so the image loads inside an email opened in an external mail client. A filename that doesn't start with the email_ prefix, or that doesn't resolve to an existing file, returns a generic 404 — never a 500.

Parameters

NameInRequiredTypeDescription
filenamepathYesstring

Responses

  • 200 — Successful Response
  • 404 — Image not found (bad prefix, path traversal attempt, or file missing)
  • 422 — Validation Error