# Receive GitHub webhooks

Set up a GitHub repository or organisation webhook behind Webhooker, verify the X-Hub-Signature-256 HMAC with your webhook secret, and route events by type.

Source: https://docs.webhooker.eu/tutorials/github/

## Before you start

- Admin rights on the repository or organisation.
- A secret you generate yourself — GitHub does not create one for you:

  ```bash
  openssl rand -hex 32
  ```

## 1. Create the source

**Sources → Create source**, name it after the repository, and copy the ingest
URL.

## 2. Add the webhook in GitHub

Repository **Settings → Webhooks → Add webhook** (or the same screen under an
organisation's settings):

- **Payload URL** — the ingest URL.
- **Content type** — `application/json`. Webhooker accepts form encoding too,
  but JSON is what makes filters on `body.…` work.
- **Secret** — the value you generated above.
- **SSL verification** — enabled.
- **Events** — "Just the push event", or **Let me select individual events** for
  pull requests, issues, releases and the rest.

## 3. Turn on verification

In Webhooker: **Settings → Authenticate inbound requests** → method **GitHub** →
paste the same secret → save.

GitHub signs the body with HMAC-SHA256 and sends it as `X-Hub-Signature-256`.
If you verify the same header in your own handler,
[the GitHub signature scheme step by step](https://webhooker.eu/blog/verify-github-webhook-signature)
has the code and the constant-time comparison it needs.
There is no timestamp in the scheme, so there is no freshness check.

## 4. Confirm the ping

GitHub sends a `ping` event the moment you save the webhook. It appears in the
live tail as `verified`, and GitHub's **Recent Deliveries** tab shows `200`.

## 5. Forward it to your app

**Destinations → Add destination → Create new**, your handler's URL, **Sign
outbound requests** on. Save.

## 6. Route by event type

GitHub puts the event name in a header, so filter on it:

```json
{
  "operator": "and",
  "rules": [
    { "path": "headers.x-github-event", "op": "in", "value": ["push", "pull_request"] }
  ]
}
```

To narrow pushes to one branch, add a body rule:

```json
{ "path": "body.ref", "op": "eq", "value": "refs/heads/main" }
```

Remember that the sender's headers are not forwarded to your endpoint — if your
handler needs the event type, filter on it per gateway, or read it from the
payload.

## Verify it works

1. GitHub **Recent Deliveries** shows `200`.
2. The Webhooker event is `verified`.
3. The delivery is `succeeded`.

## Troubleshooting

| Symptom | Cause |
| --- | --- |
| GitHub shows `401` | The secrets differ. Re-enter it in Webhooker in full. |
| Events arrive but filters never match | The content type is `application/x-www-form-urlencoded`. Switch GitHub to `application/json`. |
| `ping` arrives, nothing else | The webhook subscribes to no events you trigger. Check the event selection. |
| Some events are huge | A push with many commits can exceed 1 MiB and is rejected with `413`. Subscribe to fewer event types or handle the API call instead. |
