> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scanoss.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Notifications

> How Earnie tells your team about security, policy, and account events: the inbox, email, signed webhook, chat message, Slack, and Microsoft Teams channels, the rules that route each class of notification, and how to test a channel.

Earnie records every notification meant for you in an **inbox** in the app. An administrator can also send notifications outside the app, to a **channel** such as email, a webhook, Slack, or Microsoft Teams, and use **rules** to choose which notifications go where.

This page covers the inbox, the four kinds of channel, rules, and testing. For the people who run a self-hosted installation, it also covers the one setting that channels need.

**Before you start:** Every member can read the inbox and set their own email preferences. Only an Admin can add, change, or delete channels and rules. Operators and Viewers can see them. See [Team & roles](https://docs.scanoss.com/en/latest/earnie/administration/team-and-roles.md).

## The Inbox

The bell is in the top bar, on every page. A number on it counts the notifications you haven't read, up to 99+. The inbox is the record of every notification meant for you. Nothing you choose in Settings leaves a notification out of it.

1. Select the bell. The newest notification is first.
2. Select a notification to open the page it's about. Earnie marks it read as you go.
3. Select **Mark all read** to clear the count at once.
4. Select **Show older** to load the next page of a long list.

A read notification stays in the list, in a lighter style.

Notifications belong to a class and a kind:

| Class | Notification | When it appears |
| - | - | - |
| Security | Known exploited vulnerability | A component in one of your projects is listed as actively exploited. |
| Policy | Gate failed | A scan failed its policy gate. |
| Policy | Approval requested | An approval needs a decision. Everyone who can decide it is told, except the person who asked. |
| Policy | Approval decided | An approval was granted or rejected. |
| Account | Member added | A member was added to the organisation. |
| Account | Release available | A new stable version of Earnie is out. Self-hosted installations only, and only when [the release check](https://docs.scanoss.com/en/latest/earnie/self-hosting/releases.md#the-release-check) is on. |

If you can change organisation settings, the inbox can open with a yellow warning:

* **No channel receives security alerts.** No channel and rule carries Security, so security alerts reach the inbox only. The warning links to **Set up a channel**.
* **Channels are off because the notifications key is not set.** The deployment has no notifications key. See [Self-Hosted Installations](#self-hosted-installations). Until the key is set, the inbox works and nothing is sent anywhere else.

## Your Email Preferences

Open **Settings → Notifications**. The first part of the page is yours alone. Choose which classes Earnie also emails to you:

* **Policy** and **Account** are switches. Each change saves at once.
* **Security** is on and locked. Nobody can turn security alerts off, you or an administrator.

## Channels

A **channel** is a place Earnie sends notifications outside the app. An Admin adds one under **Settings → Notifications → Channels**. **Add channel** opens the form for the kind you pick.

| Kind | What you enter |
| - | - |
| [Email](#email) | An SMTP relay and a sender address. |
| [Webhook](#webhook) | An `https` URL, and a signing secret or an auth header. |
| [Slack](#slack) | A Slack incoming webhook URL. |
| [Microsoft Teams](#microsoft-teams) | A Teams Workflows webhook URL. |

The channel table shows each channel's last delivery, for example `Sent, 27m ago` or `Failed, timed out, 2d ago`. A failure names only its kind, never what the other side answered. Earnie makes one attempt per delivery and doesn't retry.

### Email

An email channel is an SMTP relay.

1. Pick a **Provider** to fill in the connection: Microsoft 365, Google Workspace, Amazon SES, or SendGrid. Each sets port 587 with STARTTLS. For Amazon SES, change the region in the host to yours. Choose **Other** to clear the host for a relay of your own.
2. Enter the sender address.
3. Enter a username and password if the relay needs them. They go together. A relay with no encryption can't carry them.

You can change any field the provider filled in.

### Webhook

A webhook channel sends a notification to a URL you control. The URL must use `https`.

By default, Earnie sends one `POST` for each notification, with a JSON body, and signs it so your receiver can check where it came from. The signing secret is at least 16 characters.

```json theme={null}
{
  "type": "earnie.notification.v1",
  "id": "4c1d…",
  "delivery_id": "9a07…",
  "kind": "gate_failed",
  "class": "policy",
  "title": "Policy gate failed on acme/api",
  "link": "https://earnie.example.com/projects/…",
  "counts": {"policies_failed": 2},
  "subjects": ["…"],
  "sent_at": "2026-10-20T09:15:00Z"
}
```

The body holds ids, counts, and a link. It never holds source code or finding text. Use `id` to ignore a notification your receiver has already seen. Fields can be added within `earnie.notification.v1`. A breaking change gets a new `type`.

Every request carries an `X-Earnie-Signature` header, in the form `t=<unix seconds>,v1=<hex>`. `v1` is the HMAC-SHA256 of `<t>.<raw body>`, keyed with the channel's signing secret. Verify it on the raw bytes before you parse the body, compare in constant time, and reject a `t` that is more than a few minutes old:

```python theme={null}
import hmac, hashlib, time

def verify(secret: bytes, header: str, body: bytes, tolerance=300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > tolerance:
        return False
    expected = hmac.new(secret, parts["t"].encode() + b"." + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])
```

Earnie follows no redirect, treats any `2xx` answer as delivered, and waits 10 seconds for an answer.

#### Chat Message Format

Set **Format** to **Chat message (markdown)** for a chat platform that accepts a JSON `POST` with a markdown message field, such as Mattermost or Discord. Earnie then sends a bold title and an **Open in Earnie** link in the field you name, `text` by default:

```json theme={null}
{
  "text": "**Policy gate failed on acme/api**\n[Open in Earnie](https://earnie.example.com/projects/…)"
}
```

* **Message field** is the JSON key that holds the message. It uses letters, digits, and underscores, starts with a letter or underscore, and is at most 64 characters. Discord reads `content`.
* **Signing secret** is optional in this format.
* **Auth header name** and **Auth header value** add one request header, for a platform that wants an API key, for example `Authorization: Bearer <token>` or `X-API-Key: <key>`. Enter the whole header value, such as `Bearer <token>`.
* **Send test** uses the same format and header, so it shows whether the platform accepts the message.

The auth header value is a secret. See [Secrets](#secrets). If you change the webhook URL of a channel that holds a value, enter the value again, because Earnie never sends a stored value to a URL it wasn't entered for. Earnie refuses header names it sets itself, such as `Host`, `Content-Type`, and `User-Agent`, and any name that starts with `X-Earnie-`.

### Slack

1. In Slack, create an app and turn on **Incoming Webhooks**.
2. Select **Add New Webhook to Workspace**, pick the channel, and authorise it.
3. Copy the webhook URL into the Earnie form. It must start with `https://hooks.slack.com/services/`.

The message is the notification's title and a link back to Earnie.

### Microsoft Teams

A Teams channel receives notifications through a Workflows webhook.

1. In Teams, open the channel, choose **More options**, then **Workflows**.
2. Pick the template **Send webhook alerts to a channel**.
3. Make sure anyone with the URL can trigger the workflow, and save it.
4. Copy the webhook URL into the Earnie form.

Earnie accepts only Workflows URLs, on `api.powerplatform.com` or `logic.azure.com`. It refuses the retired `webhook.office.com` connector URLs. The message is a card with the title and an **Open in Earnie** button.

### Secrets

A secret is a signing secret, an auth header value, an SMTP password, or a Slack or Teams URL. Earnie stores each one encrypted and never shows it again.

* Only a person signed in to Earnie can enter a secret. An API key or a coding agent can't.
* When you edit a channel, the secret field is empty. Leave it empty to keep the stored secret, or type a new one to replace it.
* A channel created by an agent or by the [command line](#command-line-and-agents) has no secret. It's saved disabled, and its row reads **Needs its secret**. Choose **Enter the secret** from the row menu, enter it, and choose **Save and enable**. Until then the row offers neither **Send test** nor **Enable**.

### Private Addresses

A webhook can't reach a loopback, private-network, or cloud metadata address. To send to a receiver inside your own network, an administrator of a self-hosted installation sets `EARNIE_NOTIFICATIONS_ALLOW_PRIVATE_TARGETS=true`. Cloud metadata and link-local addresses stay blocked. The setting applies to every webhook. The email relay isn't subject to it.

## Testing a Channel

**Send test** sends one fixed message, "Earnie test notification", through a channel. It reaches no inbox and follows no rule. Use it in two places:

* **Before you save.** Select **Send test** in the form. Earnie tests the settings as you typed them, saved or not, and shows the result under the form. For an email channel, the result names the address the test went to. When you edit a saved channel, leave the secret empty and the test uses the stored one.
* **After you save.** Choose **Send test** from the channel's row menu. The test uses the stored settings and updates the **Last delivery** column.

A test that worked says **Test sent**. A test that failed gives a short outcome, such as **Test could not connect**, and a line that says what to check. The result belongs to the values you tested: change a field and it goes away, so test again.

Tests are limited to 10 a minute for each person, shared with the check buttons on **Settings → Integrations**.

## Rules

A **rule** sends a class of notification to a channel. Add one under **Settings → Notifications → Rules**:

1. Pick the class: **Security**, **Policy**, or **Account**.
2. Optionally tick the kinds you want. Leave every kind unticked to match the whole class.
3. Pick an enabled channel.

A rule appears in the list as, for example, `Policy (Gate failed, Approval requested) to Ticketing webhook`. A rule only adds a route. No rule can stop a notification reaching the inbox, or the email of a member who asked for it. Deleting a channel deletes its rules.

**Add rule** is unavailable until you have an enabled channel.

> [!NOTE]
>
> **Route Security first.** A new organisation has no channels, so security alerts reach the inbox
> only. Add one channel and one Security rule, so that a known exploited vulnerability reaches
> someone who isn't looking at Earnie. When you save an enabled channel and no channel receives
> security alerts yet, Earnie offers to add the Security rule for it.

## Command Line and Agents

The [Earnie CLI](https://docs.scanoss.com/en/latest/earnie/using-earnie/earnie-cli.md#managing-notifications) and the [MCP server](https://docs.scanoss.com/en/latest/earnie/mcp/overview.md) manage channels and rules too. They can't set a secret, so a channel that needs one is saved disabled, and a person enters the secret in **Settings → Notifications**. A link of the form `/settings/notifications?channel=<id>` opens that channel's form.

## Self-Hosted Installations

Channels need a notifications key, `EARNIE_NOTIFICATIONS_KEK_HEX`, in `tenant.env`. It's 64 hex characters, and Earnie uses it to encrypt the secrets above. The installer generates it. An installation upgraded from a release without it keeps working with channels off. To turn them on, add the key to `tenant.env`, generate its value with `openssl rand -hex 32`, and restart Earnie.

Back the key up with `tenant.env`. If you lose it, the stored channel secrets can't be read and you enter them again. See [Upgrading and backing up](https://docs.scanoss.com/en/latest/earnie/self-hosting/upgrading-and-backups.md#back-up).

The firewall must let Earnie reach each channel's destination. See [Outbound network calls](https://docs.scanoss.com/en/latest/earnie/self-hosting/outbound-network-calls.md).

## What's Next

To route notifications from a script or a coding agent, see the [Earnie CLI](https://docs.scanoss.com/en/latest/earnie/using-earnie/earnie-cli.md#managing-notifications). To see who changed a channel or a rule, see the [Audit log](https://docs.scanoss.com/en/latest/earnie/evidence/audit-log.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.