Docs

Message templates

Reusable, channel-specific message bodies with mustache-style variables.

Creating a template

Open Templates in the sidebar, then + New template. Each template binds to a single channel — EMAIL, SMS, WHATSAPP, or VOICE — because every channel has different length, formatting, and approval rules.

Variables

Variables in double braces resolve from the contact record at send time:

email body
Subject: Welcome to {{workspaceName}}, {{firstName}}

Hi {{firstName}},

Thanks for joining. Use code WELCOME15 at checkout for 15% off your first order.

— {{senderName}}
  • {{firstName}}, {{lastName}}, {{email}}, {{phone}} — contact fields
  • {{workspaceName}}, {{senderName}} — workspace metadata
  • {{metadata.<key>}} — anything you've stored on the contact's metadata blob

On the EMAIL channel, click ✦ Start from layout in the HTML editor toolbar to open a small gallery of pre-built modern templates. Five layouts ship today:

  • Transactional notice — clean card with logo, headline, body, CTA.
  • Receipt / order summary — itemised lines + total + CTA.
  • Marketing announcement — color header band + two-column body.
  • Payment reminder — invoice-style amount + due + payment-link CTA (Bahasa-friendly).
  • Welcome / onboarding — friendly greeting + 3-step checklist + CTA.

Each layout exposes copy fields (headline, intro, body, CTA, footer) and brand colors (primary, text, background, surface) plus an optional logo URL. The preview iframe re-renders on every keystroke. Variables like {{first_name}} still resolve at send time — the layout is just the chrome.

AI assist (Template Generator)

Click ✨ AI build in the template editor to draft a starting point from a plain-language prompt (e.g. "3-day overdue invoice nudge in Bahasa Indonesia for WhatsApp").

Connect a provider in Settings → AI connectorto get real LLM output. Supported providers: Anthropic Claude, OpenAI GPT, OpenRouter (any of 100+ models behind one key), and local Ollama. Your key stays in the browser; the backend never sees it. Without a connector, the generator returns a deterministic stub good enough for demos.

Formatting values with pipe filters

When a partner (or your CSV import) gives you raw values — an ISO date, an integer amount, a URL — apply a filter inline so the customer sees something readable. Filters chain with| exactly like Liquid or Jinja, but the engine is tiny on purpose.

raw → rendered
{{ amount | currency:'IDR':'id' }}      → "Rp 1.500.000"
{{ due_date | date:'long':'id' }}      → "2 Juni 2026"
{{ due_date | date:'short':'id' }}     → "2 Jun 2026"
{{ count | number:'id' }}              → "1.250"
{{ name | upper }}                     → "ANDINI"
{{ note | trim | default:'—' }}        → fallback when empty
  • date:'long' | 'short' | 'iso' | 'datetime' — second arg is locale (default 'id').
  • currency:'IDR' | 'USD' | 'EUR' | … — second arg locale.
  • number:'id' | 'en'[:decimals]
  • upper, lower, trim
  • default:'fallback' — used when the value is empty

Filters that don't understand their input (e.g., a non-date string given to date) pass the value through unchanged. So a malformed value never blanks an outgoing message.

Real example — payment reminder (Bahasa)

Contact metadata as it arrives from the system of record:

contact metadata (raw)
{
  "loan_id":      "LOAN-2026-0042",
  "amount":       1500000,
  "due_date":     "2026-06-02",
  "payment_link": "https://demo.bank.example/pay/abc"
}
template body
Hi {{first_name}} 👋

Ini adalah reminder bahwa pembayaran kamu sebesar
{{ amount | currency:'IDR':'id' }} akan jatuh tempo pada
{{ due_date | date:'long':'id' }}.

Silakan lakukan pembayaran disini:
{{ payment_link }}

Terima kasih.
rendered output
Hi Andini 👋

Ini adalah reminder bahwa pembayaran kamu sebesar
Rp 1.500.000 akan jatuh tempo pada
2 Juni 2026.

Silakan lakukan pembayaran disini:
https://demo.bank.example/pay/abc

Terima kasih.

Channel-specific rules

  • WhatsApp: marketing templates must be pre-approved by Meta. Transactional ("session") messages within 24h of customer reply have no template restriction.
  • SMS: 160 chars per segment in GSM-7 encoding. Longer messages bill multiple segments — preview shows the count before save.
  • Email: HTML and plain-text variants both supported. Subject required.
  • Voice: body becomes TTS script. Business plan only.