1.6 KiB
ConnectWise PSA Production Query Patterns
Legacy Mirror Bypass
If the /service/tickets endpoint returns tickets from 2011, the request is hitting a legacy mirror.
Solution: Use the conditions parameter to force a production database hit.
- Query:
conditions=id >= 110000 - Result: This bypasses the mirror and retrieves current production records.
Secrets File Parsing & 401 Triage
~/.secrets/connectwise uses KEY=value lines with prefixed keys (CW_COMPANY_ID / CW_PUBLIC_KEY / CW_PRIVATE_KEY). Proven auth build:
import base64
d = {}
for line in open(path).read().splitlines():
if "=" in line:
k, v = line.split("=", 1); d[k.strip()] = v
preencode = d["CW_COMPANY_ID"] + d["CW_PUBLIC_KEY"] + ":" + d["CW_PRIVATE_KEY"]
auth = "Basic " + base64.b64encode(preencode.encode()).decode()
The PublicKey already starts with +, so plain concatenation is correct (no extra separator).
On 401 Unauthorized: print parsed key names and value lengths BEFORE editing code. A key-name mismatch (lookup found nothing) and a genuinely bad credential emit the same errors — Incorrect username/password or Incorrect Authorization header format — and only the parsed shape tells which fix applies. Patch the lookup; do not rewrite the whole script around it.
Data Structures
The API can return tickets in two primary formats:
- Raw List:
[{"id": 123, ...}, {...}] - Wrapped Object:
{"tickets": [{"id": 123, ...}, {...}]}
Always check for both in Python:
raw_data = json.loads(response)
tickets = raw_data['tickets'] if isinstance(raw_data, dict) and 'tickets' in raw_data else raw_data