How Do You Get All Workspaces on a Fabric Capacity?
An administrator wants to know which workspaces run on a Microsoft Fabric capacity. The community points at the Core API, but that one has no capacity filter and only shows what the caller is allowed to see. Why that distinction defines the entire inventory.

Discussion Summary
- Source
- Technology
- Microsoft Fabric
- Category
- Platform Governance
Question
How do I get a list of all workspaces assigned to a Fabric capacity?
Recommendation
Choose on scope, not on convenience. The Core API shows what the caller can access, the Admin API with a capacityId filter is the only complete inventory.
Key Points
- Why "all workspaces on a capacity" is really two different questions, depending on who is asking
- That the Core API has no capacity filter at all, and what that means for your code
- Which permissions, scopes and identities the Admin API requires, and why a service principal is the deciding factor there
- The two limits that break an inventory process: ten thousand records per call and two hundred calls per hour
- Four details that silently corrupt an inventory: personal workspaces, orphaned workspaces, two different response shapes and a missing region field
The Challenge
An administrator wants to know programmatically which workspaces run on a specific Microsoft Fabric capacity. The trigger is almost always the same: a capacity is filling up, or costs need to be allocated, or someone has to prove that a particular workload sits on a particular SKU. The question sounds like a five minute lookup.
It is, right up to the point where you notice the answer depends on something the question never states. "All workspaces" means one thing to a workspace owner and something else to a platform team running a tenant. The first means every workspace they know about, the second means every workspace that exists. Those two readings lead to two different APIs, with different permissions, different limits and even different field names in the response. Pick the wrong one and you do not get an error, you get an incomplete list that looks complete.
Community Discussion
The replies in the thread pointed in two directions, and both were correct on
their own terms. The first route was the Fabric Core REST API: retrieve
workspaces with GET /v1/workspaces and filter the results on the capacityId
field. That works, it fits in three lines of script, and it needs no
administrator role. For someone inspecting their own environment this is the
right answer.
The second route was the admin portal. Under Capacity settings each capacity lists the workspaces assigned to it, and for a one off check that is the fastest path. Clicking is not a worse answer than scripting as long as the question is asked only once.
What the thread missed was the distinction between the two. Nobody asked back what the list was going to be used for, and that is exactly what decides which route is correct. For a script that reviews a handful of your own workspaces the Core API is fine. For an inventory process that underpins cost allocation, monitoring or compliance reporting that same route is structurally unreliable, because by definition it shows only what the executing identity happens to be able to see.
Microsoft Guidance
Microsoft Learn documents both APIs, and the difference is stated in the first sentence of each.
The Core API is explicitly scoped to the caller. GET /v1/workspaces returns,
in the words of the documentation, "a list of workspaces the principal can
access". The required delegated scopes are Workspace.Read.All or
Workspace.ReadWrite.All. Workspaces assigned to a capacity carry a
capacityId in the response, along with a capacityRegion holding the region
of that capacity. See
https://learn.microsoft.com/rest/api/fabric/core/workspaces/list-workspaces.
One important detail never surfaced in the thread: this API has no
capacityId parameter. Its only query parameters are roles,
continuationToken and preferWorkspaceSpecificEndpoints. Filtering by
capacity therefore always happens in your own code, after retrieving
everything the caller is allowed to see.
The Admin API is the tenant-wide counterpart and does have that filter.
GET /v1/admin/workspaces?capacityId={capacityId} returns the workspaces on
that capacity regardless of who is calling. You can also filter on name,
state, type and encryptionStatus. The caller must be a Fabric
administrator or authenticate as a service principal, with Tenant.Read.All
or Tenant.ReadWrite.All. Besides users and service principals, managed
identities are supported as well. See
https://learn.microsoft.com/rest/api/fabric/admin/workspaces/list-workspaces.
Two documented limits come with that API. A maximum of ten thousand records is
returned per call, and a maximum of two hundred requests per hour applies.
Exceeding that returns a 429 with a Retry-After header stating in seconds
how long to wait. Both APIs are paginated through continuationToken and
continuationUri; once all records have been retrieved those fields disappear
from the response or return as null. See
https://learn.microsoft.com/rest/api/fabric/articles/pagination.
The admin portal does the same job interactively. Through the gear icon and Admin portal you reach Capacity settings, where all capacities in the tenant are listed by type. The Details tab of a capacity holds "Workspaces assigned to this capacity", which lets you add and remove workspaces. Assigning requires two roles at once: contributor on the capacity and admin on the workspace. See https://learn.microsoft.com/fabric/admin/capacity-settings.
Architecture Perspective
The real question is not which API lists workspaces. The real question is which security boundary your inventory is supposed to follow. The Core API follows the identity, the Admin API follows the tenant. Building a governance process on the first produces a report that changes the moment someone is removed from a workspace, without anything changing about the capacity. That is not an inventory, it is a snapshot of one person's access.
"The Core API tells you what this identity sees. The Admin API tells you what exists. For an inventory that is the whole difference."
Four details then decide whether the inventory is actually correct, and none of them raises an error when you miss it.
The first is personal workspaces. Alongside Workspace, the type field in
the Admin API also carries Personal and AdminWorkspace. This is not a
theoretical case: capacity settings include an option called "Preferred
capacity for My workspace", which makes a capacity the default for personal
workspaces. A filter on capacityId alone therefore includes them. For a
consumption analysis that is probably correct, because they consume real
capacity. For a list of team environments it is noise. The point is to make
that call deliberately rather than inherit it by accident.
The second is what state actually means. The values are Active and
Deleted, and Microsoft explicitly notes that orphaned workspaces, meaning
workspaces without an administrator, are displayed as active. A report that
filters on state believing it measures "in use" is measuring something else.
Orphaned workspaces are precisely the kind of finding an inventory exists to
surface.
The third is the shape of the response. The Core API returns its results under
value with a displayName field; the Admin API returns them under
workspaces with a name field. Porting a script from one to the other
because the scope changed breaks the parser in two places at once. In the
other direction, the Admin API does not return capacityRegion while the Core
API does. If you need region for data residency or for a failover scenario,
take it from the capacity itself rather than from the workspace list.
The fourth is the request limit, and that is the dominant design constraint. Two hundred calls per hour sounds generous until you design an inventory that also fetches items, roles or consumption per workspace. In a tenant with a few hundred workspaces that budget is gone within minutes. The inventory should therefore rely on broad calls returning many records at once, with enrichment as a separate step that has its own cadence and its own intermediate store.
One operational consequence deserves separate attention, because it shows why this inventory is more than a list. When a capacity is deleted, non Power BI Fabric items in the assigned workspaces are soft deleted. They stay visible in the OneLake catalog and in the workspace list, but can no longer be opened or used. If the workspace is assigned to a capacity in the same region within seven days, they come back. Those seven days are separate from the retention period for deleted workspaces. Knowing which workspaces sit on a capacity is therefore the same as knowing exactly which items go dark if that capacity disappears.
Key Takeaways
Scope is the decision, not the API:
the Core API shows what the caller may see, the Admin API shows what exists in the tenant.
The Core API has no capacity filter:
capacityId is a response field, not a query parameter, so filtering is on you.
Expect pagination:
both APIs return continuationToken and continuationUri, and the Admin API caps out at ten thousand records per call.
Two hundred calls per hour drives the design:
avoid per workspace calls and separate inventory from enrichment.
Personal and orphaned workspaces are in the answer:
a capacity can be the default for My workspace, and orphaned workspaces count as active.
TechExplained Recommendation
Recommended when
- A tenant-wide capacity inventory underpins cost allocation, monitoring or compliance
- The executing identity is a service principal or managed identity, so the result does not depend on anyone's workspace access
- The process runs on a schedule and stores its output, so enrichment and reporting can operate independently of the request limit
- Personal workspaces, orphaned workspaces and workspace state are explicitly accounted for in the definition of the inventory
Not recommended when
- This is a one off check that Capacity settings answers faster in two clicks
- No Fabric administrator role or service principal is available, which simply makes the Admin API uncallable
- The application is deliberately user facing and must only show what the signed in user can see
- A lot of extra metadata is needed per workspace and no intermediate store has been designed for the request limit
Related Content
Related Use Cases
Related Architecture Assessments
Related How-tos
