Plan limits and usage¶
Each workspace is governed by a small set of headline plan limits. The API enforces these limits at the relevant write boundaries (creating projects, adding team members, sending invitations) and exposes a single query that reports current usage so the UI can render "X of Y used" everywhere it needs to.
Enforced limits¶
| Limit | Plan field | Where it's enforced |
|---|---|---|
maxProjects |
Plan.maxProjects |
createProject mutation |
maxTeamMembers |
Plan.maxTeamMembers |
addTeamMember and inviteTeamMember mutations |
A field value of null on the plan means the metric is unlimited.
Query usage¶
query TeamPlanUsage($teamId: String!) {
teamPlanUsage(teamId: $teamId) {
teamId
planId
projects { current limit remaining }
teamMembers { current limit remaining }
}
}
limit and remaining are both null exactly when the metric is
unlimited. remaining is otherwise clamped to a minimum of 0.
Authentication: any signed-in team member can read usage for their own workspace. Super admins can read usage for any workspace.
Plan limit reached errors¶
When a write would exceed an enforced limit, the API returns a 403 with a human-readable message:
Clients should surface this verbatim (it already contains the cap) and link the user to upgrade or contact support.
Super-admin overrides¶
Workspaces can be granted per-team overrides by a system super admin — useful for support carve-outs without re-pricing a plan.
mutation SetTeamPlanOverrides(
$teamId: String!
$input: SetTeamPlanOverridesInput!
) {
setTeamPlanOverrides(teamId: $teamId, input: $input) {
teamId
overrideMaxProjects
overrideMaxTeamMembers
effectiveMaxProjects
effectiveMaxTeamMembers
}
}
Input semantics:
- Omitting a field → leave that override unchanged.
- Sending
null→ "explicit unlimited override" — bypass the plan default for this team. - Sending a non-negative integer → cap the metric at that number for this team.
clearAll: true→ drop the entire override and revert to plan defaults.
Super admins additionally bypass enforcement entirely when they perform
the underlying write themselves (e.g. a super-admin createProject is
never blocked, even if the team is over its cap).
SDK¶
const usage = await client.planLimits.usage(teamId);
// usage.projects.remaining === null → unlimited
// usage.projects.remaining === 0 → blocked on next create
// Super-admin only
await client.planLimits.setOverrides(teamId, { maxProjects: 25 });
await client.planLimits.setOverrides(teamId, { clearAll: true });
Package: @mindsize/simple-feature-requests-sdk.