ConnectWise PSA skills and tools under ops/connectwise (hub-sanitized 2026-11-01: client intel, internal workflow/credential/member/company ids, archived-page apiToken/sessionId stripped to placeholders)

This commit is contained in:
Hermes Agent committed 2026-11-01 13:34:58 -08:00
commit 9c96092034
36 files changed
+310875

No files matched your search

@@ -0,0 +1,93 @@
import requests
import re
import json
import os
import base64
from requests.auth import HTTPBasicAuth
# Configuration
BASE_URL = "https://cw.vistanetinc.com/v4_6_release/apis/3.0"
def _load_cw_client_id():
"""Resolve the ConnectWise clientId from env or ~/.secrets/connectwise."""
cid = os.getenv("CW_CLIENT_ID", "")
if cid:
return cid
path = os.path.expanduser("~/.secrets/connectwise")
if os.path.exists(path):
with open(path) as f:
for line in f:
if line.lstrip().startswith("CW_CLIENT_ID="):
return line.split("=", 1)[1].strip()
raise SystemExit(
"CW_CLIENT_ID missing: export CW_CLIENT_ID or add "
"CW_CLIENT_ID=<uuid> to ~/.secrets/connectwise"
)
CLIENT_ID = _load_cw_client_id()
SECRETS_PATH = os.path.expanduser("~/.secrets/connectwise")
def get_auth():
with open(SECRETS_PATH, 'r') as f:
lines = f.readlines()
creds = {}
for line in lines:
if '=' in line:
k, v = line.strip().split('=', 1)
creds[k] = v
auth_str = f"{creds['CW_COMPANY_ID']}{creds['CW_PUBLIC_KEY']}:{creds['CW_PRIVATE_KEY']}"
return auth_str
def clean_json(text):
if not text:
return text
return re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f]', '', text)
def cw_request(method, endpoint, params=None, json_data=None):
url = f"{BASE_URL}/{endpoint.lstrip('/')}"
auth_str = get_auth()
headers = {
"clientId": CLIENT_ID,
"Content-Type": "application/json",
"Accept": "application/json"
}
encoded = base64.b64encode(auth_str.encode()).decode()
headers["Authorization"] = f"Basic {encoded}"
response = requests.request(
method=method,
url=url,
params=params,
json=json_data,
headers=headers,
timeout=30
)
cleaned_text = clean_json(response.text)
try:
return json.loads(cleaned_text), response.status_code
except json.JSONDecodeError:
return cleaned_text, response.status_code
def get_ticket(ticket_id):
return cw_request("GET", f"service/tickets/{ticket_id}")
def list_tickets(conditions=None, page_size=100):
params = {"pageSize": page_size}
if conditions:
params["conditions"] = conditions
return cw_request("GET", "service/tickets", params=params)
def update_ticket(ticket_id, patch_data):
return cw_request("PATCH", f"service/tickets/{ticket_id}", json_data=patch_data)
def create_schedule_entry(data):
return cw_request("POST", "schedule/entries", json_data=data)
if __name__ == "__main__":
print("Testing CW Connection...")
data, status = get_ticket(121216)
print(f"Status: {status}")
print(f"Data: {data}")