Skip to content

Flag Triggers

A flag trigger is a secret URL that turns one flag on or off in one environment when something calls it. The usual caller is a monitoring tool: when error rates climb, the alert calls the URL and the kill switch flips without anyone being paged awake to do it.

Triggers are set per flag, per environment. A trigger on Production has no effect on Staging.

  1. Open the flag from your project’s Flags page.
  2. Open the Triggers tab.
  3. Pick the environment, give the trigger a name, and choose the action: Turn flag on or Turn flag off.
  4. Create it.

Featureflip shows the trigger URL and its secret once, right after you create it. Copy whichever your monitoring tool needs, as a secret, before you close the dialog. The list never shows either again, only the last four characters of the secret and when the trigger last fired. If you lose it, rotate the trigger and you get a new one.

You can also create triggers through the public API. See Managing triggers with the API below.

There are two ways to send the secret. Both do exactly the same thing.

In the URL. The secret is the last segment of the path. Every tool that can POST to a URL can use this form, including the ones that can’t set headers.

Terminal window
curl -X POST "https://api.featureflip.io/api/triggers/<secret>"

In a header. Send the secret as a bearer token to the same path without the secret on the end. Use this form when your tool stores header credentials as secrets, so the secret never appears in a URL or in the tool’s webhook settings.

Terminal window
curl -X POST "https://api.featureflip.io/api/triggers" \
-H "Authorization: Bearer <secret>"

The secret is the whole credential. You don’t need a session or an API token, and a call that carries one of those instead of a trigger secret gets the same 404 as an unknown trigger. The request body is ignored, so whatever payload your monitoring tool sends by default is fine.

Only POST is accepted. A GET is refused on purpose, so a chat app unfurling a link or a crawler following one can’t flip a flag.

A successful call returns 200:

{ "result": "applied", "flag": "checkout-v2", "environment": "production", "enabled": false }

result is applied when the call changed the flag and unchanged when the flag was already in that state. Calling a turn-off trigger twice is harmless: the second call changes nothing and sends no flag.toggled webhook.

StatusMeaning
200The trigger ran. Check result for applied or unchanged.
403A turn-on trigger whose organization no longer has a plan that includes triggers.
404The trigger is unknown, disabled, or deleted. All three look the same from outside.
429Too many calls to this trigger in a short time. Wait a moment and retry.

A firing takes the same path as a toggle in the dashboard, with the same side effects.

  • SDKs get it over the stream. Connected SDKs see the new state within seconds, with no redeploy.
  • Webhooks fire. A flag.toggled event goes to your outbound webhooks, including the Slack, Datadog, and Grafana destinations.
  • The audit log records it. The actor shows as Trigger "<name>" and the change reason reads Fired by trigger "<name>".
  • Every successful call is logged. Each one adds a Fired entry to the flag’s History tab, even when nothing changed, so you can see that your alert reached Featureflip.

A critical environment that requires a change reason still accepts trigger firings. The reason is filled in for you. Creating, editing, rotating, or deleting a trigger in a critical environment needs a reason, like any other write there.

Each trigger on the Triggers tab can be:

  • Disabled and re-enabled. A disabled trigger answers 404, the same as a deleted one.
  • Renamed. The audit log uses the current name for later firings.
  • Rotated. The old URL stops working immediately and the new one is shown once. Update your monitoring tool right away.
  • Deleted.

A flag can have up to 10 triggers per environment. Viewers can see triggers. Members and above can create and change them.

Triggers need the Team plan or above. If your organization drops below that:

  • Turn-off triggers keep working. A kill switch shouldn’t stop working because a plan lapsed.
  • Turn-on triggers return 403 until the plan is restored.
  • You can still disable or delete any trigger.

Anyone who has the URL or the secret can change that flag in production. Store it the way you store an API key: as a secret in your monitoring tool, never in a repository or a chat message. A URL can end up in proxy and access logs along the way, so prefer the header form where your tool supports it. If either leaks, rotate the trigger.

Triggers are served by the Management API at api.featureflip.io, not by the evaluation service your SDKs read from. Your SDKs keep evaluating when the Management API is unreachable, but a monitoring tool can’t flip a flag until it is back.

  1. In Grafana, go to Alerting, then Contact points, and add a contact point.
  2. Set the Integration to Webhook, paste the trigger URL into URL, and set HTTP Method to POST. To keep the secret out of the URL, use https://api.featureflip.io/api/triggers as the URL instead and put the secret in the contact point’s Authorization Header credentials. The scheme is Bearer.
  3. Route the alert to that contact point with a notification policy that matches your alert rule’s labels.

Grafana also sends a notification when the alert resolves, which calls the URL again. For a turn-off trigger that second call returns unchanged.

  1. In Datadog, open the Webhooks integration and add a webhook. Give it a name, such as kill-checkout, and paste the trigger URL into URL. To keep the secret out of the URL, use https://api.featureflip.io/api/triggers as the URL and add {"Authorization": "Bearer <secret>"} to Custom Headers.
  2. Add @webhook-kill-checkout to the message of the monitor that should flip the flag.

Datadog sends a POST with its own JSON body, which the trigger ignores. A monitor message also goes out on recovery, so wrap the handle in {{#is_alert}}@webhook-kill-checkout{{/is_alert}} if you only want the alert to call it.

Any tool that can send an HTTP POST works. From a shell, a deploy script, or an on-call runbook:

Terminal window
curl -X POST "https://api.featureflip.io/api/triggers" -H "Authorization: Bearer <secret>"

Triggers live under each flag environment in the public /api/v1:

GET /api/v1/orgs/{org}/projects/{project}/flags/{flag}/environments/{env}/triggers
POST /api/v1/orgs/{org}/projects/{project}/flags/{flag}/environments/{env}/triggers
GET /api/v1/orgs/{org}/projects/{project}/flags/{flag}/environments/{env}/triggers/{trigger}
PUT /api/v1/orgs/{org}/projects/{project}/flags/{flag}/environments/{env}/triggers/{trigger}
DELETE /api/v1/orgs/{org}/projects/{project}/flags/{flag}/environments/{env}/triggers/{trigger}
POST /api/v1/orgs/{org}/projects/{project}/flags/{flag}/environments/{env}/triggers/{trigger}/rotate

Create takes {"name", "action": "Enable" | "Disable", "description"} and returns {"trigger": {...}, "url": "...", "endpoint": "...", "secret": "..."}. The url, endpoint, and secret appear only in this response and in the rotate response. Fire a trigger with url, or POST to endpoint with Authorization: Bearer <secret>. Update takes {"name", "description", "enabled"}. Request and response shapes are in the Management API Reference.

From an AI agent, the MCP server does the same with list_flag_triggers and manage_flag_trigger.