From 61c231c2b4620b9dffa768f031d2185ea0687a16 Mon Sep 17 00:00:00 2001
From: Mark Phelps <209477+markphelps@users.noreply.github.com>
Date: Mon, 19 Oct 2026 09:24:35 -0400
Subject: [PATCH 1/4] docs: document incoming webhooks for instant v2 sync
---
docs/docs.json | 8 +
docs/v2/configuration/environments.mdx | 6 +
.../operations/environments/git-scm.mdx | 4 +
.../operations/environments/git-sync.mdx | 4 +
.../operations/environments/webhooks.mdx | 161 ++++++++++++++++++
docs/v2/pro.mdx | 1 +
docs/v2/webhooks/overview.mdx | 106 ++++++++++++
7 files changed, 290 insertions(+)
create mode 100644 docs/v2/guides/operations/environments/webhooks.mdx
create mode 100644 docs/v2/webhooks/overview.mdx
diff --git a/docs/docs.json b/docs/docs.json
index 77b60571..9c4b287d 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -66,6 +66,13 @@
"v2/configuration/licensing"
]
},
+ {
+ "group": "Webhooks",
+ "icon": "webhook",
+ "pages": [
+ "v2/webhooks/overview"
+ ]
+ },
{
"group": "Integration",
"icon": "plug",
@@ -154,6 +161,7 @@
"v2/guides/operations/environments/git-repository-initialization",
"v2/guides/operations/environments/git-sync",
"v2/guides/operations/environments/git-scm",
+ "v2/guides/operations/environments/webhooks",
"v2/guides/operations/environments/commit-signing-setup"
]
}
diff --git a/docs/v2/configuration/environments.mdx b/docs/v2/configuration/environments.mdx
index e6916a27..7d3b4182 100644
--- a/docs/v2/configuration/environments.mdx
+++ b/docs/v2/configuration/environments.mdx
@@ -133,6 +133,12 @@ Environments can be configured to use a single Source Control Management (SCM) p
See the [Git SCM Integration](/v2/guides/operations/environments/git-scm) guide for more information on how to configure Flipt v2 to use a SCM provider.
+### Webhooks
+
+With Flipt Pro, you can configure incoming webhooks to fetch changes from Git after a push or merge to a tracked branch. Polling continues as a fallback.
+
+Add `webhook.secret` under the environment's `scm` block. See the [webhook reference](/v2/webhooks/overview) for configuration and the [setup guide](/v2/guides/operations/environments/webhooks) for provider instructions.
+
### Credentials
Configuring an SCM provider requires a set of credentials to be provided. These credentials are configured via the same mechanism as the [remote storage credential configuration](/v2/configuration/storage#credentials).
diff --git a/docs/v2/guides/operations/environments/git-scm.mdx b/docs/v2/guides/operations/environments/git-scm.mdx
index 47503f52..126208cc 100644
--- a/docs/v2/guides/operations/environments/git-scm.mdx
+++ b/docs/v2/guides/operations/environments/git-scm.mdx
@@ -370,6 +370,10 @@ Start or restart your Flipt server with the updated configuration. Flipt will no

+## Receive Changes with Webhooks
+
+To fetch changes after a push or merge without waiting for the next poll, configure [incoming webhooks](/v2/webhooks/overview). The [webhook setup guide](/v2/guides/operations/environments/webhooks) covers each supported provider.
+
## 3. Troubleshooting
### Common Issues
diff --git a/docs/v2/guides/operations/environments/git-sync.mdx b/docs/v2/guides/operations/environments/git-sync.mdx
index 2061ba38..64b01b46 100644
--- a/docs/v2/guides/operations/environments/git-sync.mdx
+++ b/docs/v2/guides/operations/environments/git-sync.mdx
@@ -122,6 +122,10 @@ Start or restart your Flipt server with the updated configuration. Flipt will no
- Make sure the local path is writable by the Flipt process.
- Check Flipt logs for any sync or authentication errors.
+## Sync Changes with Webhooks
+
+With Flipt Pro, you can use [incoming webhooks](/v2/webhooks/overview) to fetch changes after a push or merge without waiting for the next poll. Follow the [webhook setup guide](/v2/guides/operations/environments/webhooks) to connect your Git provider. Polling remains the fallback for missed deliveries.
+
## Conclusion
This guide showed how to configure Flipt to sync your flag state to a GitHub repository using a Personal Access Token (PAT) for authentication.
diff --git a/docs/v2/guides/operations/environments/webhooks.mdx b/docs/v2/guides/operations/environments/webhooks.mdx
new file mode 100644
index 00000000..4a8740ea
--- /dev/null
+++ b/docs/v2/guides/operations/environments/webhooks.mdx
@@ -0,0 +1,161 @@
+---
+title: Set Up Webhooks
+description: Configure your Git provider to trigger Flipt synchronization after a push or merge.
+---
+
+import V2Pro from "/snippets/v2-pro.mdx";
+
+
+
+This guide connects your Git provider to Flipt's incoming webhook endpoint. After setup, a push or merge to a tracked branch triggers a Git fetch without waiting for the next poll.
+
+## Prerequisites
+
+- A running Flipt v2 server with an active [Pro or trial license](/v2/licensing) and webhook support.
+- An environment configured with [Git sync](/v2/guides/operations/environments/git-sync) and [SCM integration](/v2/guides/operations/environments/git-scm).
+- Permission to manage webhooks or service hooks for your Git repository.
+- An HTTPS URL for Flipt that your Git provider can reach.
+
+## 1. Create a webhook secret
+
+Generate a random secret with OpenSSL:
+
+```bash
+openssl rand -hex 32
+```
+
+Store the result securely. Set `FLIPT_WEBHOOK_SECRET` to this value in the environment of the Flipt server process. You also need this value when you configure your Git provider.
+
+Use a separate value from the access token that Flipt uses to read and write your repository.
+
+## 2. Configure Flipt
+
+Add the `webhook` block to your existing environment's `scm` configuration. This example uses the `production` environment and GitHub:
+
+```yaml highlight={8-9}
+environments:
+ production:
+ storage: github
+ default: true
+ scm:
+ type: github
+ credentials: github
+ webhook:
+ secret: ${env:FLIPT_WEBHOOK_SECRET}
+```
+
+Keep your existing storage identifier and SCM credentials. For another provider, use its [SCM type](/v2/webhooks/overview#supported-providers). You can also use a [secret reference](/v2/webhooks/overview#configuration) instead of an environment variable.
+
+Restart your Flipt server with the updated configuration. Make sure that `FLIPT_WEBHOOK_SECRET` is available to the server process. Flipt refuses to start if the webhook secret resolves to an empty value.
+
+The webhook endpoint for this example is `https://flipt.example.com/api/v2/webhooks/production`. Replace `flipt.example.com` with your Flipt host. The final path segment must match the environment's configured `name`, which defaults to its YAML key. If your existing environment sets `name: Production`, use `/api/v2/webhooks/Production`, with the same capitalization.
+
+## 3. Configure your Git provider
+
+Use the endpoint URL from the previous step and the same secret that you configured in Flipt. Keep TLS certificate verification enabled.
+
+
+
+
+1. Open your repository's **Settings > Webhooks** and select **Add webhook**.
+2. Set **Payload URL** to your Flipt webhook endpoint.
+3. Set **Content type** to `application/json`.
+4. Set **Secret** to your webhook secret.
+5. Select **Just the push event** and keep **Active** selected.
+6. Select **Add webhook**.
+
+GitHub sends a `ping` event after creation. Flipt returns `200 OK` for an authenticated ping without fetching the repository.
+
+See [GitHub's webhook documentation](https://docs.github.com/en/webhooks/using-webhooks/creating-webhooks) for details.
+
+
+
+
+1. Open your project's **Settings > Webhooks** and add a webhook.
+2. Set **URL** to your Flipt webhook endpoint.
+3. Set **Secret token** to your webhook secret.
+4. Select **Push events**. If you filter branches, include the branches that Flipt tracks.
+5. Save the webhook.
+
+
+ Flipt authenticates GitLab deliveries through `X-Gitlab-Token`. Configure the
+ **Secret token** field even if your GitLab version also offers a signing
+ token. A signing token alone does not authenticate deliveries to Flipt.
+
+
+See [GitLab's webhook documentation](https://docs.gitlab.com/user/project/integrations/webhooks/) for details.
+
+
+
+
+1. Open your repository's **Settings > Webhooks** and add a **Gitea** webhook.
+2. Set **Target URL** to your Flipt webhook endpoint.
+3. Select `POST` and the `application/json` content type.
+4. Set **Secret** to your webhook secret.
+5. Select push events, keep the webhook active, and save it.
+
+Use the native Gitea webhook type so that Gitea sends the signature and event headers that Flipt expects.
+
+See [Gitea's webhook documentation](https://docs.gitea.com/usage/webhooks) for details.
+
+
+
+
+For Bitbucket Cloud:
+
+1. Open your repository's settings and select **Webhooks > Add webhook**.
+2. Enter a title and set **URL** to your Flipt webhook endpoint.
+3. Set **Secret** to your webhook secret.
+4. Select **Repository push**, keep the webhook active, and save it.
+
+For Bitbucket Server/Data Center, add a repository webhook with the same endpoint and secret. Select the repository push event that sends `repo:refs_changed` deliveries.
+
+Both variants use `scm.type: bitbucket` in Flipt. Make sure that your Bitbucket version supports webhook secrets and sends an HMAC-SHA256 signature in `X-Hub-Signature`.
+
+See [Bitbucket Cloud's webhook documentation](https://support.atlassian.com/bitbucket-cloud/docs/manage-webhooks/) for details.
+
+
+
+
+1. Open **Project settings > Service hooks** and create a subscription.
+2. Select **Web Hooks** as the service.
+3. Select **Code pushed** as the trigger and choose your repository.
+4. If you filter branches, include the branches that Flipt tracks.
+5. Set **URL** to your Flipt webhook endpoint.
+6. Configure Basic authentication with a username, such as `flipt`, and your webhook secret as the password.
+7. Finish creating the subscription.
+
+Flipt checks the Basic authentication password against `webhook.secret`. Flipt does not require a particular username. Use `scm.type: azure` in your Flipt configuration.
+
+See [Azure DevOps' webhook documentation](https://learn.microsoft.com/en-us/azure/devops/service-hooks/services/webhooks?view=azure-devops) for details.
+
+
+
+
+## 4. Test synchronization
+
+Make a flag change in your Git repository and push it to the branch that Flipt tracks. You can also merge a pull request or merge request that changes a flag on that branch.
+
+Open your provider's webhook delivery history and inspect the push delivery. A matching push returns `202 Accepted`. Make sure that the changed flag state appears in Flipt.
+
+A `200 OK` response means that Flipt authenticated the delivery but did not schedule a fetch. Provider test buttons can send pings, unrelated events, or a branch that Flipt does not track. Use a real push to test synchronization.
+
+
+ Keep `poll_interval` configured as a fallback. In a deployment with multiple
+ replicas, a webhook updates the instance that receives it. Deliver to each
+ replica for prompt updates across the deployment. A load balancer that sends
+ each request to one replica does not broadcast the update to the others.
+
+
+## Troubleshooting
+
+| Symptom | Action |
+| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| No delivery reaches Flipt | Make sure that your provider can reach the HTTPS endpoint and that your proxy forwards the path and authentication headers. |
+| `404 Not Found` | Make sure that the URL is correct, your Flipt build includes webhook support, and a Pro license and webhook configuration are active. |
+| `401 Unauthorized` | Make sure that the configured environment name and secrets match. For GitLab, use **Secret token**. For Azure DevOps, use the secret as the Basic authentication password. |
+| `200 OK` but no update | Make sure that the delivery is a push event for a tracked branch, rather than a ping or tag event. |
+| `202 Accepted` but no update | Inspect Flipt's logs and [webhook metrics](/v2/webhooks/overview#monitoring) for Git fetch failures. Make sure that repository credentials still work. |
+| Flipt fails to start | Make sure that the webhook secret is nonempty after environment or secret resolution. |
+
+For payload limits, authentication headers, and all response codes, see the [webhook reference](/v2/webhooks/overview).
diff --git a/docs/v2/pro.mdx b/docs/v2/pro.mdx
index 378fd6c3..48d9d8b7 100644
--- a/docs/v2/pro.mdx
+++ b/docs/v2/pro.mdx
@@ -43,6 +43,7 @@ mode: "wide"
Flipt Pro provides native integration with popular source control management (SCM) platforms:
- **Multi-Provider SCM Support**: Create merge proposals directly from the Flipt UI that generate pull requests across GitHub, GitLab, Bitbucket, Azure DevOps, and Gitea
+- **Incoming Webhooks**: [Sync changes from Git](/v2/webhooks/overview) after a push or merge without waiting for the next poll
- **GPG Commit Signing**: All commits are cryptographically signed for maximum security and auditability
### Integrated Secrets Management
diff --git a/docs/v2/webhooks/overview.mdx b/docs/v2/webhooks/overview.mdx
new file mode 100644
index 00000000..3ad43553
--- /dev/null
+++ b/docs/v2/webhooks/overview.mdx
@@ -0,0 +1,106 @@
+---
+title: Webhooks
+description: Sync flag changes from your Git provider without waiting for the next poll.
+---
+
+import V2Pro from "/snippets/v2-pro.mdx";
+
+
+
+A webhook is an HTTP notification from your Git provider. When you push or merge changes to a tracked branch, Flipt fetches the repository without waiting for the next poll.
+
+Use webhooks when you need changes from Git to reach Flipt quickly, such as when you disable a flag during an incident.
+
+To configure your provider, follow the [webhook setup guide](/v2/guides/operations/environments/webhooks).
+
+## How synchronization works
+
+Your Git provider sends a push event to `POST /api/v2/webhooks/{environment}`. Flipt authenticates the request and makes sure that the event affects a branch tracked by the environment's storage.
+
+For a matching event, Flipt schedules a Git fetch and returns `202 Accepted`. The fetch updates all environments that share that repository within the Flipt instance. Flipt combines overlapping requests for the same repository to avoid concurrent webhook fetches.
+
+Flipt reads flag state from Git. The webhook payload only triggers the fetch. A merge triggers synchronization through the resulting push event on the target branch. You do not need to subscribe to pull request or merge request events.
+
+
+ A `202` response means that Flipt scheduled a fetch. It does not mean that
+ synchronization completed. Polling continues at the configured `poll_interval`
+ and remains the fallback for missed deliveries or failed fetches.
+
+
+Webhooks update the Flipt server's flag state. Your application's update timing also depends on its SDK polling or streaming configuration.
+
+## Configuration
+
+Configure `webhook.secret` under an environment's `scm` block. The environment must already use storage with a Git remote. This example assumes that the `github` storage and credentials are configured through [Git sync](/v2/guides/operations/environments/git-sync).
+
+```yaml
+environments:
+ production:
+ storage: github
+ scm:
+ type: github
+ credentials: github
+ webhook:
+ secret: ${env:FLIPT_WEBHOOK_SECRET}
+```
+
+The endpoint for this example is `/api/v2/webhooks/production`. The path uses the configured environment `name`, which defaults to the `production` key. If you explicitly set `name: live`, use `/api/v2/webhooks/live` instead.
+
+The secret is required and must match the value in your Git provider's webhook configuration. Use a separate random secret for webhook authentication, rather than your Git access token.
+
+You can supply a literal value, an [environment substitution](/v2/configuration/overview#environment-substitution-and-secret-references), or a [secret reference](/v2/configuration/secrets#secret-reference-syntax):
+
+```yaml
+webhook:
+ secret: ${secret:file:github-webhook}
+```
+
+Flipt resolves the secret at startup. If the resolved value is empty, Flipt refuses to start. Restart Flipt after you change the secret.
+
+Without a Pro license, Flipt does not register the webhook endpoint and logs a warning.
+
+## Supported providers
+
+The environment's `scm.type` selects how Flipt authenticates and parses deliveries.
+
+| Provider | `scm.type` | Event | Authentication |
+| ------------------------------------- | ----------- | ------------------- | --------------------------------------------------------- |
+| GitHub, including GitHub Enterprise | `github` | `push` | HMAC-SHA256 in `X-Hub-Signature-256` |
+| GitLab, including GitLab Self-Managed | `gitlab` | `Push Hook` | Secret token in `X-Gitlab-Token` |
+| Gitea | `gitea` | `push` | HMAC-SHA256 in `X-Gitea-Signature` |
+| Bitbucket Cloud | `bitbucket` | `repo:push` | HMAC-SHA256 in `X-Hub-Signature` |
+| Bitbucket Server/Data Center | `bitbucket` | `repo:refs_changed` | HMAC-SHA256 in `X-Hub-Signature` |
+| Azure DevOps | `azure` | `git.push` | HTTP Basic authentication with the secret as the password |
+
+HMAC-SHA256 signatures let Flipt authenticate the request body with the shared secret. Your provider generates the signature automatically.
+
+The endpoint uses provider authentication instead of a Flipt API token. Use HTTPS and allow your Git provider to reach the endpoint through your firewall or reverse proxy. Preserve the request body and authentication headers when forwarding deliveries.
+
+## Responses
+
+Flipt accepts request bodies up to 5 MiB.
+
+| Status | Meaning |
+| ------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
+| `202 Accepted` | Flipt scheduled a fetch for a tracked branch. |
+| `200 OK` | Flipt authenticated the delivery but ignored it, such as a ping, an unrelated event, a tag, or an untracked branch. |
+| `401 Unauthorized` | Authentication failed, or the environment does not exist or has no webhook configured. |
+| `400 Bad Request` | The event payload is malformed. |
+| `413 Request Entity Too Large` | The request body exceeds 5 MiB. |
+| `503 Service Unavailable` | Flipt is shutting down and cannot accept the fetch. |
+
+Only a `202` response schedules a fetch. Unknown environments and environments without webhook configuration return the same `401` response as invalid authentication.
+
+## Monitoring
+
+Flipt exposes these Prometheus metrics through its [metrics endpoint](/v2/configuration/observability#metrics):
+
+| Metric | Description |
+| ---------------------------------------------- | ---------------------------------------------------- |
+| `flipt_incoming_webhook_requests_total` | Requests by `environment`, `scm`, and `result`. |
+| `flipt_incoming_webhook_fetch_errors_total` | Failed fetches by `environment` and `scm`. |
+| `flipt_incoming_webhook_sync_duration_seconds` | Fetch duration histogram by `environment` and `scm`. |
+
+Request results are `accepted`, `ignored`, `unauthorized`, `not_found`, or `invalid`. Unknown environments use `environment="unknown"` and `scm="unknown"` to avoid creating labels for arbitrary request paths.
+
+If a delivery receives `202` but flag state does not update, inspect Flipt's logs and the fetch error counter. A successful delivery can still be followed by a Git authentication or network failure.
From f41a47c4ad179de3c0401873a9513076b947f7fb Mon Sep 17 00:00:00 2001
From: Mark Phelps <209477+markphelps@users.noreply.github.com>
Date: Mon, 19 Oct 2026 09:29:41 -0400
Subject: [PATCH 2/4] docs: move new badge to webhooks sidebar section
---
docs/docs.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/docs.json b/docs/docs.json
index 9c4b287d..1c60f78f 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -42,7 +42,6 @@
},
{
"group": "Pro Features",
- "tag": "NEW",
"icon": "crown",
"pages": [
"v2/pro",
@@ -68,6 +67,7 @@
},
{
"group": "Webhooks",
+ "tag": "NEW",
"icon": "webhook",
"pages": [
"v2/webhooks/overview"
From 900e26bf52290fcad1055e39ebaf8fb104f9b906 Mon Sep 17 00:00:00 2001
From: Mark Phelps <209477+markphelps@users.noreply.github.com>
Date: Mon, 19 Oct 2026 09:31:27 -0400
Subject: [PATCH 3/4] docs: move webhooks into configuration navigation
---
docs/docs.json | 9 +--------
docs/v2/webhooks/overview.mdx | 1 +
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/docs/docs.json b/docs/docs.json
index 1c60f78f..5db25afe 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -54,6 +54,7 @@
"pages": [
"v2/configuration/overview",
"v2/configuration/environments",
+ "v2/webhooks/overview",
"v2/configuration/storage",
"v2/configuration/secrets",
"v2/configuration/commit-signing",
@@ -65,14 +66,6 @@
"v2/configuration/licensing"
]
},
- {
- "group": "Webhooks",
- "tag": "NEW",
- "icon": "webhook",
- "pages": [
- "v2/webhooks/overview"
- ]
- },
{
"group": "Integration",
"icon": "plug",
diff --git a/docs/v2/webhooks/overview.mdx b/docs/v2/webhooks/overview.mdx
index 3ad43553..6091dadc 100644
--- a/docs/v2/webhooks/overview.mdx
+++ b/docs/v2/webhooks/overview.mdx
@@ -1,5 +1,6 @@
---
title: Webhooks
+tag: NEW
description: Sync flag changes from your Git provider without waiting for the next poll.
---
From ed7e18f54334cedbc74896da146c1a5ca43568fe Mon Sep 17 00:00:00 2001
From: Mark Phelps <209477+markphelps@users.noreply.github.com>
Date: Mon, 19 Oct 2026 09:34:05 -0400
Subject: [PATCH 4/4] docs: add webhook settings to configuration reference
---
docs/v2/configuration/overview.mdx | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/docs/v2/configuration/overview.mdx b/docs/v2/configuration/overview.mdx
index 5f040ebe..6c764a86 100644
--- a/docs/v2/configuration/overview.mdx
+++ b/docs/v2/configuration/overview.mdx
@@ -227,6 +227,18 @@ Environments configuration allows you to create isolated feature flag namespaces
| environments.[id].scm.api_url | The API URL of the SCM provider to use (optional) | | v2.0.0 |
| environments.[id].scm.credentials | The id of the credentials to use for the SCM provider | | v2.0.0 |
+#### Incoming Webhooks
+
+Incoming webhooks require Flipt Pro and an environment with a Git remote and SCM configuration. Add a `webhook` block under the environment's `scm` block to fetch changes after a push or merge to a tracked branch. Polling continues as a fallback.
+
+| Property | Description | Default | Since |
+| ------------------------------------ | -------------------------------------------------------------------------------------------------- | ------- | ------- |
+| environments.[id].scm.webhook.secret | Shared secret for authenticating incoming webhooks. Required when the webhook block is configured. | None | v2.14.0 |
+
+The secret accepts a literal value, an [environment substitution](#environment-substitution-and-secret-references), or a [secret reference](/v2/configuration/secrets#secret-reference-syntax). Flipt refuses to start if the secret resolves to an empty value.
+
+See [Webhooks](/v2/webhooks/overview) for configuration examples and endpoint details, or follow the [webhook setup guide](/v2/guides/operations/environments/webhooks) for provider instructions.
+
### User Interface
User interface configuration customizes the appearance and behavior of the Flipt web UI.