Integration · ConnectWise Manage

Connect ComplianceLayer to ConnectWise Manage

Automatically create service tickets from security findings. Route critical issues to the right board. Keep your PSA in sync with every scan.

IntegrationConnectWise Manage
MethodWebhook + REST API
CreatesService tickets
Plan RequiredProfessional+
0
Manual ticket creation
<30s
Finding to ticket
4
Severity-to-priority levels
150
Lines of bridge code
How It Works

From scan finding to service ticket

Three steps to connect ComplianceLayer findings to your ConnectWise service board. No middleware platform required.

Step 01
Configure a webhook

In your ComplianceLayer dashboard, create an outbound webhook pointing to your ConnectWise bridge endpoint. Choose which events to send — scan completed, grade changed, or critical finding detected.

Webhook URLEvent typesSecret key
Step 02
Map severity to priority

The bridge translates ComplianceLayer severity levels to ConnectWise priority IDs. Critical findings become Priority 1 tickets. High becomes Priority 2. You control the mapping.

Critical → P1High → P2Configurable
Step 03
Tickets appear on your board

When a scan completes with critical or high findings, service tickets are created on your chosen ConnectWise board. Each ticket includes the domain, grade, finding details, and remediation steps.

Service boardAuto-assignSLA tracking
What Gets Created

A real ticket, not a notification

Each critical or high finding creates a service ticket on your ConnectWise board with the domain name, security grade, finding summary, severity, remediation steps, and a link to the full ComplianceLayer report. Your techs see exactly what to fix and where to start.

ConnectWise Service Ticket
Board: Security Alerts
Auto-Created
Summary[C] acme-corp.com: SSL certificate expires in 12 days
BoardSecurity Alerts
PriorityPriority 1 - Critical
StatusNew
TypeSecurity Finding
CompanyAcme Corp
Ticket Content

Actionable detail in every ticket

The ticket body includes everything a technician needs to remediate the finding without leaving ConnectWise.

Domain: acme-corp.com
Security Grade: C (67/100)
Finding: SSL certificate expires in 12 days
Severity: Critical
Remediation:
Renew the SSL/TLS certificate before expiration.
Verify auto-renewal is enabled with the certificate
authority. Test the new certificate in staging before
deploying to production.
Full report: https://compliancelayer.net/report/abc123
Setup Guide

Get connected in 15 minutes

Step 1
Create ConnectWise API keys
In ConnectWise Manage, go to System > Members > API Members. Create a new API member with access to the Service module. Note the company ID, public key, and private key.
Step 2
Deploy the bridge script
Download the bridge.py script from our examples repository. Configure your .env file with ConnectWise credentials and the webhook secret. Deploy to any server, VM, or serverless platform.
Step 3
Create a webhook in ComplianceLayer
In your ComplianceLayer dashboard, go to Settings > Webhooks. Add a new webhook pointing to your bridge URL. Select the "scan.completed" event. Copy the signing secret to your .env.
Step 4
Configure your service board
Set the CW_BOARD_ID environment variable to your target service board ID. Optionally configure the severity-to-priority mapping to match your ConnectWise priority IDs.
Step 5
Run a test scan
Trigger a scan on any monitored domain. When findings come in with critical or high severity, verify that tickets appear on your ConnectWise board with the correct priority and details.
Step 6
Enable scheduled scanning
Set up daily or weekly scans for all client domains. The bridge will automatically create tickets for new findings. Resolved findings won't create duplicate tickets.
Code

Bridge script — Python or PowerShell

A lightweight script that receives ComplianceLayer webhooks and creates ConnectWise tickets. Full source available in our examples repository.

Pythonbridge.py
# bridge.py — receives ComplianceLayer webhooks,
# creates ConnectWise Manage service tickets

from fastapi import FastAPI, Request, HTTPException
import httpx, hashlib, hmac, os

app = FastAPI()

CW_URL    = os.environ["CW_URL"]       # e.g. https://na.myconnectwise.net/v4_6_release/apis/3.0
CW_COMPANY = os.environ["CW_COMPANY"]
CW_PUBLIC  = os.environ["CW_PUBLIC_KEY"]
CW_PRIVATE = os.environ["CW_PRIVATE_KEY"]
CW_BOARD_ID = int(os.environ.get("CW_BOARD_ID", "1"))
WEBHOOK_SECRET = os.environ["WEBHOOK_SECRET"]

SEVERITY_MAP = {
    "critical": {"id": 1, "name": "Priority 1 - Critical"},
    "high":     {"id": 2, "name": "Priority 2 - High"},
    "medium":   {"id": 3, "name": "Priority 3 - Medium"},
    "low":      {"id": 4, "name": "Priority 4 - Low"},
}

@app.post("/webhook/compliancelayer")
async def handle_webhook(request: Request):
    body = await request.body()
    signature = request.headers.get("X-Webhook-Signature", "")
    expected = hmac.new(
        WEBHOOK_SECRET.encode(), body, hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        raise HTTPException(401, "Invalid signature")

    payload = await request.json()
    domain  = payload["domain"]
    grade   = payload["grade"]

    for finding in payload.get("findings", []):
        severity = finding.get("severity", "low")
        if severity not in ("critical", "high"):
            continue

        await create_ticket(
            summary=f"[{grade}] {domain}: {finding['title']}",
            body=build_ticket_body(domain, grade, finding),
            priority=SEVERITY_MAP[severity],
        )

    return {"status": "ok"}
PowerShellbridge.ps1
# bridge.ps1 — PowerShell alternative for Windows MSPs
$webhookBody = Get-Content -Raw -Path $args[0] | ConvertFrom-Json

$cwUrl     = $env:CW_URL
$company   = $env:CW_COMPANY
$publicKey = $env:CW_PUBLIC_KEY
$privateKey = $env:CW_PRIVATE_KEY

$auth = [Convert]::ToBase64String(
  [Text.Encoding]::ASCII.GetBytes(
    "$company+$publicKey:$privateKey"
  )
)

foreach ($finding in $webhookBody.findings) {
  if ($finding.severity -notin @("critical","high")) { continue }

  $ticket = @{
    summary = "[$($webhookBody.grade)] $($webhookBody.domain): $($finding.title)"
    board   = @{ id = $env:CW_BOARD_ID }
    priority = @{
      id = switch ($finding.severity) {
        "critical" { 1 } "high" { 2 }
      }
    }
    initialDescription = @"
Domain: $($webhookBody.domain)
Grade: $($webhookBody.grade)
Finding: $($finding.title)
Severity: $($finding.severity)

Remediation:
$($finding.remediation)
"@
  } | ConvertTo-Json -Depth 5

  Invoke-RestMethod -Uri "$cwUrl/service/tickets" \
    -Method Post -Body $ticket \
    -ContentType "application/json" \
    -Headers @{ Authorization = "Basic $auth" }
}
Get Started with the API →

Start routing findings to ConnectWise

Set up webhooks in your dashboard. Deploy the bridge script. Critical findings become service tickets — automatically.

Webhooks available on Professional plan ($249/mo) and above. View pricing →