> ## Documentation Index
> Fetch the complete documentation index at: https://docs.contraforce.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Setting Up Webhooks

> Create, secure, test, and manage outbound webhooks that send ContraForce incident and Gamebook events to your own systems.

A webhook sends a signed HTTPS request to an endpoint you control every time a selected event happens in ContraForce, such as an incident being created, closed, or commented on. Use webhooks to push incidents into your ticketing system, SIEM, chat tools, or automation platform without polling the API.

<Info>
  **Who is this for?** Organization Admins and security engineers connecting ContraForce to an external system. For the payload of each event, see the [Webhook Event Reference](/api-reference/webhook-events).
</Info>

## Before you start

* You are signed in as an **Organization Admin**.
* You have an HTTPS endpoint that accepts `POST` requests and answers with a `2xx` status within 30 seconds. Plain HTTP, `localhost`, and private network addresses are rejected.
* You know how your endpoint expects to authenticate callers: no authentication, basic authentication, or a bearer token.

## Choose an authentication type

Every delivery is signed with an HMAC-SHA256 signature in the `X-CF-Signature` header, whichever option you pick. The authentication type adds an `Authorization` header on top of that signature for endpoints that require one.

| Authentication           | What ContraForce sends                                                           | Use it when                                                                               |
| ------------------------ | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| **No authentication**    | No `Authorization` header. The request is verified by its `X-CF-Signature` only. | Your endpoint verifies the signature itself, or it is a URL with a secret token built in. |
| **Basic authentication** | `Authorization: Basic <base64 of username:password>`                             | Your endpoint or gateway expects a username and password.                                 |
| **Bearer token**         | `Authorization: Bearer <token>`                                                  | Your endpoint or API gateway expects an API key or token.                                 |

## Create a webhook

<Steps>
  <Step title="Open the Developers tab">
    In the left navigation, click **Settings**, then select the **Developers** tab. The **Integrations** list shows your existing webhooks and service accounts.

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/01-developers-tab.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=ee3d27542e6c273e874356902f593b85" alt="Settings page with the Developers tab selected, showing the Integrations list and the Add integration button" width="2160" height="1350" data-path="images/webhooks/01-developers-tab.png" />
    </Frame>
  </Step>

  <Step title="Start a new webhook integration">
    Click **Add integration**. In the panel that opens, open the **Integration type** list and select **Webhook**.

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/02-integration-type.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=e0a1ada5860e1d5ea2df7b7a3526f6e7" alt="Add integration panel with the Integration type list open, showing Webhook and Service account" width="2160" height="1350" data-path="images/webhooks/02-integration-type.png" />
    </Frame>
  </Step>

  <Step title="Name the webhook and enter the endpoint URL">
    Under **Webhook details**, enter a **Name** that tells your team where the events go (for example, `SOC ticketing webhook`) and the **URL** of your endpoint, such as `https://hooks.company.example/contraforce`.

    Then open the **Authentication** list and choose the type your endpoint expects.

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/03-details-and-auth.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=5bbbe60f8a12b349364df2a60e828a1a" alt="Webhook details with Name and URL filled in and the Authentication list open, showing No authentication, Basic authentication, and Bearer token" width="960" height="692" data-path="images/webhooks/03-details-and-auth.png" />
    </Frame>
  </Step>

  <Step title="Enter the credentials for your authentication type">
    What you fill in depends on the type you picked.

    <Tabs>
      <Tab title="No authentication">
        Nothing else to enter. Verify the `X-CF-Signature` header on your endpoint so it only accepts requests from ContraForce.
      </Tab>

      <Tab title="Basic authentication">
        Enter the **Username** and **Password** your endpoint expects. Both are required.

        <Frame>
          <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/04-basic-auth.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=4c8480785c78a9b9e236bfa08777009f" alt="Basic authentication selected, with Username and Password fields" width="960" height="534" data-path="images/webhooks/04-basic-auth.png" />
        </Frame>
      </Tab>

      <Tab title="Bearer token">
        Enter the **Token** your endpoint expects. It is sent as `Authorization: Bearer <token>`.

        **Signing token** is optional. Leave it empty and ContraForce generates a signing secret for you when you save. Enter a value only if you want to supply the key used to sign `X-CF-Signature` yourself.

        <Frame>
          <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/05-bearer-token.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=7bfc1010c9b371e4563577bcd87c1d86" alt="Bearer token selected, with a required Token field and an optional Signing token field" width="960" height="534" data-path="images/webhooks/05-bearer-token.png" />
        </Frame>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Select the events to send">
    Under **Events**, turn on each event this webhook should receive. At least one is required.

    * Turn on **Webhook Test** if you want to use **Send test** later to check connectivity.
    * For close handling, pick **Incident Closed** *or* **Incident Status Changed**. A close fires both, so subscribing to both gives you two deliveries per close.

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/06-events.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=a646548c1c05a1ec976bab7c27f8653c" alt="Events list with Incident Created, Incident Closed, and Incident Comment Added turned on" width="960" height="1647" data-path="images/webhooks/06-events.png" />
    </Frame>

    <Tip>
      Click the info icon next to any event to see a sample payload exactly as your endpoint will receive it. Use **Copy JSON** to build and test your parser before any real event arrives.
    </Tip>

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/07-sample-payload.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=e2ed3d8e312ecab1409f345267ba2d9b" alt="Incident Created sample payload dialog showing the JSON envelope, with Copy JSON and Close buttons" width="1104" height="1334" data-path="images/webhooks/07-sample-payload.png" />
    </Frame>
  </Step>

  <Step title="Choose which workspaces the webhook covers">
    Under **Workspaces**, search for and add the customer workspaces this webhook should send events for. Leave the list empty to send events from **all** workspaces you manage, including ones you add later.

    The **Agent investigation completed** event is listed separately as **Owned by another flow**. You don't subscribe to it here: it is wired from an agent's classification card. See [Send agent verdicts to a webhook](#send-agent-verdicts-to-a-webhook).

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/08-agent-event-and-workspaces.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=520466f02ccd40f3fbc59ecdf825384c" alt="Owned by another flow callout for Agent investigation completed, and the Workspaces section with an empty workspace search" width="960" height="752" data-path="images/webhooks/08-agent-event-and-workspaces.png" />
    </Frame>
  </Step>

  <Step title="Save and copy the signing secret">
    Click **Save**. ContraForce shows the webhook's **signing secret** once. Copy it with the copy button and store it in your endpoint's secret store, then click **Done**.

    <Warning>
      The signing secret is not shown again after you close this dialog. If you lose it, open the webhook and click **Regenerate**, then update your endpoint with the new secret.
    </Warning>

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/09-signing-secret.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=ceb99b1d16070ef3c7121dbc25702b8a" alt="Webhook signing secret dialog with the secret value hidden, a copy button, and a Done button" width="864" height="525" data-path="images/webhooks/09-signing-secret.png" />
    </Frame>

    If you entered your own **Signing token** for a bearer-token webhook, the dialog tells you that token is used for signing instead.
  </Step>

  <Step title="Confirm the webhook is active">
    The new webhook appears in the **Integrations** list with the **Webhook** type and an **Active** status.

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/10-integration-list.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=7a84a7b2a7f6437404e1bacc1a4f9832" alt="Integrations list showing the new SOC ticketing webhook with Webhook type and Active status" width="2160" height="1350" data-path="images/webhooks/10-integration-list.png" />
    </Frame>
  </Step>
</Steps>

## Send a test and check the delivery

Test before you rely on the webhook, and again any time you change the endpoint or its credentials.

<Steps>
  <Step title="Open the webhook">
    In **Settings → Developers**, click the gear icon on the webhook's row. The **General** tab shows the endpoint, authentication, signing secret, event subscriptions, and workspaces.

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/11-details-general.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=cc13dbe123bb68321875a089c613c1d7" alt="Webhook details General tab with Pause and Delete buttons, the Endpoint section, the Authentication section with Update credentials, and the Signing secret section with Regenerate" width="1665" height="1461" data-path="images/webhooks/11-details-general.png" />
    </Frame>
  </Step>

  <Step title="Send a test event">
    Under **Event subscriptions**, click **Send test** on the **Webhook Test** row. A **Test webhook queued for delivery** message confirms the request was queued.

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/12-event-subscriptions.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=2c755d2d9d9e5944f69b7f4d3435798a" alt="Event subscriptions section with Webhook Test turned on and a Send test button" width="1665" height="495" data-path="images/webhooks/12-event-subscriptions.png" />
    </Frame>

    Test deliveries carry an `X-CF-Test: true` header and `"isTest": true` in the body, so your endpoint can tell them apart from real events.
  </Step>

  <Step title="Check the delivery log">
    Select the **Events** tab. Each delivery attempt is listed with its date, workspace, event type, and status. A test that reached your endpoint shows **Success**.

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/13-delivery-log.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=b26bd555a99aeb80542ae811327435f4" alt="Delivery events list showing a webhook.test.v1 delivery with Success status" width="1665" height="374" data-path="images/webhooks/13-delivery-log.png" />
    </Frame>
  </Step>

  <Step title="Inspect a delivery">
    Click the eye icon on a row to see the HTTP status code your endpoint returned, the latency, the attempt number, and any error message.

    <Frame>
      <img src="https://mintcdn.com/contraforce/-JmjqFAD1dEqopSD/images/webhooks/14-delivery-details.png?fit=max&auto=format&n=-JmjqFAD1dEqopSD&q=85&s=ec36d510f2d9a741e6cf4c748cad4f4d" alt="Event run details dialog showing webhook.test.v1, Success status, API response 200, latency 449 ms, and attempt 1" width="1104" height="884" data-path="images/webhooks/14-delivery-details.png" />
    </Frame>

    The delivery log stores delivery metadata only, not the body that was sent. For incident events, the details show the incident as it is now, fetched from the source. See [Delivery logs](/api-reference/webhook-events#delivery-logs).
  </Step>
</Steps>

## Manage an existing webhook

Everything below is on the webhook's **General** tab unless noted.

| To do this                                  | Do this                                                                                                                                              |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Stop deliveries temporarily                 | Click **Pause**. Click **Resume** to start again.                                                                                                    |
| Change the name, URL, events, or workspaces | Edit the field, then click **Save changes**.                                                                                                         |
| Rotate credentials                          | Click **Update credentials** in the **Authentication** section. Existing credentials are never shown.                                                |
| Rotate the signing secret                   | Click **Regenerate** in the **Signing secret** section, then update your endpoint with the new secret.                                               |
| Re-enable an auto-disabled webhook          | Fix the endpoint, then click **Enable**. A webhook is disabled automatically after 5 or more distinct incidents fail final delivery within 24 hours. |
| Resend a failed incident delivery           | On the **Events** tab, open the failed entry and redeliver it. See [Redelivery](/api-reference/webhook-events#redelivery).                           |
| Remove the webhook                          | Click **Delete**.                                                                                                                                    |

## Send agent verdicts to a webhook

The **Agent investigation completed** event (`agent.investigation.completed.v1`) is not a subscription. It fires only when an agent's classification card names this webhook as its custom action. You can create the webhook from the card itself, and it is subscribed to the event automatically when you save.

See [Configuring Security Delivery Agents](/guides/getting-started/configuring-security-delivery-agents) to set it up, and [Agent Investigation Completed Webhook](/guides/agent-center/agent-investigation-webhook) for the payload.

## Troubleshooting

| Symptom                                            | Likely cause                                                              | Fix                                                                                                                                                |
| -------------------------------------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Save** reports the URL is invalid                | The URL is plain HTTP, `localhost`, or a private address                  | Use a public HTTPS endpoint.                                                                                                                       |
| Test delivery shows **Failed** with `401` or `403` | Your endpoint rejected the credentials                                    | Click **Update credentials** and re-enter them, then send another test.                                                                            |
| Delivery shows **Failed** with a timeout           | Your endpoint took longer than 30 seconds                                 | Return a `2xx` immediately and process the event asynchronously.                                                                                   |
| Your endpoint rejects the signature                | The wrong secret, or the body was parsed before verifying                 | Verify against the raw request body with the current secret. See [Verifying the Signature](/api-reference/webhook-events#verifying-the-signature). |
| No events arrive, but tests succeed                | The event is not turned on, or the workspace is not in the webhook's list | Check **Event subscriptions** and **Workspaces** on the **General** tab.                                                                           |
| The webhook status is **Disabled**                 | Repeated final delivery failures triggered auto-disable                   | Fix the endpoint, send a test, then click **Enable**.                                                                                              |

## Related guides

<CardGroup cols={2}>
  <Card title="Webhook Event Reference" icon="webhook" href="/api-reference/webhook-events">
    Every event type, the delivery envelope, headers, retries, and signature verification.
  </Card>

  <Card title="Agent Investigation Completed Webhook" icon="robot" href="/guides/agent-center/agent-investigation-webhook">
    Receive and verify agent verdicts from a classification card.
  </Card>

  <Card title="Service Accounts" icon="key" href="/guides/general-support/service-accounts">
    Call the ContraForce API from your automation.
  </Card>

  <Card title="Incident Classification" icon="tags" href="/concepts/incident-classification">
    The classifications and reasons carried on closed incidents.
  </Card>
</CardGroup>

<Note>
  Need help? Contact [support@contraforce.com](mailto:support@contraforce.com).
</Note>
