ConnectWise Automate Alerts · git:20260713.1fbd3f3 · 2026-07-13 · sha256 951fb294041c02eb
ConnectWise Automate Alerts git:20260713.1fbd3f3A
Immutable. This exact content is served forever at /api/v1/blob/951fb294041c02eb.
---
name: "ConnectWise Automate Alerts"
description: >
Use this skill when working with ConnectWise Automate alerts - listing active
alerts, acknowledging alerts, viewing alert history, and creating tickets from
alerts. Covers alert sources (monitors, scripts, events), alert severity levels,
alert lifecycle management, and ticket integration.
when_to_use: >-
When listing active alerts, acknowledging alerts, viewing alert history, and creating tickets
from alerts. Use when: automate alert, automate notification, alert acknowledgment, alert
history, alert ticket, monitor alert, labtech alert, or automate incident.
---
# ConnectWise Automate Alert Management
## Overview
Alerts in ConnectWise Automate are notifications generated by monitors, scripts, or system events that require attention. This skill covers alert listing, acknowledgment, history tracking, and ticket creation workflows.
## Key Concepts
### Alert Sources
| Source | Description | Example |
|--------|-------------|---------|
| **Monitor** | Generated by monitor threshold | CPU > 90% |
| **Script** | Generated by script execution | Backup failed |
| **Event Log** | Windows Event Log trigger | Security event |
| **System** | Automate system events | Agent offline |
| **Manual** | User-created alerts | Maintenance note |
### Alert Severity Levels
| Level | Value | Description | Response Time |
|-------|-------|-------------|---------------|
| `Information` | 1 | Informational only | Review at convenience |
| `Warning` | 2 | Potential issue | Investigate within hours |
| `Error` | 3 | Failure detected | Respond within SLA |
| `Critical` | 4 | Severe/emergency | Immediate response |
### Alert Lifecycle
```
Generated → Active → Acknowledged → Resolved
│ │
│ └── Ticket Created
│
└── Auto-Cleared (if condition clears)
```
### Alert Status
| Status | Description |
|--------|-------------|
| `New` | Just generated, unread |
| `Active` | Open, unacknowledged |
| `Acknowledged` | Someone is working on it |
| `Resolved` | Issue fixed, alert closed |
| `Cleared` | Condition auto-cleared |
| `Suppressed` | Temporarily hidden |
## Field Reference
### Alert Fields
```typescript
interface Alert {
// Identifiers
AlertID: number; // Primary key
AlertGUID: string; // Global unique ID
// Source
Source: AlertSource; // Monitor, Script, EventLog, System
SourceID: number; // ID of source (MonitorID, ScriptID, etc.)
SourceName: string; // Name of source
// Target
ComputerID: number; // Affected computer
ComputerName: string; // Computer hostname
ClientID: number; // Parent client
ClientName: string; // Client name
LocationID: number; // Location ID
// Alert Details
Subject: string; // Alert title
Message: string; // Detailed message
Severity: AlertSeverity; // 1-4 severity level
Status: AlertStatus; // Current status
// Timestamps
TimeGenerated: string; // When created
TimeAcknowledged: string; // When acknowledged
TimeResolved: string; // When resolved
LastUpdate: string; // Last status change
// Acknowledgment
AcknowledgedBy: string; // User who acknowledged
Notes: string; // Acknowledgment notes
// Ticket Integration
TicketID: number; // Linked ticket ID
TicketStatus: string; // Ticket status
// Context
Category: string; // Alert category
AdditionalData: object; // Extra context data
}
type AlertSource = 'Monitor' | 'Script' | 'EventLog' | 'System' | 'Manual';
type AlertSeverity = 1 | 2 | 3 | 4;
type AlertStatus = 'New' | 'Active' | 'Acknowledged' | 'Resolved' | 'Cleared' | 'Suppressed';
```
### Alert History Fields
```typescript
interface AlertHistory {
HistoryID: number;
AlertID: number;
Action: string; // Status change, note added, etc.
ActionBy: string; // User who made change
ActionTime: string; // When action occurred
PreviousStatus: string;
NewStatus: string;
Notes: string;
}
```
## API Patterns
### List Active Alerts
```http
GET /cwa/api/v1/Alerts?condition=Status in ('New','Active')&pageSize=100
Authorization: Bearer {token}
```
**Response:**
```json
[
{
"AlertID": 54321,
"Subject": "Disk C: Low Space",
"Message": "Disk C: is 8% free on ACME-DC01",
"Severity": 2,
"Status": "Active",
"ComputerID": 12345,
"ComputerName": "ACME-DC01",
"ClientName": "Acme Corporation",
"Source": "Monitor",
"SourceName": "Disk Space Monitor",
"TimeGenerated": "2024-02-15T08:30:00Z",
"Category": "Performance"
}
]
```
### Get Alert Details
```http
GET /cwa/api/v1/Alerts/{alertID}
Authorization: Bearer {token}
```
**Response:**
```json
{
"AlertID": 54321,
"AlertGUID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"Subject": "Disk C: Low Space",
"Message": "Disk C: is 8% free on ACME-DC01\n\nTotal: 500 GB\nFree: 40 GB\nThreshold: 10%",
"Severity": 2,
"Status": "Active",
"ComputerID": 12345,
"ComputerName": "ACME-DC01",
"ClientID": 100,
"ClientName": "Acme Corporation",
"LocationID": 1,
"Source": "Monitor",
"SourceID": 5001,
"SourceName": "Disk Space Monitor",
"TimeGenerated": "2024-02-15T08:30:00Z",
"Category": "Performance",
"AdditionalData": {
"DriveLetter": "C:",
"FreeSpaceGB": 40,
"TotalSpaceGB": 500,
"FreePercent": 8
}
}
```
### Filter Alerts by Client
```http
GET /cwa/api/v1/Alerts?condition=ClientID = 100 and Status = 'Active'&pageSize=100
Authorization: Bearer {token}
```
### Filter Alerts by Severity
```http
GET /cwa/api/v1/Alerts?condition=Severity >= 3 and Status = 'Active'&pageSize=100
Authorization: Bearer {token}
```
### Acknowledge Alert
```http
POST /cwa/api/v1/Alerts/{alertID}/Acknowledge
Authorization: Bearer {token}
Content-Type: application/json
{
"Notes": "Investigating disk space issue"
}
```
**Response:**
```json
{
"AlertID": 54321,
"Status": "Acknowledged",
"AcknowledgedBy": "admin@example.com",
"TimeAcknowledged": "2024-02-15T10:45:00Z"
}
```
### Resolve Alert
```http
POST /cwa/api/v1/Alerts/{alertID}/Resolve
Authorization: Bearer {token}
Content-Type: application/json
{
"Notes": "Cleared 50GB of temp files. Disk now at 18% free."
}
```
### Add Note to Alert
```http
POST /cwa/api/v1/Alerts/{alertID}/Notes
Authorization: Bearer {token}
Content-Type: application/json
{
"Note": "Contacted user about large files in Downloads folder"
}
```
### Create Ticket from Alert
```http
POST /cwa/api/v1/Alerts/{alertID}/CreateTicket
Authorization: Bearer {token}
Content-Type: application/json
{
"TicketSubject": "Disk Space Critical on ACME-DC01",
"Priority": 2,
"BoardID": 1,
"Notes": "Auto-created from Automate alert"
}
```
**Response:**
```json
{
"AlertID": 54321,
"TicketID": 98765,
"TicketNumber": "TKT-2024-00123",
"TicketStatus": "New"
}
```
### Get Alert History
```http
GET /cwa/api/v1/Alerts/{alertID}/History
Authorization: Bearer {token}
```
**Response:**
```json
[
{
"HistoryID": 1,
"Action": "Created",
"ActionTime": "2024-02-15T08:30:00Z",
"NewStatus": "New"
},
{
"HistoryID": 2,
"Action": "Acknowledged",
"ActionBy": "admin@example.com",
"ActionTime": "2024-02-15T10:45:00Z",
"PreviousStatus": "Active",
"NewStatus": "Acknowledged",
"Notes": "Investigating disk space issue"
}
]
```
### Suppress Alert
```http
POST /cwa/api/v1/Alerts/{alertID}/Suppress
Authorization: Bearer {token}
Content-Type: application/json
{
"Duration": 3600,
"Reason": "Scheduled maintenance window"
}
```
### Bulk Acknowledge Alerts
```http
POST /cwa/api/v1/Alerts/BulkAcknowledge
Authorization: Bearer {token}
Content-Type: application/json
{
"AlertIDs": [54321, 54322, 54323],
"Notes": "Bulk acknowledgment for server maintenance"
}
```
## Workflows
### Get Critical Alerts Dashboard
```javascript
async function getCriticalAlertsDashboard(client) {
const criticalAlerts = await client.request(
`/Alerts?condition=Severity >= 3 and Status in ('New','Active')&pageSize=100`
);
const dashboard = {
totalCritical: criticalAlerts.length,
byClient: {},
byCategory: {},
oldest: null
};
for (const alert of criticalAlerts) {
// Group by client
const clientName = alert.ClientName || 'Unknown';
if (!dashboard.byClient[clientName]) {
dashboard.byClient[clientName] = [];
}
dashboard.byClient[clientName].push({
id: alert.AlertID,
subject: alert.Subject,
computer: alert.ComputerName,
severity: alert.Severity,
age: getAlertAge(alert.TimeGenerated)
});
// Group by category
const category = alert.Category || 'Uncategorized';
dashboard.byCategory[category] = (dashboard.byCategory[category] || 0) + 1;
// Track oldest
if (!dashboard.oldest || new Date(alert.TimeGenerated) < new Date(dashboard.oldest.TimeGenerated)) {
dashboard.oldest = alert;
}
}
return dashboard;
}
function getAlertAge(timeGenerated) {
const now = new Date();
const generated = new Date(timeGenerated);
const diffMs = now - generated;
const diffMins = Math.floor(diffMs / 60000);
if (diffMins < 60) return `${diffMins} minutes`;
if (diffMins < 1440) return `${Math.floor(diffMins / 60)} hours`;
return `${Math.floor(diffMins / 1440)} days`;
}
```
### Acknowledge and Create Ticket Workflow
```javascript
async function acknowledgeAndCreateTicket(client, alertId, options = {}) {
const {
notes = 'Acknowledged and ticket created',
priority = 2,
boardId = 1
} = options;
// Get alert details
const alert = await client.request(`/Alerts/${alertId}`);
// Acknowledge the alert
await client.request(`/Alerts/${alertId}/Acknowledge`, {
method: 'POST',
body: JSON.stringify({ Notes: notes })
});
// Create ticket
const ticketResponse = await client.request(`/Alerts/${alertId}/CreateTicket`, {
method: 'POST',
body: JSON.stringify({
TicketSubject: alert.Subject,
Priority: alert.Severity >= 3 ? 1 : priority,
BoardID: boardId,
Notes: `Auto-created from Automate alert\n\n${alert.Message}`
})
});
return {
alert: {
id: alertId,
subject: alert.Subject,
status: 'Acknowledged'
},
ticket: {
id: ticketResponse.TicketID,
number: ticketResponse.TicketNumber
}
};
}
```
### Alert Triage by Client
```javascript
async function triageAlertsByClient(client, clientId) {
const alerts = await client.request(
`/Alerts?condition=ClientID = ${clientId} and Status in ('New','Active')&pageSize=200`
);
const triage = {
client: clientId,
total: alerts.length,
critical: [],
error: [],
warning: [],
info: []
};
for (const alert of alerts) {
const summary = {
id: alert.AlertID,
subject: alert.Subject,
computer: alert.ComputerName,
source: alert.SourceName,
age: getAlertAge(alert.TimeGenerated)
};
switch (alert.Severity) {
case 4: triage.critical.push(summary); break;
case 3: triage.error.push(summary); break;
case 2: triage.warning.push(summary); break;
default: triage.info.push(summary);
}
}
return triage;
}
```
### Bulk Alert Resolution
```javascript
async function bulkResolveAlerts(client, alertIds, notes) {
const results = [];
for (const alertId of alertIds) {
try {
await client.request(`/Alerts/${alertId}/Resolve`, {
method: 'POST',
body: JSON.stringify({ Notes: notes })
});
results.push({ alertId, status: 'resolved' });
} catch (error) {
results.push({ alertId, status: 'failed', error: error.message });
}
// Respect rate limits
await sleep(100);
}
return {
resolved: results.filter(r => r.status === 'resolved').length,
failed: results.filter(r => r.status === 'failed').length,
details: results
};
}
```
### Alert Escalation Check
```javascript
async function checkAlertEscalation(client) {
const alerts = await client.request(
`/Alerts?condition=Status = 'Active' and Severity >= 2&pageSize=500`
);
const escalations = [];
const now = new Date();
for (const alert of alerts) {
const generated = new Date(alert.TimeGenerated);
const ageMinutes = (now - generated) / 60000;
// Escalation rules based on severity and age
let shouldEscalate = false;
let reason = '';
switch (alert.Severity) {
case 4: // Critical
if (ageMinutes > 15) {
shouldEscalate = true;
reason = 'Critical alert unacknowledged for 15+ minutes';
}
break;
case 3: // Error
if (ageMinutes > 60) {
shouldEscalate = true;
reason = 'Error alert unacknowledged for 1+ hour';
}
break;
case 2: // Warning
if (ageMinutes > 240) {
shouldEscalate = true;
reason = 'Warning alert unacknowledged for 4+ hours';
}
break;
}
if (shouldEscalate) {
escalations.push({
alertId: alert.AlertID,
subject: alert.Subject,
client: alert.ClientName,
computer: alert.ComputerName,
severity: alert.Severity,
ageMinutes: Math.round(ageMinutes),
reason
});
}
}
return escalations;
}
```
## Error Handling
### Common Alert API Errors
| Error | Status | Cause | Resolution |
|-------|--------|-------|------------|
| Alert not found | 404 | Invalid AlertID | Verify alert exists |
| Already resolved | 400 | Alert already closed | Check current status |
| Permission denied | 403 | No access to alert | Check user permissions |
| Invalid status | 400 | Invalid status transition | Follow lifecycle rules |
| Ticket creation failed | 400 | PSA integration error | Check ticket board config |
### Error Response Example
```json
{
"error": {
"code": "BadRequest",
"message": "Cannot acknowledge already resolved alert"
}
}
```
### Safe Alert Resolution
```javascript
async function safeResolveAlert(client, alertId, notes) {
// Get current alert status
const alert = await client.request(`/Alerts/${alertId}`);
if (alert.Status === 'Resolved' || alert.Status === 'Cleared') {
return {
success: false,
error: `Alert already ${alert.Status.toLowerCase()}`
};
}
try {
await client.request(`/Alerts/${alertId}/Resolve`, {
method: 'POST',
body: JSON.stringify({ Notes: notes })
});
return {
success: true,
alertId,
previousStatus: alert.Status,
newStatus: 'Resolved'
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
```
## Best Practices
1. **Acknowledge promptly** - Shows someone is working on it
2. **Add meaningful notes** - Document investigation steps
3. **Create tickets for tracking** - Long-running issues need tickets
4. **Use bulk operations** - Handle related alerts together
5. **Set up escalation rules** - Don't let alerts age
6. **Filter by severity** - Focus on critical first
7. **Review alert history** - Understand recurring patterns
8. **Suppress during maintenance** - Avoid alert fatigue
9. **Link to documentation** - Reference runbooks in notes
10. **Regular alert review** - Audit old/stale alerts
## Alert Response Workflow Template
```javascript
async function standardAlertResponse(client, alertId) {
const workflow = {
steps: [],
success: true
};
try {
// Step 1: Get alert details
const alert = await client.request(`/Alerts/${alertId}`);
workflow.steps.push({
step: 'Get Alert',
status: 'success',
data: {
subject: alert.Subject,
severity: alert.Severity,
computer: alert.ComputerName
}
});
// Step 2: Acknowledge if not already
if (alert.Status === 'New' || alert.Status === 'Active') {
await client.request(`/Alerts/${alertId}/Acknowledge`, {
method: 'POST',
body: JSON.stringify({ Notes: 'Investigating alert' })
});
workflow.steps.push({ step: 'Acknowledge', status: 'success' });
}
// Step 3: Create ticket if critical/error
if (alert.Severity >= 3) {
const ticket = await client.request(`/Alerts/${alertId}/CreateTicket`, {
method: 'POST',
body: JSON.stringify({
TicketSubject: alert.Subject,
Priority: alert.Severity === 4 ? 1 : 2,
BoardID: 1
})
});
workflow.steps.push({
step: 'Create Ticket',
status: 'success',
ticketId: ticket.TicketID
});
}
// Step 4: Check computer status
const computer = await client.request(`/Computers/${alert.ComputerID}`);
workflow.steps.push({
step: 'Check Computer',
status: 'success',
computerStatus: computer.Status
});
} catch (error) {
workflow.success = false;
workflow.steps.push({
step: 'Error',
status: 'failed',
error: error.message
});
}
return workflow;
}
```
## Related Skills
- [ConnectWise Automate Monitors](../monitors/SKILL.md) - Alert sources
- [ConnectWise Automate Computers](../computers/SKILL.md) - Alert targets
- [ConnectWise Automate Scripts](../scripts/SKILL.md) - Remediation scripts
- [ConnectWise Automate API Patterns](../api-patterns/SKILL.md) - Authentication and pagination