You can register webhooks on Tggl to call endpoints of your choice when a flag is updated. You can customize the URL and headers of the request.

Webhooks are mainly useful for two use-cases:

  • Monitor changes on flags and display a vertical indicator on your charts to correlate metric changes with flags updates.
  • Maintain a cache of you flags configuration up-to-date to evaluate flags locally without doing any API calls.

In both cases it is up to you to implement the logic on your side.

When are webhooks called?

All webhooks of your organization are called when a flag is updated in any of you projects.

If you want to be notified only when a flag is updated in a specific project, you have to implement some logic on your side by checking the content of the request's body.


You must use a header to authenticate the request. Most of the time you will probably want to use an Authorization header with a Bearer:

Webhook auth 2x


You can debug your webhooks by sending a test request to your endpoint and displaying the list of calls. For each call you can inspect the request and the response.

Webhook runs 2x

Request body

The request is always a POST to the endpoint you specified with the following body format:

  "flagSlug": "my_feature",
  "userEmail": "john.doe@gmail.com",
  "projectSlug": "my_project",
  "codeLikeBefore": "IF ... THEN ... ELSE ...",
  "codeLikeAfter": "IF ... THEN ... ELSE ...",
  "changes": [
    { "__typename":  "FlagConditionCreated", /*...*/ },
    { "__typename":  "FlagDescriptionChanged", /*...*/ }


The flagSlug key is the slug of the flag that was updated, you can find it on the app:

Flags slugs 2x


The projectSlug key is the slug of the project of the flag and can also be found on the app:

Project slug 2x


The email of the user who updated the flag.

codeLikeBefore and codeLikeAfter

The codeLikeBefore and codeLikeAfter keys are a string representation of the flag's conditions before and after the change. You can use them to display it directly to humans and even display a diff of the change. The code-like representation looks like this:

  userId IS ONE OF [
  Live (value: true)
  environment == "production"
  AND 20% OF userId (0% TO 20%)
  AND timestamp >= "2023-12-11T00:00"
  Live (value: true)
  Off (inactive)

Note that the code-like representation should not be parsed, it is only meant to be displayed to humans.


The changes key is an array of changes that were applied to the flag. Each change is an object with a __typename key that can be one of the following values:


Based on the __typename you can know which fields are available on the change object:

TypeScript definition
// Common types definition ----------------
type Variation = {
  id: string
  name: string
  description: string
  color: string
  active: boolean
  value: any
  order: number
type Operator =
  | 'DATE_IS'
  | 'IS_EMPTY'
  | 'IS_FALSE'
  | 'IS_TRUE'
  | 'NUM_GT'
  | 'NUM_GTE'
  | 'NUM_LT'
  | 'NUM_LTE'
type Condition = {
  id: string
  name: string
  variation: Variation
  rules: {
    [id: string]: {
      order: number
      operator: Operator
      params: any
      contextProperty: {
        id: string;
        name: string;
        key: string
  codeLike: string
  order: number
type Tag = {
  id: string
  name: string
  color: string
// Changes definition ----------------
type FlagCreated = {
  __typename: "FlagCreated"
  created: true
type FlagArchived = {
  __typename: "FlagArchived"
  oldArchived: boolean
  newArchived: boolean
type FlagActivated = {
  __typename: "FlagActivated"
  oldActive: boolean
  newActive: boolean
type FlagSlugChanged = {
  __typename: "FlagSlugChanged"
  oldSlug: string
  newSlug: string
type FlagNameChanged = {
  __typename: "FlagNameChanged"
  oldName: string
  newName: string
type FlagDescriptionChanged = {
  __typename: "FlagDescriptionChanged"
  oldDescription: string
  newDescription: string
type FlagSharingChanged = {
  __typename: "FlagSharingChanged"
  oldShareWithEveryone: boolean
  newShareWithEveryone: boolean
  oldRoles: string[]
  newRoles: string[]
  addedRoles: string[]
  removedRoles: string[]
type FlagTagsChanged = {
  __typename: "FlagTagsChanged"
  oldTags: Tag[]
  newTags: Tag[]
  addedTags: Tag[]
  removedTags: Tag[]
type FlagVariationCreated = {
  __typename: "FlagVariationCreated"
  variation: Variation
type FlagVariationDeleted = {
  __typename: "FlagVariationDeleted"
  variation: Variation
type FlagVariationUpdated = {
  __typename: "FlagVariationUpdated"
  oldVariation: Variation
  newVariation: Variation
type FlagDefaultVariationChanged = {
  __typename: "FlagDefaultVariationChanged"
  oldVariation: Variation
  newVariation: Variation
type FlagConditionCreated = {
  __typename: "FlagConditionCreated"
  condition: Condition
type FlagConditionDeleted = {
  __typename: "FlagConditionDeleted"
  condition: Condition
type FlagConditionUpdated = {
  __typename: "FlagConditionUpdated"
  oldCondition: Condition
  newCondition: Condition