doc/user/project/integrations/webhooks.md
{{< details >}}
{{< /details >}}
Webhooks connect GitLab to your other tools and systems through real-time notifications. When important events happen in GitLab, webhooks send that information directly to your external applications. Build automation workflows by reacting to merge requests, code pushes, and issue updates.
With webhooks, your team stays synchronized as changes occur:
Various events in GitLab can trigger webhooks. For example:
GitLab.com enforces webhook limits, including:
For GitLab Self-Managed, administrators can modify these limits.
GitLab limits webhook triggers for push events that include multiple changes:
push_event_hooks_limit
setting through the application settings API.If you frequently push multiple tags or branches simultaneously and need webhook notifications, contact your GitLab administrator to increase this limit.
{{< details >}}
{{< /details >}}
Group webhooks are custom HTTP callbacks that send notifications for events across all projects in a group and its subgroups.
You can configure group webhooks to listen for:
If you configure identical webhooks in both a group and a project in that group, both webhooks are triggered for events in that project. This allows for flexible event handling at different levels of your GitLab organization.
Create and configure webhooks in GitLab to integrate with your project's workflow. Use these features to set up webhooks that meet your specific requirements.
{{< history >}}
{{< /history >}}
Create a webhook to send notifications about events in your project or group.
Prerequisites:
To create a webhook:
The secret token is sent with the webhook request in the X-Gitlab-Token HTTP header.
Your webhook endpoint can use this token to verify the legitimacy of the request.
Mask sensitive portions of webhook URLs to enhance security. Masked portions are replaced with configured values when webhooks are executed, are not logged, and are encrypted at rest in the database.
To mask sensitive portions of a webhook URL:
a-z), numbers (0-9), or underscores (_).The masked values appear hidden in the UI.
For example, if you've defined variables path and value, the webhook URL can look like this:
https://webhook.example.com/{path}?key={value}
{{< history >}}
custom_webhook_headers. Enabled by default.custom_webhook_headers removed.{{< /history >}}
Add custom headers to webhook requests for authentication to external services. You can configure up to 20 custom headers per webhook.
Custom headers must:
Custom headers show in Recent events with masked values.
{{< history >}}
custom_webhook_template. Enabled by default.custom_webhook_template removed.custom_webhook_template_serialization. Disabled by default.custom_webhook_template_serialization enabled by default.custom_webhook_template_serialization removed in GitLab 18.10.{{< /history >}}
Create a custom payload template for your webhook to control the data sent in the request body.
To create a custom webhook template:
Use fields from the payload of an event in your template. For example:
{{build_name}} for a job event{{deployable_url}} for a deployment eventTo access nested properties, use periods to separate path segments.
For this custom payload template:
{
"event": "{{object_kind}}",
"project_name": "{{project.name}}"
}
The resulting request payload for a push event is:
{
"event": "push",
"project_name": "Example"
}
Custom webhook templates cannot access properties in arrays. Support for this feature is proposed in issue 463332.
Filter push events sent to your webhook endpoint by the branch name.
Use one of these filtering options:
To filter by using a wildcard pattern:
*-stable to match branches ending with -stable.production/* to match branches in the production/ namespace.To filter by using a regular expression:
For example, to exclude the main branch, use:
\b(?:m(?!ain\b)|ma(?!in\b)|mai(?!n\b)|[a-l]|[n-z])\w*|\b\w{1,3}\b|\W+
{{< details >}}
{{< /details >}}
{{< history >}}
{{< /history >}}
Configure webhooks to support mutual TLS by setting a global client certificate in PEM format.
Prerequisites:
To configure mutual TLS for webhooks:
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
Edit /etc/gitlab/gitlab.rb:
gitlab_rails['http_client']['tls_client_cert_file'] = '<PATH TO CLIENT PEM FILE>'
gitlab_rails['http_client']['tls_client_cert_password'] = '<OPTIONAL PASSWORD>'
Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Docker" >}}
Edit docker-compose.yml:
version: "3.6"
services:
gitlab:
image: 'gitlab/gitlab-ee:latest'
restart: always
hostname: 'gitlab.example.com'
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['http_client']['tls_client_cert_file'] = '<PATH TO CLIENT PEM FILE>'
gitlab_rails['http_client']['tls_client_cert_password'] = '<OPTIONAL PASSWORD>'
Save the file and restart GitLab:
docker compose up -d
{{< /tab >}}
{{< tab title="Self-compiled (source)" >}}
Edit /home/git/gitlab/config/gitlab.yml:
production: &base
http_client:
tls_client_cert_file: '<PATH TO CLIENT PEM FILE>'
tls_client_cert_password: '<OPTIONAL PASSWORD>'
Save the file and restart GitLab:
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
{{< /tab >}}
{{< /tabs >}}
After configuration, GitLab presents this certificate to the server during TLS handshakes for webhook connections.
Configure firewalls for webhook traffic based on how GitLab sends webhooks:
Webhooks are sent synchronously from Rails nodes when you test or retry a webhook in the UI.
When configuring firewalls, ensure both Sidekiq and Rails nodes can send webhook traffic.
Monitor and maintain your configured webhooks in GitLab.
View the history of webhook requests to monitor their performance and troubleshoot issues.
Prerequisites:
To view the request history for a webhook:
The Recent events section displays all requests made to a webhook in the last two days. The table includes:
200-299 codesinternal error for failed deliveriesPrerequisites:
Each webhook request in Recent events has a Request details page. This page contains the body and headers of:
To inspect the request and response details of a webhook event:
To send the request again with the same data and the same Idempotency-Key header, select Resend Request.
If the webhook URL has changed, you cannot resend the request.
You can also resend the request programmatically through the project webhooks API.
Test a webhook to ensure it's working properly or to re-enable a disabled webhook.
Prerequisites:
push events, your project must have at least one commit.To test a webhook:
Testing is not supported for some types of events for project and group webhooks. For more information, see issue 379201.
Use this technical reference to:
Implement fast and stable webhook receiver endpoints to ensure reliable webhook delivery.
Slow, unstable, or incorrectly configured receivers might be disabled automatically. Invalid HTTP responses are treated as failed requests.
To optimize your webhook receivers:
200 or 201 status:
4xx range) only for misconfigured webhooks.400 or ignore the payload.500 server error responses for handled events.{{< history >}}
auto_disabling_web_hooks.{{< /history >}}
[!flag] The availability of this feature is controlled by a feature flag. For more information, see the history.
GitLab automatically disables project or group webhooks that fail four consecutive times.
To view auto-disabled webhooks:
In the webhook list, auto-disabled webhooks display as:
Webhooks are temporarily disabled if they fail four consecutive times. If webhooks fail 40 consecutive times, they become permanently disabled.
Failure occurs when:
4xx or 5xx range.Temporarily disabled webhooks are initially disabled for one minute, with the duration extending on subsequent failures up to 24 hours. After this period has elapsed, these webhooks are automatically re-enabled.
Webhooks are permanently disabled if they fail 40 consecutive times. Unlike temporarily disabled webhooks, these webhooks are not automatically re-enabled.
Webhooks that were permanently disabled in GitLab 17.10 and earlier underwent a data migration. These webhooks might display four failures in Recent events even though the UI might state they have 40 failures.
To re-enable a disabled webhook, send a test request.
The webhook is re-enabled if the test request returns a response code in the 2xx range.
{{< history >}}
X-Gitlab-Webhook-UUID header introduced in GitLab 16.2.Idempotency-Key header introduced in GitLab 17.4.{{< /history >}}
GitLab includes the following headers in webhook requests to your endpoint:
| Header | Description | Example |
|---|---|---|
User-Agent | User agent in the format "Gitlab/<VERSION>". | "GitLab/15.5.0-pre" |
X-Gitlab-Instance | Hostname of the GitLab instance that sent the webhook. | "https://gitlab.com" |
X-Gitlab-Webhook-UUID | Unique ID for each webhook. | "02affd2d-2cba-4033-917d-ec22d5dc4b38" |
X-Gitlab-Event | Webhook type name. Corresponds to event types in the format "<EVENT> Hook". | "Push Hook" |
X-Gitlab-Event-UUID | Unique ID for non-recursive webhooks. Recursive webhooks (triggered by earlier webhooks) share the same value. | "13792a34-cac6-4fda-95a8-c58e00a3954e" |
Idempotency-Key | Unique ID consistent across webhook retries. Use to ensure idempotency in integrations. | "f5e5f430-f57b-4e6e-9fac-d9128cd7232f" |
GitLab rewrites relative image references to absolute URLs in webhook bodies.
If the original image reference in a merge request, comment, or wiki page is:

The rewritten image reference in the webhook body would be:

This example assumes:
gitlab.example.com.123.GitLab does not rewrite image URLs when: