> For the complete documentation index, see [llms.txt](https://docs.interlynk.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.interlynk.io/api/security/notifications.md).

# Manage Notifications

Interlynk sends notifications when things happen to your SBOMs: a version uploads, a scan finds new vulnerabilities, a policy fails, a license changes. The API gives you three independent controls over those notifications.

| Control         | Scope                 | What it sets                                               |
| --------------- | --------------------- | ---------------------------------------------------------- |
| **Settings**    | Organization or user  | Which message types fire, and at what severity level.      |
| **Preferences** | User, per environment | Which categories you subscribe to for a given environment. |
| **Channels**    | User                  | Where notifications go: email, Slack, Teams.               |

Settings are the only control with an organization-wide scope. Preferences and channels always belong to the calling user. Read each one before you change it, since most calls overwrite rather than merge.

## Notification settings

A setting decides whether a message type is enabled and at what level. Levels are `ALERT`, `WARN`, or `INFO`. Settings exist at two scopes: the organization default, and a per-user override. The `org` flag on the update mutation picks which one you write.

### Read the organization settings

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { organization { notificationSettings { messageType title enabled level hasOverride } } }"}'
```

```json
{
  "data": {
    "organization": {
      "notificationSettings": [
        { "messageType": "SBOM_UPLOAD_SUCCESS", "title": "Version Upload Success", "enabled": true, "level": "INFO", "hasOverride": false },
        { "messageType": "SBOM_UPLOAD_FAILED", "title": "Version Upload Failed", "enabled": true, "level": "ALERT", "hasOverride": true }
      ]
    }
  }
}
```

`hasOverride` is `true` when the organization has changed the message type from its system default. The full list of message types is in the [reference table](#message-types) below.

To read your own user-level overrides instead, query `organizationUser`:

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { organizationUser { notificationSettings { messageType title enabled level } } }"}'
```

### Update settings

`bulkUpdateNotificationSettings` writes one or more settings in a single call. Set `org` to `true` for the organization default, or `false` for your own user-level override. Each entry needs a `messageType` and at least one of `enabled` or `level`.

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation SetSettings($settingsData: [NotificationSettingInput!]!) { bulkUpdateNotificationSettings(input: { org: true, settingsData: $settingsData }) { success totalProcessed successfulCount failedCount errors } }",
    "variables": {
      "settingsData": [
        { "messageType": "SBOM_UPLOAD_FAILED", "enabled": true, "level": "ALERT" },
        { "messageType": "SBOM_UPLOAD_SUCCESS", "enabled": false }
      ]
    }
  }'
```

```json
{
  "data": {
    "bulkUpdateNotificationSettings": {
      "success": true,
      "totalProcessed": 2,
      "successfulCount": 2,
      "failedCount": 0,
      "errors": []
    }
  }
}
```

The whole batch is transactional. If any entry fails, for example an unknown `messageType`, nothing is written and the reason comes back in `errors`.

{% hint style="info" %}
Writing organization settings (`org: true`) requires the **Edit Notification Settings** permission, which Admin and Owner roles have. A Viewer can read organization settings but not change them, and gets `You are not authorized to perform this action on NotificationSetting`. Any user can write their own settings with `org: false`.
{% endhint %}

#### Message types <a href="#message-types" id="message-types"></a>

| `messageType`              | Title                                   | Default level |
| -------------------------- | --------------------------------------- | ------------- |
| `SBOM_UPLOAD_SUCCESS`      | Version Upload Success                  | INFO          |
| `SBOM_UPLOAD_FAILED`       | Version Upload Failed                   | ALERT         |
| `SBOM_VULN_SCAN_REPORT`    | Version Vulnerability Summary Report    | ALERT         |
| `NEW_VULNS_REPORT`         | Version Vulnerability Scan Report       | ALERT         |
| `VULN_DIFF_REPORT`         | Version Vulnerability Comparison Report | WARN          |
| `SBOM_POLICY_SCAN_REPORT`  | Version Policy Scan Report              | WARN          |
| `LICENSE_CREATION_SUCCESS` | Organization License Create Success     | INFO          |
| `LICENSE_CREATION_FAILED`  | Organization License Create Failed      | ALERT         |
| `LICENSE_UPDATE_SUCCESS`   | Organization License Update Success     | INFO          |
| `LICENSE_UPDATE_FAILED`    | Organization License Update Failed      | ALERT         |
| `LICENSE_SUMMARY`          | Version License Summary                 | INFO          |
| `SBOM_LICENSE_UPDATE`      | Version License Update                  | INFO          |
| `COMPONENT_LICENSE_UPDATE` | Version Component License Update        | INFO          |

Read the live list from your own organization with the settings query above. New message types are added over time.

## Notification preferences

Preferences are user-scoped and set per environment. Each environment subscribes to a set of categories. The valid categories are `none`, `all`, `vulnerabilities`, `licenses`, `policies`, and `uploads`. Use `none` to unsubscribe and `all` to subscribe to everything.

### Read your preferences for one environment

Pass the environment ID as `envId`. Get environment IDs from [List Products and Versions](/api/inventory/list-resources.md).

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { notificationPreferences(envId: \"fa803351-ec53-44cf-aec5-88d99372e59f\") }"}'
```

```json
{ "data": { "notificationPreferences": ["vulnerabilities", "policies"] } }
```

To see every product and environment at once, query `organizationUser`. The preferences are grouped by product:

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { organizationUser { notificationPreferences(first: 25) { nodes { productName projects { projectId projectName subscribedCategories } } } } }"}'
```

### Update one environment

`notificationPreferenceUpdate` replaces the categories for a single environment. The list you send is the full set of categories after the call, so include every category you want to keep.

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation SetPref($envId: Uuid!, $prefs: [NotificationPreferenceArguments!]!) { notificationPreferenceUpdate(input: { envId: $envId, notificationPreferences: $prefs }) { currentNotificationPreference { id } } }",
    "variables": {
      "envId": "fa803351-ec53-44cf-aec5-88d99372e59f",
      "prefs": ["vulnerabilities", "policies"]
    }
  }'
```

### Update many environments at once

`bulkUpdateNotificationPreferences` takes a list, one entry per environment. Each entry pairs a `projectId` (the environment ID) with its `enabledCategories`.

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation SetPrefs($preferencesData: [NotificationPreferenceInput!]!) { bulkUpdateNotificationPreferences(input: { preferencesData: $preferencesData }) { success successfulCount failedCount errors } }",
    "variables": {
      "preferencesData": [
        { "projectId": "fa803351-ec53-44cf-aec5-88d99372e59f", "enabledCategories": ["uploads"] },
        { "projectId": "44e4c17c-c04b-4994-a845-4840c45c72a4", "enabledCategories": ["all"] }
      ]
    }
  }'
```

## Delivery channels

Channels decide where your notifications go. They are user-scoped. Email, Slack, and Teams are simple on or off toggles. Slack and Teams also need a webhook URL, which you set separately.

### Read your channels

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { notificationChannels { email slack teams } notificationConfigs { slackWebhookUrl teamsWebhookUrl } }"}'
```

```json
{
  "data": {
    "notificationChannels": { "email": true, "slack": false, "teams": false },
    "notificationConfigs": { "slackWebhookUrl": null, "teamsWebhookUrl": null }
  }
}
```

### Turn channels on or off

`notificationChannelUpdate` sets all three toggles at once.

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation SetChannels($channels: NotificationChannelInput!) { notificationChannelUpdate(input: { notificationChannels: $channels }) { success } }",
    "variables": { "channels": { "email": true, "slack": false, "teams": false } }
  }'
```

### Set a webhook URL

`notificationConfigUpdate` sets one webhook per call. Send either `slackWebhookUrl` or `teamsWebhookUrl`, not both in the same call.

```bash
curl https://api.interlynk.io/lynkapi \
  -H "Authorization: Bearer $INTERLYNK_SECURITY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation SetWebhook($configs: NotificationConfigInput!) { notificationConfigUpdate(input: { notificationConfigs: $configs }) { success } }",
    "variables": { "configs": { "slackWebhookUrl": "https://hooks.slack.com/services/T000/B000/XXXX" } }
  }'
```

After setting the webhook, turn the matching channel on with `notificationChannelUpdate`.

## Errors

The bulk mutations report per-entry failures in their `errors` list and keep the operation transactional, so a single bad entry rolls back the whole batch:

```json
{
  "data": {
    "bulkUpdateNotificationSettings": {
      "success": false,
      "successfulCount": 0,
      "failedCount": 1,
      "errors": ["Unknown notification type: SBOM_UPLOADED"]
    }
  }
}
```

| Message                                                                | Cause                                                                             |
| ---------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `Unknown notification type: ...`                                       | The `messageType` is not a valid type. See the [reference table](#message-types). |
| `At least one of enabled or level must be specified`                   | A settings entry had only a `messageType`.                                        |
| `You are not authorized to perform this action on NotificationSetting` | You sent `org: true` without the Edit Notification Settings permission.           |

See [Errors](/api/reference/errors.md) for the general error model.
