# Templates

moinAI Hub supports templating throughout the platform—static answers, form labels, follow-up messages, webhook payloads, and more. The syntax is a lightweight variant of Handlebars (opens new window); any variable present in the conversation context is available for interpolation.

  • Data from addContext
  • User input captured in forms
  • Response bodies from successful webhooks

Usage:

With the variable added in the Conversation Context.

Hello {{user_name}}, welcome to the moinAI experience!

Output:

Hello Florian, welcome to the moinAI experience!

The examples below all assume a webhook that was configured with the Context Name webhook_response and returned this body:

{
  "customer": {
    "name": "Florian",
    "address": { "city": "Hamburg", "zip": "20095" }
  },
  "orders": [
    {
      "id": "A-1001",
      "status": "shipped",
      "link": "https://shop.example.com/orders/A-1001"
    },
    {
      "id": "A-1002",
      "status": "processing",
      "link": "https://shop.example.com/orders/A-1002"
    }
  ]
}

The whole body is stored under that name, so every path starts with webhook_response.

# Nested values

Use dot notation to walk into an object. There is no limit to the depth—each level is separated by a dot.

Wir liefern nach {{webhook_response.customer.address.city}} ({{webhook_response.customer.address.zip}}).

Output:

Wir liefern nach Hamburg (20095).

A path that does not exist resolves to an empty string rather than raising an error, so {{webhook_response.customer.address.country}} simply renders nothing. The same is true while the webhook is still pending or has failed—nothing is stored under webhook_response in that case, and the template renders empty.

# Values inside arrays

Array entries are addressed by their index, written in square brackets as its own path segment. Counting starts at 0.

Deine letzte Bestellung {{webhook_response.orders.[0].id}} ist {{webhook_response.orders.[0].status}}.

Output:

Deine letzte Bestellung A-1001 ist shipped.

WARNING

The brackets are required. {{webhook_response.orders.0.id}} is not valid—Handlebars only accepts a numeric segment when it is written as .[0].

# Markdown in bot messages

Bot messages support Markdown, and it can be mixed freely with templates. The template is resolved first, the result is then rendered as Markdown—so lists, bold text and links can all be built from context data.

WARNING

Markdown formatting has to be enabled for the message, otherwise the raw characters (*, [label](url)) are shown to the user as-is. See Formatting text messages (opens new window) in the Help Center.

# A list of all orders

{{#each}} repeats its content once per array entry, which pairs well with a Markdown bullet list. Inside the loop, this refers to the current entry:

Das sind deine aktuellen Bestellungen:

{{#each webhook_response.orders}}
* {{this.id}}{{this.status}}
{{/each}}

Output:

Das sind deine aktuellen Bestellungen:

* A-1001 — shipped
* A-1002 — processing

This way the message adapts to however many orders the webhook returns, instead of addressing a fixed index.

A URL from the context becomes a clickable link by placing the template inside the Markdown link syntax [label](url):

Deine Bestellung {{webhook_response.orders.[0].id}} ist unterwegs. [Sendung verfolgen]({{webhook_response.orders.[0].link}})

Output:

Deine Bestellung A-1001 ist unterwegs. [Sendung verfolgen](https://shop.example.com/orders/A-1001)

…which the widget renders as Sendung verfolgen pointing at https://shop.example.com/orders/A-1001.

The label can be templated as well, for example Bestellung {{webhook_response.orders.[0].id}}. Combined with {{#each}}, this turns the list above into one link per order:

{{#each webhook_response.orders}}
* [Bestellung {{this.id}}]({{this.link}}) — {{this.status}}
{{/each}}