> For the complete documentation index, see [llms.txt](https://docs.stepsecurity.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stepsecurity.io/administration/admin-console/integrations/webhook-integration.md).

# Webhook Integration

StepSecurity's Webhook Integration sends security events from your tenant to HTTP endpoints you control, so you can feed a SIEM, an incident response tool, or a custom pipeline in real time.

You can configure up to **ten webhooks per customer**. Each webhook has its own endpoint, its own connection settings, and its own event subscriptions, so you can route different kinds of events to different destinations. For example, you can send runtime detections to your SIEM while sending API audit logs to a separate compliance pipeline.

### Prerequisites

Before setting up the Webhook Integration:

* You must be an **Admin** in your StepSecurity organization.
* You need at least one endpoint that accepts `POST` requests over HTTPS and can parse JSON payloads. `PUT` and `PATCH` can be selected instead if your receiver requires them.
* To subscribe a webhook to **API Audit Logs**, audit logging must be enabled for your tenant. See [Audit Logs](/administration/admin-console/audit-logs.md).

### How webhooks are organized

The Webhook Integration page has one master **Enable Webhook Integration** toggle followed by a list of webhooks. The master toggle controls the integration as a whole. No webhook delivers events while it is off.

Each webhook is an independent configuration with its own:

* **Connection settings**, including endpoint URL, HTTP method, headers, and message format
* **Event subscriptions**, which decide what kinds of events this endpoint receives
* **Repository selection**, which decides which repositories this endpoint receives repository-scoped events for
* **Name**, used to tell webhooks apart once you have more than one

A single webhook subscribes to as many event types as you want, so splitting streams across endpoints is a choice rather than a requirement.

The page renders differently depending on how many webhooks you have:

* With **one webhook**, the section is titled **Webhook** and its connection settings, event subscriptions, and repository selection appear directly on the page.
* With **more than one**, each webhook becomes a collapsible card. Collapsed cards show the name, the endpoint URL, and a chip for each subscribed event type, so you can see the routing at a glance. A card with no endpoint set yet shows **No URL configured**.

### Set up a webhook

**Step 1: Navigate to your StepSecurity dashboard and Click "Admin console"**

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2Fw8PkecL5lqQy5sz7lGS9%2FScreenshot%202026-09-07%20at%2013.30.05.png?alt=media&amp;token=a4347431-b25c-4728-9aeb-a9074a290252" alt=""><figcaption></figcaption></figure>

**Step 2: Click "Integrations"**

![](https://ajeuwbhvhr.cloudimg.io/https://colony-recorder.s3.amazonaws.com/files/2025-05-30/7da0fc1e-5a59-432a-9595-600f6637e310/ascreenshot.jpeg?tl_px=130,0\&br_px=2882,1538\&force_format=jpeg\&q=100\&width=1120.0\&wat=1\&wat_opacity=1\&wat_gravity=northwest\&wat_url=https://colony-recorder.s3.amazonaws.com/images/watermarks/8B5CF6_standard.png\&wat_pad=524,182)

**Step 3: Click "Enable Webhook Integration**

![](https://ajeuwbhvhr.cloudimg.io/https://colony-recorder.s3.amazonaws.com/files/2025-05-30/1cec2a44-92c3-4a9f-8692-7c5ecb928783/ascreenshot.jpeg?tl_px=272,0\&br_px=3024,1538\&force_format=jpeg\&q=100\&width=1120.0\&wat=1\&wat_opacity=1\&wat_gravity=northwest\&wat_url=https://colony-recorder.s3.amazonaws.com/images/watermarks/8B5CF6_standard.png\&wat_pad=1038,112)

**Step 4:** Fill in **Connection Settings**, then click **Test Connection** to check that your endpoint is reachable

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FBLBij15MT1UXAvPopcHG%2FScreenshot%202026-09-07%20at%2014.06.10.png?alt=media&amp;token=97e5a240-3cb4-47a6-a71c-e4611aad7912" alt=""><figcaption></figcaption></figure>

**Step 5:** Under **Events to Subscribe**, turn on the event types this endpoint should receive.

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FqEGv51MQ1gylNLjlCNLx%2FScreenshot%202026-09-07%20at%2014.07.04.png?alt=media&amp;token=c1578d49-7041-47f7-83e6-d138f9d72828" alt=""><figcaption></figcaption></figure>

<figure><img src="broken://files/KhOft7PUzU7pNngPxQC3" alt=""><figcaption></figcaption></figure>

**Step 6:** Under **Repository Selection**, choose the repositories to send repository-scoped events for.

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FSaiUnu3KlTgBuUQKZiyg%2FScreenshot%202026-09-07%20at%2014.07.42.png?alt=media&amp;token=3710102b-4632-488b-bf94-c48e41157841" alt=""><figcaption></figcaption></figure>

<figure><img src="broken://files/MuUPhuSlE0qWS5y8kBXU" alt=""><figcaption></figcaption></figure>

**Step 7:** Click **Save changes**.

To add another destination, click **+ Add Webhook** and repeat steps 4 through 6 for the new card. Give each card a **Name** that describes its destination, for example `Splunk detections` or `Compliance audit pipeline`, then save once for all of them.

{% hint style="info" %}
**Save changes** applies every webhook on the page at once, not just the card you were editing.
{% endhint %}

### Configuration reference

#### **Connection Settings**

| Field              | Description                                                                                                                                                                                                                                                                   |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Webhook URL**    | The HTTPS endpoint events are delivered to. The field is validated, and an invalid value is rejected with `Please enter a valid URL`.                                                                                                                                         |
| **HTTP Method**    | The HTTP method used for delivery. Choose `POST`, `PUT`, or `PATCH`. `POST` is the default and is what most receivers expect.                                                                                                                                                 |
| **Headers**        | Key and value pairs sent with every request. Use these for authentication headers and for `content-type`. Click **+ Add Header** to add a row, or the red **X** to remove one. Sensitive values such as an `Authorization` token are masked, with an eye icon to reveal them. |
| **Message Format** | Either `Raw` or `Envelope`. See below.                                                                                                                                                                                                                                        |

#### **Message format**

**Raw** sends the event payload as StepSecurity generates it, with no wrapping.

**Envelope** wraps the payload in a JSON structure you define in the **Template** field. Use this when your receiver expects a specific shape, for example a SIEM that requires particular top-level keys.

The default template is:

```json
{
  "id": "{{.ID}}",
  "name": "{{.Name}}",
  "alert_timestamp": "{{.Timestamp}}",
  "event_type": "{{.EventType}}",
  "customer": "{{.Customer}}",
  "owner": "{{.Owner}}",
  "repo": "{{.Repo}}",
  "repository": "{{.Repository}}",
  "run_id": "{{.RunID}}",
  "server": "{{.Server}}",
  "data": {{.Data}}
}
```

The following variables are available. You can combine them with static text.

| Variable          | Description                                                                        |
| ----------------- | ---------------------------------------------------------------------------------- |
| `{{.ID}}`         | Unique identifier for the webhook event (UUID)                                     |
| `{{.Name}}`       | Short event title, for example `Multiple alerts for owner/repo (run 12345)`        |
| `{{.Timestamp}}`  | Timestamp when the event was generated, in RFC 3339 format                         |
| `{{.EventType}}`  | Type of event, for example `insight`, `detection`, or `secure-registry-audit-log`  |
| `{{.Customer}}`   | Customer identifier                                                                |
| `{{.Owner}}`      | Repository owner or organization                                                   |
| `{{.Repo}}`       | Repository name                                                                    |
| `{{.Repository}}` | Full repository path (`owner/repo`)                                                |
| `{{.RunID}}`      | GitHub Actions run ID or GitLab pipeline ID                                        |
| `{{.Server}}`     | GitHub server name (GitHub Enterprise Server only)                                 |
| `{{.Data}}`       | The event payload itself, for example the insights, detections, or audit log array |

{% hint style="warning" %}
`{{.Data}}` is required. A template without it delivers metadata with no event content.
{% endhint %}

You do not have to keep the default keys. Any of the variables can be dropped, renamed, or mixed with static text to match what your receiver expects. For example:

```json
{
  "sent_by": "StepSecurity",
  "message": {{.Data}}
}
```

#### **Events to Subscribe**

Turn on the event types that this webhook should receive. Any combination is valid, so one endpoint can take insights and detections together while another takes audit logs only. A webhook with no event types selected does not deliver anything.

| Event type                     | What it sends                                                                                      | Sample payload                   |
| ------------------------------ | -------------------------------------------------------------------------------------------------- | -------------------------------- |
| **Insights**                   | Code security insights findings                                                                    | Insights Response                |
| **Detections**                 | Runtime detections                                                                                 | Sample Detection Events          |
| **Secure Registry Audit Logs** | Secure Registry package request audit logs                                                         | Secure Registry Audit Log Events |
| **API Audit Logs**             | StepSecurity API audit logs, as they are recorded. Requires audit logging enabled for your tenant. | API Audit Log Events             |

#### **Repository Selection**

Repository Selection controls which repositories a webhook receives **repository-scoped** events for, which means **Insights** and **Detections**.

* Pick an organization from the dropdown. The table below lists that organization's repositories, so switch organizations to reach the rest.
* Use the search box to narrow long lists.
* Select a repository's checkbox in the **Configuration Applied** column to include it.
* Turn on **Enable for all repositories** to apply the configuration to all current and future repositories. New repositories are then covered automatically, with no change needed here.

{% hint style="info" %}
Repository Selection has **no effect on Secure Registry Audit Logs or API Audit Logs**. Those events are tenant-scoped, so a webhook subscribed to them receives every event for the tenant regardless of which repositories are selected. This is why their payloads carry empty `owner`, `repo`, `repository`, and `run_id` fields.
{% endhint %}

### Routing patterns

Because each webhook subscribes independently, you can separate event streams by destination:

| Goal                                                              | How to configure it                                                                                                        |
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| Keep large insights payloads out of a detection alerting pipeline | One webhook subscribed to Detections only, a second subscribed to Insights only, each pointing at its own endpoint         |
| Send compliance evidence to a different team than security alerts | One webhook subscribed to API Audit Logs pointing at the compliance pipeline, another subscribed to Detections for the SOC |
| Give each receiver the payload shape it expects                   | Set **Message Format** per webhook, using `Envelope` with a tailored template where the receiver is strict                 |
| Scope one destination to a subset of repositories                 | Set Repository Selection per webhook, rather than filtering downstream                                                     |

### Webhook Delivery

Once configured, StepSecurity sends events to your endpoint as HTTP requests containing JSON payloads, using the method selected for that webhook. The examples below assume the default, `POST`.

#### **How delivery works**

* Each event is sent as a **single HTTP request** with `Content-Type: application/json`.
* The entire JSON payload is contained within one HTTP request body.
* For detections, each request represents **one workflow run** that triggered one or more detections. Multiple detections from the same workflow run are bundled together in a single payload inside the `data` array.
* Every webhook subscribed to an event type receives its own copy of that event, delivered independently. A failure at one endpoint does not affect the others.

#### **Payload structure**

Each webhook payload follows a parent and child structure. The top-level object contains metadata about the event group, and the `data` array contains the individual event objects.

| Field             | Type     | Description                                                           |
| ----------------- | -------- | --------------------------------------------------------------------- |
| `id`              | UUID     | Unique identifier for this alert group (parent ID)                    |
| `name`            | String   | Human-readable summary of the alert group                             |
| `alert_timestamp` | ISO 8601 | Timestamp when the alert was generated                                |
| `event_type`      | String   | Type of event, for example `detection` or `secure-registry-audit-log` |
| `customer`        | String   | Customer account identifier                                           |
| `owner`           | String   | GitHub organization or owner name                                     |
| `repo`            | String   | Repository name                                                       |
| `repository`      | String   | Full repository path (`owner/repo`)                                   |
| `run_id`          | String   | GitHub Actions workflow run ID                                        |
| `data`            | Array    | Array of individual event objects (see next section)                  |

**Example top-level payload:**

```json
{
  "id": "81d3597b-b8ca-4ac1-abf0-cc7a9961714d",
  "name": "Detections for workflow run 98765",
  "alert_timestamp": "2025-02-20T14:30:00Z",
  "event_type": "detection",
  "customer": "acme-corp",
  "owner": "acme",
  "repo": "api-service",
  "repository": "acme/api-service",
  "run_id": "98765",
  "data": [
    { "...detection object 1..." },
    { "...detection object 2..." }
  ]
}
```

For tenant-scoped event types, the repository fields are present but empty.

#### **Parent and child correlation**

Every webhook payload has a top-level `id` field that serves as the **parent identifier**. Each detection object within the `data` array includes a `parent_id` field that references this top-level `id`. This allows you to correlate all detections that originated from the same workflow run.

```
Top-level:   "id":        "81d3597b-b8ca-4ac1-abf0-cc7a9961714d"
Detection:   "parent_id": "81d3597b-b8ca-4ac1-abf0-cc7a9961714d"
```

### Detection object fields

Each object in the `data` array of a detection payload represents an individual detection. The following fields are common across all detection types:

| Field            | Type       | Description                                         |
| ---------------- | ---------- | --------------------------------------------------- |
| `id`             | String     | Detection type identifier (e.g., `"Reverse-Shell"`) |
| `event_id`       | UUID       | Unique ID for this specific detection event         |
| `parent_id`      | UUID       | References the top-level alert group `id`           |
| `type`           | String     | Detection type classification                       |
| `name`           | String     | Human-readable detection name                       |
| `run_id`         | String     | GitHub Actions run ID                               |
| `job_id`         | String     | GitHub Actions job ID                               |
| `job`            | String     | Job name within the workflow                        |
| `timestamp`      | Unix epoch | Detection timestamp (seconds since epoch)           |
| `detection`      | String     | Detection signature identifier                      |
| `html_url`       | URL        | Link to the detection in StepSecurity dashboard     |
| `is_resolved`    | Boolean    | Whether the detection has been resolved             |
| `is_suppressed`  | Boolean    | Whether the detection is suppressed                 |
| `process_events` | Array      | Process-level details (varies by detection type)    |

**Example detection object:**

```json
{
  "id": "Reverse-Shell",
  "event_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "parent_id": "81d3597b-b8ca-4ac1-abf0-cc7a9961714d",
  "type": "network",
  "name": "Reverse Shell Detected",
  "run_id": "98765",
  "job_id": "build-and-test",
  "job": "Build and Test",
  "timestamp": 1740062400,
  "detection": "reverse_shell_v2",
  "html_url": "https://app.stepsecurity.io/detections/f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "is_resolved": false,
  "is_suppressed": false,
  "process_events": []
}
```

> For complete payload examples for every event type, see [Sample Detection Events](/administration/admin-console/integrations/sample-detection-events.md).

***

### SIEM Integration

If you are forwarding StepSecurity webhooks to a SIEM (for example Splunk, Microsoft Sentinel, or Elastic), follow these guidelines to ensure events are ingested correctly.

**Separate endpoints by event type**

Insights payloads are significantly larger than detection payloads and are more likely to exceed default SIEM receiver size limits. Rather than sending everything to one receiver, give each event type its own webhook and its own endpoint. Each receiver can then be tuned, indexed, and size-limited independently, and a size problem in one stream does not affect the others.

A common arrangement is one webhook for Detections into the alerting index, one for Insights into a lower-priority index, and one for API Audit Logs into a compliance index.

**Understanding payload size**

Because multiple detections from a single workflow run are bundled into one webhook request, payload sizes vary. A single payload may contain anywhere from one to many detection objects in the `data` array.

**HTTP JSON receiver**

Configure your SIEM to accept webhooks via an HTTP or HTTPS endpoint that can receive JSON `POST` requests, or set the webhook's HTTP method to whichever of `PUT` or `PATCH` your receiver expects. Ensure your receiver is configured to read the **full HTTP request body** as a single JSON message, rather than splitting on newlines or fixed byte boundaries.

**Line breaking**

{% hint style="warning" %}
**Important:** Do not configure line breaking or message splitting on the raw HTTP body. Each request is one complete, self-contained JSON document. If your SIEM splits on newlines, the pretty-printed JSON will be broken across multiple events.
{% endhint %}

Configure your HTTP input to treat each request as a **single event**.

**Event flattening**

If your SIEM requires **one event per detection** rather than one event per workflow run, use your SIEM's JSON parsing or transformation pipeline to iterate over the `data` array and create individual events.

When flattening, carry forward the following parent fields into each individual event to preserve context:

* `id` (parent alert group ID)
* `customer`
* `owner`
* `repo`
* `repository`
* `run_id`

**Example: flattening logic (pseudocode)**

```json
for each detection in payload.data:
    event = detection
    event.alert_group_id = payload.id
    event.customer       = payload.customer
    event.owner          = payload.owner
    event.repo           = payload.repo
    event.repository     = payload.repository
    event.run_id         = payload.run_id
    emit(event)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.stepsecurity.io/administration/admin-console/integrations/webhook-integration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
