Email Actions
Send a transactional email every time a webhook event is delivered to a webhook — no extra infrastructure required. Templates support dynamic variables drawn from the event payload and delivery response.
How it works
An email action is attached to one or more webhooks. When a delivery to that webhook succeeds (or always, depending on the trigger mode), HostWebhook renders the email template and sends it via your configured email provider.
Trigger modes
Each email action has a triggerOn setting that controls when the email fires:
| Mode | When it fires |
|---|---|
success (default) | Only when the HTTP delivery to the webhook's target URL returns a 2xx status code. |
always | On the first delivery attempt, regardless of success or failure. Useful for user-facing emails (e.g. "you've been registered") that should not wait for delivery retries. |
always mode, the email is sent at most once per event — retries will not re-send it.Template syntax
All text fields (To, Subject, Body, From name) support {{variable}} interpolation. Paths use dot-notation to access nested fields.
<p>Hi {{payload.customer.name}},</p>
<p>Your order <strong>#{{payload.order.id}}</strong> has been confirmed.</p>
<p>Total: {{payload.order.total}} USD</p>Pipe transforms
Append | pipeName after any expression to transform the resolved value before inserting it.
| Pipe | Effect | Example |
|---|---|---|
| json | Pretty-printed JSON (2-space indent) — ideal for <pre> blocks | {{response.body | json}} |
| upper | Convert to UPPERCASE | {{payload.status | upper}} |
| lower | Convert to lowercase | {{payload.name | lower}} |
| trim | Remove leading/trailing whitespace | {{payload.description | trim}} |
| json inside a <pre> tag:Available context variables
The following top-level objects are available in every email template.
payload
The original incoming webhook payload — always the root event data, regardless of whether the endpoint is in a webhook chain or not.
| Expression | Description |
|---|---|
| {{payload.type}} | Top-level event type field (e.g. payment.succeeded) |
| {{payload.customer.email}} | Any nested field using dot-notation |
| {{payload.amount ?? 0}} | Null-coalescing fallback when field may be missing |
response
The HTTP response returned by the webhook's target URL for this delivery. Only available when the target responded with a body.
| Expression | Description |
|---|---|
| {{response.status}} | HTTP status code returned by the target URL (e.g. 200) |
| {{response.body.id}} | Parsed JSON response body from the target URL |
| {{response.raw}} | Raw response body as a string |
{{payload.*}} and {{response.body.*}} lets you enrich emails with data returned by your own API. For example: receive a Stripe event, deliver to your CRM to look up the customer, then email the resolved customer name.chain (chain events only)
When a webhook is part of a webhook chain, extra context about the chain execution is available under chain. This is only present when the endpoint is a chain step (step ≥ 1).
| Expression | Description |
|---|---|
| {{chain.step}} | Chain step index (1 = first chain hop, 2 = second, etc.) |
| {{chain.previous}} | Parsed response from the previous step's target URL (if any) |
| {{chain.priorResponse.status}} | HTTP status code from the previous step's delivery |
| {{chain.original}} | The root event payload (same as payload — exposed for explicit access) |
Subject: New user {{payload.details.commitAuthor}} deployed to {{payload.resource.environment.name}}
<!-- payload = original Railway webhook (always unwrapped) -->
<p>Branch: {{payload.details.branch}}</p>
<p>Commit: {{payload.details.commitMessage}}</p>
<!-- response = what the CRM returned when Webhook 2 delivered -->
<p>Customer: {{response.body.customer.name}} ({{response.body.customer.plan}})</p>
<p>Email: {{response.body.customer.email}}</p>
<!-- chain context (only available on chain steps) -->
<p>Chain step: {{chain.step}}</p>Scheduled Workflows
Email actions can also be attached to Scheduled Workflows. When a scheduled run completes, the following additional variables are available alongside payload:
| Variable | Description |
|---|---|
| {{name}} | Name of the Scheduled Workflow |
| {{runAt}} | ISO 8601 timestamp of the scheduled run |
| {{status}} | success or partial_failure depending on whether all deliveries succeeded |
Payload filters
You can attach filter rules to an email action so it only fires for specific event types or payload values. Filters are evaluated against the original (unwrapped) payload — the same rules work whether the webhook is direct or part of a chain.
payload.type == "payment.succeeded"
payload.amount > 100