Inbound E3b Halo Ticket is PARTIAL (tickets only; Basic under path token → DirtyFlagBoard → sync). Poll stays; store unchanged; no body→store. HMAC UNKNOWN. No Autotask/CW inbound parsers. Live Halo→Bitlync ingress UNKNOWN / not proven. Mount-when-wired — route may be absent from this public OpenAPI. Badge OFF.
Machine API auth is X-API-Key only. The ISV console is separate: magic-link and Sign in with Microsoft (invite-only; live Entra prove needs env — no fake live claim; no invented production host). Sandbox unchanged. Badge OFF.
GET /tenants/{tenant_id}/tickets
POST /tenants/{tenant_id}/tickets
Tickets
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. Grants: psa.ticket.create, psa.ticket.update, psa.ticket.events. When a ticket is created, updated, noted, closed, or reopened, you can list those events or get a signed webhook. After a tenant sync, GET /tenants/{id}/connections/events?kind=ticket.closed (also created, updated, noted, reopened). Optional signed webhook. Grant is the connection (psa.ticket.events). Missing is grant_missing. 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. You can close a ticket once they accept the connection. Auto-close when a finding is fixed is a separate switch. Hours are a write, not a read. Required member is the picker id from GET /tenants/{tenant_id}/members. Create and update accept optional board, status, and priority list ids (GET …/ticket-boards, ticket-statuses, ticket-priorities on ConnectWise and Halo); unknown id → 422. Autotask has no boards list here. dry_run defaults true.
Store-served. 501 when the connector does not support agreements. We do not mint a header.
GET
/tenants/{tenant_id}/members
Time picker. Halo and ConnectWise live list when permitted. Autotask → 501. Permission miss is honest English (ConnectWise may 403 without System Members inquire). Empty list stays empty — never invent. Each id is what CreateTimeEntryBody.member accepts.
GET
/tenants/{tenant_id}/ticket-boards
Ids for CreateTicketBody.board / write board (CW board; Halo team). ConnectWise and Halo. Autotask → 501. Empty list stays empty.
GET
/tenants/{tenant_id}/ticket-statuses
Ids create/update may use for status. ConnectWise and Halo. Unknown id on write → 422.
GET
/tenants/{tenant_id}/ticket-priorities
Ids create/update may use for priority. ConnectWise and Halo. Unknown id on write → 422.
GET
/tenants/{tenant_id}/devices
Store-served device list.
GET
/tenants/{tenant_id}/applications
GET
/tenants/{tenant_id}/audit
GET
/tenants/{tenant_id}/connections
GET
/tenants/{tenant_id}/connections/events
GET
/tenants/{tenant_id}/identity/mappings
GET
/tenants/{tenant_id}/identity/unmapped
GET
/tenants/{tenant_id}/incidents
GET
/tenants/{tenant_id}/status
GET / PUT
/tenants/{tenant_id}/routing
POST
/tenants/{tenant_id}/companies
POST
/tenants/{tenant_id}/findings/route
POST
/sandbox/reset
Sandbox tenants only
Ticket
GET and POST /tenants/{tenant_id}/tickets. 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. When a ticket is created, updated, noted, closed, or reopened, you can list those events or get a signed webhook. After a tenant sync, GET /tenants/{id}/connections/events?kind=ticket.closed (also created, updated, noted, reopened). Optional signed webhook. Grant is the connection (psa.ticket.events). Missing is grant_missing. 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. You can close a ticket once they accept the connection. Auto-close when a finding is fixed is a separate switch. Time has no notes field. Required member is the picker id from GET /tenants/{tenant_id}/members. Board, status, and priority on create/update take ids from the ticket-boards / ticket-statuses / ticket-priorities lists (ConnectWise and Halo); unknown → 422. Sandbox unchanged. Badge OFF.
Company
POST /tenants/{tenant_id}/companies. Pax8 matches a company 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. Exact-name auto-Match fills Match only — never auto-import; ambiguous → Needs match. Leftover UI: Match, company import from PSA, Skip, Needs match (unset). When the ISV book supports company import from PSA, Import creates a leftover in the ISV after preview (bulk Import unmatched uses the same path). When that write is unavailable, Import returns 501. We never create the company in the PSA. Contacts are list and match only — no contact create.
Member
GET /tenants/{tenant_id}/members. PSA people for the time picker (ConnectWise System Members; Halo Agents). Public word is always member. Halo and ConnectWise live list when permitted. Autotask → honest 501. Permission miss is honest English — ConnectWise Invent may 403 without System Members inquire. Empty list stays empty — we never invent a member. Time write uses the listed id as CreateTimeEntryBody.member. Sandbox unchanged. Badge OFF.
Device
GET /tenants/{tenant_id}/devices.
Agreement
GET /tenants/{tenant_id}/agreements. Recurring MSP service billing arrangement. Not “PSA Contract.” We do not mint an agreement header.