IntegrationsWebhooks and custom sources

40. Webhooks and custom sources

When no typed integration fits, webhooks are the universal adapter — POST JSON in, get events on the timeline.

When none of Daalu’s typed integrations fit, webhooks connect anything else. CI pipelines, homegrown alerters, internal scripts, IoT — all can write to Daalu’s timeline by POSTing JSON to the ingest endpoint. The reverse direction works too: Daalu can POST to your URL when an alert or proposal fires.

At a glance

What it connectsAnything that can POST JSON — CI, scripts, IoT, custom alerters; and outbound to your own receivers
Auth modelInbound: a per-tenant ingest key in the X-Daalu-Key header. Outbound: Daalu signs each delivery so you can verify it.
Where to set it upManaged Infra → Webhooks

Inbound: send events to Daalu

You hold a per-tenant ingest key; anything that can make an HTTPS POST sends events to a single endpoint with that key in a header. Daalu records each event on the timeline, and if an alert rule matches, an alert fires.

The endpoint

POST https://ops.daalu.io/api/v1/events
X-Daalu-Key: <your ingest key>
Content-Type: application/json

Find or rotate the ingest key under Managed Infra → Webhooks → Ingest key. Daalu stores only a hash of it — treat it like a password.

Request body

The body is an event envelope:

{
  "type": "deploy.failed",
  "module": "ci",
  "source": "github-actions",
  "summary": "prod deploy of api failed at step build",
  "severity": "warning",
  "payload": {
    "service": "api",
    "env": "prod",
    "commit": "a1b2c3d",
    "url": "https://github.com/acme/api/actions/runs/123"
  }
}
FieldMeaning
typeFreeform, but follow a <system>.<verb> shape (deploy.failed, backup.completed) so it’s queryable.
moduleA routing category for the event (ci, security, custom, …).
sourceStable identifier for the sender.
summaryOne human-readable line; this is what shows on the timeline.
severityOne of info, warning, critical. Defaults to info.
payloadAny JSON you want carried along and surfaced in the UI.

Note: The tenant is resolved from your ingest key, never from the body. Daalu drops any tenant_id you try to set — a key can only write into its own tenant.

A worked example

INGEST_KEY="<your ingest key>"
curl -X POST https://ops.daalu.io/api/v1/events \
  -H "X-Daalu-Key: $INGEST_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "check.failed",
    "module": "custom",
    "source": "nightly-cron",
    "summary": "disk usage on backup host exceeded 90%",
    "severity": "warning",
    "payload": {"host": "backup-1", "pct": 93}
  }'

A successful ingest returns 202 Accepted. Requests with a missing or wrong key are rejected with 401.


Outbound: Daalu posts to you

The reverse path: Daalu POSTs to a URL you provide when configured triggers fire.

Setup

  1. Managed Infra → Webhooks → Add outbound webhook.
  2. Pick the trigger — which events fire it (alerts of severity X, proposals of kind Y, and so on).
  3. Provide your receiving URL.
  4. Daalu shows a signing secret. It signs every delivery with it so you can verify the POST really came from Daalu.

Verifying deliveries

Each outbound POST carries an HMAC-SHA256 signature of the body in the X-Daalu-Signature header. Recompute the HMAC with your signing secret and compare:

# pseudo-receiver
SIG_HEADER="$X_Daalu_Signature"
EXPECTED=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
[ "$SIG_HEADER" = "$EXPECTED" ] || reject

Retries

If your receiver returns a non-2xx, Daalu retries with exponential backoff for up to an hour. After that the delivery is marked failed and surfaces on the webhook detail page.

Use cases

  • Pipe Daalu events into your warehouse.
  • Trigger your own automation from a Daalu alert.
  • Mirror change proposals into your ticket system.

Webhook detail page

For each webhook (in or out):

  • Endpoint / URL.
  • Secret or ingest key — masked, with a Reveal button.
  • Last delivery — timestamp, status, and the request/response pair.
  • Recent history — the 100 latest deliveries with timings.
  • Rotate secret — issues a new one; the old one keeps working for 24 hours so you can roll it out without downtime.

Limits

  • Body size: 1 MiB per POST.
  • Rate: 10 POSTs/second per ingest key (inbound); 50/second outbound to your URL.
  • Retention: 30 days of delivery history.

Need more? Email support.


Patterns from the field

”Deploy started” event from CI

A GitHub Action POSTs type=deploy.started when each prod deploy begins. The alert-explainer agent uses these to correlate — “the latency spike at 14:32 coincided with the deploy at 14:30.”

Dead-man’s-switch heartbeat

A cron in your environment POSTs type=heartbeat every minute. A Daalu rule fires an alert if those stop arriving. Cheap, reliable liveness checking.

Mirroring to a warehouse

An outbound webhook on every event fires to your Snowflake/BigQuery ingest URL, giving you a long-term record of every Daalu event for your own analysis.

Cross-tool plumbing

When a Daalu change proposal is approved, an outbound webhook opens a Jira ticket so your existing ticketing workflow stays in sync.


Next: Chapter 41 — Deploying Daalu Edge