Webhooks

Receive real-time notifications when scans finish, fail, or your usage changes. CodeSec sends a signed POST to each configured endpoint.

2 endpoints

  • https://api.acme.dev/hooks/codesec
    scan.completedscan.failed
    Added 5/20/2026Last delivery just now
  • https://hooks.slack.com/services/T000/B000/XXXX
    usage.limit_reached
    Added 4/11/2026Last delivery 2d ago

Events

Each event delivers a JSON payload with a top-level event name and a data object.

scan.completed

Fired when a scan finishes successfully and results are ready.

{
  "event": "scan.completed",
  "created_at": "2026-06-03T10:04:12Z",
  "data": {
    "scan_id": "scan_123",
    "target": "https://example.com",
    "status": "completed",
    "score": 87,
    "findings_count": 4
  }
}
scan.failed

Fired when a scan could not complete (unreachable target, timeout).

{
  "event": "scan.failed",
  "created_at": "2026-06-03T10:04:12Z",
  "data": {
    "scan_id": "scan_124",
    "target": "https://unreachable.example",
    "status": "failed",
    "error": "target_unreachable"
  }
}
subscription.updated

Fired when the account's plan or subscription status changes.

{
  "event": "subscription.updated",
  "created_at": "2026-06-03T10:04:12Z",
  "data": {
    "plan": "business",
    "previous_plan": "pro",
    "status": "active"
  }
}
usage.limit_reached

Fired when a plan quota (scans or requests) is exhausted.

{
  "event": "usage.limit_reached",
  "created_at": "2026-06-03T10:04:12Z",
  "data": {
    "resource": "scans",
    "limit": 500,
    "used": 500,
    "period_end": "2026-07-01T00:00:00Z"
  }
}

Verifying signatures

Every request includes a CodeSec-Signature header — an HMAC-SHA256 of the raw request body using your endpoint’s signing secret. Always verify it before trusting a payload.

import crypto from class="tok-str">"crypto";

export function verifySignature(rawBody, signature, secret) {
  const expected = crypto
    .createHmac(class="tok-str">"sha256", secret)
    .update(rawBody)
    .digest(class="tok-str">"hex");
  // Constant-time comparison
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}