A webhook is a write-only alert endpoint scoped to a team. You create one in the dashboard, copy its URL identifier, and post signed JSON to it from anywhere — CI pipelines, queue workers, third-party platforms with outbound webhooks, internal scripts. Each POST either creates a new alert or is folded into an existing one.
Anatomy of a webhook
- URL identifier — a short URL-safe string appended to
/api/alerts/trigger/. Treated as a public token; the HMAC signature is what authenticates. - Default severity — the severity assigned when the POST doesn't specify one. Individual posts can override it.
- Filter rules — Sentry-style conditions evaluated against the incoming payload. A rule can drop the alert or override its severity at the edge.
- Notification policy — which policy pages people for incidents from this webhook. Left unset, the team's default policy applies.
- Rate cap — each webhook accepts up to 60 requests per minute; requests above that get
429.
Triggering an alert
import { Zvono } from "@zvono/sdk";
const zvono = new Zvono({ secret: process.env.ZVONO_SECRET! });
const res = await zvono.alert("deploy-failures", {
title: "Deploy failed: api-gateway",
description: "Migration step exited with code 137",
severity: "sev1",
group_key: "deploy:api-gateway",
metadata: {
commit: "a1b2c3d",
environment: "production",
runId: 48211,
},
});
console.log(res.status); // "created" | "occurrence_added" | "filtered" | "reopened"Field reference
| Field | Type | Description |
|---|---|---|
titlerequired | string | Short label (max 200 chars). Shown in Slack, the dashboard, and notifications. |
description | string | Long-form context (max 2000 chars). Renders as the alert body in Slack. |
severity | "sev0" – "sev4" | Overrides the webhook default. Drives notification policy routing. |
metadata | Record<string, any> | Arbitrary payload (max 100 KB, max 10 nesting levels). Available to filter rules. |
group_key | string | Explicit grouping key. Identical keys collapse into one alert until it's resolved. |
Without the SDK
The SDK is just a convenience wrapper — any HTTP client works. POST signed JSON straight to the trigger endpoint: see Trigger alert for the request, headers, and error reference, and Authentication for how to sign the request body.
Filter rules
Every webhook can carry a list of filter rules — conditions evaluated against the incoming payload. Rules can match nested fields, regex patterns, and combinations of logical operators. A rule either drops the alert (returning filtered with a reason) or overrides its severity.
Example: a CI webhook that ignores alerts from feature branches but keeps anything on main:
IF metadata.branch != "main" THEN drop with reason "non-main branch"Filters run before any quota or notification work, so dropped payloads cost nothing.
Sentry
A webhook can be created with Sentry as its source. A Sentry endpoint has its own URL (/api/integrations/sentry/<identifier>) and accepts Sentry's webhook format directly. You don't need code or the SDK. The source can't be changed after the endpoint is created.
- Create the endpoint with source Sentry.
- In Sentry, go to Settings → Developer Settings → Custom Integrations and create an Internal Integration. Set its webhook URL to the endpoint URL and turn on Alert Rule Action. Save it.
- Copy the integration's Client Secret and paste it into the Connect Sentry card on the endpoint page. Requests are verified against Sentry's
Sentry-Hook-Signatureheader, and every request is rejected until the secret is saved. - In any Sentry issue or metric alert rule, add the action Send a notification via your integration.
| Sentry sends | Zvono does |
|---|---|
| Issue alert fired | Creates an alert. Each Sentry issue groups into one alert. fatal maps to sev1, error to sev2, warning to sev3, info/debug to sev4. |
| Metric alert critical / warning | Creates an alert at sev1 / sev3. Each metric incident groups into one alert, so warning then critical raises the same alert's severity. |
| Anything else, including resolves | Acknowledged and listed as Ignored in the endpoint history. Resolve the alert in Zvono. |
Sentry fields land in metadata (environment, release, level, project, rule, url, tags.*), so filter rules work on them. For example, metadata.environment eq production keeps only production errors. In tag names, dots and other punctuation become underscores, so Sentry's os.name tag is metadata.tags.os_name.
Response shape
{
"alertId": "65f3...",
"status": "created",
"message": "Alert created",
"occurrenceCount": 1,
"reason": null
}For the full status enum and grouping behaviour, see Alerts. For request signing details, see Authentication.