---
name: Replace existing integrations
description: >-
  Use when an ISV already has ConnectWise, Autotask, Halo, or other vendor
  clients and is replacing those with Bitlync. Not for first-day Quickstart,
  company-map import, or moving an MSP from one PSA to another.
---
# Replace existing integrations

Public title: **Replace existing integrations**. Not Import. Not Move your PSA. Not Direct in the title. Internal notes may say migration.

The job: they already wrote vendor clients. They change those calls to Bitlync. Bitlync does not ingest their old code or import their tokens.

## Rules

- Check coverage against what Bitlync actually ships. Do not invent objects or routes.
- Reads first. Then writes. Webhooks only if they already exist in product.
- Keep the old vendor clients until Bitlync matches in their environment.
- Use `dry_run` as the shadow pass on writes. Compare shape, do not cut over on a preview.
- Never mint an agreement header. Never auto-create an unmatched company.
- Write a line on an existing agreement only. Public word is Agreement, not Contract. Site word for the line is Line item.
- MSP pastes their own keys. Name a missing permission in the connect flow. Do not claim OAuth unless that vendor actually publishes a partner app.
- No Rewst (or other vendor) screenshots in anything that ships.
- Do not add `pass_through`, Proxy, or vault token-import. Those are a different product.
- Do not turn on live PSA POST until HTTP retry is GET-only or vendor-idempotent.

## Phase 1 — Inventory

1. List the vendor APIs they call today (PSA first: ConnectWise, Autotask, Halo).
2. For each, list the operations they use (list/get/create/update/close) and the fields they depend on.
3. Map each to a Bitlync word: Ticket, Company, Contact, Device, Agreement, Line item, Project.
4. Mark gaps honestly. A gap is not a bug. Later or Never stays named.

## Phase 2 — Coverage

1. Confirm the connector is on the Connectors tile and the object is actually listed (pull or push).
2. Run connect. The probe must name a missing permission before they take a support ticket.
3. Customer map is ISV customer to PSA company: sure match auto-maps, leftover asks the MSP to create that company in the ISV, UNMAPPED is a human match. Never auto-create.

## Phase 3 — Reads

Replace list/get first. Same Bitlync call for every vendor. Reads come from the store, not a live hit on every request.

Typical left-to-right:

- ConnectWise `service/tickets` / Autotask `Tickets` / Halo `Tickets` → Ticket
- Company / Account / Client → Company
- Configuration / Asset (documented device) → Device
- Agreement / Contract → Agreement
- Addition / Contract charge → Line item

Keep `.raw` for vendor-only fields they still need. Do not log it. Do not put Hudu passwords on a public docs-read path.

## Phase 4 — Writes

Replace create/update only after reads match.

- 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`. You can close a ticket once they accept the connection. Auto-close when a finding is fixed is a separate switch.
- Line items: on an existing agreement only.
- Time on a ticket: hours the caller states, on a linked ticket.
- Company create is a separate grant (`psa.company.create`). Company create is off unless the MSP turns it on for your grant. We always match first. If two records match, we refuse. `dry_run`. Distributor create is not a PSA create.
- Device write is off unless the MSP turns it on for your grant.

Every write: `dry_run` first, then apply. Same payload in sandbox. If they hit a Never, the 422 is a stable code, one English sentence, and a docs URL.

## Phase 5 — Webhooks

Subscribe with `psa.ticket.events` when granted. 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`. Do not fake a unified event. If the grant is off, they keep their vendor webhooks.

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`.

## Done when

- Their app talks to Bitlync for the inventoried objects
- Old vendor clients are still in the repo until they verify
- Never list was not bypassed
- Connect named any missing permission
- No Rewst pixels, no invented OAuth, no live POST retry duplicates
