Webhooks
Subscribe to Asqav events and receive them as signed HTTP POSTs to your endpoint. Available on all tiers.
Create a webhook
The secret is generated server-side and returned exactly once. Store it. Use it to verify every incoming request.
curl -X POST https://api.asqav.com/api/v1/alerts/webhooks \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/asqav","events":["*"]}'
Response:
{
"id": "wh_...",
"url": "https://example.com/asqav",
"secret": "whsec_...",
"events": ["*"],
"created_at": "2026-04-19T12:00:00+00:00"
}
Delivery format
Every delivery has two headers and a JSON body:
| Header | Value |
|---|---|
X-Asqav-Signature | sha256=<hex> |
X-Asqav-Timestamp | Unix seconds when the event was sent |
The signature is HMAC-SHA256 over <timestamp>.<body> where body is the compact JSON with sorted keys.
Verification
Verify by recomputing HMAC-SHA256 over timestamp + '.' + body_compact_sorted with your webhook secret. Your receiver MUST parse the JSON body then re-serialize with json.dumps(body, sort_keys=True, separators=(',', ':')) before computing HMAC. Asqav's backend normalizes this way, and variations in whitespace will break verification.
Verify a delivery
import hmac, hashlib, json, time
def verify(secret, headers, raw_body, tolerance=300):
ts = headers["X-Asqav-Timestamp"]
sig = headers["X-Asqav-Signature"].split("=", 1)[1]
if abs(time.time() - int(ts)) > tolerance:
raise ValueError("stale webhook")
body = json.dumps(json.loads(raw_body), separators=(",", ":"), sort_keys=True)
expected = hmac.new(secret.encode(), f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
raise ValueError("bad signature")
Rotate the secret
If a secret leaks, rotate it. The response returns a new secret once.
curl -X POST https://api.asqav.com/api/v1/alerts/webhooks/wh_.../rotate \
-H "X-API-Key: sk_live_..."
If the URL points to Slack, Discord, or Microsoft Teams, Asqav formats the payload for that channel automatically. For generic endpoints you receive the raw event JSON.
Manage webhook subscriptions from the terminal with asqav webhooks (list, create, delete).