Slack Integration
Connect ComplianceLayer directly to your Slack workspace to receive real-time scan notifications, run scans from any channel with a slash command, and get automated weekly security digest summaries — all without leaving Slack.
Key Features
/compliancelayer scan domain.com from any channel to kick off a scan and receive results directly in the conversation.Setup
Connecting your Slack workspace takes less than two minutes. Follow these steps:
- Navigate to Settings → Integrations → Slack in the ComplianceLayer dashboard.
- Click Connect to Slack. You will be redirected to Slack's OAuth consent screen.
- Review the requested permissions and click Allow to authorize ComplianceLayer in your workspace.
- Back in the dashboard, select a notification channel from the dropdown (the bot must be a member of the channel).
- Choose which events to receive (scan completed, score changed, alerts, weekly digest).
- Optionally toggle Weekly Digest on and pick a day and time.
- Click Save. A test notification is sent to confirm everything is working.
#security-alerts for ComplianceLayer notifications so they don't get lost in general conversation.# Verify the Slack integration is active via API
curl -s -H "Authorization: Bearer cl_YOUR_API_KEY" \
https://api.compliancelayer.net/v1/settings/integrations/slack | jq .
# Example response
{
"connected": true,
"workspace": "Acme Corp",
"channel": "#security-alerts",
"events": ["scan.completed", "score.changed", "alert.triggered"],
"weekly_digest": {
"enabled": true,
"day": "monday",
"time": "09:00"
},
"connected_at": "2026-03-15T10:30:00Z",
"connected_by": "jane@acme.com"
}Architecture
When a qualifying event occurs, ComplianceLayer's Slack service formats a Block Kit message and delivers it to your workspace via the Slack Web API. Here is the high-level flow:
Scan Engine
Message Builder
chat.postMessage
#security-alerts
For slash commands, the flow is reversed: Slack sends the command payload to ComplianceLayer's endpoint, the scan runs, and the result is posted back as an ephemeral message visible only to the user who invoked the command.
Notification Types
ComplianceLayer sends four categories of Slack notifications. Each is delivered as a rich Block Kit message with contextual information.
scan.completedSent when a domain scan finishes. Includes the overall grade, numeric score, issue counts by severity, and the top three findings. Links directly to the full report in the ComplianceLayer dashboard.
{
"channel": "C0123SECURITY",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Scan Complete: example.com"
}
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Grade:*\nB (85/100)" },
{ "type": "mrkdwn", "text": "*Scanned At:*\n2026-04-05 14:32 UTC" }
]
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Critical:* 0" },
{ "type": "mrkdwn", "text": "*High:* 2" },
{ "type": "mrkdwn", "text": "*Medium:* 3" },
{ "type": "mrkdwn", "text": "*Low:* 3" }
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Top Findings:*\n1. Missing Content-Security-Policy header\n2. DNSSEC not enabled\n3. TLS 1.0 still supported"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "View Full Report" },
"url": "https://compliancelayer.net/app/scans/12345",
"style": "primary"
}
]
}
]
}score.changedTriggered when a monitored domain's score changes by more than your configured threshold (default: 5 points). Shows the old score, new score, and direction of change.
{
"channel": "C0123SECURITY",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Score Change: example.com"
}
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Previous Score:*\n92 (A)" },
{ "type": "mrkdwn", "text": "*Current Score:*\n78 (C+)" }
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Change:* -14 points (drop)\n*Trigger:* Score decreased below threshold"
}
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "Detected at 2026-04-05 09:15 UTC | <https://compliancelayer.net/app/domains/example.com|View Domain>"
}
]
}
]
}alert.triggeredSent when a configured alert condition fires, such as an SSL certificate expiring within 14 days, a critical vulnerability detected, or a new security issue found on a monitored domain.
{
"channel": "C0123SECURITY",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Alert: SSL Certificate Expiring Soon"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Domain:* example.com\n*Severity:* High\n*Details:* SSL certificate expires in 12 days (2026-04-17). Renew immediately to avoid downtime."
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "View Alert" },
"url": "https://compliancelayer.net/app/alerts/789",
"style": "danger"
}
]
}
]
}Alert Types: cert_expiring_soon, cert_expired, critical_issue, score_drop, config_change
weekly_digestA scheduled summary posted once per week at your configured day and time. Lists every monitored domain with its current grade, score trend (up/down/unchanged), and count of open issues.
{
"channel": "C0123SECURITY",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Weekly Security Digest - Apr 5, 2026"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*5 domains monitored* | *Avg Score: 82*"
}
},
{ "type": "divider" },
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*example.com* - A (92) | +3 | 2 open issues\n*store.example.com* - B (85) | -- | 5 open issues\n*api.example.com* - B+ (88) | +1 | 3 open issues\n*blog.example.com* - C+ (78) | -4 | 8 open issues\n*docs.example.com* - A (95) | +2 | 1 open issue"
}
},
{ "type": "divider" },
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "Period: Mar 29 - Apr 5, 2026 | <https://compliancelayer.net/app/domains|View All Domains>"
}
]
}
]
}Slash Command
The /compliancelayer slash command lets anyone in your workspace trigger a scan directly from Slack. Results are returned as an ephemeral message visible only to the user who invoked the command.
Usage
/compliancelayer scan example.com
# The bot responds with an ephemeral message:
# "Scanning example.com... Results will appear here shortly."
# After 15-30 seconds, the result appears:
# Grade: B (85/100) | Critical: 0 | High: 2 | Medium: 3
# Top findings: Missing CSP header, DNSSEC not enabled
# [View Full Report]Available Sub-Commands
| Command | Description | Example |
|---|---|---|
scan <domain> | Run a full security scan on a domain | /compliancelayer scan example.com |
status <domain> | Show the latest scan results for a monitored domain | /compliancelayer status example.com |
list | List all monitored domains with current grades | /compliancelayer list |
help | Show available commands and usage | /compliancelayer help |
Response Format
The slash command response is delivered as an ephemeral Block Kit message. Here is the structure returned for a scan sub-command:
{
"response_type": "ephemeral",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Scan Results: example.com"
}
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Grade:*\nB (85/100)" },
{ "type": "mrkdwn", "text": "*Duration:*\n2.8s" }
]
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Critical:* 0" },
{ "type": "mrkdwn", "text": "*High:* 2" },
{ "type": "mrkdwn", "text": "*Medium:* 3" },
{ "type": "mrkdwn", "text": "*Low:* 3" }
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Top Findings:*\n1. Missing Content-Security-Policy header\n2. DNSSEC not enabled\n3. TLS 1.0 still supported"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "View Full Report" },
"url": "https://compliancelayer.net/app/scans/12345"
},
{
"type": "button",
"text": { "type": "plain_text", "text": "Share to Channel" },
"action_id": "share_scan_12345"
}
]
}
]
}Channel Configuration
Fine-tune which notifications are delivered and how they behave from Settings → Integrations → Slack.
Event Selection
Toggle individual event types on or off. Only enabled events will generate Slack messages:
| Event | Default | Description |
|---|---|---|
scan.completed | On | Notify when any scan finishes |
score.changed | On | Notify when a score crosses the configured threshold |
alert.triggered | On | Notify when an alert condition fires |
weekly_digest | Off | Post a weekly summary of all monitored domains |
Score Change Threshold
Control the minimum score change required to trigger a score.changed notification. This prevents noise from minor fluctuations:
- Default: 5 points
- Range: 1 - 50 points
- Set to 1 for maximum sensitivity or 10+ for only significant changes
# Update score change threshold via API
curl -X PUT \
-H "Authorization: Bearer cl_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"score_threshold": 10}' \
https://api.compliancelayer.net/v1/settings/integrations/slack/configWeekly Digest Schedule
When the weekly digest is enabled, choose the delivery day and time:
- Day: Monday through Sunday (default: Monday)
- Time: Any hour in 30-minute increments, specified in UTC (default: 09:00 UTC)
{
"weekly_digest": {
"enabled": true,
"day": "monday",
"time": "09:00",
"timezone_note": "All times are in UTC. A Monday 09:00 UTC digest arrives at 04:00 EST / 01:00 PST."
}
}Multiple Channels
Enterprise and MSP plans support routing different event types to different channels. For example, send critical alerts to #incidents and weekly digests to #security-weekly:
{
"channels": [
{
"channel_id": "C0123ALERTS",
"channel_name": "#security-alerts",
"events": ["scan.completed", "score.changed", "alert.triggered"]
},
{
"channel_id": "C0456WEEKLY",
"channel_name": "#security-weekly",
"events": ["weekly_digest"]
},
{
"channel_id": "C0789INCIDENTS",
"channel_name": "#incidents",
"events": ["alert.triggered"],
"filter": { "severity": ["critical", "high"] }
}
]
}/invite @ComplianceLayer in the target channel.Notification Examples
Below are realistic examples of how each notification type appears when rendered by Slack.
Scan Completed Notification
A scan completion message includes the grade prominently, issue breakdown, top findings, and a direct link to the full report:
{
"channel": "C0123SECURITY",
"text": "Scan completed for example.com: B (85/100)",
"blocks": [
{
"type": "header",
"text": { "type": "plain_text", "text": "Scan Complete: example.com" }
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Grade:*\nB (85/100)" },
{ "type": "mrkdwn", "text": "*Modules:*\n16/16 passed" },
{ "type": "mrkdwn", "text": "*Duration:*\n2.8 seconds" },
{ "type": "mrkdwn", "text": "*Scanned At:*\nApr 5, 2026 14:32 UTC" }
]
},
{ "type": "divider" },
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Issue Breakdown:*\nCritical: 0 | High: 2 | Medium: 3 | Low: 3"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Top Findings:*\n1. Missing Content-Security-Policy header (High)\n2. DNSSEC not enabled (High)\n3. TLS 1.0 still accepted (Medium)"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "View Full Report" },
"url": "https://compliancelayer.net/app/scans/12345",
"style": "primary"
},
{
"type": "button",
"text": { "type": "plain_text", "text": "Rescan Domain" },
"action_id": "rescan_example_com"
}
]
},
{
"type": "context",
"elements": [
{ "type": "mrkdwn", "text": "ComplianceLayer | Scan ID: 12345" }
]
}
]
}Score Change Alert
{
"channel": "C0123SECURITY",
"text": "Score dropped for example.com: 92 -> 78 (-14 points)",
"blocks": [
{
"type": "header",
"text": { "type": "plain_text", "text": "Score Drop: example.com" }
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Previous:*\nA (92/100)" },
{ "type": "mrkdwn", "text": "*Current:*\nC+ (78/100)" },
{ "type": "mrkdwn", "text": "*Change:*\n-14 points" },
{ "type": "mrkdwn", "text": "*Trend:*\nDecreasing" }
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*New Issues Detected:*\n- SSL certificate chain incomplete\n- HTTP Strict-Transport-Security header missing max-age"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "Investigate" },
"url": "https://compliancelayer.net/app/domains/example.com",
"style": "danger"
}
]
}
]
}Programmatic Notification via API
You can also trigger a test notification or send a custom message through the integration API:
import requests
API_KEY = "cl_YOUR_API_KEY"
BASE_URL = "https://api.compliancelayer.net/v1"
# Send a test notification to verify the integration
response = requests.post(
f"{BASE_URL}/settings/integrations/slack/test",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"message": "Test notification from ComplianceLayer"}
)
print(response.json())
# {"status": "sent", "channel": "#security-alerts", "ts": "1712345678.123456"}Security
The ComplianceLayer Slack integration follows the principle of least privilege. Here is exactly what is requested and how your data is handled.
OAuth Scopes
When you authorize ComplianceLayer, the following Slack OAuth scopes are requested:
| Scope | Purpose |
|---|---|
chat:write | Post notification messages to channels the bot has been invited to |
commands | Register and respond to the /compliancelayer slash command |
channels:read | List public channels so you can select a notification target during setup |
groups:read | List private channels the bot belongs to for notification targeting |
Data Shared with Slack
Only the following data is included in Slack messages:
- Domain names being scanned
- Security scores and grades (numeric score, letter grade)
- Issue counts by severity (critical, high, medium, low)
- Top finding summaries (brief one-line descriptions, not full technical details)
- Links to the ComplianceLayer dashboard for full reports
Full scan payloads, raw vulnerability data, and detailed technical findings are never sent to Slack. Users must click through to the dashboard for complete information.
Token Storage
The Slack OAuth access token is stored encrypted at rest in ComplianceLayer's database using AES-256-GCM encryption. Tokens are only decrypted in memory when needed to send a message and are never logged or exposed in API responses.
Revoking Access
You can disconnect the Slack integration at any time:
- Go to Settings → Integrations → Slack in the ComplianceLayer dashboard.
- Click Disconnect.
- Confirm the disconnection. This immediately revokes the stored OAuth token.
You can also revoke access from the Slack side:
- Open your Slack workspace settings.
- Go to Manage Apps.
- Find ComplianceLayer and click Remove App.
Troubleshooting
Bot Not Posting to Channel
- Verify the bot is a member of the target channel. Use
/invite @ComplianceLayerin the channel. - Check that the integration is still connected in Settings → Integrations → Slack.
- Ensure the channel has not been archived or deleted.
- For private channels, confirm the bot was explicitly invited (it cannot discover private channels on its own).
Slash Command Not Working
- Verify the ComplianceLayer app is installed in your workspace (check Manage Apps in Slack).
- Try typing
/compliancelayer helpto test basic functionality. - If you see "This command is not available", the app may need to be reinstalled. Disconnect and reconnect from the ComplianceLayer dashboard.
- Ensure your user account is linked to the ComplianceLayer organization that owns the integration.
Missing Notifications
- Check which events are enabled in Settings → Integrations → Slack.
- For
score.changedevents, verify the threshold setting. If set to 10, changes smaller than 10 points will not trigger a notification. - Weekly digest notifications require the digest to be explicitly enabled and a day/time configured.
- Check the integration activity log in the dashboard for any delivery errors.
Duplicate Notifications
- If you have multiple channels configured for the same event, each channel will receive its own copy. This is expected.
- Check for duplicate webhook endpoints that might also be sending Slack notifications independently.
Reconnecting After Issues
If the integration enters an error state, follow these steps to reconnect:
- Go to Settings → Integrations → Slack and click Disconnect.
- Wait 30 seconds for the token revocation to propagate.
- Click Connect to Slack and re-authorize the app.
- Re-select your notification channel and event preferences.
- Click Send Test Notification to verify the connection.
# Check the current integration status via API
curl -s -H "Authorization: Bearer cl_YOUR_API_KEY" \
https://api.compliancelayer.net/v1/settings/integrations/slack | jq .
# Healthy response
{
"connected": true,
"status": "active",
"last_message_at": "2026-04-05T14:32:00Z",
"errors_last_24h": 0
}
# Error state response
{
"connected": true,
"status": "error",
"last_error": "token_revoked",
"last_error_at": "2026-04-05T12:00:00Z",
"errors_last_24h": 5
}API Reference
Manage the Slack integration programmatically using these endpoints:
/v1/settings/integrations/slackReturns the current Slack integration status, connected workspace, channel configuration, and event settings.
/v1/settings/integrations/slack/configUpdate event selection, score threshold, channel routing, and weekly digest settings.
/v1/settings/integrations/slack/testSend a test notification to the configured Slack channel to verify the connection is working.
/v1/settings/integrations/slackDisconnect the Slack integration and revoke the stored OAuth token. This action is immediate and cannot be undone.
Next Steps
Support
Need help with the Slack integration? Contact our support team:
- Email: support@compliancelayer.net
- Dashboard: Check integration status in Settings → Integrations → Slack
- Status: Check the system status page for any ongoing issues