Guide

Send Sentry Issue Alerts by Email (CLI)

Forward Sentry issue alerts to email through a webhook handler that parses the issue title, level, and permalink, then sends an enriched message with nylas email send.

Written by Hazik Director of Product Management

Reviewed by Qasim Muhammad

VerifiedCLI 3.1.17 · Gmail, Outlook · last tested June 9, 2026

Why route a Sentry alert through email instead of the built-in one?

Sentry already emails project members, but the built-in notification stops at Sentry's template and recipient list. Routing the alert through a webhook handler that calls the Nylas CLI lets you reshape the subject, pick recipients per error level, and attach internal runbook links. The handler runs nylas email send with full control over the message.

Sentry's integration platform delivers issue alerts as HTTP POST requests with a JSON body. The free Developer plan allows custom internal integrations, and Sentry documents the webhook resource as event_alert and issue_alert. According to the Sentry webhooks documentation, each request carries a Sentry-Hook-Resource header so your handler can branch on the event type. One small handler replaces a paid alerting add-on, and the CLI removes any SMTP setup from that handler.

How do I receive the Sentry issue alert payload?

A Sentry issue alert webhook is an HTTP POST your handler must accept and parse. The body is JSON with a top-level data.event object holding the issue title, level, and a web_url permalink. Your handler reads those three fields, then shells out to the CLI. Sentry retries failed webhook deliveries automatically, so return a non-2xx status when your handler fails to trigger another attempt.

Configure the alert under Alerts in your Sentry project, add a webhook action, and point it at your handler URL. For local testing you can capture and inspect a real Nylas-style webhook payload with the CLI's own tunnel server, which is handy while you shape the parser. The nylas webhook server command opens a local listener on a chosen port.

# Inspect incoming webhook payloads locally while you build the handler
nylas webhook server --port 4000

How do I enrich the email with issue title, level, and permalink?

Enrichment means lifting the three high-signal fields out of the payload and placing them where a recipient scans first: the subject line and the first body line. The handler reads title, level (one of fatal, error, warning, or info), and the web_url permalink, then composes a message. This takes about 15 lines of shell.

The example below uses jq to extract fields from the POST body, then calls nylas email send with a subject that leads with the level and title. The --track-label flag tags the message sentry-alert so you can find every routed alert later, and --metadata stores the issue level as a filterable key.

#!/usr/bin/env bash
# handler.sh -- reads a Sentry issue-alert JSON body on stdin
payload="$(cat)"

title=$(printf '%s' "$payload" | jq -r '.data.event.title')
level=$(printf '%s' "$payload" | jq -r '.data.event.level')
url=$(printf '%s' "$payload" | jq -r '.data.event.web_url')

nylas email send "$NYLAS_GRANT_ID" \
  --to "$ALERT_EMAIL_TO" \
  --subject "[$level] $title" \
  --body "Sentry issue: $title

Level: $level
Permalink: $url" \
  --track-label sentry-alert \
  --metadata level="$level" \
  --yes \
  --json

How do I route by severity and send richer HTML?

Severity routing sends fatal and error issues to an on-call address while warning and info go to a quieter list. A single shell case statement picks the recipient before the send. Sentry assigns each event one of 5 documented levels, so the routing table stays small and predictable.

For a scannable message, write a short HTML block and pass it as the --body, which accepts HTML or plain text. Keep it to a heading, the permalink, and the level. The command below builds the body from the parsed fields and routes the recipient by level, so a fatal error reaches the right inbox within seconds of Sentry firing the alert.

case "$level" in
  fatal|error) to="$ONCALL_EMAIL" ;;
  *)           to="$DIGEST_EMAIL" ;;
esac

body="<h1>Sentry: $title</h1>
<p>Level: <strong>$level</strong></p>
<p><a href=\"$url\">Open the issue in Sentry</a></p>"

nylas email send "$NYLAS_GRANT_ID" \
  --to "$to" \
  --subject "[$level] $title" \
  --body "$body" \
  --track-label sentry-alert \
  --yes \
  --json

Why keep the API key and grant out of the handler code?

The handler needs a Nylas API key and a sender grant ID, and both belong in environment variables, not in the script. Read NYLAS_API_KEY and NYLAS_GRANT_ID from the process environment so the same handler file is safe to commit. A dedicated automation grant is easier to audit and revoke than a developer mailbox, and rotating it takes 1 command.

Configure credentials once with nylas auth config --api-key for interactive use, or export the variables in the service that runs the handler for headless deployments. Never echo the key in logs. The CLI reads the key from the environment, so the handler passes only the grant ID, recipient, and message content on the command line.

# Headless: export credentials in the service that runs handler.sh
export NYLAS_API_KEY="nyk_..."
export NYLAS_GRANT_ID="grant-uuid"
export NYLAS_DISABLE_KEYRING=1

# Verify the grant can send before wiring the webhook
nylas email list "$NYLAS_GRANT_ID" --limit 1 --json

Next steps