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

# Set up Slack integration

> Learn how to integrate Slack with Endor Labs and receive finding notifications

export const CodeFile = ({src, lang, expandable = true, maxLines = 15}) => {
  const [content, setContent] = useState(null);
  const [wrapperLang, setWrapperLang] = useState('text');
  const [error, setError] = useState('');
  const [copied, setCopied] = useState(false);
  const [isDark, setIsDark] = useState(false);
  const [expanded, setExpanded] = useState(false);
  useEffect(() => {
    const root = document.documentElement;
    const checkTheme = () => setIsDark(root.dataset.theme === 'dark' || root.classList.contains('dark'));
    checkTheme();
    const observer = new MutationObserver(checkTheme);
    observer.observe(root, {
      attributes: true,
      attributeFilter: ['data-theme', 'class']
    });
    return () => {
      observer.disconnect();
    };
  }, []);
  useEffect(() => {
    if (!src) {
      setError('No src provided.');
      return undefined;
    }
    const ac = new AbortController();
    fetch(src, {
      signal: ac.signal
    }).then(r => {
      if (!r.ok) throw new Error(r.status + ' ' + r.statusText);
      return r.json();
    }).then(data => {
      setContent(data.content || '');
      if (data.lang) setWrapperLang(data.lang);
    }).catch(err => {
      if (err.name !== 'AbortError') {
        setError('Unable to load ' + src + ': ' + err.message);
      }
    });
    return () => {
      ac.abort();
    };
  }, [src]);
  const language = lang || wrapperLang || 'text';
  const handleCopy = () => {
    if (!content) return;
    navigator.clipboard.writeText(content).then(() => {
      setCopied(true);
      setTimeout(() => {
        setCopied(false);
      }, 2000);
    }).catch(() => {});
  };
  const toggleExpand = () => {
    setExpanded(v => !v);
  };
  const statusBoxStyle = variant => {
    const base = {
      padding: '12px 16px',
      borderRadius: '6px',
      fontSize: '14px'
    };
    if (variant === 'error') {
      return {
        ...base,
        background: isDark ? '#451a1a' : '#fef2f2',
        color: isDark ? '#fca5a5' : '#dc2626',
        border: '1px solid ' + (isDark ? '#7f1d1d' : '#fecaca')
      };
    }
    return {
      ...base,
      background: isDark ? '#1f2937' : '#f5f5f5',
      color: isDark ? '#9ca3af' : '#6b7280'
    };
  };
  const shellStyle = {
    position: 'relative',
    borderRadius: '8px',
    border: '1px solid ' + (isDark ? 'rgba(255,255,255,0.1)' : '#d1d5db'),
    overflow: 'hidden'
  };
  const copyBtnIdleBg = isDark ? 'rgba(255,255,255,0.15)' : '#f6f8fa';
  const copyBtnHoverBg = isDark ? 'rgba(255,255,255,0.25)' : '#e5e7eb';
  const copyBtnStyle = {
    position: 'absolute',
    top: '8px',
    right: '8px',
    padding: '4px 8px',
    fontSize: '12px',
    lineHeight: '1',
    border: '1px solid ' + (isDark ? 'rgba(255,255,255,0.3)' : '#d1d5db'),
    borderRadius: '4px',
    background: copyBtnIdleBg,
    color: isDark ? '#fff' : '#1f2937',
    cursor: 'pointer',
    zIndex: 2,
    transition: 'background 0.15s, color 0.15s'
  };
  const renderErrorBox = () => <div style={statusBoxStyle('error')}>{error}</div>;
  const renderLoadingBox = () => <div style={statusBoxStyle('loading')}>Loading…</div>;
  const countLogicalLines = text => {
    const normalized = text.replace(/\n+$/, '');
    if (normalized === '') {
      return 0;
    }
    return normalized.split('\n').length;
  };
  const lineCount = content ? countLogicalLines(content) : 0;
  const showTruncate = expandable && lineCount >= maxLines && !expanded;
  const showExpandToggle = expandable && lineCount >= maxLines;
  const LINE_HEIGHT_PX = 25;
  const previewMaxHeightPx = maxLines * LINE_HEIGHT_PX;
  const preStyle = {
    margin: 0,
    padding: '16px',
    overflow: 'auto',
    maxHeight: showTruncate ? previewMaxHeightPx + 'px' : 'none',
    overflowY: showTruncate ? 'hidden' : 'auto'
  };
  const toggleLinkStyle = {
    display: 'block',
    width: '100%',
    boxSizing: 'border-box',
    background: 'none',
    border: 'none',
    padding: '8px 16px 12px 16px',
    cursor: 'pointer',
    color: isDark ? '#26D07C' : '#047857',
    fontSize: '13px',
    fontFamily: 'inherit',
    textAlign: 'left'
  };
  const renderLoaded = () => <div style={shellStyle}>
      <button type="button" onClick={handleCopy} aria-label="Copy code" style={copyBtnStyle} onMouseEnter={e => {
    e.currentTarget.style.background = copyBtnHoverBg;
  }} onMouseLeave={e => {
    e.currentTarget.style.background = copyBtnIdleBg;
  }}>
        {copied ? 'Copied!' : 'Copy'}
      </button>
      <pre style={preStyle} tabIndex={0} role="region" aria-label={'Code file: ' + (typeof src === 'string' && src.split('/').filter(Boolean).pop() || 'code sample')}>
        <code className={'language-' + language} style={{
    fontSize: '14px'
  }}>
          {content}
        </code>
      </pre>
      {showExpandToggle ? <button type="button" style={toggleLinkStyle} onClick={toggleExpand} aria-expanded={expanded ? 'true' : 'false'} aria-label={expanded ? 'Show less code' : 'See all ' + lineCount + ' lines of code'}>
          {expanded ? '... Show less' : '... See all ' + lineCount + ' lines'}
        </button> : null}
    </div>;
  if (error) {
    return renderErrorBox();
  }
  if (content === null) {
    return renderLoadingBox();
  }
  return renderLoaded();
};

Integrate Endor Labs with Slack and automatically receive policy violations as notifications in your Slack channels. If you are using Slack for team communication and notifications, this integration helps you to seamlessly integrate Endor Labs into your organization's existing workflows.

* [Create incoming webhooks in Slack](#create-incoming-webhooks-in-slack)
* [Configure Slack integration](#configure-slack-integration)
  * [Associate an action policy with a Slack notification](#associate-an-action-policy-with-a-slack-notification)
  * [Manage Slack notification targets in Endor Labs](#manage-slack-notification-targets-in-endor-labs)
  * [Customize Slack notification templates](#customize-slack-notification-templates)
  * [Data model](#data-model)
* [Run a scan](#run-a-scan)
  * [View notifications in Slack](#view-notifications-in-slack)

## Create incoming webhooks in Slack

Create an incoming webhook to your Slack channel to enable Endor Labs to post notifications in the channel. The **Incoming Webhook** provides a unique URL to integrate your Slack channel in Endor Labs.

<Note>
  We recommend you designate a channel in your Slack workspace for receiving Endor Labs notifications and create an incoming webhook for that channel.
</Note>

To create incoming webhooks in Slack:

1. Create a [Slack app](https://api.slack.com/apps?new_app=1) for Endor Labs or use an existing app.
   * Click **Create New App**.
   * Choose **From Scratch** and Enter a name for the app, for example, **Endor Labs**.
   * Select your workspace and click **Create App**
   * You can enter basic, install, or display information for your [Endor Labs app in Slack](https://api.slack.com/apps?new_app=1).
   * In **Display Information**, you can upload a logo and customize App colours to distinguish the Endor Labs App on the Slack workspace.
   * Click **Save Changes**.
2. Under **Features**, select **Incoming Webhooks**, then turn on **Activate Incoming Webhooks**.
3. Refresh the page and click **Add New Webhook to Workspace**.
4. Select a channel to receive Endor Labs findings in **Post to**, then select **Authorize**. If you need to add the incoming webhook to a private channel, you must first be in that channel.
5. From **Settings**, copy the webhook URL under  **Webhook URLs for Your Workspace**. Keep this URL handy to enter in Endor Labs.

For details on creating incoming webhooks in Slack, see [Slack Integration](https://api.slack.com/messaging/webhooks)

## Configure Slack integration

To configure Slack integration, follow these steps:

1. Select **User menu** > **Integrations** from the left sidebar.
2. Under **Notifications**, click **Add** on the **Slack** card. If you already have a Slack integration, click **Manage** instead.
3. Click **Add Notification Integration** to open the **Send Notifications to Slack** dialog.
4. Enter a **Name** and **Description** for this integration.
5. In **Webhook URL**, enter the incoming webhook URL you copied from Slack.
6. Optional: select **Propagate this notification target to all child namespaces** to make this integration available in child namespaces.
7. Click **Add Notification Integration** to save the integration.

### Associate an action policy with a Slack notification

Users can create action policies to send a Slack notification when a scan matches policy conditions. For example, if there is a critical or high vulnerability, send the findings to Slack.

To send a Slack message when a scan produces matching findings, create an action policy with a **Send Notification** action that targets your Slack integration. For the full procedure, see [Create an action policy](/platform-administration/policies/action-policies).

The Slack-specific choices are:

* Under **Choose an Action**, select **Send Notification**.
* From **Select notification targets**, choose the Slack integration you created.

From **Select aggregation type**, choose how findings are grouped into notifications.

* **None (Notify for each Finding)** sends a separate notification for each finding.
* **Project** sends a single notification for all findings in a project.
* **Dependency** sends a notification for every dependency.
* **Dependency per Package Version** sends a notification for every unique combination of dependency and package version.

Slack messages show the top three findings from the highest available severity level. If fewer than three findings exist, only those appear.

### Manage Slack notification targets in Endor Labs

You can view and manage the Endor Labs Slack notification targets created for a project.

1. Select **User menu** > **Integrations** from the left sidebar.
2. Under **Notifications**, click **Manage** on the **Slack** card. You can view all your created notification targets for Slack.
3. To edit a notification target, click the vertical three dots and choose **Edit Notification Integration**.
4. To delete a notification target, click the vertical three dots and choose **Delete Notification Integration**.

### Customize Slack notification templates

Endor Labs provides a default standard template with standard information for the Slack message. You can use the default template or you can choose to edit and customize this template to fit your organization's specific requirements. You can also create custom templates using [Go Templates](https://pkg.go.dev/text/template).

1. Select **User menu** > **Integrations** from the left sidebar.
2. Under **Notifications**, click **Manage** on the **Slack** card to view the configured notification integrations.
3. Choose one, click the vertical three dots on the right side, and click **Edit Template**.
4. Make required changes to any of the following templates and click **Save Template**.
   * **Open** - This template applies when Endor Labs raises new notifications.
   * **Update** - This template applies when an existing notification updates, such as when findings change.
5. Click **Restore to Default** to revert the changes.
6. Use the download icon on the top right corner to download this template.
7. Use the copy icon to copy the information in the template.

### Data model

To create custom templates for Slack messages, you must understand the data supplied to the template.

See the protobuf specification `NotificationData` message used for the templates.

<CodeFile src="/templates/notifications/notification_data.json" lang="proto" />

To understand Project, Finding, PackageVersion, and RepositoryVersion definitions used in this protobuf specification, see:

* [Project resource kind](/developers-api/rest-api/using-the-rest-api/data-model/resource-kinds#project)
* [Finding resource kind](/developers-api/rest-api/using-the-rest-api/data-model/resource-kinds#finding)
* [PackageVersion resource kind](/developers-api/rest-api/using-the-rest-api/data-model/resource-kinds#packageversion)
* [RepositoryVersion resource kind](/developers-api/rest-api/using-the-rest-api/data-model/resource-kinds#repositoryversion)

See the following specification to understand a few additional functions available to the template. You can access these functions by using their corresponding keys.

<CodeFile src="/templates/notifications/notification_func_map.json" lang="go" />

## Run a scan

Run the endorctl scan on your configured projects. See [endorctl scan commands](/developers-api/cli/commands/scan) for more information.

### View notifications in Slack

View Endor Labs' findings in Slack and take remedial actions.

* Sign in to Slack and view the notifications on the configured channel.
* You can view the top 3 findings by their severity level. Click **View All** to see all the findings in Endor Labs.

<img src="https://mintcdn.com/endorlabs-b4795f4f/dHzwUrp_QbpzV9uv/images/integrations/slack/slack_notifications.webp?fit=max&auto=format&n=dHzwUrp_QbpzV9uv&q=85&s=046954c16dbfa7d988c3ca9e975300c7" alt="View notifications in Slack" width="1992" height="1358" data-path="images/integrations/slack/slack_notifications.webp" />


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