API Reference
Webhook events
The event catalog WASViking emits, the payload shape, and how to verify the signature.
WASViking® emits signed webhook events on every meaningful state transition. Events are JSON-over-HTTPS to a URL you register, with HMAC-SHA256 signing.
Registering a webhook
curl -sS https://api.wasviking.com/v1/webhooks \
-H "Authorization: ApiKey ${KEY}" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/wasviking-hook",
"events": ["finding.escalated", "finding.sla_breached"],
"description": "SIEM ingestion"
}'
{
"id": "wh_88aa12",
"url": "https://example.com/wasviking-hook",
"secret": "whsec_xxxxxxxxxxxxxxxxxxxx",
"events": ["finding.escalated", "finding.sla_breached"]
}
The secret is shown once at creation. Store it; you cannot retrieve
it later.
Event catalog
Findings
| Event | When |
|---|---|
finding.created |
A new finding is written. |
finding.reopened |
A previously closed finding came back. |
finding.escalated |
Status or risk score jumped to a higher band. |
finding.status_changed |
Any status transition. |
finding.sla_breached |
Finding crossed its SLA window. |
finding.assigned |
Owner field updated. |
Scans
| Event | When |
|---|---|
scan.queued |
Scan accepted into the queue. |
scan.started |
Scan transitioned to running. |
scan.completed |
Scan completed (with or without findings). |
scan.failed |
Engine error or hard timeout. |
scan.canceled |
Operator cancellation. |
Inventory and assets
| Event | When |
|---|---|
asset.first_seen |
New asset discovered. |
asset.disappeared |
Asset is no longer reachable. |
asset.reappeared |
Asset returned after a disappeared. |
Supply chain
| Event | When |
|---|---|
sbom.submitted |
New SBOM landed via /sentinel/sbom/submit. |
sbom.intel_match |
Daily OSV+KEV ingest matched a live SBOM. |
bundle.created |
SBOM Evidence Bundle issued. |
bundle.accessed |
Recipient accessed a share. |
bundle.revoked |
Operator revoked a share. |
Secrets
| Event | When |
|---|---|
secret.detected |
New secret detection landed. |
secret.verified_live |
Live verifier confirmed the secret is active. |
Posture Shares
| Event | When |
|---|---|
posture_share.created |
New share issued. |
posture_share.accessed |
Recipient accessed it. |
posture_share.revoked |
Operator revoked it. |
Edge intel
| Event | When |
|---|---|
edge.correlation_match |
Adversary traffic matched an open finding (risk amplification). |
Payload shape
Every event is a JSON object with:
{
"id": "evt_88aa12d4",
"type": "finding.escalated",
"created_at": "2026-05-21T14:08:11Z",
"organization": "acme",
"data": {
"finding_id": "f_8ab2",
"category": "graphql_bola",
"cwe": "CWE-639",
"risk_score": 88,
"previous_risk_score": 62,
"asset_id": "a_19ff",
"asset_criticality": "high",
"sla_window_hours": 24,
"primary_risk_category": "authorization",
"compliance": ["PCI 6.5.8", "LGPD Art.46"]
}
}
type tells your consumer how to read data. Treat unknown event types
as forward-compatible: log and skip rather than fail.
Signing
WASViking signs every payload with HMAC-SHA256 using your webhook secret.
Headers on every delivery:
| Header | Value |
|---|---|
Wasviking-Signature |
t=<timestamp>,v1=<hex-hmac> |
Wasviking-Event |
The event type, mirrored in the body. |
Wasviking-Delivery |
UUID for this delivery attempt. |
Verifying in Python
import hmac, hashlib, time
def verify(body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
timestamp = int(parts["t"])
sig = parts["v1"]
if abs(time.time() - timestamp) > tolerance:
return False
payload = f"{timestamp}.".encode() + body
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig)
Verifying in Node
const crypto = require("crypto");
function verify(body, header, secret, tolerance = 300) {
const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > tolerance) return false;
const payload = `${parts.t}.${body}`;
const expected = crypto.createHmac("sha256", secret).update(payload).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
Delivery semantics
- At-least-once. A network error retries with exponential backoff for up to 24 hours.
- Ordered per finding. Events for the same finding are delivered in order.
- Test delivery.
POST /webhooks/{id}/testsends a syntheticwebhook.testpayload to verify your endpoint.
Common consumer patterns
- SIEM. Subscribe to
finding.*,secret.verified_live, andsbom.intel_match. Forward straight to your SIEM index. - Slack / Teams. Subscribe to
finding.escalatedandfinding.sla_breached. Most teams find broader subscriptions noisy. - Internal automation. Subscribe to
asset.first_seento kick off internal asset workflows.
