The Five-Tool Problem
If you run a service business, your operational data lives in at least five different systems. A PSA for ticketing and project management. An RMM for device monitoring and remote access. A CRM for sales and relationship tracking. An accounting platform for invoicing and revenue. And usually one or two more: a documentation wiki, a communication tool, a time-tracking system.
Each tool does its job. None of them talk to each other in a meaningful way.
The result is a fragmented picture of your business that requires a human to manually synthesize information across systems every time someone needs to answer a question that spans more than one tool. "How much revenue does this client generate relative to the ticket volume they create?" requires data from your PSA and your accounting platform. "Which clients are at risk of churning?" requires data from your CRM, your PSA, and your RMM.
This post is a technical deep-dive into how we approach the problem of integrating multiple operational tools into a single, unified dashboard. It covers the real engineering challenges, the architectural decisions, and the tradeoffs involved.
The Integration Landscape
Before discussing architecture, it helps to understand the specific tools and their integration characteristics.
PSA Platforms
ConnectWise Manage offers a comprehensive REST API with good coverage of tickets, projects, companies, contacts, and configurations. Rate limits are generous for read operations (typically 1,000 requests per 5 minutes for cloud-hosted instances). The data model is deep but complex, with extensive use of custom fields that vary wildly between deployments.
Datto Autotask provides a SOAP-based API that has been supplemented with REST endpoints in recent years. The API coverage is solid for core entities but has gaps in reporting data. Rate limits are stricter than ConnectWise, and the SOAP endpoints require more careful handling around session management.
Atera uses a straightforward REST API with clear documentation. It is simpler than ConnectWise or Autotask, which makes integration faster but also means less granular data is available through the API. Rate limits are reasonable for small to mid-sized implementations.
RMM Platforms
ConnectWise Automate (LabTech) and Datto RMM (formerly Autotask AEM) both expose device health, patch status, and alert data through their APIs. The challenge with RMM data is volume. A 500-endpoint environment generates thousands of data points per day across patch status, antivirus definitions, hardware health, and alert events.
NinjaRMM and Atera's built-in RMM offer cleaner API surfaces but with less depth. The tradeoff is faster integration time versus less granular monitoring data.
CRM Systems
Most service businesses use either HubSpot, Salesforce, or their PSA's built-in CRM functionality. HubSpot's API is well-documented and permissive with rate limits. Salesforce's API is powerful but complex, with multiple API versions (REST, SOAP, Bulk, Streaming) suited to different use cases.
Accounting Platforms
QuickBooks Online provides a solid REST API with OAuth 2.0 authentication. The main challenges are around data mapping: QuickBooks' chart of accounts, customer hierarchy, and invoice structures vary significantly between deployments. Xero offers a similar REST API with slightly better developer documentation.
Architectural Decisions
Building a unified dashboard on top of these systems requires making several foundational architectural decisions early.
Real-Time Sync vs. Batch Processing
The first question is how fresh the data needs to be.
Real-time sync (via webhooks or polling at sub-minute intervals) gives the freshest data but creates engineering complexity around error handling, deduplication, and managing webhook reliability. Not all tools offer webhooks, and those that do often have reliability issues (missed events, delayed delivery, or changed payloads without notice).
Batch processing (scheduled syncs every 5 to 60 minutes) is simpler to build and debug. The data is not instant, but for most dashboard use cases, a 5 to 15 minute delay is perfectly acceptable. Clients checking their portal are not expecting real-time telemetry. They want to see what has happened today, this week, this month.
Our approach: batch-first with real-time escalation. We sync most data on a 5 to 15 minute cycle using scheduled jobs. For high-priority events (critical alerts, major status changes), we implement webhook listeners where available or increase polling frequency for specific endpoints.
This gives us the reliability and debuggability of batch processing for 95% of the data, with near-real-time responsiveness for the events that actually matter to clients.
The Unified Data Model
This is the hardest and most important engineering challenge. Each tool has its own data model, its own terminology, and its own way of representing relationships.
A "ticket" in ConnectWise is a "Service Request" in Autotask and a "Ticket" in Atera, but the fields, statuses, and relationships differ. A "Company" in the PSA may or may not map cleanly to a "Customer" in QuickBooks or a "Contact" in HubSpot.
We build an intermediate data model, a canonical representation that abstracts away the source-specific details. This model defines core entities:
- Organization: The canonical representation of a client, mapped from the PSA, CRM, and accounting platform
- Contact: Individual people associated with an organization, with role information
- Ticket/Request: Any unit of work, normalized to a common schema with status, priority, category, and timeline fields
- Device: Endpoints and infrastructure, with health status and compliance data from the RMM
- Project: Multi-phase work with milestones, mapped from the PSA's project module
- Financial Record: Invoices, payments, and revenue data from the accounting platform, linked to the canonical organization
Each entity in our unified model carries source metadata: which system it came from, when it was last synced, and the original source ID. This allows us to trace any dashboard data point back to its origin and handle conflicts when the same entity appears in multiple systems with different values.
Handling Data Conflicts
When you merge data from five systems, conflicts are inevitable. The client's name is "Acme Corp" in the PSA, "Acme Corporation" in QuickBooks, and "Acme Corp." in the CRM.
We handle this with a source priority hierarchy. For each entity type, one system is designated as the source of truth for specific fields:
- Organization name and contact details: CRM is authoritative
- Ticket and project data: PSA is authoritative
- Device health and compliance: RMM is authoritative
- Financial data: Accounting platform is authoritative
When conflicts exist, we flag them in an administrative view for the provider to review and resolve. We do not silently pick one version. Transparency about data quality builds trust in the system.
Entity Resolution
Beyond naming conflicts, there is the harder problem of entity resolution: determining that "Acme Corp" in the PSA and "Acme Corporation" in QuickBooks represent the same real-world entity.
We use a combination of approaches:
- Deterministic matching on shared identifiers (email domains, tax IDs, phone numbers)
- Fuzzy matching on company names using edit distance and token overlap algorithms
- Manual confirmation for ambiguous matches, presented to the administrator during initial setup
The initial entity resolution during onboarding is the most labor-intensive part of the integration process. Once established, ongoing resolution for new entities is largely automated.
API Challenges and Solutions
Working with five different APIs simultaneously surfaces a set of recurring engineering challenges.
Rate Limiting
Every API has rate limits, and they are all different. ConnectWise allows 1,000 requests per 5 minutes. QuickBooks allows 500 requests per minute. HubSpot's limits vary by subscription tier.
Our approach is a centralized rate limiter that tracks usage per API, per credential set. Each integration module requests API capacity from the rate limiter before making calls. When limits are approaching, the system automatically throttles by queuing requests and extending sync intervals.
For initial data loads (when first connecting a tool with years of historical data), we implement backfill jobs that run during off-hours with conservative rate consumption to avoid impacting the provider's normal API usage.
Authentication Lifecycle
OAuth tokens expire. API keys get rotated. Service accounts get disabled. Authentication failures are the most common cause of integration downtime, and they need to be handled gracefully.
We implement proactive token refresh (refreshing OAuth tokens before they expire, not after), health check endpoints that verify authentication is valid before each sync cycle, and automated alerting when credentials need manual intervention.
Schema Changes
APIs change. Fields get renamed, deprecated, or restructured. A ConnectWise update might change how custom fields are returned. A QuickBooks API version bump might alter the invoice object structure.
We version our API adapters independently and implement integration tests that run against sandbox environments. When a schema change is detected (a field returns unexpected types or a required field disappears), the system degrades gracefully, continuing to sync available data and alerting our team about the schema change.
Pagination and Large Data Sets
Pulling thousands of tickets, tens of thousands of device records, or years of financial history requires careful pagination handling. Each API paginates differently (cursor-based, offset-based, page-number-based), and some have inconsistencies in their pagination behavior.
We abstract pagination into our API adapter layer so that the sync logic simply requests "all records modified since X" and the adapter handles the mechanics of iterating through pages, handling edge cases like records being added or modified mid-pagination.
The Data Pipeline
Once data is extracted from source APIs, it flows through a pipeline that transforms, validates, and loads it into our unified data model.
Extract
Each integration module is responsible for extracting data from its source API. Modules track their own sync state (last successful sync timestamp, cursor positions) and implement incremental extraction: only pulling records that have changed since the last sync.
Transform
Raw API responses are transformed into our canonical data model. This stage handles:
- Field mapping: Converting source-specific field names and values to canonical equivalents
- Data enrichment: Calculating derived fields (e.g., ticket age from creation date, SLA compliance from response timestamps)
- Relationship linking: Connecting entities across systems using the entity resolution mappings
Validate
Before loading, data passes through validation rules that catch common issues: missing required fields, values outside expected ranges, broken relationship links. Invalid records are quarantined and surfaced for review rather than silently dropped or loaded with errors.
Load
Validated data is loaded into the unified data store with full audit trails. Every change is logged with its source, timestamp, and the sync job that produced it. This makes debugging straightforward: if a dashboard shows unexpected data, we can trace it back through the pipeline to the exact API response that produced it.
Building the Dashboard Layer
With clean, unified data in place, the dashboard layer is comparatively straightforward. But there are still important design decisions.
Query Performance
Dashboard queries need to return in under 200 milliseconds to feel responsive. With hundreds of thousands of records across multiple entity types, this requires thoughtful indexing, pre-computed aggregations for common views, and caching for expensive queries.
We pre-compute the most common dashboard views (account health scores, ticket summaries, uptime metrics) during the sync pipeline rather than calculating them at query time. This moves computation to the background and keeps the dashboard snappy.
Multi-Tenancy
The dashboard serves multiple clients of the same provider, each seeing only their own data. Multi-tenant data isolation is non-negotiable from both a security and a privacy perspective.
We implement tenant isolation at the data layer with organization-scoped queries enforced at the API level. Every query automatically includes the organization filter, and we test regularly for data leakage between tenants.
Role-Based Access
Within a single client organization, different people need different views. The office manager sees tickets and project status. The CEO sees financial summaries and strategic metrics. The IT contact sees device health and security posture.
Role-based access is implemented at the view level, not just the data level. Each role gets a different dashboard layout, different default views, and different notification settings.
Lessons From Production
Several lessons only became clear after operating these integrations in production across multiple client environments.
Every Deployment Is Different
Two ConnectWise instances are never configured the same way. Custom fields, workflow rules, status codes, and categorization schemes vary dramatically. Our integration modules need to be configurable enough to handle these variations without custom code for each deployment.
Monitoring Is Everything
With five integrations running continuously, something is always slightly broken. An API returns an unexpected error code. A webhook delivery fails silently. A rate limit is hit at an unusual time.
Comprehensive monitoring with clear alerting is not optional. We monitor sync freshness (how recently each integration successfully completed), error rates per API, data volume anomalies (sudden drops or spikes that indicate a problem), and authentication health.
Clients Notice Stale Data Immediately
If the dashboard shows a ticket as "open" that the client knows was resolved an hour ago, trust in the system erodes instantly. Sync freshness indicators (showing clients when data was last updated) and rapid investigation of staleness complaints are critical for maintaining adoption.
The Outcome
When it works, and it does work, the result is transformative. A provider can log in and see their entire business in one place: client health scores, revenue metrics, ticket trends, device compliance, project progress. All from data that already existed but was locked in five separate tools.
The client logs in and sees a curated view of their relationship with the provider: what is happening, what has been accomplished, what is coming next. No more calling for updates. No more wondering what they are paying for.
The integration layer is invisible. And that is exactly the point.
Let's Connect Your Stack
If you are running 4, 5, or 6 tools and manually synthesizing data across them, we should talk. We build the integration layer and unified dashboard that makes your existing tools work together, without replacing any of them.
