Skip to content

Sources ​

Sources are incoming webhooks that create Pulses. Configure them in the app under Connections → Sources.

Exhale turns paging and observability alerts into Pulses — scrubbed payloads in PostgreSQL, optional async triage, and the customer UI. Each source is an HTTPS webhook that creates or updates tenant-scoped pulse rows.

This is not Context (enrichment at triage time) and not Notifications (outbound after triage). See the Connections overview.

Today: paging sources — PagerDuty, JSM Operations (Opsgenie), Splunk On-Call, and incident.io — plus observability sources — Grafana, Datadog, Alertmanager, New Relic, Sentry, Honeycomb, Elastic Observability, Dynatrace, and AWS CloudWatch — and tenant manual webhooks are production ingest paths.

Hosted ingest URLs use /webhooks/... on https://exhaleoncall.com. Session and admin routes in these guides are written as /v1/auth/...; the app calls them under /api. See API versioning.


How ingest works (all sources) ​

Every incoming source follows the same pipeline:

  1. Authenticate — vendor signature, shared secret, or tenant token (per source).
  2. Size limit — reject bodies over the configured maximum (default 1 MiB → 413).
  3. Dedupe — delivery id and/or (tenant_id, source, external_id) to avoid duplicate Pulses.
  4. Scrub — regex + structural masking before persist and before LLM.
  5. Resolve tenant — pulse source registry (an account hint on an account-mapped paging source, or a webhook token).
  6. Upsert pulse — set source, external_id, title, status, ephemeral payload.
  7. Enqueue triage — when async triage is enabled and lifecycle rules allow.

Shipped today ​

SourceEndpointPulse sourceGuide
PagerDutyPOST /webhooks/pagerdutypagerdutyPagerDuty webhooks
JSM Operations (Opsgenie)POST /webhooks/opsgenie (header X-Exhale-Webhook-Token) or POST /webhooks/opsgenie/{token}opsgenieJSM Operations (Opsgenie)
Splunk On-CallPOST /webhooks/splunk-oncall (header X-Exhale-Webhook-Token) or POST /webhooks/splunk-oncall/{token}splunk_oncallSplunk On-Call
incident.ioPOST /webhooks/incident-io (header X-Exhale-Webhook-Token) or POST /webhooks/incident-io/{token}incident_ioincident.io
GrafanaPOST /webhooks/grafana (header X-Exhale-Webhook-Token) or POST /webhooks/grafana/{token}grafanaGrafana
DatadogPOST /webhooks/datadog (header X-Exhale-Webhook-Token) or POST /webhooks/datadog/{token}datadogDatadog
Prometheus AlertmanagerPOST /webhooks/alertmanager (header X-Exhale-Webhook-Token) or POST /webhooks/alertmanager/{token}alertmanagerAlertmanager
New RelicPOST /webhooks/newrelic (header X-Exhale-Webhook-Token) or POST /webhooks/newrelic/{token}new_relicNew Relic
SentryPOST /webhooks/sentry (header X-Exhale-Webhook-Token) or POST /webhooks/sentry/{token}sentrySentry
HoneycombPOST /webhooks/honeycomb (header X-Exhale-Webhook-Token) or POST /webhooks/honeycomb/{token}honeycombHoneycomb
Elastic ObservabilityPOST /webhooks/elastic (header X-Exhale-Webhook-Token) or POST /webhooks/elastic/{token}elasticElastic
DynatracePOST /webhooks/dynatrace (header X-Exhale-Webhook-Token) or POST /webhooks/dynatrace/{token}dynatraceDynatrace
AWS CloudWatchPOST /webhooks/aws-cloudwatch (header X-Exhale-Webhook-Token) or POST /webhooks/aws-cloudwatch/{token}aws_cloudwatchAWS CloudWatch
Manual webhookPOST /webhooks/manual (header X-Exhale-Webhook-Token) or POST /webhooks/manual/{token}other (UI: Manual webhook)Manual webhook

Customer setup: Connections → Sources. Account-mapped paging sources use self-serve account id registration and a shared webhook URL. Token-auth sources use a per-tenant URL token from Connect (manual webhooks also use HMAC).

A token webhook URL is a credential. Treat the URL like a password and share it only with people who should create Pulses. Exhale stores only a hash for lookup and does not return the URL to teammates with the Viewer role. Owners, admins, and members can read it; only admins and owners can rotate it, and the previous URL stops working right away. PagerDuty is the exception: /webhooks/pagerduty carries no token and stays visible to every role.

Incoming slots: Trial/Starter allow one primary paging ingest source and a separate supporting observability pool (Trial 1, Starter 3, Growth primary 3 / supporting 8, Business primary 10 / supporting 25). Enterprise is unlimited. Manual and OAuth connections for the same vendor share one slot (JSM Operations). Each named manual webhook endpoint occupies one primary or supporting slot. New connect returns 403 when the tenant is at cap; ingest for an already-wired source is unchanged.


Sources vs Context vs Notifications ​

TrackPurposeExamples
Sources (this section)Creates PulsesPaging and observability webhooks
ContextEnrichment at triage timeGrafana API key, GitHub repos, markdown runbooks
NotificationsOutbound after triageSlack, Teams, email, SMS

Some vendors appear in both Sources and Context. Connect the webhook if that vendor should create Pulses. Connect Context if you want enrichment on Pulses that already exist.


Use the guides above for signing, dedupe, tenancy, and lifecycle behavior. Source setup in the app uses an admin session and CSRF.

Exhale by Kolstrom Systems LLC