Docs / Webhooks

Developers

Webhooks

Every event that matters — actions executed, savings recorded, idle clusters detected, pre-warm predictions — delivered to your endpoints. Signed, retried, logged, and replayable.

Register an endpoint

Create endpoints from the dashboard (Settings → Webhooks) or the API. Each endpoint gets a signing secret (whsec_…) shown once at creation — store it like a password. You can rotate it at any time.

# Subscribe to specific events (empty list = all events)
curl -X POST https://api.digitaltap.ai/v1/webhooks \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.example.com/hooks/digitaltap",
    "description": "Savings feed for finance",
    "event_types": ["savings.recorded", "savings.verified", "action.executed"]
  }'
HTTPS only. Endpoints must resolve to public addresses — private, loopback, link-local, and cloud-metadata ranges are rejected at registration and again at delivery time.

Event catalog

EventFires when
action.executedAn agent executed an optimization (hibernate, resize, cleanup) under SafetyGate.
action.recommendedCopilot created a recommendation awaiting your approval.
savings.recordedA savings record was written for an executed action.
savings.verifiedThe verification engine confirmed measured savings against the baseline — the billable ground truth.
cluster.idle_detectedA cluster crossed its (adaptive) idle threshold.
prediction.prewarmThe Nerve Engine predicted an idle→busy transition and scheduled a pre-warm.
platform.connectedA platform link passed its connectivity test.
endpoint.testTest ping fired from the dashboard or API.

Delivery contract

Deliveries are POST requests with a JSON body and a signature header:

POST /hooks/digitaltap HTTP/1.1
Content-Type: application/json
X-DigitalTap-Signature: t=1751830920,v1=5f8a2c…c21e

{
  "id": "4b6db6a2-6d0f-4a8e-9b2e-1a2b3c4d5e6f",   // delivery id — use for idempotency
  "event": "savings.verified",
  "created": 1751830920,
  "data": { /* event-specific payload */ }
}

Verify signatures

The header is t=<unix ts>,v1=<hex HMAC-SHA256 of "<t>.<raw body>" with your signing secret>. Verify with a constant-time comparison and reject stale timestamps to block replays:

Python

import hmac, hashlib, time

def verify(raw_body: bytes, header: str, secret: str, tolerance_s: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    ts, their_sig = parts["t"], parts["v1"]
    if abs(time.time() - int(ts)) > tolerance_s:
        return False  # stale — possible replay
    signed = f"{ts}.".encode() + raw_body
    our_sig = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(our_sig, their_sig)

Node

const crypto = require("crypto");

function verify(rawBody, header, secret, toleranceS = 300) {
  const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > toleranceS) return false;
  const signed = `${parts.t}.${rawBody}`;
  const ourSig = crypto.createHmac("sha256", secret).update(signed).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(ourSig), Buffer.from(parts.v1));
}
Always verify against the raw request body — parse the JSON only after the signature checks out. Re-serialized JSON will not match the signed bytes.

Test it

# Fire an endpoint.test event at your endpoint right now
curl -X POST https://api.digitaltap.ai/v1/webhooks/{id}/test \
  -H "Authorization: Bearer $TOKEN"

# Inspect the delivery log (status, response codes, attempts)
curl https://api.digitaltap.ai/v1/webhooks/{id}/deliveries \
  -H "Authorization: Bearer $TOKEN"

API reference →