# Receive Alert Notifications via Flock

> Setup Flock integration and receive alert notifications from Last9.

Source: https://last9.io/docs/flock-integration/

Last9 can send alert notifications and resolutions to Flock, a team messaging platform. This document provides step-by-step instructions on how to set up Flock integration with Last9 and start receiving alert notifications.

:::tip
Last9 automatically detects Flock webhook URLs and formats messages using [FlockML](https://docs.flock.com/) for rich, readable notifications with severity indicators, alert details, and direct links to Last9 dashboards.
:::

## Setting up an Incoming Webhook in Flock

1. Navigate to the [Flock Developer Dashboard](https://dev.flock.com) and sign in with your Flock account

2. Click **Webhooks** in the left navigation menu

3. Click **Add** next to **Incoming Webhook**

   ![Flock webhooks page](../../../../../assets/content/docs/alerting/guides/flock-integration/flock-add-webhook.png)

4. Configure your webhook:

   - Select the **Channel** where you want alert notifications to be posted
   - Give the webhook a descriptive **Name** (e.g., "Last9 Alerts")
   - Optionally, set an **Icon** for the webhook messages

   ![Flock webhook configuration](../../../../../assets/content/docs/alerting/guides/flock-integration/flock-add-admin-webhook.png)

5. Click **Save and Generate URL**

6. Copy the generated webhook URL from the success dialog

   ![Flock webhook URL generated](../../../../../assets/content/docs/alerting/guides/flock-integration/flock-internal-webhook.png)

7. Your webhook will now appear under **Manage Webhooks**

   ![Flock webhook saved](../../../../../assets/content/docs/alerting/guides/flock-integration/flock-webhook-saved.png)

:::note
Keep this webhook URL secure. Anyone with access to this URL can post messages to your Flock channel.
:::

## Setting up a notification channel in Last9

1. In [Notification Channels](https://app.last9.io/alerting/notification-channels/), click **Add** to create a new channel

   ![Notification channels list](../../../../../assets/content/docs/alerting/overviews/notification-channels-overview/notification-channel-1.png)

2. Provide the following details:

   - **Channel Name**: A descriptive name to easily identify the channel (e.g., "Flock Production Alerts")
   - **Channel**: Select **Webhook** from the dropdown
   - **Webhook URL**: Paste the Flock webhook URL copied from the previous step
   - **Send Resolved**: Enable this option if you want to be notified when an alert has been resolved

   ![Add Flock webhook channel](../../../../../assets/content/docs/alerting/guides/flock-integration/flock-webhook-in-last9.png)

3. Click **Save** to enable the channel

:::tip
Last9 automatically detects Flock webhook URLs (containing `api.flock.com` or `flock.co`) and formats the notifications appropriately for Flock.
:::

## Assigning a notification channel to an alert group

1. Navigate to your Alert Group in [Alerting](https://app.last9.io/alerting/)

2. Click on the notification channel icons at the top of the alert group to configure notifications

   ![Alerting notification icons](../../../../../assets/content/docs/alerting/guides/flock-integration/last9-set-notification-channel-for-alert-group.png)

3. Select your Flock channel from the **Webhook** dropdown under either **Channels for Threat Notification** or **Channels for Breach Notification**

   ![Select Flock channel for alerts](../../../../../assets/content/docs/alerting/guides/flock-integration/last9-notification-set-flock-alerts.png)

:::tip
You can set different notification channels for `threat` and `breach` notifications depending on the severity of the alerts.
:::

## Flock Notification Format

Last9 sends notifications to Flock using FlockML, which provides rich formatting.

### Trigger Notifications

When an alert is triggered, the notification includes:

| Field          | Description                                                      |
| -------------- | ---------------------------------------------------------------- |
| Header         | 🚨 TRIGGER: {severity icon} {summary}                            |
| Severity       | BREACH or THREAT (uppercase)                                     |
| Component      | The affected component or service                                |
| Class          | Type of alert (e.g., Static Threshold, SLO Breach)               |
| Timestamp      | When the alert was triggered (e.g., "Jan 15, 2024 at 10:30 UTC") |
| Custom Details | Additional context like service, environment, error rates        |
| Inspect        | Link to "View in Last9"                                          |

### Resolved Notifications

When an alert is resolved (requires **Send Resolved** to be enabled), the notification includes:

| Field              | Description                               |
| ------------------ | ----------------------------------------- |
| Header             | ✅ RESOLVED: {summary}                    |
| Status             | RESOLVED                                  |
| Original Severity  | The severity when the alert was triggered |
| Component          | The affected component or service         |
| Original Timestamp | When the alert was originally triggered   |
| Custom Details     | Context from the original alert           |
| Inspect            | Link to "View in Last9"                   |

### Severity Indicators

| Severity | Icon             | Description                                   |
| -------- | ---------------- | --------------------------------------------- |
| Breach   | 🔴 Red circle    | Critical alerts requiring immediate attention |
| Threat   | 🟠 Orange circle | Warning alerts indicating potential issues    |

---

## JSON Payload Format (Opt-in)

By default, Last9 sends Flock notifications using **FlockML** — a rich text format that works out of the box with no configuration needed.

Teams that want to **customize** how alert notifications appear in Flock (add, remove, or reformat fields) can opt into receiving a **JSON attachments payload** instead. This gives full control over the message layout using [Flock's incoming webhook attachments API](https://docs.flock.com/).

### Enabling JSON format

Add the header `X-Last9-Payload-Format: json` to your notification channel's **Webhook Headers**.

1. In [Notification Channels](https://app.last9.io/alerting/notification-channels/), open your Flock channel
2. Under **Webhook Headers**, add:

   | Header name              | Value  |
   | ------------------------ | ------ |
   | `X-Last9-Payload-Format` | `json` |

3. Click **Save**

:::note
This is opt-in per channel. Channels without this header continue receiving the default FlockML format — existing alerts are not affected.
:::

### JSON payload structure

When opted in, Last9 sends a payload of this shape:

```json
{
  "text": "🚨 TRIGGER: 🔴 High Error Rate on API Service",
  "attachments": [
    {
      "title": "🚨 TRIGGER: 🔴 High Error Rate on API Service",
      "color": "#E53935",
      "views": {
        "flockml": "<b>Severity:</b> BREACH<br/><b>Component:</b> api-gateway<br/><b>Timestamp:</b> Jan 15, 2024 at 10:30 UTC"
      },
      "buttons": [
        {
          "name": "View in Last9",
          "action": {
            "type": "openBrowser",
            "url": "https://app.last9.io/alerts/12345"
          }
        }
      ]
    }
  ]
}
```

#### Color coding

| Severity | Color  | Hex       |
| -------- | ------ | --------- |
| Breach   | Red    | `#E53935` |
| Threat   | Orange | `#FB8C00` |
| Resolved | Green  | `#43A047` |
| Default  | Blue   | `#1976D2` |

### Terraform example with JSON opt-in

```hcl
resource "last9_notification_channel" "flock_json" {
  name          = "flock-production-alerts-json"
  type          = "webhook"
  destination   = "https://api.flock.com/hooks/sendMessage/YOUR-WEBHOOK-TOKEN"
  send_resolved = true

  webhook_headers = {
    "X-Last9-Payload-Format" = "json"
  }
}
```

---

## Customizing notifications with JSON Payload Transformer

Once you opt into JSON format, Flock's **JSON Payload Transformer** (configured on the Flock webhook) lets you cherry-pick fields from the Last9 payload and format the Flock message however you want.

### Where to configure

1. Open the Flock webhook in the [Flock Developer Dashboard](https://dev.flock.com)
2. Scroll to **JSON Payload Transformer** (optional field)
3. Paste a template like the examples below
4. Click **Save**

### Available payload paths

Top-level fields Last9 emits in the JSON payload:

| Path                                           | Description                                                                        |
| ---------------------------------------------- | ---------------------------------------------------------------------------------- |
| `$(json.text)`                                 | One-line summary, e.g. `🚨 TRIGGER: 🔴 High Error Rate on API Service`             |
| `$(json.attachments[0].title)`                 | Same as `text` — the alert headline                                                |
| `$(json.attachments[0].color)`                 | Severity color hex (`#E53935` / `#FB8C00` / `#43A047` / `#1976D2`)                 |
| `$(json.attachments[0].views.flockml)`         | Pre-formatted FlockML body (severity, component, class, timestamp, custom details) |
| `$(json.attachments[0].buttons[0].action.url)` | "View in Last9" deep link to the alert                                             |

### Indexed fields for granular access

For fine-grained customization, every alert attribute is also emitted as an indexed field under `views.widget.fields[]`. Access individual fields via:

```
$(json.attachments[0].views.widget.fields[N].title)
$(json.attachments[0].views.widget.fields[N].value)
```

Field order (stable; new fields appended at end):

| Index | Title          | Example value                     |
| ----- | -------------- | --------------------------------- |
| 0     | Severity       | `BREACH` / `THREAT` / `RESOLVED`  |
| 1     | Class          | `Static Threshold` / `SLO Breach` |
| 2     | Timestamp      | `Jan 15, 2024 at 10:30 UTC`       |
| 3+    | Custom details | Varies per alert — see below      |
| last  | Component      | `api-gateway`                     |

**Custom-detail field titles** are derived from the alert's custom_details map by converting `snake_case` keys to `Title Case`. Common examples (indices depend on which keys your alert actually carries):

| Original key                 | Field title                |
| ---------------------------- | -------------------------- |
| `description`                | Description                |
| `start` / `end`              | Start / End                |
| `time_in_alert`              | Time In Alert              |
| `entity_name`                | Entity Name                |
| `entity_type`                | Entity Type                |
| `algo_type`                  | Algo Type                  |
| `inspect`                    | Inspect                    |
| `metric_degradation`         | Metric Degradation         |
| `metric_degradation_percent` | Metric Degradation Percent |
| `expression`                 | Expression                 |

Empty or `nil` values are skipped. Hash and Array values are stringified as JSON.

:::note
Custom-detail field **indices vary** between alerts — Static Threshold alerts have a different custom_details set than SLO Breach alerts. Use the debug template (Example 3 below) to discover indices for your alerts.
:::

### Example 1 — minimal custom format

```json
{
  "text": "$(json.text)\n\n📊 Severity: $(json.attachments[0].views.widget.fields[0].value)\n📅 Time: $(json.attachments[0].views.widget.fields[2].value)"
}
```

### Example 2 — detailed alert card

```json
{
  "text": "$(json.text)\n\n🔴 SEVERITY: $(json.attachments[0].views.widget.fields[0].value)\n📅 TIME: $(json.attachments[0].views.widget.fields[2].value)\n🔗 INSPECT: $(json.attachments[0].buttons[0].action.url)"
}
```

### Example 3 — debug "show all fields"

Drop this template in once to discover what fields your alert emits and at which indices:

```json
{
  "text": "$(json.text)\n\nField 0: $(json.attachments[0].views.widget.fields[0].title) = $(json.attachments[0].views.widget.fields[0].value)\nField 1: $(json.attachments[0].views.widget.fields[1].title) = $(json.attachments[0].views.widget.fields[1].value)\nField 2: $(json.attachments[0].views.widget.fields[2].title) = $(json.attachments[0].views.widget.fields[2].value)\nField 3: $(json.attachments[0].views.widget.fields[3].title) = $(json.attachments[0].views.widget.fields[3].value)\nField 4: $(json.attachments[0].views.widget.fields[4].title) = $(json.attachments[0].views.widget.fields[4].value)\nField 5: $(json.attachments[0].views.widget.fields[5].title) = $(json.attachments[0].views.widget.fields[5].value)\nField 6: $(json.attachments[0].views.widget.fields[6].title) = $(json.attachments[0].views.widget.fields[6].value)\nField 7: $(json.attachments[0].views.widget.fields[7].title) = $(json.attachments[0].views.widget.fields[7].value)"
}
```

Trigger an alert, observe which field-titles land at which indices, then build your real template using those indices.

### Iterate

If a field shows blank, it likely doesn't exist in that specific alert payload. Use the debug template (Example 3) to confirm what's actually there, then adjust indices in your real template.

---

## Using Terraform

You can also create the Flock notification channel using the [Last9 Terraform Provider](/docs/terraform-provider/):

```hcl
resource "last9_notification_channel" "flock" {
  name          = "flock-production-alerts"
  type          = "webhook"
  destination   = "https://api.flock.com/hooks/sendMessage/YOUR-WEBHOOK-TOKEN"
  send_resolved = true
}
```

---

## Troubleshooting

- **Notifications not appearing in Flock**

  1. Verify the webhook URL is correct and starts with `https://api.flock.com/hooks/`
  2. Check that the webhook is still active in the [Flock Developer Dashboard](https://dev.flock.com)
  3. Ensure the channel selected for the webhook still exists

- **Messages are not formatted correctly**

  Last9 auto-detects Flock webhooks based on the URL pattern. Ensure your webhook URL contains `api.flock.com` or `flock.co`.

Please get in touch with us on [Discord](https://discord.com/invite/Q3p2EEucx9) or [Email](mailto:support@last9.io) if you have any questions.
