A question that comes up in almost every sales-ops project: "our leads and deals live in [HighLevel / Zoho / Salesforce / Pipedrive], how do we get that into Power BI?" The honest answer is "it depends on the CRM and the volume," because there are three real paths — a native connector or Power Query against the CRM's REST API, or a staged pipeline through Azure Data Factory (or Fabric) — and picking the wrong one for the situation either wastes a day building something Power BI already does for free, or leaves you with a fragile report that breaks every time the CRM changes a field.
Path 1 — Native connector or direct Power Query
Power BI ships native connectors for the big platforms (Salesforce Objects, Dynamics 365, HubSpot via the Power Query community connector) and, for anything without one, Power Query's Web or OData source can call a REST API directly from Get Data, handling pagination and authentication with a parameterized function.
- Pros: nothing to deploy outside Power BI — one M query, one dataset, one scheduled refresh (Pro: every 30 min; Premium: as often as every few minutes). Fastest path to a working report, and the easiest for a client's existing Pro license to maintain without extra infrastructure.
- Cons: every refresh re-pulls and re-transforms the full payload (or whatever incremental filter you hand-build in M), so it gets slow once a CRM has tens of thousands of contacts or deals. Credentials live inside the PBIX/dataset's data source settings, which is fine for one report but gets messy once three reports need the same CRM data — each one re-implements its own API logic, and a field rename in the CRM breaks all three independently.
This is the right call for a single report, a CRM under ~50k records, or a client who doesn't want anything beyond their Power BI license to maintain.
Path 2 — REST API with Power Query, properly parameterized
This is still "just Power Query," but built as a reusable function instead of a one-off query: a parameterized fnGetCrmPage(endpoint, cursor) function that handles the CRM's specific pagination (HighLevel and Zoho both use cursor/offset pagination with a few hundred records per page), wrapped in List.Generate to walk every page until the API signals there's no more data.
- Pros: same "nothing outside Power BI" simplicity as Path 1, but centralizing the paging/auth logic in one function means every table (contacts, opportunities, pipelines) reuses it, and a credential or schema change only needs fixing in one place.
- Cons: still bound by Power Query's refresh model — no incremental load without Premium's incremental refresh policies (which need a date column the CRM API supports filtering on), and the API's own rate limits become Power BI's problem during a full refresh. HighLevel in particular throttles aggressively enough that a full contacts pull can take longer than a Pro refresh window allows.
Worth the extra setup time whenever more than one report (or more than one CRM object) needs the same source, even if volume is still moderate.
Path 3 — Azure Data Factory (or Fabric Data Factory) staging layer
For real volume — six figures of contacts, deal history going back years, or a CRM combined with other sources into one model — move the extraction out of Power BI entirely. An ADF (or Fabric) pipeline calls the CRM's REST API on a schedule, lands the raw response in a Data Lake (or a staging database), and Power BI reads the already-cleaned, already-incremental table instead of hitting the CRM at all.
- Pros: incremental extraction (ADF's own watermarking, not Power Query's), retries and alerting built into the pipeline instead of a silent refresh failure, and the CRM is only ever called once regardless of how many reports or datasets consume the result. This is also the only path that scales past a Premium incremental-refresh policy, because the heavy lifting happens before the data ever reaches a Power BI dataset.
- Cons: real infrastructure to build and own — a pipeline, a landing zone, usually a small orchestration layer for error handling — which is overkill for a single report and adds a cost line (ADF pipeline runs, storage) that a native connector doesn't have. It also adds a hop: Power BI's "last refreshed" no longer tells you when the CRM data is actually current, only when the dataset last read the staging table, so the pipeline's own run history needs to be visible somewhere the team actually checks it.
How to decide
Three questions settle it in practice: how many reports need this CRM data (one → Path 1, several → Path 2), how large is the object you're pulling (under ~50k rows, either Power Query path is fine; well past that, Path 3), and does the CRM need combining with other sources into one model anyway (if yes, that data warehouse layer is already Path 3's staging area, so the CRM extraction belongs there too). Most CRM-to-Power-BI requests we see start as "just connect it" and turn into Path 3 within a year, once a second report or a second data source shows up — building the parameterized Power Query function in Path 2 from day one keeps that migration from being a full rewrite later.
If you're stuck between "a connector should just work" and "this needs real plumbing" for your CRM, talk to us — we'll tell you which path actually fits your volume, not the one that sounds the most impressive.