/webhooks endpoints with the webhooks:read and webhooks:manage scopes.
Event Types
Routing models
Subscription routing
Subscription routing
The webhook lists the event type in its
eventTypes array. Every active webhook in scope receives the event.Scope resolution covers the incident’s own account plus any managing service provider accounts. A service provider webhook with a non-empty monitoredAccountIds list only receives events from the accounts it lists; an empty list means all managed accounts.Externally configured routing
Externally configured routing
Subscribing alone does not opt a webhook in. An owning entity has to name the webhook explicitly. Today this applies only to
agent.investigation.completed.v1, where an Agent Configuration’s classification card selects the target webhook.The webhook must also keep agent.investigation.completed.v1 in its eventTypes. If it is unsubscribed while still bound to a classification card, the delivery is recorded as Failed in the delivery log rather than dropped silently.Manual routing
Manual routing
webhook.test.v1 is only produced by the Send test action against one specific webhook. It is not a subscribable event.The incident Trigger webhook action is also manual, but it reuses incident.created.v1 so that existing receivers process it without code changes. Subscription matching is bypassed for that fire, though monitoredAccountIds is still enforced.The Delivery Envelope
Every event, regardless of type, is delivered as the same outer envelope. The event-specific schema lives underdata.
All payload property names are camelCase.
Request Headers
Verifying the Signature
The signature covers the timestamp and the exact raw request body:signing_key is the secret shown once when the webhook was created, unless you supplied your own signing token override when setting bearer-token credentials, in which case it is that token.
webhook.test.v1
A synthetic connectivity check, sent only by the Send test action on a single webhook. It carries X-CF-Test: true and isTest: true, and is signed exactly like a live event, so you can validate your verification code end to end before any real traffic arrives.
The payload mirrors the incident.created.v1 shape with fixed sample values.
Test deliveries are excluded from the auto-disable circuit breaker, so a failing test never takes a live webhook offline.
incident.created.v1
Fires when a new incident is ingested into a workspace the webhook monitors. The same event type is emitted by the incident Trigger webhook action so that receivers do not need a separate code path for a manually replayed incident.
Fields
Null fields are omitted from this payload rather than serialized as
null. Treat a missing owner or lastActivityAt as absent.incident.closed.v1
Fires when an incident reaches Closed, whichever route got it there: the portal, a bulk close, the AI agent, or the public API. Closures performed directly in the vendor’s own console are also picked up by reconciliation and delivered here, distinguished by closedBy.origin.
Fields
gamebook.run.v1
Fires when a Gamebook is dispatched to the executor against an incident, whether an analyst started it from the portal or public API, or the AI agent did.
Gamebooks awaiting approval do not fire this event while queued. The event is emitted when the run is actually dispatched.
Fields
agent.investigation.completed.v1
Fires once per investigation, when a Security Delivery Agent completes and reaches a classification whose card has a webhook custom action configured.
This event is configured per classification on an Agent Configuration card, not as a broadcast subscription. Set it up under Configuring Security Delivery Agents by enabling Advanced mode and choosing a webhook as the custom action for a classification. Full walkthrough and troubleshooting: Agent Investigation Completed Webhook.
Fields
Delivery Rules
These apply to every event type.Retries
Delivery is at-least-once. A failed attempt is retried with a fixed backoff, up to 10 attempts within a 5 minute window from the first attempt. Whichever limit is hit first ends the retry budget and the event is dead-lettered.
Retries are triggered by HTTP
408, 429, 500, 502, 503, and 504, and by connection or timeout errors. Any other non-success status is treated as a permanent failure and is not retried.
A Retry-After header is honored when it is longer than the scheduled backoff, clamped to the 5 minute retry window.
Event IDs
incident.created.v1 and incident.closed.v1 and gamebook.run.v1 derive a deterministic event ID from the underlying subject, so a republished event produces the same ID and can be deduplicated. Test events and manually triggered incident fires get a fresh ID per fire, which is what distinguishes a manual replay from the original automatic event.
Auto-disable
If 5 or more distinct incidents fail final delivery to the same webhook within a rolling 24 hours, the webhook is automatically disabled and stops receiving events. Test deliveries never count toward this threshold. Re-enable it withPOST /webhooks/{id}/enable or from the webhook detail page in the portal, after fixing the endpoint.
Requirements for your endpoint
- Must be reachable over HTTPS. Plain HTTP, localhost, and private network addresses are rejected at configuration time.
- Must respond within 30 seconds. Acknowledge with a 2xx immediately and do the real work asynchronously.
- Response bodies are read up to 1 MB for the delivery log; anything larger is truncated.
- Should default-ignore unknown values of
X-CF-Schemaso new event types do not break your handler.
Subscribing
Set the event types when you create or update a webhook. At least one is required.webhook.test.v1 is not subscribable. agent.investigation.completed.v1 must be listed here and selected on an Agent Configuration classification card before it delivers anything.
Delivery outcomes for every event are visible per webhook under Settings → Developer Integrations, and through GET /webhooks/{id}/delivery-logs.
Questions about webhook events? Contact us at support@contraforce.com.