Skip to main content
Email templates are what a journey’s SEND_EMAIL node sends. You can author them in the app’s builder, or from an agent or script with five tools (each is also a REST endpoint): A template is written one of two ways, and you send exactly one:
  • document — the builder’s blocks: heading, text, button, image, divider, spacer, html, social, footer, plus container (a framed card) and columns (side by side). Styling is optional; what you leave out takes the builder’s defaults.
  • html — your own markup. It is sanitized on save: scripts, event handlers and external stylesheets are removed, and the response lists what was removed in removed.
Boom renders the deliverable HTML and plain text itself. Variables use the {{path}} grammar in the subject and the body — {{customer.name}}, {{person.<attribute>}}, {{engagement.chatLink}} — and resolve at send; see Template variables for what a path can be. A template’s variables lists each path once, even when it is written both {{x}} and {{ x }}; both spellings render.
The same template as HTML is { "name": …, "subject": …, "html": "<table>…</table>" }.

Sending one

A template sends through a journey. Build it on an email initiative with a SEND_EMAIL step that points at the PUBLISHED template (journeys_email_templates lists those, along with whether your domain and sender are ready), then launch the initiative, which publishes the journey. Then enroll people:
  • Directly: initiatives_participants_add with an email for each person.
  • On behavior: give the journey a cdp_event trigger, and every time that event is recorded for a person with an email (cdp_events_record), they are enrolled.
People on your Do Not Contact list are skipped either way.

Rules worth knowing

  • New templates are drafts. A journey can only send a PUBLISHED template; publish with email_templates_update and "status": "PUBLISHED".
  • Changing a published template needs "confirm": true. Journeys reference the template itself, so an edit changes what they send from their next send, and setting it back to DRAFT makes those sends fail. Call without confirm first to see the refusal.
  • Unknown fields are rejected, not ignored, so a typo such as background for a button’s bg fails with a validation error instead of quietly taking the default.
  • Blocks → HTML is one way. Sending html to a block template converts it; an HTML template does not accept a document again.
  • A footer block goes at the top level of the email, not inside a container or a column. Omit unsubscribeLabel for the document language’s default link text, or send "" for no unsubscribe link (transactional email).
  • Not available here yet: test sends, image upload (use an image URL you host, or one from the builder’s library), and deleting a template.

Preview with a real event

email_templates_preview renders a template the way a journey triggered by an event would send it, without sending anything. Name the event one way:
  • latestEventName — the most recent event with that name, e.g. "payment_due"; add personExternalId for that person’s most recent one.
  • eventExternalId — the id your backend sent the event with.
  • eventId — Boom’s id, from cdp_events_list.
The event’s properties fill event.* (and engagement.workflowState.*), including inside Liquid tags, so loops and conditions render as they will in the real email. When the event names a person, customer.* and person.* come from that person, as in the email the journey would send; fields your organization marked sensitive stay hidden from an assistant. The response has the subject, html and text, plus:
  • unresolved — the paths of variables that came out blank. A blank event.* variable usually means the event doesn’t carry that property.
  • liquidError — set when the Liquid failed to render.
  • redactedKeys — event properties your organization marked sensitive. An assistant (MCP) always sees them masked; an API key sees real values.
  • event — which event was used (null without one, when sample values are used instead).
values overrides any path with fixed text ({ "customer.name": "Ana" }), and bindings previews the email as a journey Send email step that remaps its variables.