Template syntax
Templates turn raw webhook JSON into human-readable messages. Use $${field.path} placeholders and optional pipes to format values.
Variable substitution
Wrap a dot-notation path in $${…}. Hooks reads the value from the parsed payload and inserts it as text.
:tada: *New payment*
Customer: ${data.object.customer_email|default:unknown}
Amount: *${data.object.amount_total|div:100} ${data.object.currency|default:USD}*Not supported: conditionals, loops, or custom functions. For complex branching, use multiple routes with different filters.
Pipes
Chain pipes after the field path, separated by |. Applied left to right.
|default:UnknownUse a fallback when the field is missing or null.|date:relativeFormat Unix timestamps or ISO strings. Use date:relative for “3 hours ago”, or omit the arg for ISO output.|div:100Divide a number (e.g. Stripe cents → dollars).|mul:100Multiply a number.
Channel tips
- Slack: Markdown works: *bold*, _italic_, :emoji:, and line breaks.
- Discord: Markdown-style formatting (**bold**, line breaks). Embeds are supported in pre-built templates.
- Email: Plain text subject + body. HTML is supported in the body field for richer layouts.
- Webhook: Rendered string is sent as the outbound payload body—you control the text, not a raw JSON pass-through.
Pre-built examples
These samples ship in Hooks (from lib/templates/library.ts). Fork them in the route editor when creating a route.
stripe → slack: Payment succeeded
Fires when a Stripe Checkout session completes (one-time payment or subscription signup)
:tada: *New payment received*
Customer: ${data.object.customer_email|default:unknown}
Amount: *${data.object.amount_total|div:100} ${data.object.currency|default:USD}*stripe → email: Payment succeeded
Fires when a Stripe Checkout session completes (one-time payment or subscription signup)
Subject: Payment received — ${data.object.amount_total|div:100} ${data.object.currency|default:USD}
A new payment was completed.
Customer: ${data.object.customer_email|default:unknown}
Amount: ${data.object.amount_total|div:100} ${data.object.currency|default:USD}
Session ID: ${data.object.id|default:—}stripe → discord: Payment succeeded
Fires when a Stripe Checkout session completes (one-time payment or subscription signup)
**New payment received** :tada:
Customer: ${data.object.customer_email|default:unknown}
Amount: **${data.object.amount_total|div:100} ${data.object.currency|default:USD}**stripe → webhook: Payment succeeded
Fires when a Stripe Checkout session completes (one-time payment or subscription signup)
Payment received: ${data.object.amount_total|div:100} ${data.object.currency|default:USD} from ${data.object.customer_email|default:unknown}shopify → slack: Order created
Fires on each new order. Point your Shopify "orders/create" webhook topic at this endpoint.
:shopping_cart: *New order #${order_number}*
Customer: ${email|default:Guest}
Total: *${total_price} ${currency}*
First item: ${line_items.0.title|default:see order}shopify → email: Order created
Fires on each new order. Point your Shopify "orders/create" webhook topic at this endpoint.
Subject: New order #${order_number} — ${total_price} ${currency}
A new order has been placed.
Order: #${order_number}
Customer: ${email|default:Guest}
Total: ${total_price} ${currency}
First item: ${line_items.0.title|default:see order}
Status: ${financial_status|default:pending}shopify → discord: Order created
Fires on each new order. Point your Shopify "orders/create" webhook topic at this endpoint.
**New order #${order_number}** :shopping_cart:
Customer: ${email|default:Guest}
Total: **${total_price} ${currency}**
First item: ${line_items.0.title|default:see order}shopify → webhook: Order created
Fires on each new order. Point your Shopify "orders/create" webhook topic at this endpoint.
New Shopify order #${order_number}: ${total_price} ${currency} from ${email|default:Guest}github → slack: PR opened
Fires when a pull request is opened (action: "opened", pull_request exists)
:arrow_up: *New PR on ${repository.full_name}*
*#${pull_request.number}: ${pull_request.title}*
By ${pull_request.user.login} → ${pull_request.base.ref}
${pull_request.html_url}github → email: PR opened
Fires when a pull request is opened (action: "opened", pull_request exists)
Subject: [${repository.full_name}] PR #${pull_request.number}: ${pull_request.title}
A new pull request has been opened.
Repository: ${repository.full_name}
PR #${pull_request.number}: ${pull_request.title}
Author: ${pull_request.user.login}
Base branch: ${pull_request.base.ref}
${pull_request.html_url}github → discord: PR opened
Fires when a pull request is opened (action: "opened", pull_request exists)
**New PR on ${repository.full_name}** :arrow_up:
**#${pull_request.number}: ${pull_request.title}**
By ${pull_request.user.login} → ${pull_request.base.ref}
${pull_request.html_url}github → webhook: PR opened
Fires when a pull request is opened (action: "opened", pull_request exists)
PR opened: [${repository.full_name}] #${pull_request.number} "${pull_request.title}" by ${pull_request.user.login}