Reading a Dataverse solution from the outside: solutioncomponents, ObjectTypeCodes and why flow names come back as GUIDs
The solution has 400 components and the API describes them as type 10080, type 29 and a list of GUIDs. Here is how to turn that into a table with names on it — including the two ids every cloud flow carries and the one that actually matches.

A solution's contents are in solutioncomponents: one row per component with an objectid, a componenttype and a rootcomponentbehavior. Query it with _solutionid_value eq <id> and you get the list. Making it readable is the work.
Component types
Some codes are fixed across every organisation: 1 is a table, 29 is a workflow (cloud flow, desktop flow, business process flow — the category on the workflow row distinguishes them), 80 is a model-driven app, 300 is a canvas app, 10 is a relationship, 9 an option set, 61 a web resource. Codes of 10000 and above are custom tables and are specific to that organisation: type 10080 in one tenant is a different table from 10080 in another. Resolve them through EntityDefinitions?$select=ObjectTypeCode,LogicalName,DisplayName for that environment, not from a static list.
Resolving names
- Tables:
objectidis theMetadataId; readEntityDefinitions(<id>)for the logical and display names. - Cloud and desktop flows:
objectidis a workflow id. Read theworkflowstable with$select=workflowid,workflowidunique,name,category,statecode,_ownerid_valueand index it by both ids — different solutions record different ones, and a lookup on only one leaves half the flows as GUIDs. - Canvas apps:
objectidis thecanvasappid. The app's Flow-API-style id — the one the admin APIs use — is in itsappopenuri, so keep both for joining to the rest of the inventory. - Model-driven apps:
objectidis theappmoduleid, and the name is onappmodules.
Batching without tripping the URL limit
Filtering workflows by two hundred workflowid eq clauses exceeds the URL length Dataverse accepts. Either batch in groups of twenty-five, or — simpler and faster for anything above a few hundred flows — read the whole table once per environment and index it in memory. The whole-table read is one paginated request and answers every solution in that environment.
The second hop for flows
solutioncomponents sometimes records a flow by workflowidunique and sometimes by workflowid, depending on how it was added. The Flow API knows only workflowidunique. So a component that resolves to a workflow row still needs a second hop to the Flow API name before it can be matched to the flow in the inventory — and that hop is why an unindexed lookup makes every solution flow look like it belongs to no solution.
Warnings are data
Some reads will be refused: a table the account has no privilege on, an EntityDefinitions call for a component that was deleted after the solution recorded it. Do not swallow these. Show the count of components that could not be named and the reason, because "three components could not be read: privilege denied on msdyn_..." is an answer, and a silent GUID is not.
Keep reading

How to inventory an entire Microsoft 365 tenant's Power Platform estate in an afternoon
Every environment, every Power App, every Power Automate flow, every connection — the estate is all there, spread across four admin APIs that each refuse to describe the whole. Here is how to bring it into one list, and what to do about the parts Microsoft will not tell you.

The Power Platform Center of Excellence Starter Kit and Power Insights: what each does best
Microsoft's CoE Starter Kit is the reference toolkit for a Power Platform Center of Excellence, and many tenants run it well. Power Insights covers some of the same ground and none of some of it. This is a plain account of which does what, written for the administrator who has to decide whether they need one, the other, or both.

Power Apps migration planning: the dependency checklist nobody gives you
Moving a Power App between environments or tenants is rarely hard because of the app. It is hard because of the eleven things the app quietly depends on, none of which appear in the export dialog. This is the list, in the order they bite.