Pushrail Docs
Open app
Guides

Destination health events

Receive a webhook when a destination starts failing, degrades, or recovers.

Destination health events

Pushrail evaluates the health of each destination on a rolling basis. When a destination's health changes, Pushrail emits a platform event so you can react without polling the delivery log. You receive these events the same way you receive any other event: configure a webhook destination and a routing rule that matches them.

Event types

Three event types cover the full failure lifecycle:

| Event type | When it fires | |---|---| | destination.unhealthy | A destination's recent delivery success rate drops into the unhealthy band (severe failures) | | destination.degraded | A destination's success rate drops into the degraded band (elevated failures, not yet severe) | | destination.recovered | A destination that was unhealthy or degraded returns to a healthy success rate |

The health window is the last 1 hour of delivery attempts. Pushrail emits at most one notification per destination per status transition, with a cooldown to prevent flapping noise.

How to receive them

  1. Create a webhook destination in the Pushrail dashboard pointing at an endpoint in your own infrastructure.
  2. Add routing rules for the event types you care about (destination.unhealthy, destination.degraded, destination.recovered) that route to that destination.
  3. Verify the signature on incoming requests so your endpoint only acts on genuine Pushrail events. See Verifying webhook signatures.

You can also configure this through the failure-notifications portal. Your backend mints a short-lived portal session by calling POST /me/failure-notifications/portal-session with a manage-scoped API key (or a dashboard session); mount the returned token in the embed portal and your team can configure the webhook endpoint and routing rules without writing API calls directly.

Payload shape

Every health event carries the same payload structure. The recentFailures block is present on destination.unhealthy and destination.degraded; it is omitted on destination.recovered.

{
  "destination": {
    "id": "dest_01j8kz...",
    "name": "Acme order webhook",
    "type": "WEBHOOK",
    "environment": "PRODUCTION"
  },
  "customerAccount": {
    "id": "cust_01j8kz...",
    "externalId": "acme-corp",
    "name": "Acme Corp"
  },
  "health": {
    "status": "UNHEALTHY",
    "previousStatus": "HEALTHY",
    "successRate": 0.12,
    "window": "1h",
    "evaluatedAt": "2026-06-22T14:05:00.000Z"
  },
  "recentFailures": {
    "topErrorCategories": [
      { "category": "CONNECTION_TIMEOUT", "count": 34 },
      { "category": "HTTP_5XX", "count": 8 }
    ],
    "failedCount": 42,
    "totalCount": 48
  },
  "links": {
    "destinationHealth": "https://app.pushrail.io/destinations/dest_01j8kz.../health"
  }
}

A destination.recovered payload looks the same except recentFailures is absent and health.status is "HEALTHY" with the previous status being the state it recovered from.

Handling the event

On receipt, a typical handler:

  1. Parses and validates the payload.
  2. Checks health.status and health.previousStatus to understand the transition.
  3. Routes to the right internal action: page an on-call engineer for UNHEALTHY, log a warning for DEGRADED, resolve the incident alert for destination.recovered.
  4. Uses links.destinationHealth to deep-link to the destination health view in Pushrail.

The customerAccount.externalId field matches the customerExternalId you use to identify this customer in your ingest events. Use it to look up the affected customer in your own systems.

Retry and replay

Health events go through the same delivery pipeline as any other event. If your handler is temporarily unavailable, Pushrail retries with backoff. If retries are exhausted, the delivery enters the dead-letter queue and is visible in Observability → Deliveries. You can replay it from there once your handler is back up.