If your compliance dashboards always seem a step behind, you’re not alone. Most standard tools skip over entire categories of critical risk, and manual reporting eats up hours only to deliver incomplete results.
Today, you’ll see exactly which Microsoft Graph APIs hold your compliance blindspots and how to plug those gaps using scripts and Purview—no guesswork, just real answers that turn compliance chaos into clarity.
Why Your Compliance Reports Miss the Big Picture
Let’s start with that nagging feeling you get after a compliance audit: You’re staring at spreadsheets, exports, or the default Microsoft 365 dashboards, but something always seems off. No matter how many times you hit “Export CSV” or download a fresh report, the confidence just isn’t there. You review the numbers, scroll through pages of rows, and maybe you even try cross-referencing the data with incident notifications or emails from your security team. The frustration settles in quickly. Why does it always seem like there’s something missing, even when you’ve done everything the official guidance recommends?
The answer usually sits in how the majority of teams treat Microsoft 365 compliance reporting as a box to check. Built-in dashboards, Security & Compliance Center exports, audit log downloads—they’re all simple, accessible, and they look official enough to pass a glance in an annual review. For a lot of admins, running those out-of-the-box reports feels like covering your bases. If there are checkboxes, percentage bars, or even a few green lines, it’s easy to assume you’ve captured the most important risks. But real-world incidents have a habit of slipping past these reports, unnoticed until they explode into actual problems.
Consider a review scenario that plays out more often than anyone wants to admit. An external auditor sits down and asks for evidence of DLP incidents handled in the last quarter. You share your compliance exports—after all, that’s what Microsoft recommends in the UI. The auditor, though, is scanning for a very specific case that the legal team flagged months ago. You check again, but it’s nowhere. After some back-and-forth, you realize there was an eDiscovery case that the compliance portal never even listed, because it lived outside the normal workflow. The incident, documented in emails and maybe even in a few Teams chats, didn’t make its way into the standard report. Now you’re left scrambling, patching together fragmented evidence and hoping there’s no follow-up question you can’t answer.
It’s not just a fluke. Microsoft’s documentation makes a point of reminding admins that standard dashboards provide summary overviews, but advanced or “hidden” details only show up if you tap into specific, less obvious data sources. There are a handful of blunt hints in the docs: “Certain compliance actions may not appear in standard audit logs” or “To access advanced eDiscovery activities, use Graph or PowerShell endpoints.” It’s like running an antivirus scan you assume checks everything, only to learn it skipped an entire disk partition without telling you. The users feel safe, but the threat’s still lurking, just out of sight.
When you stack these gaps across multiple teams and multiple review cycles, you start to see just how much risk goes undetected. The Compliance Center UI, for example, doesn’t always reflect the full scope of DLP policies and can lag behind on status from ongoing eDiscovery cases. And when something gets flagged outside the usual channels—maybe by a third-party tool or a direct alert from Graph APIs—it rarely gets retroactively added to your last quarterly report. Here’s where the illusion of coverage bites back: More than 60% of compliance personnel admitted, in a 2023 study, they lean almost exclusively on standard Microsoft 365 dashboards and exports for their compliance evidence packages. That means the majority are working with incomplete or stale data, missing everything from shadow eDiscovery cases to the quiet DLP hits that don’t generate visible alerts.
It’s not just an admin problem, either. Legal, HR, and risk teams all build business, disciplinary, or investigational decisions off these Microsoft-recommended views. When these professionals run their own checks—imagine a legal hold that never shows up in the UI, or an HR inquiry into information leakage that comes up blank—they’re getting only a slice of what’s happening in their tenant. Every scenario like this chips away at trust in compliance data, leading to more manual reviews, longer audits, and way more room for error.
So, why are these blind spots so hard to actually see? It comes down to how Microsoft structures its reporting endpoints. Standard compliance exports are based on high-level, aggregated tables designed to be quick and consumable. The deep-dive data—the good stuff with granular eDiscovery history, underlying alert metadata, and the full run-down of DLP policy matches—lives in separate endpoints accessed through Microsoft Graph. Most admins never touch these endpoints, either because they’re not aware they exist or they assume it’s only something developers would need. But these Graph APIs are where the most actionable compliance data is hidden. They aren’t front-and-center in the interface, the permissions are confusing, and even seasoned IT pros can go years without realizing there’s a whole other universe of data just outside their reach.
The reality is, if you’re only looking at the built-in compliance dashboards, you’re running with partial visibility. All the exports in the world can’t save you from invisible risks if you don’t know where to look. So, let’s get right to it: There are Graph API endpoints that surface all those missing incidents, policies, and cases—and you can start unlocking them without risking your tenant or breaking your reporting workflows. This isn’t theory, and it isn’t just for coders. Anyone who’s worked with compliance data knows how much easier life gets once you stop guessing and start pulling the data that’s actually there. And this is where things start to get interesting—because next, we’re going to get hands-on with the endpoints that do all the heavy lifting under the hood, and talk about how to tap into them, one by one.
Cracking Open Microsoft Graph for Compliance Gold
It’s easy to dismiss the Microsoft Graph API as something only developers care about. There’s code everywhere, permissions lists that scroll for miles, and endpoints with names that don’t exactly roll off the tongue. But here’s the thing: buried in those REST endpoints is compliance data that never makes it into your regular dashboards or audit logs. If you skip Graph, you’re missing whole categories of traceability your organization needs. Microsoft Graph is more than a developer toyset; it’s the central nervous system of all your Microsoft 365 data, tying together everything from Teams messages and Azure AD accounts to SharePoint file activity. But—and this is what most folks don’t realize—not every Graph endpoint is created equal when it comes to compliance. In fact, only a handful of them actually surface incident-level information that legal or risk teams care about.
So let’s talk about what actually happens when you point your scripts at Graph. When an admin first opens up Graph Explorer or fires off a test request in PowerShell, the default instinct is to try the endpoints that sound familiar. /users, /mail, /drive—these are where all the demos and documentation start. You get mailbox activity, sign-in logs, or some SharePoint site changes. It’s all fairly safe, and most of it looks similar to what you can already see in the admin center. But that’s where the compliance coverage starts and ends for most people. If you’re only poking at these surface-level endpoints, you’re blind to the places where Microsoft 365 really buries incident data.
Now, say you’re an admin tasked with pulling a quarterly compliance report. You get your mailbox logs without much trouble, because the permissions are basic and the docs are everywhere. But DLP activity? Suddenly you get a string of errors about missing permissions—or, worse, your query just returns zero results with no explanation. This exact scenario plays out all the time. Nobody tells you upfront that incidents like DLP hits and eDiscovery case activity don’t appear unless you use specific endpoints, like /security/dataLossPreventionPolicies and /compliance/ediscovery/cases. Miss these, and you’re left with an incomplete audit trail that skips over some of the most sensitive actions happening in your environment.
The catch is, Microsoft intentionally segregates these compliance-heavy endpoints from the regular core Graph namespace. For anything sensitivity-related or involving security incidents, you usually have to authenticate against the Security & Compliance Center—sometimes with a completely different set of permissions than what you’d use for user or group queries. It’s not as simple as just using your global admin account either. Some of these permissions are so specific that even experienced admins get tripped up the first time around. That’s led to a cottage industry of half-baked scripts shared in forums or GitHub repos, which look useful on the surface but quietly skip the endpoints where the real compliance gold is stored.
What’s interesting is that until recently, Microsoft’s own reporting APIs were even less capable than they are now. After several public incidents—where breaches or data leaks slipped past standard compliance exports—Microsoft started rolling more compliance signals into Graph. They didn’t send a press release or put a sticky banner next to the Azure AD portal. Instead, you have to dig through release notes or Git commits to notice how, for example, /security/alerts has quietly grown to cover more alert types, or how /compliance/ediscovery/cases lets you pull both open and closed investigations, with detailed event history attached. These changes matter because they signal that Microsoft’s thinking has finally shifted. Compliance isn’t just a reporting layer anymore; it’s now a first-class citizen in the Graph API ecosystem, if you know where to look.
The pitfall is still lurking, though: picking the wrong endpoint, or botching the authentication flow for these protected segments. One admin I talked to last month built an automated script to export mailbox audit logs—great. But the same script tried hitting DLP and eDiscovery endpoints with generic user permissions, only to bring back empty results. Because the Security & Compliance Center endpoints sit on their own permission island, you end up with two-thirds of the data and one massive hole where the incidents should be. The result? Hours lost to debugging, with nothing to show in the compliance report but blank cells.
Let’s put some clarity on which endpoints are worth your time. For compliance reporting that actually closes the data loop, the heavy hitters are /security/alerts, /compliance/ediscovery/cases, and /security/dataLossPreventionPolicies. Each endpoint taps into a different risk vector—active threat alerts, legal case activity, and DLP events. But this isn’t just a matter of plugging in a new URL. For each of these, you need to pre-authorize the right permissions, scope the OAuth tokens carefully, and double-check what each response object gives you. The differences aren’t just in the field names but in the presence—or absence—of entire nested entities. That dictates whether your output just shows a summary or delivers deep detail, like user actions, escalation steps, or even remediation timestamps. Without this, your compliance “evidence” is always just a partial story.
Getting through those permission puzzles is worth it, though, because once you have access, the quality of the output jumps. You’re not just seeing whether a policy fired; you’re getting who triggered the event, what files were involved, what remediation steps got taken, and the chain of actions inside an eDiscovery case. That’s the granular context auditors chase and business leaders need to make real decisions.
So with all that said, having the right keys to these Graph endpoints gives you a live window into compliance risk as it happens, not just historical snapshots. But having access is only part of the challenge. Next comes the task of scripting—and actually pulling the events, policies, and cases that matter, in a way that makes sense for your business and is defendable in an audit. Let’s walk through what that really looks like, and what you need to watch for if you want your compliance reporting to actually deliver.
Scripting Compliance: PowerShell and Python in Action
If you’ve ever fired up PowerShell or Python to script compliance reporting, you know firsthand it’s not a smooth ride. You’ve followed the docs, maybe borrowed some sample code, and punched in your tenant details—only to watch OAuth authentication fail, or find your output filled with empty arrays when you’re sure incidents happened that week. It’s that classic scenario where you know the data is hiding somewhere, but every attempt to automate ends up making the gaps look bigger, not smaller.
On paper, scripting against Graph seems straightforward. In practice, Microsoft’s OAuth flow brings a checklist of hurdles: you need the right application registrations, explicit admin consent on the right scopes, and a solid grasp of how Graph expects you to pass tokens. Miss any step, and the API returns either opaque errors or worse, a successful query with absolutely zero content. This is the point where you start triple-checking portal logs and wondering if something’s wrong with your tenant. Most of the time, the issues boil down to mismatched permissions or endpoints that require elevated scopes—especially for anything under /security or /compliance.
And then there’s the structure of the API responses themselves. The Graph documentation lays out payloads as JSON, but the nested properties and inconsistent field population can throw off even experienced admins. When you’re dealing with something like DLP policy matches, the actual incidents are nested three or four layers deep within the response. If your script only parses the top level, you’ll never see who triggered which incident or whether a remediation workflow was kicked off. That’s why so many DIY scripts floating around fail to return anything useful for compliance endpoints: they grab the summary, miss the detail, and leave you reporting on a set of empty shells.
Let’s say someone writes a PowerShell script that uses the /security/dataLossPreventionPolicies endpoint. The query works, and they get a list of policy objects. It looks promising until you realize none of the returned fields cover the incident status, the user involved, or the kind of matched content that actually landed you in hot water with the auditor last quarter. The same goes for eDiscovery case status—you need to hit both the /compliance/ediscovery/cases and the nested event endpoints, otherwise major changes like custodian adds, removals, or escalation events go missing from your final report. One script does its job, but without the full set of API calls wired up, you get a piecemeal view of risk.
Another headache is the authentication story. Even for admins, using delegated permissions rarely cuts it for compliance endpoints. The majority require application permissions, which means going through extra hoops with app registrations and admin consent. And while open-source tools try to fill the gap—there are modules like MSGraph for PowerShell or Python’s requests-based scripts—they don’t provide pre-built functions for DLP events or eDiscovery case management. Most of the example repos you’ll find stop at exporting user data or mail activity, and veer away from anything security-sensitive. So every team ends up building their own fragile wrappers or pasting together half a dozen scripts just to get through an audit.
The biggest pitfall is treating the Graph query as the finish line. It isn’t enough to pull “some” JSON and assume the story’s complete. APIs for compliance only expose what the token and scope allow, and often omit the child properties if you forget to explicitly expand them in your query. You need to use $expand clauses, dig into nested lists, and double-check the actual field names. It’s brutally easy to run a script, scan the first page of output, and miss entire clusters of incidents that never loaded because of a pagination or filter miss. And pagination—don’t get me started. Anything with serious volume, like multiple DLP incidents in a busy enterprise, requires looped requests and robust handling of nextLink pointers. A one-liner often isn’t enough.
But here’s the kicker: If you script it correctly, the heavy lifting doesn’t take hundreds of lines. With a clear understanding of which endpoints feed which report sections, you can surface DLP incidents, case statuses, and security alerts in as little as 15 to 20 lines of Python or PowerShell. Pull the data, parse the nested results, join with user properties for context, and suddenly you have a compliance snapshot that goes way beyond what the portal gives you. This is the difference between telling an auditor, “here’s what the dashboard says,” and actually proving, “here’s every action that happened, when, and who was involved.”
One thing to always do before patting yourself on the back: Take your script’s output and compare it, line by line, against your standard portal exports. Missing an incident? Check your scopes. Empty fields? Dive deeper into the JSON. Discrepancies will tell you which API calls or permission tweaks you’ve missed. Every false negative in your automation is a potential risk hiding in plain sight—so that cross-check isn’t just best practice, it’s ground truth.
Once you have scripts reliably pulling down the incidents, case changes, and DLP events that usually vanish from standard views, you hit a new wall—how to get this technical data into a format your compliance, legal, or business teams actually use. Raw JSON, CSV, or Excel dumps only take you so far if people can’t interpret them quickly. That’s where centralizing, tagging, and transforming these raw results with Microsoft Purview starts to shift the game. Here’s where all those fragmented scripts finally work together.
Turning Data into Decisions: Centralizing with Purview
If you’ve ever tried to make sense of a folder stuffed with JSON files from all those automated Graph queries, you know the headache. Pulling the raw data is already a battle—now, staring at those exports, the next battle starts: actually turning all this noise into a compliance report that your CISO or an external auditor can understand without hours of handholding. There’s no nice summary, just deeply nested lists, cryptic incident IDs, and a level of granularity that looks impressive right up until someone asks, “So, is this everything?” Realistically, security teams end up dumping these outputs into Excel, writing hasty formulas, then wrestling with ten-minute Power BI refreshes that still leave inconsistencies. That’s not compliance insight—it’s just digital clutter.
The thing is, most teams run into the same bottleneck. Everyone cobbles together two or three scripts—one for DLP activity, another for eDiscovery cases, maybe a third for pulling security alerts. It’s the “just get it out fast” approach. But these exports never line up perfectly. You’re left with separate CSVs, maybe a half-finished dashboard, and more manual copy-paste than any modern enterprise should tolerate. The result? When it’s time for a review, someone has the fun job of playing air traffic controller, sorting through hundreds of rows, trying to reconcile case names that were typed slightly differently, checking timestamps, and inevitably missing context on at least half the incidents flagged. If even one security event slips through, the audit trail shreds itself just as the scrutiny ramps up.
Now picture an audit scenario for a global business. You’ve just built a shiny new set of Graph scripts, but as soon as an external auditor requests a DLP incident summary, you realize the data is actually spread out across three CSVs and an aging Power BI dashboard synced to last month’s data. Each tool shows a piece of the picture, and neither one lines up perfectly with the story your risk team needs to tell. Incidents show up with different labels. User info is missing. If anyone on the review call starts asking for detailed case activity—say, “Can you show me who reviewed incident #246 in this list?”—suddenly it’s a patchwork of manually-stitched exports. It’s a story that’s missing chapters.
Here’s where Microsoft Purview starts to make sense as more than just another portal. The usual compliance workflow is a minefield of manual steps, but with Purview in the middle, you can create a single hub that receives, tags, and contextualizes everything from your Graph-powered scripts. At its core, Purview lets you bring together data sources—API exports, custom script outputs, even third-party logs—and centralize them under a tagging and labeling system that your compliance staff can actually use. No more paste-and-pray in Excel, no more scrolling through raw JSON. Incidents get tagged by type, mapped to owners, and surfaced in unified dashboards. For the first time, you can see every case, alert, or policy breach in one place—alongside real user context and actions taken.
But let’s not pretend the handoff is plug-and-play. Microsoft markets Purview as “the single pane of glass for risk and compliance,” but actually wiring up external script outputs takes more effort than the press materials suggest. You’ll spend time mapping JSON fields to Purview’s schema, tweaking import formats, and sometimes working around API limitations that seem designed by a team that’s never met a compliance analyst. And yet, if you’ve gotten as far as building clean outputs from Graph, these extra steps are just the finish line you need. The real trick is standardizing your scripts’ outputs to match what Purview expects. That means grooming your CSVs, normalizing field names, and turning cryptic incident logs into tags and labels that surface in Purview workbooks or reports.
Once you get the hang of it, though, Purview gives you automation options you simply do not get with isolated reports. You can create rules that flag specific incident types, push recurring policy matches to the right reviewers, and even set up alerts when particular user accounts are flagged repeatedly across different data sources. Everything is timestamped and auditable in one place—not just in disparate logs or scattered spreadsheets. For teams chasing ISO standards, GDPR readiness, or internal audit requirements, this move from fragmented data to centralized, tagged reporting is transformational: you’re not just compiling evidence, you’re building defensible stories about compliance health.
There’s also a practical side—integrating directly with Purview means you can finally automate exports, generate PDFs or digest emails on schedule, and track incident status in near-real time. No one’s locked into the labyrinth of admin centers and browser tabs. You gather what matters, automate the reporting cycle, and actually make compliance tracking proactive instead of reactive. The old chase-and-assemble pattern that plagued your monthly reviews is gone.
The payoff is straightforward: Your compliance dashboards finally reflect real risk, not just what the default tools want you to see. Incidents show up live. Decision makers spot trends before they explode into full-blown investigations. And if audit day rolls around, you have a clean, consistent call log, every incident tied to a case, with full history and resolution details ready to go—not buried across fragmented outputs.
With a single, unified reporting hub in Purview, you move out of survival mode and give your business the clarity it actually needs. And with scripts feeding real incidents into that hub, you’re not just showing that a tool ran—you’re proving that every critical event was caught, tagged, and handled. That kind of visibility is what turns compliance from checkbox exercise into real risk management.
This shift isn’t just about making audits easier—it’s about knowing your blind spots are closed and your reporting can keep pace with real-world incidents. So now, if legal, HR, or business leadership wants to see what’s really happening, the data finally has answers, not excuses. And that brings us to what this kind of proactive visibility actually means for your compliance posture, moving forward.
Conclusion
If you’re tired of compliance reports that leave you guessing, you’re not stuck with what Microsoft 365 shows out of the box. Graph and Purview let you uncover what’s missing and actually back up your compliance work with hard evidence—no more blind spots, and no more mystery incidents just out of reach. Once you start scripting your own queries, you stop piecing together partial views and start telling the whole story. If you’re looking for more real-world automation tactics for Microsoft 365, make sure you subscribe. Drop your most frustrating compliance questions in the comments, and we’ll tackle them in a future episode.
Share this post