ποΈ Recipe Β· Microsoft 365 Governance
Generate an Organization Tree Map and Entity List via Microsoft Graph
Build a complete hierarchical org chart and entity inventory from your Microsoft 365 tenant using Graph API, manager relationships, departments, and groups.
Complexity
Intermediate
Impact
read-only + reporting + governance + audit-ready
Context
Why This Matters
Understanding an organization's structure is foundational to governance, onboarding, access reviews, and communications planning. While Microsoft 365 stores rich organizational data β user profiles, manager relationships, departments, and group memberships β there is no built-in admin view that presents a complete hierarchical tree alongside an entity inventory.
This recipe walks through generating that view programmatically by combining data from /users, /users/{id}/manager, and /groups in Microsoft Graph. The result is a visual reporting-line tree plus a consolidated list of departments and groups that exist in the tenant.
When to run this recipe
- During annual access reviews or governance audits
- Before a reorganization, merger, or acquisition
- When onboarding new HR or IT leadership who need to understand the org
- As part of a readiness assessment for Conditional Access, Sensitivity Labels, or lifecycle workflows that depend on department/manager attributes
- To detect data quality issues (missing managers, missing departments, orphaned users)
Expected Outcomes
After completing this recipe you will have:
- A hierarchical ASCII/text tree showing every reporting chain in the tenant, starting from users with no manager (CEOs, contractors, service accounts)
- A complete list of departments with employee counts per department
- An inventory of all Microsoft 365 Groups and Security Groups, including descriptions and type
- Summary statistics: total users, top-level managers, department count, group count
- A downloadable
organization-map.txtreport suitable for sharing with HR, leadership, or auditors
You can feed the same data into Visio, Mermaid diagrams, or BI tools for richer visualizations.
Risks & Considerations
Data accuracy
- The tree is only as good as the
managerattribute in Entra ID. Many tenants have incomplete manager data β users without managers will appear as roots, producing a flat-looking tree. - Users with
departmentleft blank will be grouped under "No Department". - Guest users (
userType = Guest) are included by default. Filter them out if you only want employees.
Performance and throttling
- Fetching manager relationships requires one API call per user. For tenants with 10,000+ users, batch requests or use
$expand=managerto reduce call volume. - Microsoft Graph throttles at roughly 10,000 requests / 10 minutes per app per tenant. Implement retry with exponential backoff on HTTP 429.
Privacy and handling
- The output contains PII (names, titles, email addresses, reporting lines). Treat the file as confidential and store it only in approved locations.
- Do not email the raw report externally β it can reveal sensitive org structure to attackers for spear-phishing.
Do not
- Do not mutate user or group data from this recipe β it is read-only by design.
- Do not rely on the tree for compliance attestations without validating manager data against HRIS first.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| User.Read.All | Enumerate all users and read profile properties (displayName, jobTitle, department, mail). |
| Directory.Read.All | Read manager relationships via /users/{id}/manager to build the reporting hierarchy. |
| Group.Read.All | Enumerate Microsoft 365 Groups and Security Groups as organizational entities. |
| Organization.Read.All | Retrieve tenant organization details (display name, verified domains). |
The fastest way to get this done: just ask Dex. Copy the prompt below and paste it into your Dex conversation.
For IT Admins
Paste into Dex Pro
For End Users
How an employee would ask Dex for help
Manual walkthrough in the Microsoft 365 admin center and Entra portal
There is no single GUI that produces a complete tree map, but you can assemble equivalent information across three admin surfaces. This approach is suitable for small tenants (<50 users) or spot-checks.
Step 1 β Export the user list from Microsoft 365 admin center
- Sign in to as a Global Reader or User Admin.
- Navigate to .
- Click Export users in the toolbar. A CSV containing display name, UPN, licenses, and basic profile data will download.
Step 2 β Capture manager/department detail from Entra ID
- Go to .
- Click Download users β Start. The resulting CSV includes
department,jobTitle, andcity, but not manager. Manager must be read per-user: - For each user you care about, open the user blade β tab β note the Manager field.
Step 3 β Inventory groups
- In Entra, go to .
- Click Download groups β Start. The CSV lists every group with its type (Security / Microsoft 365), mail-enabled flag, and description.
Step 4 β Build the tree
- Open the user CSV in Excel. Add a Manager column populated from Step 2.
- Use a PivotTable or a tool like Visio β Create from Data β Organization Chart Wizard, pointing at the CSV with Name and Reports to columns. Visio will render a hierarchy automatically.
Because manager data is read one user at a time in the GUI, the API or PowerShell approach below is strongly recommended for tenants with more than a handful of users.
Graph API recipe
Three Graph endpoints are combined to produce the tree map and entity list.
1. Read tenant organization details
GET https://graph.microsoft.com/v1.0/organizationReturns tenant display name and verified domains. Useful as the report header.
2. Enumerate users with paging
GET https://graph.microsoft.com/v1.0/users?$select=id,displayName,jobTitle,department,mail,userPrincipalName&$top=999Follow the @odata.nextLink until it is absent. Keep $select narrow to minimize payload.
3. Resolve manager per user
The list endpoint does not return manager in the default projection. Either expand it or call per-user:
// Option A: expand on the list call
GET /v1.0/users?$select=id,displayName,department,jobTitle&$expand=manager($select=id,displayName)
// Option B: per-user lookup (used in the reference script)
GET /v1.0/users/{user-id}/manager?$select=id,displayNameA 404 on the per-user manager call means the user has no manager assigned β treat them as a tree root. Do not treat 404 as an error.
4. Enumerate groups
GET /v1.0/groups?$select=id,displayName,description,groupTypes,mailEnabled,securityEnabled&$top=999Groups where groupTypes contains Unified are Microsoft 365 Groups; otherwise they are Security or Distribution groups.
Sample response fragment
{
"value": [
{
"id": "2f2d3187-5fad-4d73-a9f5-3c356e68a038",
"displayName": "Patti Fernandez",
"jobTitle": "Chief Executive Officer",
"department": "Executive"
}
]
}Throttling
On HTTP 429, honor the Retry-After header. For large tenants, use JSON batching (20 requests per batch) to fetch manager relationships more efficiently.
PowerShell recipe using Microsoft.Graph
The reference script below uses the official Microsoft.Graph module. It authenticates interactively, pages through all users, resolves managers, collects groups, and writes a formatted organization-map.txt.
Prerequisites
- PowerShell 7+ (recommended) or Windows PowerShell 5.1
Install-Module Microsoft.Graph -Scope CurrentUser- A Global Reader (or higher) account for the target tenant
How it works
Connect-MgGraphprompts for consent on the four required scopes.Get-MgUser -All -ExpandProperty Managerfetches every user in a single paged call with the manager attribute expanded β avoiding one-call-per-user.- The script builds a hashtable keyed by user ID, attaches children to their manager, and identifies roots (users with no manager).
- A recursive
Write-Treefunction emits the ASCII tree withβββ,βββ, and indentation. Get-MgGroup -Allpulls the group inventory.- Everything is written to
organization-map.txtin the current directory.
Running the script
.\Generate-OrgTreeMap.ps1 -OutputPath "C:\Reports\org-map.txt"Use -IncludeGuests:$false (the default) to exclude external guests from the tree.
Next steps