Skip to content

Templates

Templates define the message content for each event and channel. Use Handlebars-style syntax (with a few Sendivent helpers) for dynamic content.

Variables

Use {{...}} to insert values.

You writeGets sent
Hi {{contact.name}}Hi Alice
Order #{{order_id}}Order #12345

Data sources

Contact data — from the to field (recipient info):

  • {{contact.name}}, {{contact.email}}
  • {{contact.firstName}}, {{contact.lastName}} (auto-extracted from name)
  • {{contact.meta.plan}} (custom fields)

Payload data — from the payload field (notification-specific):

  • {{order_id}}, {{reset_link}}, {{amount}}

Example request:

bash
curl -X POST https://api.sendivent.com/v1/send/order-shipped \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": {
      "email": "alice@example.com",
      "name": "Alice Johnson"
    },
    "payload": {
      "order_id": "12345",
      "tracking_url": "https://track.example.com/12345"
    }
  }'

Fallback values

Use the pipe | to provide a fallback when a value is missing:

TemplateHas nameNo name
Hi {{contact.name}}Hi AliceHi
Hi {{contact.name | "Guest"}}Hi AliceHi Guest
Hi {{contact.name | app.domain}}Hi AliceHi example.com

Quoted literals: Use quotes to force a literal fallback value ("Guest").

Variable fallbacks: Unquoted fallbacks try variable resolution first, then use as literal if not found.

Always add fallbacks for optional fields to avoid awkward blank spaces.

Conditionals

Show content only when a value exists:

handlebars
{{#if contact.meta.isPremium}}
  Thanks for being a premium member!
{{else}}
  Upgrade to unlock premium features.
{{/if}}

Loops

Render lists from payload arrays:

handlebars
Your order contains:
{{#each items}}
  - {{this.name}}: {{this.price}}
{{/each}}

Accessing variables inside loops

Inside {{#each}} blocks, the context changes to the current item. System variables like contact, app, cdn, sender, and platform work automatically:

handlebars
{{#each items}}
  {{contact.name}} ordered {{this.name}}
  <img src="{{cdn.images}}icons/check.png">
{{/each}}

For custom payload variables, use @root to access the root context:

handlebars
{{#each items}}
  Order #{{@root.order_id}}: {{this.name}}
{{/each}}

Helpers

Sendivent provides helpers via handlebars-helpers:

Comparison

HelperExampleResult
Compare{{#compare credits ">" 100}}...{{/compare}}Content if true
Greater than{{#if (gt credits 100)}}...{{/if}}Content if true
Less than{{#if (lt age 21)}}...{{/if}}Content if true
Equal{{#if (eq status "active")}}...{{/if}}Content if true

Compare operators: ==, ===, !=, !==, <, <=, >, >=, typeof

String

HelperExampleResult
Uppercase{{uppercase name}}ALICE
Lowercase{{lowercase name}}john doe
Capitalize{{capitalize status}}Active

Date

HelperExampleResult
ISO format{{date created_at "YYYY-MM-DD"}}2024-12-17
Friendly{{date created_at "MMM D, YYYY"}}Dec 17, 2024
With time{{date created_at "YYYY-MM-DD HH:mm"}}2024-12-17 14:30

Fallback

HelperExampleResult
Quoted literal{{contact.name | "Guest"}}Alice or "Guest"
Variable fallback{{contact.name | app.domain}}Alice or app.domain value
Default helper{{default contact.name "User"}}Alice or "User"

Multi-language templates

Create language variants in the dashboard. Request a specific language:

bash
curl -X POST https://api.sendivent.com/v1/send/welcome \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "to": "anders@example.com", "language": "sv" }'

Fallback: If the requested language doesn't exist, Sendivent uses the application's default language.

Common pitfalls

  • Blank variables — your template references fields not sent in to or payload
  • Wrong nesting — custom contact fields go under contact.meta.*
  • Missing fallback — add a fallback for optional fields (see Fallback values above)

See also

  • Contacts — recipient fields and meta
  • Events — how templates attach to events
  • Routing — channel selection

Released under the MIT License.