You can opt to receive audit events as an HTTP POST to a configured webhook.

Below is an example HTTP POST request made to a webhook URL:

POST / HTTP/1.1
Content-Length: 275
Accept-Encoding: gzip
Content-Type: application/json
X-Forwarded-For: 136.54.97.144
X-Forwarded-Proto: https

{
  "version": "0.1",
  "type": "flag",
  "action": "updated",
  "metadata": {
    "actor": {
      "authentication": "none",
      "ip": "127.0.0.1"
    }
  },
  "payload": {
    "description": "",
    "enabled": true,
    "key": "maintenance-mode",
    "name": "Maintenance Mode",
    "namespace_key": "default"
  },
  "timestamp": "2023-09-13T13:05:18-04:00"
}

Automatic Retries

If the webhook server returns a non-200 response, Flipt will retry sending the request using an exponential backoff strategy until a maximum elapsed duration. The default maximum elapsed duration is 15 seconds.

You can configure the maximum duration using the following configuration:

audit:
  sinks:
    webhook:
      max_backoff_duration: 15s

See the Audit Events - Webhook section of the configuration documentation for more details.

Security

You may provide a signing secret for requests to your webhook. If you specify a signing secret, you will receive a request with the X-Flipt-Webhook-Signature header populated. This value can be set in the Audit Events - Webhook section of the Flipt server configuration.

The value in the X-Flipt-Webhook-Signature header is the request body HMAC SHA256 signed with the signing secret you specified. On the webhook server, you can validate the signature by using the same signing secret. It’s strongly recommended that you do this to prevent requests to your webhook server that are from invalid origins.

Templates

You can specify a template for the body of an Audit Event Webhook request. This allows you to customize the body of the request to your webhook server.

A sample configuration can look something like this:

audit:
  sinks:
    webhook:
      enabled: true
      templates:
        - url: https://example.com
          headers:
            Content-Type: application/json
            Authorization: Bearer <token>
          body: |
            {
              "type": "{{ .Type }}",
              "action": "{{ .Action }}"
              "payload": {{ toJson .Payload }}
            }

The Go template contains a toJson utility function that will transform an input into JSON if it fits the structure.

This configuration tells Flipt to send a POST request when events need to be emitted to the URL https://example.com with the HTTP headers, Content-Type and Authorization, and the body which is a Go template that will be executed when an event comes in.

The event structure looks like this:

type Event struct {
	Version string `json:"version"`
	Type    Type   `json:"type"`
	Action  Action `json:"action"`

	Metadata Metadata `json:"metadata"`

	Payload interface{} `json:"payload"`

	Timestamp string `json:"timestamp"`
}

Any of the values that are exposed by Flipt are available for inclusion in your HTTP body template.

Example: Slack

Below is an example of a Slack webhook integration that uses the templating feature to send a Slack message when a flag is updated.

audit:
  sinks:
    webhook:
      enabled: true
      templates:
        - url: "https://hooks.slack.com/services/xxxxx"
          headers:
            Content-Type: "application/json"
          body: |
            {
              "text": "Flipt Event: {{ .Type }}/{{ .Action }}\n\n```{{ .Payload }}```"
            }

The above configuration will send a Slack message that looks like this:

Slack Message

You can find more information about Slack webhooks here. You can also use the Slack Block Kit Builder to build more complex messages.