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

# Webhooks

> Configure webhooks to integrate Gitea with external services and automate workflows

## Overview

Webhooks allow you to build or set up integrations that subscribe to specific events in your Gitea repositories. When an event is triggered, Gitea sends an HTTP POST payload to the webhook's configured URL. Webhooks can be configured to trigger for specific events or all repository events.

## Webhook Types

Gitea supports multiple webhook formats for integration with various platforms:

* **Gitea** - Native Gitea webhook format
* **Gogs** - Gogs-compatible webhook format
* **Slack** - Slack notifications
* **Discord** - Discord channel notifications
* **DingTalk** - DingTalk group notifications
* **Telegram** - Telegram bot messages
* **Microsoft Teams** - Teams channel notifications
* **Feishu** - Feishu/Lark notifications
* **Matrix** - Matrix room notifications
* **WeCom** - WeChat Work notifications
* **Packagist** - Packagist package updates

## Event Types

Webhooks can be configured to trigger on the following events:

| Event                          | Description                                                    |
| ------------------------------ | -------------------------------------------------------------- |
| `create`                       | Branch or tag created                                          |
| `delete`                       | Branch or tag deleted                                          |
| `fork`                         | Repository forked                                              |
| `push`                         | Git push to repository                                         |
| `issues`                       | Issue opened, closed, reopened, edited, or deleted             |
| `issue_assign`                 | Issue assigned or unassigned                                   |
| `issue_label`                  | Issue labels updated                                           |
| `issue_milestone`              | Issue milestone changed                                        |
| `issue_comment`                | Comment created, edited, or deleted on issue                   |
| `pull_request`                 | Pull request opened, closed, reopened, edited, or synchronized |
| `pull_request_assign`          | Pull request assigned or unassigned                            |
| `pull_request_label`           | Pull request labels updated                                    |
| `pull_request_milestone`       | Pull request milestone changed                                 |
| `pull_request_comment`         | Comment on pull request                                        |
| `pull_request_review_approved` | Pull request approved                                          |
| `pull_request_review_rejected` | Pull request rejected                                          |
| `pull_request_review_comment`  | Review comment on pull request                                 |
| `pull_request_sync`            | Pull request synchronized                                      |
| `pull_request_review_request`  | Review requested on pull request                               |
| `repository`                   | Repository created or deleted                                  |
| `release`                      | Release published, updated, or deleted                         |
| `package`                      | Package created or deleted                                     |
| `wiki`                         | Wiki page created, edited, or deleted                          |
| `status`                       | Commit status updated                                          |
| `workflow_run`                 | GitHub Actions workflow run event                              |
| `workflow_job`                 | GitHub Actions workflow job event                              |

Reference: `modules/webhook/type.go:10-43`

## Creating a Webhook

<Steps>
  ### Navigate to webhook settings

  1. Go to your repository settings
  2. Click on **Webhooks** in the sidebar
  3. Click **Add Webhook** and select the webhook type

  ### Configure the webhook

  Provide the following configuration:

  * **Payload URL**: The endpoint that will receive webhook POST requests
  * **Content Type**: Choose between `application/json` or `application/x-www-form-urlencoded`
  * **Secret**: Optional secret token for validating payloads
  * **Trigger events**: Select which events should trigger the webhook
  * **Active**: Enable or disable the webhook

  ### Test the webhook

  After creating the webhook, you can trigger a test delivery to verify the configuration.
</Steps>

## Webhook Configuration

### HTTP Method

By default, webhooks use POST requests. You can configure a custom HTTP method if needed:

```go theme={null}
type Webhook struct {
    HTTPMethod  string  // Default: POST
    URL         string
    ContentType HookContentType
}
```

Reference: `models/webhook/webhook.go:129`

### Content Types

Webhooks support two content types:

* **JSON** (`application/json`) - Recommended format, payload sent as JSON
* **Form** (`application/x-www-form-urlencoded`) - Payload sent as form data

### Authorization Headers

You can configure custom authorization headers for webhooks:

```bash theme={null}
# Example: Bearer token authentication
Authorization: Bearer your-token-here

# Example: Basic authentication
Authorization: Basic base64-encoded-credentials
```

The authorization header is encrypted and stored securely in the database.

Reference: `models/webhook/webhook.go:209-229`

## Webhook Payloads

All webhook payloads follow a consistent structure with event-specific data.

### Push Event

<CodeGroup>
  ```json Push Event Payload theme={null}
  {
    "ref": "refs/heads/main",
    "before": "9049f1265b7d61be4a8904a9a27120d2064dab3b",
    "after": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
    "compare_url": "http://localhost:3000/gitea/test/compare/9049f1265b7d...0d1a26e67d8f",
    "commits": [
      {
        "id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
        "message": "Update README.md",
        "url": "http://localhost:3000/gitea/test/commit/0d1a26e67d8f",
        "author": {
          "name": "John Doe",
          "email": "john@example.com",
          "username": "johndoe"
        },
        "committer": {
          "name": "John Doe",
          "email": "john@example.com",
          "username": "johndoe"
        },
        "timestamp": "2026-03-10T12:00:00Z",
        "added": [],
        "removed": [],
        "modified": ["README.md"]
      }
    ],
    "total_commits": 1,
    "head_commit": {
      "id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
      "message": "Update README.md",
      "url": "http://localhost:3000/gitea/test/commit/0d1a26e67d8f"
    },
    "repository": {
      "id": 1,
      "name": "test",
      "full_name": "gitea/test",
      "html_url": "http://localhost:3000/gitea/test"
    },
    "pusher": {
      "id": 1,
      "login": "johndoe",
      "email": "john@example.com"
    },
    "sender": {
      "id": 1,
      "login": "johndoe"
    }
  }
  ```
</CodeGroup>

Reference: `modules/structs/hook.go:298-325`

### Issue Event

<CodeGroup>
  ```json Issue Opened Payload theme={null}
  {
    "action": "opened",
    "number": 42,
    "issue": {
      "id": 123,
      "number": 42,
      "title": "Bug: Application crashes on startup",
      "body": "When launching the application...",
      "state": "open",
      "user": {
        "id": 1,
        "login": "reporter",
        "email": "reporter@example.com"
      },
      "labels": [
        {
          "id": 1,
          "name": "bug",
          "color": "ee0701"
        }
      ],
      "created_at": "2026-03-10T12:00:00Z",
      "updated_at": "2026-03-10T12:00:00Z"
    },
    "repository": {
      "id": 1,
      "name": "project",
      "full_name": "org/project"
    },
    "sender": {
      "id": 1,
      "login": "reporter"
    }
  }
  ```
</CodeGroup>

Reference: `modules/structs/hook.go:384-405`

### Pull Request Event

<CodeGroup>
  ```json Pull Request Opened Payload theme={null}
  {
    "action": "opened",
    "number": 15,
    "pull_request": {
      "id": 456,
      "number": 15,
      "title": "Add new feature",
      "body": "This PR implements...",
      "state": "open",
      "user": {
        "id": 2,
        "login": "contributor"
      },
      "head": {
        "ref": "feature-branch",
        "sha": "abc123..."
      },
      "base": {
        "ref": "main",
        "sha": "def456..."
      },
      "mergeable": true,
      "merged": false
    },
    "repository": {
      "id": 1,
      "name": "project",
      "full_name": "org/project"
    },
    "sender": {
      "id": 2,
      "login": "contributor"
    }
  }
  ```
</CodeGroup>

Reference: `modules/structs/hook.go:427-452`

### Create Event

<CodeGroup>
  ```json Branch Created Payload theme={null}
  {
    "sha": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
    "ref": "refs/heads/new-feature",
    "ref_type": "branch",
    "repository": {
      "id": 1,
      "name": "test",
      "full_name": "gitea/test"
    },
    "sender": {
      "id": 1,
      "login": "johndoe"
    }
  }
  ```
</CodeGroup>

Reference: `modules/structs/hook.go:155-172`

## Webhook Security

### Secret Token Validation

When you set a secret token for your webhook, Gitea signs the payload with HMAC-SHA256 and includes the signature in the request headers:

```http theme={null}
X-Gitea-Signature: sha256=<signature>
```

Validate the signature in your webhook handler:

```python theme={null}
import hmac
import hashlib

def verify_signature(payload_body, secret_token, signature_header):
    expected = 'sha256=' + hmac.new(
        secret_token.encode('utf-8'),
        payload_body.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)
```

### Request Headers

Webhook requests include identifying headers:

```http theme={null}
X-Gitea-Event: push
X-Gitea-Delivery: 550e8400-e29b-41d4-a716-446655440000
X-Gitea-Signature: sha256=...
Content-Type: application/json
User-Agent: GiteaServer
```

## Branch Filtering

You can configure webhooks to trigger only for specific branches using glob patterns:

```bash theme={null}
# Trigger only for main branch
main

# Trigger for release branches
release/*

# Trigger for feature branches
feature/**

# Multiple patterns (comma-separated)
main,develop,release/*
```

Reference: `models/webhook/webhook.go:25`

## Webhook Delivery Status

Webhooks have three possible delivery statuses:

* **None** - Not yet delivered
* **Succeed** - Successfully delivered (2xx response)
* **Fail** - Delivery failed (non-2xx response or network error)

Reference: `modules/webhook/type.go:133-141`

### Viewing Delivery History

Each webhook maintains a delivery history showing:

* Request payload
* Response status code
* Response body
* Delivery timestamp
* Delivery duration

You can redeliver any previous webhook event from the delivery history.

## System Webhooks

Administrators can create system-level webhooks that trigger for events across all repositories:

1. Navigate to **Site Administration**
2. Click **System Webhooks**
3. Configure webhook with the same options as repository webhooks

System webhooks are useful for:

* Organization-wide event monitoring
* Security auditing
* Automated backups
* External analytics

Reference: `models/webhook/webhook.go:127`

## Troubleshooting

### Webhook Not Triggering

* Verify the webhook is **Active**
* Check that the event type is enabled in webhook settings
* Verify branch filter matches the pushed branch
* Check webhook delivery history for errors

### Timeout Errors

* Webhook endpoints must respond within the configured timeout
* Use asynchronous processing for long-running tasks
* Return 2xx response immediately, process in background

### Authentication Failures

* Verify secret token matches on both sides
* Check authorization header format
* Ensure HTTPS is used for secure token transmission

## Best Practices

1. **Use HTTPS**: Always use HTTPS endpoints for webhooks to protect secrets and payload data
2. **Validate signatures**: Always verify the webhook signature before processing payloads
3. **Respond quickly**: Return HTTP 2xx response immediately, process asynchronously
4. **Handle retries**: Implement idempotency to handle duplicate deliveries
5. **Log deliveries**: Maintain logs of webhook deliveries for debugging
6. **Use specific events**: Subscribe only to needed events to reduce noise
7. **Secure secrets**: Store webhook secrets securely, rotate regularly

## API Reference

Manage webhooks programmatically using the Gitea API:

```bash theme={null}
# Create a webhook
curl -X POST "https://gitea.example.com/api/v1/repos/{owner}/{repo}/hooks" \
  -H "Authorization: token YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "gitea",
    "config": {
      "content_type": "json",
      "url": "https://example.com/webhook"
    },
    "events": ["push", "pull_request"],
    "active": true
  }'

# List webhooks
curl "https://gitea.example.com/api/v1/repos/{owner}/{repo}/hooks" \
  -H "Authorization: token YOUR_TOKEN"

# Delete a webhook
curl -X DELETE "https://gitea.example.com/api/v1/repos/{owner}/{repo}/hooks/{id}" \
  -H "Authorization: token YOUR_TOKEN"
```

Reference: `modules/structs/hook.go:48-83`
