Skip to content

Webhook Health Alert Emails

Sparrow already tracks each webhook’s health (unknown / healthy / degraded / unhealthy) and retries failed deliveries until they succeed or exhaust their attempts. This feature lets you get emailed the moment either of those things happens, without polling the API or wiring up your own monitor.

Sparrow emits two events into a Sparrow-owned internal consumer, _sparrow, using its own event/subscription/delivery pipeline — the same one your events flow through:

EventFires when
sparrow.webhook.health_changedA webhook’s health transitions (e.g. healthy → degraded). The very first unknown → healthy transition is skipped — every webhook starts unknown and this would otherwise fire on every registration.
sparrow.webhook.delivery_failedA delivery exhausts all of its retries and is marked permanently failed.

You never subscribe to these events directly. Instead, you register an alert config naming an email address; Sparrow embeds every matching recipient into the event’s payload (payload.alert_recipients) at the moment it’s pushed, and a mail-sending recipe (see below) fans that out to a real email via SendGrid.

  1. Consumer-wide — every webhook under a consumer:

    Terminal window
    curl -X POST http://localhost:8080/v1/consumers/acme/alert-configs \
    -H 'Content-Type: application/json' \
    -d '{
    "email": "ops@acme.example.com",
    "event_types": ["sparrow.webhook.health_changed", "sparrow.webhook.delivery_failed"]
    }'
  2. One specific webhook — add webhook_id:

    Terminal window
    curl -X POST http://localhost:8080/v1/consumers/acme/alert-configs \
    -H 'Content-Type: application/json' \
    -d '{
    "webhook_id": "wh_123",
    "email": "oncall@acme.example.com",
    "event_types": ["sparrow.webhook.delivery_failed"]
    }'
  3. List or remove configs the same way you would any other resource:

    Terminal window
    curl http://localhost:8080/v1/consumers/acme/alert-configs
    curl -X DELETE http://localhost:8080/v1/consumers/acme/alert-configs/{alert_config_id}

A webhook whose own consumer is _sparrow never generates these events — that would create a feedback loop.

The system events above only become emails once you wire a mail-sending webhook under the _sparrow consumer. Sparrow ships a bundled SendGrid recipe for exactly this — apply it with the CLI:

Terminal window
sparrow --consumer _sparrow use sendgrid \
--param api_key=$SENDGRID_API_KEY \
--param from_email=alerts@yourdomain.com \
--param from_name="Sparrow Alerts" \
--event sparrow.webhook.health_changed \
--event sparrow.webhook.delivery_failed

That registers the SendGrid webhook, subscribes it to both system events, and installs the transform in one step. The transform ranges payload.alert_recipients into SendGrid’s v3 personalizations array — one SendGrid API call delivers to every opted-in recipient, each in their own personalization.

  • Events are always recorded. Every health transition and permanent delivery failure pushes an event under _sparrow, even when no alert configs or subscriptions match — alert_recipients is then an empty list. Nothing is sent unless a webhook subscribes to these events; with the SendGrid recipe, an empty list goes to its default_recipient (typically your ops inbox) as a catch-all.
  • Health measures the receiving system only. Deliveries that fail because a subscription’s template did not render (template_error), and deliveries held by a paused subscription, are faults or choices on the sending side. They never change a webhook’s health or trigger these events.
  • Errors here never affect delivery. If emitting a system event fails, Sparrow logs it and moves on; it never retries or blocks the webhook delivery that triggered it.
  • _sparrow’s events are internal. They don’t show up in your consumer’s event history — they live under the _sparrow consumer and exist only to drive this alerting pipeline.