What we write
What we write.
Line items on an existing agreement. Locks and refusals.
ConnectWise, Autotask, and Halo write line items on an existing agreement. Verbs: add, rewrite, end, replace. dry_run defaults true and returns the same payload. Halo and ConnectWise agreement-line apply commit when dry_run is false. Autotask apply runs on fixtures and dry_run. An Autotask host that is not a fixture returns 501. We do not mint an agreement header.
You need an active agreement so we can write the line.
Tickets are two-way when the MSP grants it. You can create, update, and close. You can subscribe to events when the MSP changes the ticket in their PSA.
Time on a linked ticket needs a required member. List with GET /tenants/{tenant_id}/members — Halo and ConnectWise live when permitted; Autotask → honest 501; permission miss is honest English (ConnectWise may 403 without System Members inquire). Empty list stays empty — never invent. The time picker uses the listed id.
When a device is created or updated, you can list those events or get a signed webhook. After a tenant sync, GET /tenants/{id}/connections/events?kind=device.updated (also created). Optional signed webhook. Grant is the connection (rmm.device.events). Missing is grant_missing.
When a company is created or updated, you can list those events or get a signed webhook. After a tenant sync, GET /tenants/{id}/connections/events?kind=company.updated (also created). Optional signed webhook. Grant is the connection (psa.company.events). Missing is grant_missing.
Reads include vendor: { connector, native_id, native }. native is the same payload as .raw. .raw is read-only. Ticket writes accept optional vendor_native on POST /tickets and POST /tickets/write.
Company create is off unless the MSP turns it on for your grant. We always match first. If two records match, we refuse.
We do not mint an agreement header. Device write is off unless the MSP turns it on for your grant. We never auto-create an unmatched company. Exact-name auto-Match fills Match only when the PSA company name uniquely hits one ISV customer — never auto-import; ambiguous → Needs match. A leftover row is Match, company import from PSA, Skip, or Needs match (unset only); bulk unmatched import supports dry_run preview. When company import from PSA is unavailable, Import returns 501. We never create the company in the PSA. Contacts are list and match only — no contact create. Ticket create and update accept board, status, and priority ids from the ConnectWise and Halo list routes; unknown id → 422. Autotask boards are not invented. psa_company_create_refused is leftover only when the grant is on; missing grant is grant_missing.
If they try anyway: a stable code, one English sentence, and doc_url.
agreement_header_not_supported — they tried to mint a header. Autotask’s API would create one. Bitlync still refuses. That is policy.
agreement_requires_existing — missing or unknown agreement.
ConnectWise, Autotask, and Halo write on an existing project. We do not mint a Project header. Baseline cannot take that write.
project_requires_existing — missing or unknown project.
project_header_not_supported — they tried to mint a Project header. Bitlync still refuses. That is policy.
project_not_writable — Baseline cannot take that write.
project_company_cannot_update — the project’s company cannot be updated.
Pax8 matches companies it already has, then creates the rest. Matching then creating at a distributor is not a PSA create. Company create is off unless the MSP turns it on for your grant. We always match first. If two records match, we refuse.
psa_company_create_refused — leftover only when the grant is on. Missing grant is grant_missing. When the grant is on we still match first; two matches refuse.
company_match_ambiguous — more than one match. We do not create.
distributor_required — no connected distributor for this write.