Skip to content

Webhook payloads

Reference for the JSON bodies posted to your configured outbound webhook. For setup and signature verification see the Outbound webhook guide.

Common envelope

Every event uses the same outer shape:

{
  "event": "<event_type>",
  "delivered_at": "<ISO-8601 UTC>",
  "client_slug": "<your account slug>",
  "finding": { ... }
}
  • event — one of the event types below.
  • delivered_at — when CredWatch sent the request, not when the underlying state change happened. The finding itself contains its own timestamps.
  • client_slug — useful if your endpoint receives webhooks from multiple CredWatch accounts (rare but possible for MSPs).
  • finding — full finding object, identical shape to what the GET /api/v1/findings/{id} returns.

Event types

finding.new

Fires after the validation worker has tested a freshly-detected finding against the issuing service. The event includes the validation_status (valid, invalid, unvalidated, or unreachable) and validation_confidence so your handler can filter on certainty.

{
  "event": "finding.new",
  "delivered_at": "2026-05-21T14:33:12Z",
  "client_slug": "acme",
  "finding": {
    "id": "a3f8c2d1-b4e5-46f0-9a8b-1c2d3e4f5a6b",
    "status": "active",
    "validation_status": "valid",
    "validation_confidence": "high",
    "composite_score": 87,
    "source_type": "repo",
    "source_visibility": "public",
    "source_url": "https://github.com/acme/web/blob/abc/src/config.ts#L42",
    "repo_full_name": "acme/web",
    "file_path": "src/config.ts",
    "line_number": 42,
    "matched_text": "sk-a1****cd34",
    "pattern": {
      "name": "OpenAI API Key",
      "secret_type": "openai"
    },
    "first_seen_at": "2026-05-21T14:30:01Z",
    "last_seen_at": "2026-05-21T14:30:01Z",
    "seen_count": 1
  }
}

This is the primary signal — fires for every new finding once validation has run, regardless of score. If you only want to act on high-severity confirmed leaks, filter on validation_status == "valid" and composite_score >= 80 in your handler.

Use this to: import into a SIEM, notify a custom Slack channel, file a ticket in a tracker we don't natively support, kick off an automated rotation workflow.

finding.resolved

Fires when a finding transitions to resolved — either manually in the portal/API, or auto-resolved on rescan when CredWatch confirms the credential is gone.

{
  "event": "finding.resolved",
  "delivered_at": "2026-05-21T16:02:08Z",
  "client_slug": "acme",
  "finding": {
    "id": "a3f8c2d1-b4e5-46f0-9a8b-1c2d3e4f5a6b",
    "status": "resolved",
    "resolved_at": "2026-05-21T16:02:05Z",
    "resolution_note": "Rotated key, force-pushed to remove commit",
    "resolution_evidence": {
      "auto_resolved": false,
      "resolved_by": "[email protected]"
    },
    "validation_status": "invalid",
    "composite_score": 87,
    "source_url": "https://github.com/acme/web/blob/abc/src/config.ts#L42",
    "matched_text": "sk-a1****cd34",
    "pattern": {
      "name": "OpenAI API Key",
      "secret_type": "openai"
    }
  }
}

Use this to: close the corresponding incident in your tracker, update internal compliance dashboards, post a "resolved" message into Slack.

finding.false_positive

Fires when a finding is marked as a false positive in the portal or via the API.

{
  "event": "finding.false_positive",
  "delivered_at": "2026-05-21T15:44:00Z",
  "client_slug": "acme",
  "finding": {
    "id": "a3f8c2d1-b4e5-46f0-9a8b-1c2d3e4f5a6b",
    "status": "false_positive",
    "source_url": "...",
    "pattern": {"name": "Generic API Key", "secret_type": "generic"}
  }
}

Use this to: prune your local copy of CredWatch data, train internal models on which matches are noise.

Headers

POST /your-endpoint HTTP/1.1
Content-Type: application/json
X-CredWatch-Signature: sha256=8f4a3b2c...
User-Agent: CredWatch-Webhook/1.0
Header Use
X-CredWatch-Signature HMAC-SHA256 of the raw body with your webhook secret. Verify.
User-Agent Always CredWatch-Webhook/1.0. Optional to check.
Content-Type Always application/json.

Delivery semantics

  • At most once — we do not retry on failure.
  • Timeout — 10 seconds. Slower endpoints will time out and the event is dropped.
  • Ordering — not guaranteed. A finding.resolved event for one finding may arrive before the finding.new event for another.

For critical workflows, backstop the webhook with a periodic GET /api/v1/findings pull.

Securing your endpoint

Beyond signature verification, defence-in-depth:

  • IP allowlist the CredWatch egress IP (we publish it; contact support if you need it).
  • Reject events with delivered_at older than 5 minutes to prevent replay attacks.
  • Log all received events with their signature and verification result for audit.