Back to blog

ConnectWise API + AI: What You Can Actually Automate in 2026

9 min read

The ConnectWise API is one of the most capable PSA APIs in the MSP ecosystem — and one of the most underused. Most MSPs interact with ConnectWise exclusively through the UI, clicking through tickets, updating statuses, and logging time by hand. But underneath that UI sits a full REST API that lets you read, create, update, and delete nearly every object in your PSA. When you pair that API with AI, the automation possibilities go from “save a few clicks” to “eliminate entire workflow categories.”

This post is a practical guide to the ConnectWise Manage REST API: what endpoints matter for MSP automation, how authentication works, what the rate limits look like, and — most importantly — what you can actually build when AI sits on top of the API. If you’ve read our ConnectWise PSA + AI guide or the no-migration upgrade post, this goes deeper into the technical layer that makes all of it work.

ConnectWise API basics: authentication and structure

The ConnectWise Manage API is a standard REST API that uses JSON payloads. Every request requires three things:

  1. A client ID — registered through the ConnectWise Developer Portal. This identifies your integration.
  2. API keys — a public/private key pair tied to a CW member account. The member’s security role determines what the API can access.
  3. Base URL — typically https://api-na.myconnectwise.net/{codebase}/apis/3.0/ for North American cloud instances. The codebase is version-specific (e.g., v2025_1) — fetch yours from https://api-na.myconnectwise.net/login/companyinfo/{yourcompany}.

Authentication goes in the Authorization header as a Basic auth string, constructed from {companyId}+{publicKey}:{privateKey}, base64-encoded. The clientId header is sent separately.

Authorization: Basic {base64(companyId+publicKey:privateKey)}
clientId: your-client-id-uuid

A quick test to confirm your credentials work:

curl -s \
  -H "Authorization: Basic $(echo -n 'yourcompany+publickey:privatekey' | base64)" \
  -H "clientId: your-client-id" \
  "https://api-na.myconnectwise.net/v2025_1/apis/3.0/system/info" | python3 -m json.tool

If you get a JSON response with version info, you’re connected.

Rate limits

ConnectWise enforces rate limits per client ID, though the exact thresholds are not publicly documented and vary by hosting tier. In practice, most integrations hit limits around 1,000 requests per minute for cloud-hosted instances. The API returns 429 Too Many Requests when you exceed the limit, with a Retry-After header.

For AI-driven automation, this means you need to be thoughtful about batching. Polling every ticket every 30 seconds across a large board will burn through your limit fast. Webhook-driven architectures — where ConnectWise pushes events to your system — scale much better.

Pagination

All list endpoints support page and pageSize parameters (max 1,000 per page) and return a Link header with pagination URLs. For large datasets like ticket history or time entries, always paginate — don’t try to pull everything in a single request.

The endpoints that matter for MSP automation

The ConnectWise API covers hundreds of endpoints across service, project, sales, procurement, finance, and system modules. For AI-powered service desk automation, these are the ones that matter:

Service tickets — /service/tickets

This is the core endpoint. You can create tickets, update any field (status, priority, type, subtype, board, assigned resource), add internal and external notes via /service/tickets/{id}/notes, and query tickets with CW’s condition syntax.

GET /service/tickets?conditions=board/name="Service Desk" AND status/name!="Closed"&orderBy=dateEntered desc&pageSize=50

The conditions parameter supports =, !=, >, <, contains, like, and logical operators. It’s powerful but has quirks — string values need double quotes inside the query parameter, and nested object fields use slash notation.

Contacts — /company/contacts

Every ticket references a contact. The contact endpoint lets you look up users, get their company association, pull communication items (email, phone), and check custom fields. For AI triage, this is how you identify who submitted the ticket and pull their context.

Companies — /company/companies

Company data includes contract information, territory, SLA settings, and custom fields. When AI triages a ticket, knowing the company’s service tier changes the priority calculation.

Configurations — /company/configurations

Configurations are ConnectWise’s asset/device records. They map to workstations, servers, network devices, and software. You can create, update, and query configurations — useful for syncing device data from your RMM or flagging devices related to a ticket.

GET /company/configurations?conditions=company/id=250 AND type/name="Workstation"

Time entries — /time/entries

Time tracking is where most MSPs lose money. The API lets you create time entries programmatically — specifying the ticket, member, hours, work type, and billable status. For automated workflows, this means logging time the moment a runbook completes, not after a tech remembers to do it.

{
  "chargeToId": 12345,
  "chargeToType": "ServiceTicket",
  "member": { "identifier": "rwatne" },
  "timeStart": "2026-05-14T09:00:00Z",
  "timeEnd": "2026-05-14T09:05:00Z",
  "workType": { "id": 1 },
  "billableOption": "Billable"
}

Callbacks (webhooks) — /system/callbacks

Instead of polling for changes, register callbacks that fire on specific events. You can listen for ticket creation, ticket updates, contact changes, and more. The callback sends a POST to your URL with the object ID and action — you then fetch the full object with a follow-up API call.

{
  "url": "https://your-endpoint.com/cw-webhook",
  "objectId": 1,
  "type": "ticket",
  "level": "owner",
  "description": "New ticket notifications"
}

This is how production-grade ConnectWise integrations work. Poll for the initial sync, then switch to webhook-driven processing for real-time response.

Practical automation examples

Knowing the endpoints is table stakes. Here’s what you build with them.

Auto-triage with AI-generated internal notes

When a new ticket arrives (via webhook), the AI reads the ticket subject and initial description via the API, classifies the intent, queries connected tools (RMM, documentation, M365) for relevant context, and posts an internal note back to the ticket:

POST /service/tickets/{id}/notes
{
  "text": "## AI Triage Summary\n**Classification:** Password Reset\n**Priority:** Medium\n**User:** Sarah Johnson (sjohnson@acmecorp.com)\n**Device:** ACME-WS-042 — Online, 12 days uptime\n**M365:** Account active, MFA enabled, no recent sign-in failures\n**ITGlue SOP:** Password Reset — Standard (link)\n**Recommendation:** Run password reset runbook",
  "internalAnalysisFlag": true,
  "detailDescriptionFlag": false
}

The tech opens the ticket and the research is already done. That’s 10 minutes of context-gathering eliminated per ticket. (This is exactly what Junto’s triage pipeline does on every incoming ticket — but using the ConnectWise API alongside NinjaOne, ITGlue, M365, and Sophos simultaneously.)

Auto-update status and priority

AI doesn’t just read tickets — it writes back. After classification, the AI can update the ticket’s type, subtype, priority, and board assignment via a PATCH:

PATCH /service/tickets/{id}
[
  { "op": "replace", "path": "priority", "value": { "id": 8 } },
  { "op": "replace", "path": "type", "value": { "id": 250 } },
  { "op": "replace", "path": "board", "value": { "id": 30 } }
]

ConnectWise uses JSON Patch format for updates. Each operation specifies the field and the new value. This is cleaner than sending the entire ticket object back and avoids accidental overwrites.

Auto-log time entries after runbook execution

When an automated runbook resolves a ticket — say, a password reset that took the AI 45 seconds — the system creates a time entry and closes the ticket:

POST /time/entries
{
  "chargeToId": 12345,
  "chargeToType": "ServiceTicket",
  "member": { "identifier": "junto-automation" },
  "timeStart": "2026-05-14T14:30:00Z",
  "timeEnd": "2026-05-14T14:31:00Z",
  "workType": { "id": 1 },
  "notes": "Automated password reset via runbook. User confirmed access.",
  "billableOption": "Billable"
}

No tech forgot to log time. No disputed invoices. The time entry is accurate because it was logged by the system that did the work.

Create configurations from RMM data

When a new device appears in your RMM (NinjaOne, Datto, etc.) but doesn’t exist in ConnectWise, the AI can create the configuration automatically:

POST /company/configurations
{
  "name": "ACME-WS-057",
  "type": { "id": 5 },
  "company": { "id": 250 },
  "contact": { "id": 1042 },
  "serialNumber": "PF2KR3N1",
  "installedBy": { "identifier": "junto-automation" },
  "vendorNotes": "Auto-created from NinjaOne device sync"
}

This keeps your PSA asset records in sync with your RMM without anyone manually creating configurations.

ConnectWise native AI vs. what you can build on the API

ConnectWise has invested in AI through Sidekick (their AI assistant across PSA, Automate, RMM, and Security products) and their recent acquisition of zofiQ for agentic AI capabilities. Here’s how the native options stack up against what you can build on the API:

CapabilityConnectWise Sidekick + zofiQAPI + external AI
Ticket summarizationYes (native)Yes — and with context from non-CW tools
Auto triage / classificationYes (Sidekick for PSA)Full intent-based classification with custom training
Cross-tool contextCW ecosystem (PSA, Automate, RMM, ScreenConnect)Any tool with an API — NinjaOne, ITGlue, Hudu, M365, Sophos, SentinelOne
Automated resolutionzofiQ (emerging)Runbooks with approval workflows and execution
Time entry automationNoFull API support for creating and updating time entries
Custom workflowsCW Flow (limited)Unlimited — you control the logic

The native AI is strongest within the ConnectWise ecosystem. If your stack is 100% ConnectWise — Automate, ScreenConnect, RMM — Sidekick covers the basics and zofiQ is adding agentic capabilities. But most MSPs run a mixed stack. NinjaOne or Datto for RMM. ITGlue or Hudu for documentation. SentinelOne or Sophos for security. The ConnectWise API is the bridge that lets external AI work with your PSA data alongside everything else.

The MCP approach: wrapping the ConnectWise API for AI

Raw API calls work, but they’re brittle. Every endpoint has its own quirks — conditions syntax, pagination, nested object references, patch format. When you’re building AI that interacts with the ConnectWise API, you don’t want the AI crafting raw HTTP requests. You want it working through a structured interface.

That’s where MCP (Model Context Protocol) comes in. We wrote a full guide to Claude MCP servers for MSPs covering setup, config, and build-vs-buy. An MCP server wraps the ConnectWise API into a set of tools that an AI model can invoke naturally. Instead of the AI needing to know that ticket notes require POST /service/tickets/{id}/notes with internalAnalysisFlag: true, it calls a tool like add_internal_note(ticket_id, text).

We covered MCP in depth in our MCP for MSPs post. The short version: MCP standardizes how AI connects to external tools. A ConnectWise MCP server exposes tools like:

  • search_tickets(conditions, limit) — query tickets with natural language translated to CW conditions
  • get_ticket_details(ticket_id) — full ticket with contact, company, and configuration data
  • add_ticket_note(ticket_id, text, internal) — post notes without worrying about the note flag schema
  • update_ticket(ticket_id, fields) — update status, priority, type, board with validation
  • create_time_entry(ticket_id, member, duration, notes) — log time with proper work type mapping

The AI works through these tools instead of raw HTTP. It asks “find open tickets on the Service Desk board assigned to nobody” instead of constructing a conditions query string. The MCP server handles the translation, authentication, pagination, and error handling.

For MSPs building their own ConnectWise MCP server, the core challenge is multi-tenancy. Every API call needs to use the right credentials for the right client instance. Credential management, tenant isolation, and audit logging all need to be handled at the server level — not by the AI model.

What Junto does with the ConnectWise API

Junto connects to ConnectWise PSA via the same API endpoints described in this post. Here’s what happens on a real ticket:

A user at Acme Corp emails “Outlook keeps crashing.” The ticket lands in ConnectWise. Within 30 seconds, Junto’s AI:

  1. Reads the ticket via GET /service/tickets/{id}
  2. Identifies the user and pulls their device from NinjaOne — finds 3 pending Outlook updates and a 22-day uptime
  3. Searches ITGlue for Acme Corp’s Outlook configuration docs — finds they’re on Microsoft 365 E3 with a specific Outlook profile policy
  4. Checks recent tickets via GET /service/tickets?conditions=contact/id=1042 and summary contains "Outlook" — finds two similar tickets last month, both resolved with an Outlook profile repair
  5. Posts an internal note via POST /service/tickets/{id}/notes with all of this context and a suggested resolution
  6. Updates the ticket type, priority, and board via PATCH /service/tickets/{id}

The tech opens the ticket and sees: device context, documentation, history, and a suggested fix. No tab switching. No 10-minute research phase. Every API call above is one you could build yourself — Junto just chains them together across your entire stack, for every ticket, automatically.

See the full list of supported tools at juntoai.com/integrations.

Getting started

If you want to explore the ConnectWise API directly, start here:

  1. Register a client ID at the ConnectWise Developer Portal
  2. Create an API member in your CW instance with a scoped security role — don’t use an admin account
  3. Generate API keys for that member
  4. Start with read-only callsGET /service/tickets, GET /company/contacts, GET /system/info
  5. Add webhook callbacks for real-time ticket processing
  6. Scope write access carefully — use CW’s security roles to limit what the API member can modify

If you’d rather see AI working on your ConnectWise tickets in an hour instead of building it over a month, book a 15-minute demo. We’ll connect to your PSA, pull a few real tickets, and show you what automated triage looks like using the same API calls described above — across ConnectWise, NinjaOne, ITGlue, and the rest of your stack.

See Junto in action

15-minute demo. We'll show you AI triage working on your actual tickets.

Book a Demo