Skip to main content
You compose a notification from a list of elements. Courier renders each one for email, push, SMS, inbox, and direct message. A document has two top-level fields, and a send passes it as message.content:
string
required
The Elemental format version. The only supported value is "2022-01-01".
CourierElement[]
required
The elements that make up the notification. Every type is documented below.
Two ways to write content ElementalContentSugar is a shorthand for simple notifications. Pass title and body instead of a full element tree, and omit version and elements. Courier converts it to full Elemental internally: title becomes a meta element, body becomes a text element.
Use the sugar format for a title and body with no conditionals, loops, or layout. Use full Elemental for everything else: multi-channel customization, columns and groups, if/loop/ref, locales, and styling. Element nesting Elemental is a tree. The root elements array holds elements, and the container types hold their own elements arrays:
  • group: conditions and loops
  • channel: channel-specific content
  • columns: holds column elements
  • list: holds list-item elements
Nesting makes conditional groups, per-channel branches, and multi-column layouts possible.
Common properties Every element has a required type string. Each section below gives its value, for example "text" for the text element. Most elements also accept these shared properties:
  • channels: an array of channel names. The element renders only for the listed channels.
  • if: a condition that controls whether the element renders. Accepts a string expression or a .
  • loop: an expression that repeats the element for each item in an array.
  • ref: a reference identifier for the element.
below covers all four. Many elements also accept a locales object for multi-language content, covered in . Where a property is central to an element, such as if and loop on group and list, it is listed in that element’s fields below. Text fields support variables. They resolve against message.data, for example data.first_name.

The elements

Every element also takes if, loop, ref, and channels. Those four are documented once, in .

Sending a document and storing one differ

A send takes the document above as message.content and renders it for every channel it routes to. Storing the same document on a Template needs its top-level elements wrapped in a channel element. A send accepts a bare element list. The write API does not, and its rejection names a schema path rather than the rule you broke. covers the round trip.