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.

Webhook received──▶Delivery succeeds──▶Email sent

Trigger modes

Each email action has a triggerOn setting that controls when the email fires:

ModeWhen it fires
success (default)Only when the HTTP delivery to the webhook's target URL returns a 2xx status code.
alwaysOn 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.
Idempotency is enforced: even in 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.

htmlExample body template
<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.

PipeEffectExample
jsonPretty-printed JSON (2-space indent) — ideal for <pre> blocks{{response.body | json}}
upperConvert to UPPERCASE{{payload.status | upper}}
lowerConvert to lowercase{{payload.name | lower}}
trimRemove leading/trailing whitespace{{payload.description | trim}}
To render a JSON object nicely in the email, use | json inside a <pre> tag:
<pre>{{response.body | json}}</pre>

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.

ExpressionDescription
{{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.

ExpressionDescription
{{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
Combining {{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).

ExpressionDescription
{{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)
htmlChain event example — email on Webhook 2 (CRM lookup step)
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:

VariableDescription
{{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.

textExample filter
payload.type  ==  "payment.succeeded"
payload.amount  >  100
Filters on email actions use the same expression syntax as webhook payload filters. See the Webhooks docs for the full filter reference.