Skip to content

Integrations

Integrations connect Breeze to the tools your team already uses – PSA platforms for ticketing, communication channels for alerting, and monitoring endpoints for telemetry forwarding. Each integration is scoped to an organization and configured independently, so MSPs can tailor connections per customer without cross-tenant interference. PSA credentials are encrypted at rest using AES-256-GCM, and every configuration change is recorded in the audit log.


Breeze supports three categories of integrations, each served by a dedicated set of API routes.

Category Providers Purpose
Communication Slack, Microsoft Teams, Discord Alert notifications, status updates, and on-call messaging
PSA / Ticketing Jira, ServiceNow, ConnectWise, Autotask, Freshservice, Zendesk Ticket creation, bi-directional sync, and workflow automation
Monitoring External monitoring endpoints Forward device telemetry and health data to third-party observability platforms
Accounting QuickBooks Online Connect your accounting platform (see Accounting)
Distributors Pax8, TD SYNNEX Sync licenses and pull live distributor pricing into your Product Catalog
Network UniFi (Ubiquiti Site Manager cloud, or a self-hosted controller) Discover UniFi fleet inventory and WAN health via the cloud, or connect a self-hosted controller directly through a Breeze agent – with optional agent-collected deep telemetry either way (see UniFi Network)

Communication integrations push notifications from Breeze into your team’s messaging platform. Each provider is configured with a POST request containing the webhook URL and any provider-specific settings.

Terminal window
POST /integrations/slack
Content-Type: application/json
{
"webhookUrl": "https://hooks.slack.com/services/T00/B00/xxxx",
"channel": "#breeze-alerts",
"username": "Breeze RMM",
"notifyOn": ["alert.critical", "alert.warning", "device.offline"]
}

Each provider endpoint accepts an optional "test": true flag in the request body. When present, the API queues a test notification to the configured webhook. Note that the configuration is saved to the in-memory store before the test is executed, so sending "test": true does persist the settings for the lifetime of the current API process.

Terminal window
POST /integrations/slack
{
"webhookUrl": "https://hooks.slack.com/services/T00/B00/xxxx",
"test": true
}

Response:

{ "success": true, "message": "slack test notification queued." }

Fetch the current communication configuration for an organization:

Terminal window
GET /integrations/communication?orgId=<uuid>

The response contains all configured providers in a single object:

{
"data": {
"slack": { "webhookUrl": "...", "channel": "#breeze-alerts" },
"teams": { "webhookUrl": "..." }
}
}

If no communication settings exist for the organization, the endpoint returns 404.


The monitoring integration forwards device telemetry to an external observability platform. Configuration is stored as a freeform JSON object, so you can include whatever fields your monitoring endpoint requires.

Terminal window
PUT /integrations/monitoring
Content-Type: application/json
{
"orgId": "<uuid>",
"endpoint": "https://monitoring.example.com/ingest",
"apiKey": "mon_xxxxxxxxxxxx",
"metricsEnabled": true,
"forwardEvents": ["cpu", "memory", "disk", "network"]
}
Terminal window
GET /integrations/monitoring?orgId=<uuid>

Returns the stored configuration object, or an empty object {} if nothing has been configured.

Terminal window
POST /integrations/monitoring/test

Returns { "success": true, "message": "Connection successful." } when the monitoring endpoint is reachable.


The ticketing integration provides a lightweight configuration store for generic ticketing systems that are not covered by the dedicated PSA routes.

Terminal window
POST /integrations/ticketing
Content-Type: application/json
{
"orgId": "<uuid>",
"provider": "custom",
"apiUrl": "https://tickets.example.com/api",
"apiKey": "tk_xxxxxxxxxxxx",
"projectKey": "BREEZE",
"autoCreate": true
}
Terminal window
GET /integrations/ticketing?orgId=<uuid>
Terminal window
POST /integrations/ticketing/test

Returns { "success": true, "message": "Connection successful. Credentials validated." }.


PSA (Professional Services Automation) integrations are the most fully featured integration type. They are backed by a dedicated database table (psa_connections) with encrypted credential storage, sync tracking, and ticket mapping. Use the /psa routes for all PSA operations.

Provider Enum Value Typical Credentials
ConnectWise Manage connectwise Company ID, public key, private key, site URL
Datto Autotask autotask Username, secret, integration code
Jira jira Email, API token, site URL, project key
ServiceNow servicenow Instance URL, username, password or OAuth token
Freshservice freshservice Domain, API key
Zendesk zendesk Subdomain, email, API token
  1. Choose a provider from the supported list above.

  2. Send a POST request with the connection name, provider, and credentials:

    Terminal window
    POST /psa/connections
    Content-Type: application/json
    {
    "orgId": "<uuid>",
    "provider": "connectwise",
    "name": "ConnectWise — Contoso",
    "credentials": {
    "companyId": "contoso",
    "publicKey": "pk_xxxx",
    "privateKey": "sk_xxxx",
    "siteUrl": "https://na.myconnectwise.net"
    },
    "settings": {
    "defaultBoard": "Service Board",
    "defaultStatus": "New"
    }
    }
  3. The API encrypts the credentials and returns the new connection (without credentials in the response):

    {
    "id": "uuid",
    "orgId": "uuid",
    "provider": "connectwise",
    "name": "ConnectWise — Contoso",
    "settings": { "defaultBoard": "Service Board", "defaultStatus": "New" },
    "createdAt": "2026-02-18T...",
    "updatedAt": "2026-02-18T...",
    "lastTestedAt": null,
    "lastSyncedAt": null,
    "hasCredentials": true
    }
  4. Test the connection to verify credentials are valid (see Testing Connections below).

Update the name, credentials, or settings of an existing connection. Only the fields you include will be changed.

Terminal window
PATCH /psa/connections/:id
Content-Type: application/json
{
"name": "ConnectWise — Contoso (Production)",
"settings": {
"defaultBoard": "MSP Board",
"defaultStatus": "New",
"autoSync": true
}
}

PSA credentials follow a strict security model:

Behavior Detail
Encryption All credentials are encrypted with AES-256-GCM using the APP_ENCRYPTION_KEY before being written to the database
Response redaction List and detail endpoints never return raw credentials. The hasCredentials boolean indicates whether credentials are stored
Rotation Update credentials via PATCH /psa/connections/:id with a new credentials object. The old encrypted value is replaced atomically
Deletion Deleting a connection removes the encrypted credentials and all associated ticket mappings from the database

Connect Breeze to your accounting platform from the Accounting tab on the Integrations page. Accounting integrations are a partner-level feature – they’re set up once for your practice, not per customer.

QuickBooks Online connects through Intuit’s standard OAuth consent flow:

  1. Open Integrations → Accounting and click Connect to QuickBooks.
  2. You’re taken to Intuit’s consent screen to authorize Breeze; approving it returns you to Breeze with the connection established.
  3. The tab then shows the connection status, the connected environment, and a Disconnect option. You can also choose whether issued invoices push to QuickBooks automatically or manually.

Once QuickBooks is connected, you can bring your existing QuickBooks customers into Breeze as organizations – no re-typing. Each imported customer becomes one Breeze organization (customer type) with a default site, carrying over the billing contact and address.

  1. On the connected QuickBooks Online panel, open the Import customers section and click Load customers.
  2. Tick the customers you want to import. Customers you’ve already imported show an Already imported badge and are skipped automatically (select-all excludes them).
  3. Click Import selected. Breeze reports how many were imported, skipped, and failed, with an inline list of any failures.

The import is idempotent – it keys off the QuickBooks customer id, so re-running it never creates duplicates. It requires partner scope, and one QuickBooks company (realm) is connected per partner.


Distributor integrations live on the Distributors tab of the Integrations page and let you bring vendor licenses and pricing into Breeze. They’re partner-scoped.

Pax8 syncs your clients and their subscription/license quantities, which you can map to organizations and link to recurring contract lines. After connecting your Pax8 account and mapping companies to Breeze organizations, open the Subscriptions tab to manage how each subscription connects to a contract line.

Each subscription row offers these actions:

Action Description Requires MFA
Link for observation Connect the subscription to an existing contract line, or create a new manual line on the spot, so Pax8-reported quantities can be compared with Breeze billing Yes
Change Re-point the subscription to a different contract line Yes
Pause observations Stop recording new Pax8 quantity observations while keeping the link intact Yes
Resume observations Resume recording Pax8 quantity observations and surfacing drift Yes
Unlink Remove the connection between the subscription and the contract line Yes

When Track Pax8 reported quantity for drift is enabled on a link, each Pax8 sync records the latest known quantity as an observation and surfaces any difference from the linked manual contract-line quantity. Breeze’s order ledger and linked manual quantity remain authoritative for billing; observation sync never overwrites that billing quantity. Pausing stops new observations and drift updates while leaving the link and billing quantity intact.

Beyond subscription sync, you can also search the Pax8 catalog and import individual products into your Product Catalog – see Product Catalog for that workflow.

TD SYNNEX provides live product price and availability you can import straight into your catalog. The end-to-end workflow – including EC Express live pricing – is documented under Product Catalog → Importing from distributor catalogs.


The UniFi integration discovers your Ubiquiti network fleet across every customer site and reconciles it into Breeze’s unified network view – so gateways, switches, and access points show up alongside your agent-discovered assets without duplicating them. It’s a partner-level integration set up once for your practice, and it’s strictly read-only: Breeze never changes your UniFi configuration.

There are two ways to connect it: through Ubiquiti’s cloud (Site Manager), optionally paired with on-site deep telemetry agents for richer per-port and per-client detail, or fully self-hosted with no Ubiquiti cloud account at all, where a Breeze agent talks directly to your on-prem controller and is the only path Breeze uses to reach it.

Paste a single Ubiquiti Site Manager API key that covers your whole account, and Breeze discovers every UniFi console and its sites. After you map each UniFi site to a Breeze site, Breeze syncs device inventory – model, MAC, type, firmware version and whether an upgrade is available, uptime, and adoption state – plus the latest WAN/ISP health per site.

  1. Open Integrations → UniFi.
  2. Generate a Site Manager API key in your Ubiquiti account (at unifi.ui.com / UniFi Site Manager).
  3. Paste it into the UniFi Site Manager API key field and click Connect to UniFi. Breeze validates the key before saving – a bad key is rejected with a clear message, and a UniFi outage is reported separately so a working key isn’t wrongly blamed.
  4. In the Site mapping card, choose the matching Breeze site (grouped by organization) for each discovered UniFi site, then Save mappings. The organization is derived from the site you pick; unmapped UniFi sites are simply not synced.
  5. Inventory syncs automatically about every half hour. Use Sync now to pull immediately, and review per-run created / updated / unchanged / removed counts in the Sync history table.

The cloud key is read-only – it can only ever read your UniFi account, never change it – and reaches behind customer NAT through Ubiquiti’s cloud, so there’s nothing to install on site.

The cloud key is deliberately shallow: it can’t see per-port PoE, throughput, or the clients attached to each device. To get that depth, designate a Breeze agent already running at the site as a collector for a given console. That agent polls the console’s local Network Integration API (read-only, requires controller firmware 9.3 or newer) and reports back per-port PoE detail (power draw, link speed, mode), device health (uptime, CPU/memory, throughput, client count), and the currently-connected clients (hostname, IP, which AP or switch, wired vs Wi-Fi and SSID, signal strength).

  1. In the Deep telemetry collectors card, for each console set the Breeze site it serves, a collector agent (only online agents at that site can be selected), the Controller URL (for example https://192.168.1.1), and the console’s local Network Integration API key.
  2. Click Enable deep telemetry. Breeze encrypts the local key, pushes the configuration to the chosen agent, and the agent begins polling on schedule (about once a minute).
  3. Open the Deep telemetry card and select a site to view its device table (PoE ports and total watts, client counts) and connected-clients table.

The collector’s status badge shows reachability (pending, connected, unreachable, error, or firmware-too-old). This layer is also strictly read-only – restart, PoE-cycle, and client-block actions are planned for a future release. Deep telemetry requires an agent build that includes the UniFi collector, so promote your fleet to a current agent version before relying on it.

Self-hosted controllers (no cloud account)

Section titled “Self-hosted controllers (no cloud account)”

If you’d rather not create a Ubiquiti cloud account at all, connect UniFi in self-hosted mode instead. In this mode there’s no Site Manager API key anywhere – a Breeze agent that already has network access to your on-prem UniFi Network controller polls it directly over the same read-only local Network Integration API used for deep telemetry (controller firmware 9.3 or newer). The agent is the primary, and only, path Breeze uses to reach the controller.

  1. Open Integrations → UniFi. On the not-yet-connected screen, choose Self-hosted controller instead of Cloud (Site Manager API key), optionally give it an account label (for example, “Acme HQ controllers”), and click Connect. This just creates the self-hosted integration – there’s nothing to validate yet since no controller has been registered.
  2. In the Controllers card, register each controller: pick the Breeze site it primarily serves, a collector agent (an existing enrolled agent at that site that can reach the controller over the LAN), the Controller URL (for example https://192.168.1.1), and the controller’s local API key, then click Register controller. The local key is encrypted before storage and pushed to the chosen agent.
  3. Once the assigned agent reaches the controller (within about a minute), the controller’s own local sites are discovered automatically and appear in the Site mapping card. Map each discovered site to whichever Breeze site it corresponds to, then save.
  4. Devices and clients polled from each mapped site are reconciled into that site’s discovered assets, with the same per-port PoE, throughput, uptime, and connected-client detail as agent-collected deep telemetry above – self-hosted controllers use the same telemetry pipeline.

Because sites are mapped individually rather than the whole controller, one self-hosted controller can feed many UniFi sites across several different Breeze organizations – for example, an MSP running a single controller that manages several clients’ networks only needs one collector agent and one controller registration; each of the controller’s discovered local sites is then mapped to whichever organization it actually belongs to.

Breeze polls the controller on an interval you can tune via the API (pollIntervalSeconds, roughly 15–3600 seconds); the default is about once a minute, matching the deep telemetry cadence.


Every integration type provides a test endpoint. Testing verifies that the configured credentials and endpoint are reachable.

Pass "test": true in the provider configuration body:

Terminal window
POST /integrations/slack
{ "webhookUrl": "https://hooks.slack.com/...", "test": true }
Terminal window
POST /integrations/monitoring/test
Terminal window
POST /integrations/ticketing/test

Test a specific saved PSA connection by ID:

Terminal window
POST /psa/connections/:id/test

On success, the API updates the connection’s syncSettings with a lastTestedAt timestamp and sets the status to verified. The response confirms the result:

{ "success": true, "message": "Credentials verified" }

This endpoint also writes an audit log entry with action psa.connection.test.


Terminal window
GET /psa/connections?orgId=<uuid>&provider=connectwise&page=1&limit=50

All query parameters are optional. Results are paginated and ordered by most recently updated.

Parameter Type Description
orgId UUID Filter to a specific organization
provider string Filter by PSA provider (jira, connectwise, etc.)
page integer Page number (default: 1)
limit integer Results per page (default: 50, max: 100)
Terminal window
GET /psa/connections/:id

Returns the connection detail including settings, sync timestamps, and hasCredentials flag. Credentials themselves are not included.

Terminal window
DELETE /psa/connections/:id

Manually trigger a data sync for a PSA connection:

Terminal window
POST /psa/connections/:id/sync

Response:

{
"id": "uuid",
"provider": "connectwise",
"syncedAt": "2026-02-18T...",
"status": "queued"
}

The sync runs asynchronously. The connection’s lastSyncAt and lastSyncStatus fields are updated as the sync progresses.

Set a custom status on a connection (e.g., active, paused, error):

Terminal window
POST /psa/connections/:id/status
Content-Type: application/json
{ "status": "paused" }

PSA connections can map Breeze alerts and devices to external tickets. Ticket mappings track the relationship between internal entities and their corresponding tickets in the PSA platform.

Terminal window
GET /psa/tickets?page=1&limit=50

Returns all ticket mappings across connections accessible to the authenticated user. Results include:

Field Description
id Internal mapping ID
psaId The PSA connection this ticket belongs to
title Display title derived from the external ticket ID
status Current ticket status
syncedAt Last sync timestamp
raw.externalTicketId The ticket ID in the external PSA system
raw.externalTicketUrl Direct URL to the ticket in the PSA platform
raw.alertId Associated Breeze alert ID (if any)
raw.deviceId Associated Breeze device ID (if any)
Terminal window
GET /psa/connections/:id/tickets?page=1&limit=50

Returns only ticket mappings associated with the specified PSA connection.


Method Path Description
GET /integrations/communication Retrieve communication integration settings for an organization
POST /integrations/slack Configure or test Slack integration
POST /integrations/teams Configure or test Microsoft Teams integration
POST /integrations/discord Configure or test Discord integration
GET /integrations/monitoring Retrieve monitoring integration settings
PUT /integrations/monitoring Save monitoring integration settings
POST /integrations/monitoring/test Test monitoring endpoint connectivity
GET /integrations/ticketing Retrieve ticketing integration settings
POST /integrations/ticketing Save ticketing integration settings
POST /integrations/ticketing/test Test ticketing endpoint connectivity
GET /integrations/psa Retrieve legacy PSA settings (use /psa routes instead)
POST /integrations/psa Save legacy PSA settings
PUT /integrations/psa Update legacy PSA settings
POST /integrations/psa/test Test legacy PSA connection
Method Path Description
GET /psa/connections List PSA connections (filterable by orgId, provider)
POST /psa/connections Create a new PSA connection with encrypted credentials
GET /psa/connections/:id Get a single PSA connection detail
PATCH /psa/connections/:id Update connection name, credentials, or settings
DELETE /psa/connections/:id Delete a connection and its ticket mappings
POST /psa/connections/:id/test Test connection credentials
POST /psa/connections/:id/sync Trigger a manual data sync
POST /psa/connections/:id/status Update connection status
GET /psa/connections/:id/tickets List ticket mappings for a connection
GET /psa/tickets List all ticket mappings across accessible connections

PSA connections and ticket mappings are stored in two tables defined in the integrations schema.

Column Type Description
id UUID Primary key
org_id UUID Organization this connection belongs to
provider enum PSA provider (connectwise, autotask, jira, servicenow, freshservice, zendesk)
name varchar(255) Display name for the connection
credentials JSONB Encrypted credential payload (AES-256-GCM)
settings JSONB Provider-specific configuration (board, project, defaults)
sync_settings JSONB Internal sync metadata including lastTestedAt and status
enabled boolean Whether the connection is active (default: true)
last_sync_at timestamp Last successful sync time
last_sync_status varchar(50) Status of the most recent sync (queued, running, completed, failed)
last_sync_error text Error message from the last failed sync
created_by UUID User who created the connection
created_at timestamp Creation timestamp
updated_at timestamp Last modification timestamp
Column Type Description
id UUID Primary key
connection_id UUID Foreign key to psa_connections
alert_id UUID Associated Breeze alert (nullable)
device_id UUID Associated Breeze device (nullable)
external_ticket_id varchar(100) Ticket ID in the external PSA system
external_ticket_url text Direct URL to the external ticket
status varchar(50) Current ticket status
last_sync_at timestamp Last sync timestamp for this mapping
created_at timestamp Creation timestamp
updated_at timestamp Last modification timestamp

Communication webhook not receiving notifications. Verify the webhook URL is correct and publicly reachable. Use the "test": true flag to send a test notification. Check that your messaging platform has not revoked or rotated the webhook token.

PSA connection test fails. Confirm that the credentials are correct and the PSA platform’s API is accessible from your Breeze API server. Some providers require IP allowlisting or VPN access. Check the lastTestedAt and sync status fields on the connection for additional context.

“Failed to encrypt credentials” error on PSA connection creation. The APP_ENCRYPTION_KEY environment variable is not set or is invalid. In production, this variable is required. In development, the API falls back to JWT_SECRET or SESSION_SECRET, but these must also be present.

Ticket mappings not appearing. Ticket mappings are created during PSA sync operations. Ensure the connection has been synced at least once via POST /psa/connections/:id/sync. Also verify that the connection’s enabled flag is true.

“Organization context required” error. Integration routes require an organization scope. If you are authenticated with a partner or system scope, pass the orgId query parameter or include it in the request body to specify which organization’s integrations you are managing.

Deleted connection – can I recover ticket mappings? No. Deleting a PSA connection removes all associated ticket mappings from the database. This action is irreversible. Export or back up ticket data before deleting a connection if you need to retain it.