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

# Webhook Events

> Reference for the GitHub webhook events Kolaria processes, how they are filtered, and what they trigger

Kolaria only accepts four GitHub event types on its webhook endpoint: `ping`, `push`, `release`, and `pull_request`. Every other event type is acknowledged with `200` and `"ignored": true` so GitHub does not retry it, and nothing else happens.

<Info>
  These are events Kolaria receives from GitHub. Kolaria does not emit its own webhook events; see [No outbound webhooks](/api/webhooks/overview#no-outbound-webhooks) for polling and streaming alternatives.
</Info>

## Processing order

<Steps>
  <Step title="Route check">
    The organization, integration, and repository IDs in the payload URL must exist, belong together, and the integration must be enabled.
  </Step>

  <Step title="Event type">
    `X-GitHub-Event` must be one of the four supported types, otherwise the delivery is logged and ignored.
  </Step>

  <Step title="Duplicate check">
    Deliveries with an `X-GitHub-Delivery` ID seen in the last 24 hours are skipped.
  </Step>

  <Step title="Signature">
    The body is verified against the repository's secret using `X-Hub-Signature-256`.
  </Step>

  <Step title="Filter">
    Each event type has its own rules (below). Events that do not pass are logged as filtered and return `200`.
  </Step>

  <Step title="Dispatch">
    Push and release events are saved as context for chat and matched against your event triggers. Merged pull requests are recorded as signals for Iris.
  </Step>
</Steps>

## Push

Sent when commits are pushed to the repository.

<ResponseField name="Event" type="string" required>
  `push`
</ResponseField>

<ResponseField name="Processed action" type="string" required>
  `pushed`
</ResponseField>

### Filtering

A push is processed only when both conditions hold:

<Check>`ref` is the repository's default branch (`refs/heads/{default_branch}`)</Check>
<Check>The payload contains at least one commit</Check>

Pushes to other branches, tag pushes, and empty pushes (for example a branch deletion) are filtered.

### Processed payload

This is the shape Kolaria passes to event triggers and returns under `processed` in the webhook response.

<CodeGroup>
  ```json Example theme={null}
  {
    "type": "push",
    "action": "pushed",
    "data": {
      "ref": "refs/heads/main",
      "branch": "main",
      "commits": [
        {
          "id": "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d",
          "message": "Add new feature",
          "author": {
            "name": "Jane Developer",
            "email": "jane@example.com",
            "username": "janedev"
          },
          "timestamp": "2026-09-01T10:30:00Z",
          "url": "https://github.com/owner/repo/commit/7fd1a60b01f91b314f59955a4e4d4e80d8edf11d"
        }
      ],
      "headCommit": {
        "id": "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d",
        "message": "Add new feature"
      }
    }
  }
  ```

  ```typescript Type theme={null}
  interface PushEvent {
    type: "push";
    action: "pushed";
    data: {
      ref: string;
      branch: string;
      commits: Array<{
        id: string;
        message: string;
        author: { name: string; email: string; username?: string };
        timestamp: string;
        url: string;
      }>;
      headCommit: { id: string; message: string } | null;
    };
  }
  ```
</CodeGroup>

## Release

Sent when a release changes state.

<ResponseField name="Event" type="string" required>
  `release`
</ResponseField>

<ResponseField name="Processed actions" type="string" required>
  `published` or `prereleased`
</ResponseField>

### Filtering

<Check>GitHub's `action` is `published` or `prereleased`</Check>
<Check>The release is not a draft</Check>

`created`, `edited`, `deleted`, `released`, and `unpublished` actions are filtered. Draft releases never pass, so publishing a draft is processed once, when GitHub sends `published`.

### Processed payload

<CodeGroup>
  ```json Example theme={null}
  {
    "type": "release",
    "action": "published",
    "data": {
      "tagName": "v1.2.0",
      "name": "Version 1.2.0",
      "body": "## What's Changed\n- New feature X\n- Bug fix Y",
      "prerelease": false,
      "draft": false,
      "publishedAt": "2026-09-01T14:30:00Z",
      "url": "https://github.com/owner/repo/releases/tag/v1.2.0"
    }
  }
  ```

  ```typescript Type theme={null}
  interface ReleaseEvent {
    type: "release";
    action: "published" | "prereleased";
    data: {
      tagName: string;
      name: string | null;
      body: string | null;
      prerelease: boolean;
      draft: boolean;
      publishedAt: string | null;
      url: string;
    };
  }
  ```
</CodeGroup>

## Pull request

Sent when a pull request is opened, closed, or updated. Kolaria only keeps merges.

<ResponseField name="Event" type="string" required>
  `pull_request`
</ResponseField>

<ResponseField name="Processed action" type="string" required>
  `merged`
</ResponseField>

### Filtering

<Check>GitHub's `action` is `closed`</Check>
<Check>`pull_request.merged` is `true`</Check>

Opened, synchronized, and closed-without-merge pull requests are filtered.

### Processed payload

<CodeGroup>
  ```json Example theme={null}
  {
    "type": "pull_request",
    "action": "merged",
    "data": {
      "number": 842,
      "title": "Add webhook retries",
      "body": "Adds exponential backoff to delivery.",
      "url": "https://github.com/owner/repo/pull/842",
      "mergedAt": "2026-09-01T09:12:00Z",
      "mergeCommitSha": "0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d",
      "author": "janedev",
      "baseBranch": "main"
    }
  }
  ```

  ```typescript Type theme={null}
  interface PullRequestEvent {
    type: "pull_request";
    action: "merged";
    data: {
      number: number;
      title: string;
      body: string | null;
      url: string;
      mergedAt: string | null;
      mergeCommitSha: string | null;
      author: string | null;
      baseBranch: string | null;
    };
  }
  ```
</CodeGroup>

<Note>
  Merged pull requests feed Iris signals only. They are not stored as chat context and do not fire event triggers; event triggers can only subscribe to `push` and `release`.
</Note>

## Ping

Sent by GitHub when you save the webhook or click **Redeliver** on the ping in your webhook settings.

<ResponseField name="Event" type="string" required>
  `ping`
</ResponseField>

Ping deliveries are signature-checked, logged, and answered with:

```json theme={null}
{
  "message": "Pong! Webhook configured successfully",
  "event": "ping",
  "delivery": "12345678-1234-1234-1234-123456789abc"
}
```

They do not trigger any workflow.

## Event triggers

Push and release events are matched against enabled event triggers whose targets include the repository. The trigger's `sourceConfig` decides which events fire it:

<CodeGroup>
  ```json Pushes and releases theme={null}
  {
    "sourceType": "github_webhook",
    "sourceConfig": {
      "eventTypes": ["push", "release"],
      "includePreReleases": true
    }
  }
  ```

  ```json Releases only, no pre-releases theme={null}
  {
    "sourceType": "github_webhook",
    "sourceConfig": {
      "eventTypes": ["release"],
      "includePreReleases": false
    }
  }
  ```
</CodeGroup>

* `eventTypes` accepts `push` and `release`. Triggers created through the API must list at least one.
* `includePreReleases` defaults to `true`. When `false`, `prereleased` events are skipped for that trigger.
* Each matching trigger starts one generation run per delivery. The run is keyed by trigger ID and delivery ID, so a redelivered event does not start a second run.

See [Event triggers](/automation/event-based) for creating and managing triggers in the dashboard.

## Log entries

Each delivery writes one entry to **Settings**, then **Logs**. The `integrationType` is `github`, `direction` is `incoming`, and `referenceId` is the `X-GitHub-Delivery` ID.

<ResponseField name="title" type="string" required>
  What happened, for example `Processed release event`, `Filtered push event`, `Unsupported event type: issues`, `Invalid webhook signature`, or `Webhook ping received`
</ResponseField>

<ResponseField name="status" type="string" required>
  `success` for processed, filtered, ignored, and ping deliveries; `failed` for rejected ones
</ResponseField>

<ResponseField name="statusCode" type="number">
  The HTTP status Kolaria returned to GitHub
</ResponseField>

<ResponseField name="errorMessage" type="string">
  Set on failed entries, for example `Missing X-Hub-Signature-256 header`
</ResponseField>

<ResponseField name="payload" type="object">
  For processed events: `event`, `action`, and the processed `data`. For filtered events: `event`, `action`, and `filtered: true`. For unsupported event types: `event` and `ignored: true`.
</ResponseField>

<CodeGroup>
  ```json Processed theme={null}
  {
    "id": "log_a1b2c3d4",
    "referenceId": "12345678-1234-1234-1234-123456789abc",
    "title": "Processed push event",
    "integrationType": "github",
    "direction": "incoming",
    "status": "success",
    "statusCode": 200,
    "errorMessage": null,
    "payload": {
      "event": "push",
      "action": "pushed",
      "data": {
        "ref": "refs/heads/main",
        "branch": "main",
        "commits": [
          {
            "id": "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d",
            "message": "Add new feature",
            "author": { "name": "Jane Developer", "email": "jane@example.com", "username": "janedev" },
            "timestamp": "2026-09-01T10:30:00Z",
            "url": "https://github.com/owner/repo/commit/7fd1a60b01f91b314f59955a4e4d4e80d8edf11d"
          }
        ],
        "headCommit": { "id": "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", "message": "Add new feature" }
      }
    },
    "createdAt": "2026-09-01T10:30:00.000Z"
  }
  ```

  ```json Failed theme={null}
  {
    "id": "log_x9y8z7w6",
    "referenceId": "87654321-4321-4321-4321-cba987654321",
    "title": "Invalid webhook signature",
    "integrationType": "github",
    "direction": "incoming",
    "status": "failed",
    "statusCode": 401,
    "errorMessage": "Invalid webhook signature",
    "payload": null,
    "createdAt": "2026-09-01T10:35:00.000Z"
  }
  ```

  ```json Filtered theme={null}
  {
    "id": "log_m5n6o7p8",
    "referenceId": "11112222-3333-4444-5555-666677778888",
    "title": "Filtered push event",
    "integrationType": "github",
    "direction": "incoming",
    "status": "success",
    "statusCode": 200,
    "errorMessage": null,
    "payload": { "event": "push", "action": "", "filtered": true },
    "createdAt": "2026-09-01T10:40:00.000Z"
  }
  ```
</CodeGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Webhooks overview" icon="webhook" href="/api/webhooks/overview">
    Payload URL, secret, security checks, and polling alternatives
  </Card>

  <Card title="Configure triggers" icon="bolt" href="/automation/event-based">
    Generate content automatically from push and release events
  </Card>
</CardGroup>
