Files

35 lines
1.6 KiB
Markdown

# 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:
```python
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:
1. **Raw List**: `[{"id": 123, ...}, {...}]`
2. **Wrapped Object**: `{"tickets": [{"id": 123, ...}, {...}]}`
Always check for both in Python:
```python
raw_data = json.loads(response)
tickets = raw_data['tickets'] if isinstance(raw_data, dict) and 'tickets' in raw_data else raw_data
```