Ticket Trigger
The ConnectWise PSA Trigger node monitors service tickets via the MSP Copilot Watchtower service and fires your workflow when tickets match specified conditions.
Key benefits:
- Push-based, not polling — MSP Copilot Watchtower monitors tickets and pushes events to n8n instantly (CRUD events) or on a schedule (state machine events)
- Rich filtering — monitor multiple boards, statuses, priorities, and sources in a single trigger
- State machine events — trigger on Enter, Repeat, and Exit transitions, not just raw CRUD changes
- Change tracking — UPDATE events include a summary of exactly which fields changed, so your workflow can react to specific changes
- Computed fields — status history (
last_status,status_last_changed_at) is tracked automatically — no need to store and compare previous states - Noise reduction — conditions are evaluated server-side, so your workflow only runs when it matters
- Time-based logic — minimum ages, repeat schedules, and re-entry cooldowns that raw callbacks can’t do
Beta feature. The trigger node requires an Access Key from MSP Copilot Link.
How It Works
MSP Copilot Watchtower combines two delivery methods — callbacks for immediate CRUD events and scheduled polling for time-aware state machine events — with server-side filtering, deduplication, and condition evaluation built in.
sequenceDiagram
participant Workflow as n8n Workflow
participant WT as MSP Copilot Watchtower
participant CW as ConnectWise PSA
Workflow->>WT: Register webhook + filters
rect rgba(99, 102, 241, 0.1)
Note over WT,CW: Dual monitoring - callbacks + polling
CW-->>WT: Callback - ticket created, updated, deleted
WT->>WT: Evaluate filters, timing, dedup
WT->>Workflow: POST matched event
Note over Workflow: Workflow executes
WT->>CW: Scheduled poll
CW-->>WT: Ticket data
WT->>WT: Evaluate filters, timing, dedup
WT->>Workflow: POST matched event
Note over Workflow: Workflow executes
end
Two paths, one result:
| Path | How it works | Events | Latency |
|---|---|---|---|
| Callbacks | ConnectWise pushes changes to MSP Copilot Watchtower the moment they happen | Create, Update, Delete, Enter, Exit | Seconds |
| Polling | MSP Copilot Watchtower periodically queries ConnectWise and evaluates tickets against your conditions | Enter, Repeat, Exit | Schedule-based |
Both paths feed into a deduplication layer, so your workflow never fires twice for the same event — even if a ticket change triggers an Enter via callback and the next poll cycle detects it too. Callbacks give you immediate Enter and Exit detection when a ticket change causes a state transition; polling catches transitions that callbacks miss and handles time-based Repeat events.
Quick Start
To get a basic trigger that fires when a ticket enters a specific status, you only need these fields:
| Field | What to set | Example |
|---|---|---|
| Trigger On | Ticket | Ticket |
| Lifecycle Events | Enter | Select Enter |
| Board | The board to watch | Select from dropdown |
| Status | The status to match | Select from dropdown (filtered by board) |
What happens
- You activate the workflow
- A ticket on the selected board moves into the selected status
- MSP Copilot Watchtower detects the match and POSTs the ticket data to your n8n webhook
- Your workflow executes with the full ticket payload
You now have a working trigger. Read on to learn about filters, timing conditions, and repeat behavior, then test it.
Reference — Lifecycle Events
State machine events
These are evaluated periodically by MSP Copilot Watchtower. They track whether a ticket currently matches your filter conditions.
| Event | When it fires |
|---|---|
| Enter | A ticket first matches conditions (was not matching before, now is) |
| Repeat | A ticket continues matching conditions (fires periodically while still matching) |
| Exit | A ticket stops matching conditions (was matching before, now is not) |
CRUD callback events
These fire immediately when ConnectWise reports a change, if the ticket matches your filter conditions.
| Event | When it fires |
|---|---|
| Create | A new ticket is created that matches conditions |
| Update | A matching ticket is updated in ConnectWise |
| Delete | A matching ticket is deleted from ConnectWise |
You can select multiple events. For example, selecting both Enter and Exit lets you trigger on transitions in and out of a status — useful for tracking SLA windows.
Reference — Filters
All filters are optional. When a filter is left empty, all values for that field are matched.
| Filter | Behavior when empty | Notes |
|---|---|---|
| Ticket Type | Service Ticket (only option) | Currently only service tickets are supported |
| Board | All active service boards | Multi-select. Determines which statuses appear in the Status dropdown. |
| Status | All statuses | Multi-select. Depends on Board — select boards first to narrow the list. If no boards are selected, statuses from all active service boards are shown. |
| Priority | All priorities | Multi-select. |
| Source | All sources | Multi-select. |
Filters combine with AND logic — a ticket must match all non-empty filters to trigger.
Reference — Timing Conditions
Timing conditions add minimum age requirements. They are inside the Timing Conditions collection (click “Add Condition” to add them).
| Condition | Description | Example values |
|---|---|---|
| Minimum Ticket Age | Only trigger for tickets older than this duration | 15m, 2h, 3d |
| Minimum Time in Current Status | Only trigger for tickets that have been in their current status longer than this | 30m, 1h, 1d |
Duration format: use a number followed by a unit — m (minutes), h (hours), d (days). Examples: 15m, 2h, 3d.
Reference — Repeat Settings
These fields only appear when the Repeat lifecycle event is selected.
| Field | Default | Description |
|---|---|---|
| Repeat Every | 15m | How often to send repeat notifications while a ticket continues matching. Required when Repeat is selected. |
| Maximum Repeats | Unlimited | Maximum repeat notifications per ticket. Leave blank for unlimited. |
Example: with Repeat Every set to 1h and Maximum Repeats set to 5, a ticket that stays in a matching status will trigger the workflow once per hour, up to 5 times.
Reference — Re-entry Behavior
The If Ticket Re-Enters setting controls what happens when a ticket exits your conditions and later re-enters them. This only applies to Enter events.
| Mode | Description |
|---|---|
| Never Notify Again (default) | Once a ticket has triggered an Enter event, it will not trigger again — even if it leaves and re-enters the matching conditions. |
| Notify Immediately | Trigger again immediately when the ticket re-enters conditions. |
| Notify After Cooldown | Wait for a cooldown period after the last Enter event before allowing a re-trigger. Requires the Cooldown Duration field. |
When Notify After Cooldown is selected, an additional field appears:
| Field | Default | Description |
|---|---|---|
| Cooldown Duration | 15m | How long to wait before the ticket can re-trigger. Uses the same duration format (15m, 1h, 2d). |
Example: a ticket enters status “Waiting on Client”, triggering the workflow. The technician updates the ticket, moving it out. Later the ticket returns to “Waiting on Client”. With Notify Immediately, the workflow fires again right away. With Notify After Cooldown of 1h, it only fires if at least 1 hour has passed since the last Enter event. With Never Notify Again, it stays silent.
Reference — Skip Existing Matches
| Field | Default | Description |
|---|---|---|
| Skip Existing Matches | On | When the trigger is first created or updated, don’t fire for tickets that already match the conditions. Only fire for tickets that newly enter the matching state. |
When enabled (the default), activating a workflow won’t produce a flood of events for tickets that already match your filters. Only tickets that change into a matching state after activation will trigger.
Testing Your Trigger
When you click Test Workflow in n8n, MSP Copilot Watchtower evaluates your current filters against live ConnectWise data and returns a full diagnostic snapshot - no need to wait for a real ticket event.
The test output is added to each ticket as a __watchtower object containing event metadata, computed state, and trigger diagnostics. The trigger_details section only appears during test events — live events include event_type, computed, and the other top-level fields, but not the diagnostic details.
{
"__watchtower": {
"trigger_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event_type": "TEST", // ENTER, REPEAT, EXIT, CREATE, UPDATE, DELETE, or TEST (test runs only)
"fired_at": "2026-02-17T21:00:58Z",
"entity_fire_count": 0,
"entity_repeat_count": 0,
"entity_first_fired_at": null,
"entity_last_fired_at": null,
"computed": {
"status_last_changed_at": "2026-02-17T20:59:05Z", // ISO 8601 timestamp of when the ticket's status last changed
"last_status": { // The previous status before the current one
"id": 158,
"name": "Process Still Running"
}
},
"trigger_details": { // Only included in test events
"trigger_total_events": 11,
"trigger_first_fired_at": "2026-02-15T00:27:01Z",
"trigger_last_fired_at": "2026-02-16T23:10:57Z",
"queue_pending": 710, // Events waiting in the delivery queue (non-zero if n8n was recently unreachable)
"queue_last_error": "HTTP 502: Bad Gateway", // Last delivery error, if any
"queue_backoff_until": "in 12m", // When the next retry will be attempted
"matches_found": 748, // Total tickets currently matching your filters
"matches_summary": [ // Preview of matching tickets with ticket number, company, status, and summary
"#50421 | Acme Corp | In Progress | Vendor File Locked Error in Accounting App",
"#50420 | Summit LLC | Active Queue | VPN Setup Request for Remote Laptop",
"#50418 | Northwind | Process Still Running | Admin Credentials Needed",
"#50415 | Northwind | Process Still Running | Issues with Signing in",
"#50414 | Westside Electric | Quick Fix | iPhone Email Sync Issue",
"#50412 | Pacific Mfg | Process Still Running | Issues With QuickBooks Password",
"#50411 | Acme Corp | Active Queue | Request to Redirect Faxes to Email",
"#50410 | Lakewood Tech | Closed | Batch Report Cannot Pull Up Information",
"#50409 | Bayview Dental | Closed | Remote Access to Server for Portal App",
"#50407 | Riverdale Inc | Scheduled | Backup Internet Failover Test",
"#50406 | Hillcrest Co | Closed | Printer Swap Instructions Needed",
"#50405 | Valley Systems | Closed | Desktop Icons Missing After Update",
"#50404 | Hartfield Electric | Completed | Unable to Connect to Shared Drive",
"And 733 more..."
],
"skipped_count": 702, // How many matches would be skipped due to Skip Existing Matches
"recent_events": [ // Historical events that would have fired your trigger, with relative timestamps and event types
"22h | ENTER | #50201 | Ridgeway Inc | Network Alert - Firewall Packet Loss",
"1d | ENTER | #50418 | Lakewood Tech | New Employee Onboarding Request",
"1d | ENTER | #50417 | Lakewood Tech | Outstanding Assignment Reminder",
"1d | ENTER | #50416 | Bayview Dental | Support Ticket",
"1d | ENTER | #50415 | Acme Corp | Email Address Update Request",
"1d | ENTER | #50414 | Catchall | Marketing Newsletter Notification",
"2d | ENTER | #50410 | Lakewood Tech | New Document Scans Available",
"2d | ENTER | #50409 | Catchall | Missed Call from Dispatch",
"2d | ENTER | #50301 | Westpark Ltd | Test Ticket",
"2d | ENTER | #50300 | Westpark Ltd | Test Ticket"
],
"callback_status": { // Whether the ConnectWise callback is registered and active
"registered": true
}
}
}
}
This is the fastest way to validate your configuration. If the matching tickets and recent events look right, your trigger is ready to activate. If you see too many matches, narrow your filters. If you see zero matches, broaden them or double-check that the right boards and statuses are selected.
Reference — Event Payload
Every event delivered to your workflow includes the full ConnectWise ticket data plus a __watchtower object with event metadata. The payload shape differs slightly between event types.
Computed fields
Watchtower tracks status history so you don’t have to. Every event includes computed fields that ConnectWise doesn’t provide natively:
| Field | What it tells you |
|---|---|
computed.status_last_changed_at | ISO 8601 timestamp of when the ticket’s status last changed — useful for “time stuck in status” logic |
computed.last_status | The previous status (id and name) before the current one — lets you build “moved from X to Y” workflows |
For new tickets, status_last_changed_at is set to the ticket creation time and last_status is null. When a ticket changes status, last_status captures where it came from and the timestamp resets.
Change tracking (CRUD events)
UPDATE events include a changes object showing exactly which fields changed, with their new values. This lets your workflow react to specific field changes without fetching the ticket’s previous state.
{
"__watchtower": {
"trigger_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event_type": "UPDATE",
"fired_at": "2026-02-18T14:32:10Z",
"changes": { // Only present on UPDATE events
"status": { "id": 159, "name": "In Progress" }, // New values only
"priority": { "id": 3, "name": "P2" }
}
},
"id": 50421,
"summary": "Vendor File Locked Error in Accounting App",
"status": { "id": 159, "name": "In Progress" },
"priority": { "id": 3, "name": "P2" },
"company": { "id": 12, "name": "Acme Corp" },
"board": { "id": 1, "name": "Service" }
// ... full ticket data
}
The changes object only contains fields that actually changed — so you can use an IF node to check {{ $json.__watchtower.changes.status }} to only continue when the status specifically moved.
Internal metadata fields (computed fields, URL references) are excluded from change tracking to avoid false positives.
State machine events
State machine events (Enter, Repeat, Exit) include lifecycle tracking fields instead of changes:
{
"__watchtower": {
"trigger_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event_type": "ENTER",
"fired_at": "2026-02-18T14:32:10Z",
"entity_fire_count": 1, // Total events ever sent for this ticket on this trigger
"entity_repeat_count": 0, // REPEAT events in the current matching cycle
"entity_first_fired_at": "2026-02-18T14:32:10Z", // When this ticket first matched
"entity_last_fired_at": "2026-02-18T14:32:10Z", // Last time any event fired for this ticket
"computed": {
"status_last_changed_at": "2026-02-18T14:30:00Z",
"last_status": { "id": 119, "name": "New" } // Was "New", now matches your trigger conditions
}
},
"id": 50421,
"summary": "Vendor File Locked Error in Accounting App",
"status": { "id": 159, "name": "In Progress" },
"company": { "id": 12, "name": "Acme Corp" },
"board": { "id": 1, "name": "Service" }
// ... full ticket data
}
Use entity_fire_count and entity_repeat_count to build escalation logic — for example, only page a manager when entity_repeat_count exceeds 3.
Server-Side Intelligence
MSP Copilot Watchtower evaluates your conditions server-side before delivering events to n8n. Your workflow only runs when it matters — no firehose of raw changes to filter through.
Noise reduction. Conditions are evaluated before delivery. Only events that match your board, status, priority, and source filters reach your workflow. Everything else is silently discarded.
Time-aware logic. Watchtower understands change and duration:
| Capability | What it enables |
|---|---|
| Minimum Ticket Age | Ignore tickets younger than a threshold — skip transient issues that resolve themselves |
| Minimum Time in Status | Only fire after a ticket has been stuck in a status long enough to matter |
| Repeat | Re-fire periodically while a ticket stays in a matching state — escalation reminders, SLA nudges |
| Enter / Exit | Detect state transitions (ticket moved into or out of a status), not just “ticket was updated” |
| Re-entry cooldowns | Prevent rapid re-triggering when tickets bounce in and out of a status |
The result: raw change events become meaningful lifecycle events with time awareness built in.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| ”Access Key is required for trigger functionality” | No Access Key in your ConnectWise PSA credentials | Add an Access Key in the credential settings |
[401] Authentication failed | Invalid or expired Access Key | Check that your Access Key is correct and active |
[403] Access denied | Access Key lacks permissions | Verify the Access Key is valid and has trigger permissions |
[502] / [503] / [504] MSP Copilot Watchtower unavailable | Watchtower service is temporarily down | Wait a moment and try activating the workflow again |
If the workflow activates successfully but never fires, check:
- Filters are not too narrow — try removing Status or Priority filters to test with just a Board
- Lifecycle events — make sure you selected the right event type (Enter vs Create, etc.)
- Skip Existing Matches — if enabled, only new transitions trigger; existing matches are ignored
- Timing conditions — if set, tickets must meet the minimum age requirements before triggering