Webhooks

OneAnalytics can POST to your HTTPS endpoint when events happen — alert fires, export completes, dataset refresh fails, sharing grant created, SCIM user provisioned. Each delivery is HMAC-signed and retried on transient failure.

Register a webhook

Settings → Webhooks → Create or via API:

POST /v1/webhooks
{
  "url": "https://hooks.acme.com/oa",
  "events": ["alert.fire", "export.succeeded", "dataset.refresh.failed"],
  "secret": "<optional; we generate one if omitted>"
}

Only https:// URLs are accepted. http://, file://, ftp:// are rejected with 400 webhook/scheme-not-allowed.

Signature

Every outbound request carries:

X-OneAnalytics-Signature: t=1744797931,v1=8a3d6...
X-OneAnalytics-Event:     alert.fire
X-OneAnalytics-Delivery:  dlv_01H...

The v1 value is HMAC-SHA256(secret, "{t}.{raw_body}") hex-encoded.

Verifying (Python)

import hmac, hashlib

def verify(headers, raw_body, secret, tolerance=300):
    sig = headers["X-OneAnalytics-Signature"]
    parts = dict(p.split("=", 1) for p in sig.split(","))
    t, v1 = int(parts["t"]), parts["v1"]
    if abs(time.time() - t) > tolerance:
        return False   # replay protection
    expected = hmac.new(secret.encode(),
                        f"{t}.{raw_body.decode()}".encode(),
                        hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, v1)

The 5-minute tolerance window prevents replay of intercepted requests.

Retry schedule

Per-attempt timeout is 5 seconds. Failure classification:

  • 2xx → success.
  • 404 or 410 → permanent failure; webhook is disabled, we email you.
  • 5xx or network error → retryable; we retry at 5s, 10s, 20s, 40s, 60s, 60s (6 attempts total, about 3 minutes elapsed).
  • 3xx redirects are not followed — update the registered URL.

After all retries exhausted, the delivery is marked failed and visible in Webhooks → Deliveries. Manual re-deliver is available.

Event payloads

Every payload shares an envelope:

{
  "id":         "evt_01H...",
  "type":       "alert.fire",
  "created_at": "2026-04-16T09:42:11.134Z",
  "workspace_id": "...",
  "data": { /* event-specific */ }
}

data is documented per-event in the UI's Webhooks → Events tab, with a copyable JSON sample for every one.

Best practices

  • Idempotency — process by id; we may deliver the same event twice under retry.
  • Fast ack — respond 200 within 5 s, do heavy work async.
  • Allowlist our egress IPs10.20.0.129, 10.20.0.130.
  • Rotate secrets — from the Webhooks → Edit page. Old secret is accepted for 24 h to avoid drops.

Event catalog

alert.fire, alert.resolve, export.succeeded, export.failed, dataset.refresh.started, dataset.refresh.succeeded, dataset.refresh.failed, sharing.grant.created, sharing.grant.revoked, scim.user.provisioned, scim.user.deprovisioned, audit.event (firehose — opt-in, Scale only).