API Documentation

Complete guide to integrating ComplianceLayer into your security workflow.

Microsoft Teams Integration

Deliver rich Adaptive Card notifications directly to your Microsoft Teams channels. Get instant visibility into scan results, score changes, and security alerts with interactive cards that include grade displays, finding summaries, and action buttons linking back to full reports.

Plan Requirement: The Microsoft Teams integration is available on Enterprise and MSP plans. Upgrade from Pricing to enable this feature.

Overview

The Teams integration connects ComplianceLayer to your Microsoft Teams workspace using the Bot Framework and Microsoft Graph API. When configured, it delivers:

  • Adaptive Card notifications with structured layouts, grade columns, and action buttons
  • Rich formatting including ColumnSets for side-by-side data, FactSets for key-value pairs, and color-coded severity indicators
  • Interactive action buttons that link directly to full scan reports in ComplianceLayer
  • Weekly security digests summarizing all monitored domains with ranked scores and trend indicators
  • Configurable event routing so different channels receive different notification types

Setup

Connect ComplianceLayer to your Teams workspace in a few steps:

  1. Navigate to Settings → Integrations → Teams
  2. Click Connect to Teams
  3. Sign in with your Microsoft account when the OAuth prompt appears
  4. Authorize ComplianceLayer to send messages on behalf of the bot
  5. Select the team and channel where notifications should be posted
  6. Choose which events you want to receive (scan completed, score changed, alerts)
  7. Optionally enable the weekly security digest
  8. Click Save Configuration
Admin Consent Required: Your Microsoft 365 administrator may need to grant tenant-wide consent for the ComplianceLayer bot application. If you see a "Need admin approval" screen during authorization, contact your IT department to approve the app in the Azure AD admin center.

Architecture

The Teams integration uses Microsoft Bot Framework v4 to deliver Adaptive Cards to your channels. Here is how notifications flow from a scan event to your Teams channel:

ComplianceLayer
Scan Engine
Scan Event
Event Bus
Teams Service
Card Builder
Adaptive Card
Schema v1.4
Bot Framework
Microsoft API
Teams Channel
Notification

When a subscribed event fires, the Teams Service constructs an Adaptive Card payload tailored to the event type, then delivers it through the Bot Framework to your configured channel. Cards are rendered natively by the Teams client with full support for dark mode, mobile, and desktop layouts.

Notification Types

EVENTscan.completed

Delivered when a domain scan finishes successfully. The Adaptive Card uses a ColumnSet layout to display the grade prominently alongside the score and issue breakdown, with an action button linking to the full report.

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4",
  "body": [
    {
      "type": "TextBlock",
      "text": "Scan Completed: example.com",
      "weight": "Bolder",
      "size": "Large",
      "wrap": true
    },
    {
      "type": "ColumnSet",
      "columns": [
        {
          "type": "Column",
          "width": "auto",
          "items": [
            {
              "type": "TextBlock",
              "text": "B",
              "size": "ExtraLarge",
              "weight": "Bolder",
              "color": "Warning"
            },
            {
              "type": "TextBlock",
              "text": "Grade",
              "size": "Small",
              "isSubtle": true,
              "spacing": "None"
            }
          ]
        },
        {
          "type": "Column",
          "width": "auto",
          "items": [
            {
              "type": "TextBlock",
              "text": "85",
              "size": "ExtraLarge",
              "weight": "Bolder"
            },
            {
              "type": "TextBlock",
              "text": "Score",
              "size": "Small",
              "isSubtle": true,
              "spacing": "None"
            }
          ]
        },
        {
          "type": "Column",
          "width": "stretch",
          "items": [
            {
              "type": "FactSet",
              "facts": [
                { "title": "Critical", "value": "0" },
                { "title": "High", "value": "2" },
                { "title": "Medium", "value": "3" },
                { "title": "Low", "value": "3" }
              ]
            }
          ]
        }
      ]
    },
    {
      "type": "TextBlock",
      "text": "Scanned at 2026-03-08 12:34 UTC in 2.8s",
      "size": "Small",
      "isSubtle": true,
      "spacing": "Medium"
    }
  ],
  "actions": [
    {
      "type": "Action.OpenUrl",
      "title": "View Full Report",
      "url": "https://compliancelayer.net/report/12345"
    }
  ]
}
EVENTscore.changed

Delivered when a domain's security score changes between consecutive scans. Uses a FactSet to display old and new values with a delta indicator, making it easy to spot improvements or regressions at a glance.

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4",
  "body": [
    {
      "type": "TextBlock",
      "text": "Score Changed: example.com",
      "weight": "Bolder",
      "size": "Large",
      "wrap": true
    },
    {
      "type": "FactSet",
      "facts": [
        { "title": "Previous Score", "value": "92 (A)" },
        { "title": "Current Score", "value": "78 (C+)" },
        { "title": "Change", "value": "-14 points" },
        { "title": "Previous Grade", "value": "A" },
        { "title": "Current Grade", "value": "C+" }
      ]
    },
    {
      "type": "TextBlock",
      "text": "Score decreased by 14 points since the last scan on 2026-03-01.",
      "wrap": true,
      "spacing": "Medium"
    }
  ],
  "actions": [
    {
      "type": "Action.OpenUrl",
      "title": "View Report",
      "url": "https://compliancelayer.net/report/12346"
    },
    {
      "type": "Action.OpenUrl",
      "title": "Compare Scans",
      "url": "https://compliancelayer.net/domains/example.com/history"
    }
  ]
}
EVENTalert.triggered

Delivered when an alert condition is met, such as a critical vulnerability detected, certificate expiration, or score drop below threshold. The card uses color-coded attention styles based on severity level.

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4",
  "body": [
    {
      "type": "TextBlock",
      "text": "Security Alert: example.com",
      "weight": "Bolder",
      "size": "Large",
      "color": "Attention",
      "wrap": true
    },
    {
      "type": "Container",
      "style": "attention",
      "items": [
        {
          "type": "TextBlock",
          "text": "CRITICAL",
          "weight": "Bolder",
          "color": "Attention"
        },
        {
          "type": "TextBlock",
          "text": "SSL Certificate Expired",
          "weight": "Bolder",
          "size": "Medium",
          "wrap": true
        },
        {
          "type": "TextBlock",
          "text": "The SSL/TLS certificate for example.com expired on 2026-03-07. Visitors will see browser security warnings and connections are no longer encrypted.",
          "wrap": true
        }
      ]
    },
    {
      "type": "FactSet",
      "facts": [
        { "title": "Alert Type", "value": "cert_expired" },
        { "title": "Severity", "value": "Critical" },
        { "title": "Domain", "value": "example.com" },
        { "title": "Detected At", "value": "2026-03-08 12:34 UTC" }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.OpenUrl",
      "title": "View Alert Details",
      "url": "https://compliancelayer.net/alerts/456"
    },
    {
      "type": "Action.OpenUrl",
      "title": "View Domain Dashboard",
      "url": "https://compliancelayer.net/domains/example.com"
    }
  ]
}

Severity Styles: critical uses Attention (red) container style, high uses Warning (yellow), medium uses Accent (blue), low uses Default styling.

DIGESTweekly.digest

Delivered once per week (configurable day and time) with a summary of all monitored domains. Domains are ranked by score with trend indicators showing improvement or regression since the previous week.

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4",
  "body": [
    {
      "type": "TextBlock",
      "text": "Weekly Security Digest",
      "weight": "Bolder",
      "size": "Large"
    },
    {
      "type": "TextBlock",
      "text": "Week of March 3 - March 9, 2026",
      "isSubtle": true,
      "spacing": "None"
    },
    {
      "type": "FactSet",
      "facts": [
        { "title": "Domains Monitored", "value": "12" },
        { "title": "Average Score", "value": "81 (B)" },
        { "title": "Scans Run", "value": "48" },
        { "title": "Alerts Triggered", "value": "3" }
      ]
    },
    {
      "type": "TextBlock",
      "text": "Domain Rankings",
      "weight": "Bolder",
      "size": "Medium",
      "spacing": "Large"
    },
    {
      "type": "ColumnSet",
      "columns": [
        {
          "type": "Column",
          "width": "stretch",
          "items": [
            { "type": "TextBlock", "text": "Domain", "weight": "Bolder", "size": "Small" },
            { "type": "TextBlock", "text": "secure-app.com" },
            { "type": "TextBlock", "text": "api.example.com" },
            { "type": "TextBlock", "text": "dashboard.acme.io" },
            { "type": "TextBlock", "text": "store.example.com" }
          ]
        },
        {
          "type": "Column",
          "width": "auto",
          "items": [
            { "type": "TextBlock", "text": "Grade", "weight": "Bolder", "size": "Small" },
            { "type": "TextBlock", "text": "A (95)" },
            { "type": "TextBlock", "text": "B+ (88)" },
            { "type": "TextBlock", "text": "B (82)" },
            { "type": "TextBlock", "text": "C (71)" }
          ]
        },
        {
          "type": "Column",
          "width": "auto",
          "items": [
            { "type": "TextBlock", "text": "Trend", "weight": "Bolder", "size": "Small" },
            { "type": "TextBlock", "text": "+3" },
            { "type": "TextBlock", "text": "0" },
            { "type": "TextBlock", "text": "-2" },
            { "type": "TextBlock", "text": "+5" }
          ]
        }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.OpenUrl",
      "title": "View Full Dashboard",
      "url": "https://compliancelayer.net/dashboard"
    }
  ]
}

Adaptive Card Format

ComplianceLayer uses Adaptive Cards schema version 1.4, which is supported by Microsoft Teams on desktop, web, and mobile clients. Cards are constructed server-side and delivered through the Bot Framework connector.

Card Structure

Every notification card follows this base structure:

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4",
  "body": [
    {
      "type": "TextBlock",
      "text": "Card Title",
      "weight": "Bolder",
      "size": "Large",
      "wrap": true
    }
    // ... card-specific content
  ],
  "actions": [
    {
      "type": "Action.OpenUrl",
      "title": "Button Label",
      "url": "https://compliancelayer.net/..."
    }
  ]
}

Key Card Elements

The integration uses several Adaptive Card element types to present scan data effectively:

ElementUsageExample
ColumnSetSide-by-side layout for grade, score, and issue countsGrade column next to score column next to findings
FactSetKey-value pairs for structured data like old/new scoresPrevious Score: 92, Current Score: 78
ContainerStyled wrappers for severity-based coloringRed container for critical alerts
TextBlockHeadings, descriptions, timestampsCard title, scan timestamp, descriptions
Action.OpenUrlButtons linking to ComplianceLayer reportsView Full Report, Compare Scans

Color Mapping

Adaptive Card colors are mapped to ComplianceLayer grades for consistent visual feedback:

GradeScore RangeAdaptive Card Color
A / A+90 - 100Good (green)
B / B+80 - 89Warning (yellow)
C / C+70 - 79Warning (yellow)
D60 - 69Attention (red)
F0 - 59Attention (red)

Channel Configuration

Configure which events are delivered to each Teams channel and set thresholds to control notification volume.

Event Selection

Choose which events trigger notifications for each connected channel. Available events:

EventDescriptionDefault
scan.completedFires when any domain scan finishesEnabled
score.changedFires when a score changes between consecutive scansEnabled
alert.triggeredFires when an alert condition is metEnabled
weekly.digestScheduled weekly summary of all domainsDisabled

Score Threshold

Set a minimum score threshold to reduce noise. When configured, scan.completed notifications are only sent when the domain scores below the threshold. This is useful for filtering out passing scans and only alerting on domains that need attention.

{
  "channel_id": "19:abc123@thread.tacv2",
  "team_id": "team-uuid-here",
  "events": ["scan.completed", "alert.triggered"],
  "score_threshold": 80,
  "weekly_digest": {
    "enabled": true,
    "day": "monday",
    "time": "09:00",
    "timezone": "America/New_York"
  }
}
Threshold Behavior: A score threshold of 80 means you will only receive scan.completed cards when the score is below 80. Alerts and score change events are always delivered regardless of the threshold setting.

Weekly Digest Schedule

When enabled, the weekly digest is sent at a fixed day and time each week. Configure the schedule from Settings:

  • Day: Any day of the week (default: Monday)
  • Time: Hour in 24-hour format (default: 09:00)
  • Timezone: IANA timezone string (default: UTC)

Multiple Channels

You can route different event types to different channels. Common patterns include:

  • #security-alertsalert.triggered only, for immediate response
  • #scan-resultsscan.completed and score.changed, for the security team
  • #weekly-reviewweekly.digest only, for management visibility

To add additional channels, return to Settings → Integrations → Teams and click Add Channel. Each channel has independent event and threshold settings.

Programmatic Configuration

You can also configure the Teams integration via the ComplianceLayer API. This is useful for MSPs managing multiple tenants or automating setup.

# List configured Teams channels
curl -X GET https://api.compliancelayer.net/v1/integrations/teams/channels \
  -H "Authorization: Bearer cl_your_api_key"

# Update channel configuration
curl -X PUT https://api.compliancelayer.net/v1/integrations/teams/channels/{channel_id} \
  -H "Authorization: Bearer cl_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["scan.completed", "alert.triggered", "score.changed"],
    "score_threshold": 75,
    "weekly_digest": {
      "enabled": true,
      "day": "monday",
      "time": "09:00",
      "timezone": "America/New_York"
    }
  }'

# Send a test notification
curl -X POST https://api.compliancelayer.net/v1/integrations/teams/test \
  -H "Authorization: Bearer cl_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "channel_id": "19:abc123@thread.tacv2"
  }'

# Disconnect Teams integration
curl -X DELETE https://api.compliancelayer.net/v1/integrations/teams \
  -H "Authorization: Bearer cl_your_api_key"

Security

The Teams integration follows security best practices for OAuth, API access, and data handling.

Azure AD OAuth Scopes

During authorization, ComplianceLayer requests the following Azure AD permissions:

PermissionTypePurpose
ChannelMessage.SendApplicationSend messages to authorized Teams channels
Team.ReadBasic.AllDelegatedList teams for channel selection during setup
Channel.ReadBasic.AllDelegatedList channels within selected teams during setup
Minimal Permissions: ComplianceLayer only requests the permissions needed to send notifications. It cannot read your messages, access files, or modify any Teams settings.

Graph API Permissions

The bot uses Microsoft Graph API to deliver messages. All API calls are authenticated using the Bot Framework service-to-service token. ComplianceLayer does not store your Microsoft password or personal access tokens.

Bot Framework Authentication

Communication between ComplianceLayer and Microsoft Teams uses the Bot Framework Connector service with the following security measures:

  • Service-to-service auth: Bot Framework tokens are issued by Azure AD and validated on every request
  • Channel binding: Tokens are scoped to specific channels, preventing message delivery to unauthorized destinations
  • TLS encryption: All traffic between ComplianceLayer and Microsoft services uses TLS 1.2+
  • Token rotation: Bot Framework tokens are short-lived and automatically rotated

Data Shared with Teams

Notification cards include only summary-level data. The following information is included in cards:

  • Domain name
  • Overall security score and grade
  • Issue counts by severity (critical, high, medium, low)
  • Alert type and severity level
  • Timestamps
  • Links back to ComplianceLayer (full report data requires authentication)

Detailed scan findings, raw vulnerability data, and personally identifiable information are never included in notification cards. Users must authenticate with ComplianceLayer to view full report details.

Revoking Access

To disconnect the Teams integration and revoke all access:

  1. Navigate to Settings → Integrations → Teams
  2. Click Disconnect
  3. Confirm the disconnection in the dialog

This immediately revokes the bot's ability to send messages to your channels. You can also revoke access from the Azure AD admin center:

  1. Go to Azure Portal → Azure Active Directory → Enterprise Applications
  2. Search for "ComplianceLayer"
  3. Select the application and click Properties
  4. Click Delete to fully remove the application grant
Re-authorization Required: After revoking access from Azure AD, you will need to go through the full authorization flow again to reconnect. Channel configurations are preserved on the ComplianceLayer side for 30 days after disconnection.

Troubleshooting

Bot Not Appearing in Channel

  • Verify that your Microsoft 365 admin has approved the ComplianceLayer bot application
  • Check that the bot is not blocked by a Teams app permission policy in your organization
  • Ensure the selected channel allows bot messages (some private channels restrict bot access)
  • Try removing and re-adding the bot: go to the channel, click the + tab, search for ComplianceLayer, and add it
  • Wait up to 5 minutes for bot registration to propagate across Teams

Cards Not Rendering

  • Adaptive Cards v1.4 requires Teams desktop 1.5+ or web client. Update your Teams client to the latest version
  • Some older mobile clients may show a simplified fallback. Update the Teams mobile app
  • Check if your organization has policies restricting Adaptive Card rendering
  • Verify the card appears correctly using the Adaptive Cards Designer by pasting the card JSON
  • If action buttons are missing, check that external link policies allow compliancelayer.net

Authentication Errors

  • "Need admin approval" — Your Azure AD admin must grant consent for the app. Share the admin consent URL from the error screen with your IT department
  • "Invalid grant" — The authorization code has expired. Start the connection flow again from Settings
  • "AADSTS65001" — The user has not consented to the required permissions. Re-authorize from Settings → Integrations → Teams
  • "Insufficient privileges" — Your account does not have permission to install bots in the selected team. Contact your Teams owner

Reconnecting After Token Expiry

Bot Framework tokens are automatically refreshed. However, if the refresh token itself expires (typically after 90 days of inactivity), you will need to reconnect:

  1. Go to Settings → Integrations → Teams
  2. You will see a Reconnect Required banner if the token has expired
  3. Click Reconnect to start the OAuth flow again
  4. Your channel configurations and event settings are preserved
Proactive Alerts: ComplianceLayer sends an email notification 7 days before your Teams token is due to expire, giving you time to reconnect without missing any notifications.

Notifications Delayed

  • Bot Framework message delivery typically takes 1-3 seconds but can be delayed during Microsoft service incidents
  • Check the Microsoft 365 service health page for ongoing issues
  • Verify the notification was sent by checking Settings → Integrations → Teams → Delivery History
  • Rate limiting may apply if sending more than 4 messages per second to a single channel

Missing Events

  • Confirm the event type is enabled for the target channel in your configuration
  • Check if the score threshold is filtering out the notification (only applies to scan.completed)
  • Verify the domain being scanned is in your monitored domains list
  • Review delivery history for any failed delivery attempts and error messages

Next Steps

Support

Need help with the Teams integration? Contact our support team: