E EMBAN / Docs

Webhooks

Webhooks are how Emban delivers notifications to your systems. They are not a separate resource — a webhook is just a URL attached to an alert or a scheduled report. When that rule triggers, Emban POSTs to the URL and records the attempt in the webhook_deliveries table.

There is no webhook object to create directly. The API surface area is /v1/alerts and /v1/reports. The Admin → Webhooks page is a read-only dashboard that aggregates deliveries across all alert and report rules in your org.

Two delivery profiles

Emban sends two fundamentally different kinds of webhook, and the retry/timeout profile reflects that:

SourcePayloadRetriesPer-attempt timeoutBackoff
alertJSON body3 attempts10 s0s, 30s, 120s
reportRaw artifact bytes (CSV/PNG/PDF)1 attempt20 s

Alerts retry because they are small, time-sensitive signals where eventual delivery matters more than the exact minute. Reports do not retry because the artifact is large, the cadence is periodic (daily/weekly/monthly), and it is usually less work to wait for the next scheduled run than to re-deliver a stale one.

Alert payload

POST https://your-receiver.example.com/emban
Content-Type: application/json

{
  "alert_id": 42,
  "name": "API error rate too high",
  "dashboard_id": "dash_abc123",
  "widget_id": "w_api_calls",
  "condition": {
    "type": "threshold",
    "operator": "gt",
    "value": 50
  },
  "state": "firing",
  "fired_at": "2026-04-24T14:30:00Z"
}

The body identifies the alert, the widget it evaluates, and the exact condition that fired. A 2xx response stops retries; 4xx, 5xx, connection errors, and timeouts trigger the next attempt. After 3 failed attempts the delivery is given up and logged to webhook_deliveries for inspection.

Report payload

Reports POST the artifact bytes directly as the body, with the correct Content-Type and three identification headers:

POST https://your-receiver.example.com/emban-reports
Content-Type: text/csv | image/png | application/pdf
X-Emban-Report-Id: 17
X-Emban-Report-Name: Weekly usage summary
X-Emban-Dashboard-Id: dash_abc123

<raw artifact bytes>

Because reports don't retry, your receiver should be prepared to either persist the artifact immediately or fail fast. A slow receiver that times out loses that run's artifact — but the next run will still fire on schedule with fresh data.

SSRF protection

Every webhook URL is validated before the first attempt. Emban blocks URLs that could be used to probe internal infrastructure:

If you need internal delivery, route webhooks through a public relay you control (e.g. an ingress endpoint that forwards to your private network). Emban will not deliver directly to internal IPs even if the URL is syntactically valid.

Authenticating incoming webhooks

Emban does not yet sign webhook payloads with an HMAC. That means your receiver cannot cryptographically verify that a given POST came from Emban. Until signing lands, use one of these patterns:

Pattern 1 Secret in the URL path Generate a random token and include it in the webhook URL itself (https://hooks.example.com/emban/<random-token>). Your receiver rejects any POST whose path token doesn't match. Simple and effective as long as the URL isn't leaked into logs.
Pattern 2 IP allowlist Emban's outbound IP set is stable. Configure your receiver (or its upstream load balancer) to accept POSTs only from that range. Combines well with TLS and a path token for defense in depth.
Pattern 3 Correlate on X-Emban-* headers For reports, the X-Emban-Report-Id / X-Emban-Dashboard-Id headers can be cross-checked against the report ID you created. A POST with an unknown ID is silently dropped. Useful as a lightweight spam filter.
Pattern 4 Treat webhook data as untrusted Even with the above, don't let webhook payload fields land unvalidated in downstream systems. Validate alert_id / report_id against what you've created, drop anything you don't recognize, and log the rest.

Observability

Every delivery attempt — successful, failed, retried — is persisted to the webhook_deliveries table:

FieldDescription
org_idYour organization ID. All queries are org-scoped.
sourcealert or report.
source_idThe alert_id or report_id this delivery was for.
webhook_urlThe URL that was POSTed to.
attemptAttempt number (1-3 for alerts, always 1 for reports).
status_codeHTTP response code. 0 means a connection-level failure (DNS, TCP, TLS, timeout).
errorTruncated error string if the request never completed.
response_excerptFirst 512 bytes of the response body. Useful for diagnosing 4xx from a misbehaving receiver.
duration_msEnd-to-end duration of the attempt.
created_atAttempt timestamp.

Admin dashboard

The Admin → Webhooks page aggregates the last 24 hours of deliveries per alert/report:

This is enough to spot a receiver that's been silently 500-ing for a day without anyone noticing. If you want historical context beyond 24 hours, query webhook_deliveries directly through the Query Builder.

Design patterns

Pattern 1 Ack fast, process async Return 202 immediately and push the payload onto a queue. A slow synchronous handler increases the chance of timeout retries for alerts and silent loss for reports.
Pattern 2 Idempotent by (source, source_id, attempt) Alert retries mean your receiver may see the same firing twice. Use the alert_id + fired_at (or report_id + started_at) as an idempotency key and no-op on replays.
Pattern 3 Return useful error bodies When you reject a payload, return a short human-readable message. Emban captures the first 512 bytes into response_excerpt — "missing X-Correlation-Id" is far more debuggable than a bare "bad request".
Pattern 4 Alert on the alerts Add a no_data alert on the events emitted by your webhook receiver. If Emban ever stops POSTing entirely — or if your receiver stops receiving — you get paged from your own system.
Pattern 5 One URL per purpose Don't fan out notifications through a single webhook URL and then branch server-side by name. One URL per alert (or per category) makes the admin dashboard readable and makes it easy to pause one channel without touching others.
Related: Alerts for the full alert model and firing lifecycle, Scheduled Reports for the report artifact formats, and the API reference for the alert/report endpoints that accept webhook_url.