Skip to main content

Webhook Relays

Overview

Webhook Relays let you forward webhook payloads from external services directly into a Roam group chat, without writing any code. Each relay provides a unique URL that accepts POST requests with a JSON payload and posts the content to your configured recipients.

┌─────────────┐         ┌─────────────────┐         ┌──────────────┐
│ PagerDuty │ │ Webhook Relay │ │ Roam Group │
│ Grafana │──POST──▶│ (unique URL) │───msg──▶│ Chat │
│ Sentry ... │ │ │ │ │
└─────────────┘ └─────────────────┘ └──────────────┘
Your service Templates, filters, Your team sees
sends a webhook and colors applied the notification

This is ideal for receiving notifications from services like PagerDuty, Grafana, Sentry, Datadog, GitHub, or any tool that supports outgoing webhooks.

With Webhook Relays you can:

  • Template messages using fields from the incoming payload
  • Add buttons that link back to the source service
  • Color-code messages to indicate severity or status
  • Override colors dynamically based on payload values
  • Filter delivery so only matching payloads produce messages

Create a Webhook Relay

  1. In Roam, navigate to Settings > Developer > Webhook Relays.
  2. Click Add and enter a name and optional description for the relay.
  3. After creation, the relay's unique Webhook URL is displayed. Copy it — you'll paste this into your external service.

The URL is a secret. Anyone with the URL can post messages to your chat, so treat it like a credential.

Add Recipients

Under Webhook Message Recipients, add the groups or individuals that should receive relay messages. You can target:

  • Groups — Messages appear in the group chat.
  • Individuals (by email) — Messages are delivered to a direct conversation.

Configure the Message

The template editor lets you customize how incoming payloads are displayed.

Message Text

Write your message using Markdown. Insert fields from the payload using {{field}} placeholders. Use Insert Field to pick from fields found in the sample payload.

For example, given this payload:

{
"title": "CPU usage above 90%",
"source": "monitor-1",
"url": "https://app.datadoghq.com/monitors/123"
}

A template like:

**{{title}}**
Source: `{{source}}`

produces:

CPU usage above 90% Source: monitor-1

Nested fields are accessed with dot notation: {{event.data.id}}.

Buttons

Add buttons that appear below the message. Each button has a label and a URL. Button URLs can also use {{field}} placeholders — for example, {{url}} to link back to the alert in your monitoring tool.

Set a Color

Choose a color that renders as a vertical strip on the left side of the message. Pick from presets:

PresetColor
GoodGreen
WarningYellow / amber
DangerRed

Or toggle Use Custom Color to enter any hex color (e.g. #5B3FD9).

Color Override Rules

Color overrides let you dynamically change the message color based on payload values. Each rule specifies:

  1. A field from the payload (e.g. status)
  2. A match value (e.g. critical)
  3. A color (Good, Warning, or Danger)

The first matching rule wins. If no rules match, the base color is used.

Example: For an alerting service that sends a severity field:

FieldValueColor
severitycriticalDanger
severitywarningWarning
severityokGood

This way, critical alerts appear with a red strip and resolved alerts appear green — all from the same relay.

Delivery Conditions

By default, every incoming webhook produces a message. Delivery conditions let you filter so that only matching payloads are delivered.

Each condition specifies:

  1. A field from the payload (e.g. action)
  2. An operator (see table below)
  3. One or more values

The available operators are:

OperatorDescription
isExact match against a single value
is notNegated exact match against a single value
is one ofMatches any value in a comma-separated list
is not one ofMatches none of the values in a comma-separated list
containsSubstring match against a single value
does not containNegated substring match against a single value

All conditions must match for the message to be delivered. Payloads that don't match are still captured (updating the sample payload and last-received timestamp) but no message is sent.

Example: Only deliver when severity is one of high, critical:

FieldOperatorValues
severityis one ofhigh, critical

Example: Only deliver when the message field contains error:

FieldOperatorValues
messagecontainserror

This prevents low-priority noise from flooding your chat while still capturing all payloads for debugging.

Sender Profile Image

Optionally upload a custom avatar that appears as the sender's profile image for relay messages. This helps distinguish different relays at a glance — for example, using the PagerDuty logo for PagerDuty alerts.

Sample Payload

The first webhook received by a new relay is automatically captured as the sample payload. This sample powers the Insert Field button, which lists available fields and shows example values from the captured payload.

If the payload structure changes (e.g. you switch to a different event type), click Clear to discard the sample. The next incoming webhook will be captured as the new sample.

Connect Your External Service

In your external service's webhook or notification settings, paste the relay's Webhook URL as the destination. The relay accepts POST requests with a JSON body.

Common services with outgoing webhook support:

  • PagerDuty — Events & Incidents webhooks
  • Grafana — Contact point webhooks
  • Sentry — Issue & error alert webhooks
  • Datadog — Monitor notification webhooks
  • GitHub — Repository webhooks (push, PR, issues, etc.)
  • GitLab — Project webhooks
  • Jira — Automation webhooks
  • Stripe — Event webhooks

Any service that can send a POST request with a JSON body to a URL will work.

Example: PagerDuty Incident Alerts

Here's a complete example setting up a relay for PagerDuty incident notifications.

1. Create a relay named "PagerDuty Alerts" and add your ops group as a recipient.

2. In PagerDuty, add a Generic Webhook (v3) integration and paste the relay URL.

3. Trigger a test incident so PagerDuty sends a payload. The relay captures it as the sample. A PagerDuty payload looks like:

{
"event": {
"event_type": "incident.triggered",
"data": {
"title": "Disk usage above 90%",
"urgency": "high",
"status": "triggered",
"html_url": "https://your-org.pagerduty.com/incidents/Q1EXAMPLE"
}
}
}

4. Configure the message template:

**{{event.data.title}}**
Status: {{event.data.status}} · Urgency: {{event.data.urgency}}

Add a button with label "View in PagerDuty" and URL {{event.data.html_url}}.

5. Add color override rules:

FieldValueColor
event.data.statustriggeredDanger
event.data.statusacknowledgedWarning
event.data.statusresolvedGood

6. Add a delivery condition to only deliver high-urgency incidents:

FieldOperatorValues
event.data.urgencyis one ofhigh

Now your ops group receives color-coded PagerDuty alerts for high-urgency incidents, with a direct link back to PagerDuty.

HTTP Response Codes

When an external service posts to a relay URL, the following responses are returned:

StatusMeaning
200 OKPayload accepted and message delivered (or captured if relay is disabled)
400 Bad RequestRequest body is not valid JSON
404 Not FoundRelay URL does not exist
413 Payload Too LargeJSON payload exceeds the size limit
429 Too Many RequestsRate limit exceeded — retry after the indicated period