# Gitea Webhooks

## When to Use This Skill

* How do I receive Gitea webhooks?
* How do I verify the `X-Gitea-Signature` header?
* Why is my Gitea webhook signature verification failing?
* How do I handle `push`, `pull_request`, `issues`, `issue_comment`, `create`, `delete` or `release` events from Gitea?
* Why do Gitea webhooks sent as `application/x-www-form-urlencoded` fail verification?

## Verification (core)

Gitea signs the **JSON payload** with HMAC-SHA256 keyed on the webhook **Secret**. That payload is the raw request body only for `POST` + `application/json`, so configure the webhook that way. `X-Gitea-Signature` is the bare lowercase hex digest (no `sha256=` prefix). If no secret is configured, the header is still sent but empty, so reject an empty signature. Gitea also sends the GitHub-style `X-Hub-Signature-256` (`sha256=<hex>`) with the same digest; this skill verifies `X-Gitea-Signature`.

Node:

```javascript
const crypto = require('crypto');

function verify(rawBody, signature, secret) {
  if (!signature || !secret) return false; // empty header = no secret configured
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  try {
    return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
  } catch {
    return false; // length mismatch
  }
}

```

Python:

```python
import hmac, hashlib

def verify(raw_body: bytes, signature: str, secret: str) -> bool:
    if not signature or not secret:
        return False
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(signature.encode(), expected.encode())

```

Use `POST` with `application/json`, read the raw bytes, and parse only after verifying. Gitea can also send form-encoded deliveries (`payload=<url-encoded JSON>`) or `GET` deliveries (payload in the query string), but the signature still covers the JSON payload rather than the bytes you receive, so those never verify against the request body.

> **For complete handlers with route wiring, event dispatch, and tests**, see:
> 
> * [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/gitea-webhooks/examples/express/)
> * [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/gitea-webhooks/examples/nextjs/)
> * [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/gitea-webhooks/examples/fastapi/)

## Common Event Types

The event name is in the `X-Gitea-Event` header (not the body).

| Event | Description |
| --- | --- |
| `push` | Commits pushed to a branch or tag |
| `pull_request` | Pull request opened, closed, reopened, edited, deleted |
| `issues` | Issue opened, closed, reopened, edited, deleted |
| `issue_comment` | Comment on an issue |
| `create` | Branch or tag created |
| `delete` | Branch or tag deleted |
| `release` | Release published, updated, deleted |

Other events include `fork`, `wiki`, `repository`, `package`, `status`, `workflow_run` and `workflow_job`. `X-Gitea-Event-Type` carries the more specific trigger (e.g. `issue_assign`).

> **Full event reference**: [Gitea webhooks](https://docs.gitea.com/usage/webhooks)

## Important Headers

| Header | Description |
| --- | --- |
| `X-Gitea-Signature` | Hex HMAC-SHA256 of the JSON payload, the raw body for `POST` + JSON (empty if no secret) |
| `X-Hub-Signature-256` | Same digest as `sha256=<hex>` (GitHub-compatible) |
| `X-Gitea-Event` | Event name (`push`, `issues`, ...) |
| `X-Gitea-Event-Type` | Specific trigger, e.g. `issue_assign` |
| `X-Gitea-Delivery` | Unique delivery UUID for this attempt |

## Environment Variables

```bash
GITEA_WEBHOOK_SECRET=your_webhook_secret   # The "Secret" field of the Gitea webhook

```

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 gitea --path /webhooks/gitea

```

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/gitea-webhooks/references/overview.md) - Gitea webhook concepts and events
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/gitea-webhooks/references/setup.md) - Configuration guide
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/gitea-webhooks/references/verification.md) - Signature verification details