Skip to content

Configuration

sarmakska edited this page May 3, 2026 · 3 revisions

Configuration

Six env vars. Two required, four optional.

Required

RESEND_API_KEY

Resend API key. Sign up at resend.com, free tier ships 3,000 emails/month.

NOTIFY_EMAIL

Where every webhook email lands. Single recipient. For multi-recipient, comma-separate:

NOTIFY_EMAIL=alice@team.com,bob@team.com

Optional

FROM_EMAIL

Default: webhooks@onresend.dev

In production, use your own verified domain. Resend's onresend.dev sender is fine for testing but flagged as spam by some receivers.

To verify a domain: Resend → Domains → Add. Add the DNS records they show. Done in 5 minutes if you have DNS access.

WEBHOOK_SECRET

If set, every request must include a valid HMAC-SHA256 signature in the X-Signature, X-Hub-Signature-256, or X-Stripe-Signature header.

WEBHOOK_SECRET=long-random-string-please

Generate one:

openssl rand -hex 32

When unset, signature verification is disabled. Use only for internal sources you trust.

SLACK_WEBHOOK_URL

If set, every email is also posted to Slack via the incoming webhook URL.

SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../...

Get one from Slack → Apps → Incoming Webhooks → Add to channel.

The Slack message is plaintext (subject + first 2,500 chars of body in a code block). For richer formatting, edit sendSlack() in src/index.js to use Slack Block Kit.

PORT

Default: 3000

The port Express listens on.

Limits and tuning

The service is configured for typical webhook volumes. For higher load, consider:

  • Body size: 1MB limit (express.json({ limit: '1mb' })). Bump in src/index.js if needed.
  • Connection limits: Express defaults are generous. Behind nginx or your platform's load balancer, the limits there usually kick in first.
  • Resend rate limits: 100 emails/sec on free tier. If you exceed, scale up Resend or queue ahead of this service.

Per-route configuration (advanced)

For different sources to email different recipients, route in the URL:

// src/index.js
const ROUTING = {
  stripe: 'finance@team.com',
  github: 'eng@team.com',
  default: process.env.NOTIFY_EMAIL,
}

// in the handler:
const recipient = ROUTING[source] || ROUTING.default
await sendEmail({ to: recipient, ...formatted })

Roughly 20 lines of changes. Add when needed.

Clone this wiki locally