Skip to content

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:

Plan limit reached: this workspace allows up to 3 projects. Upgrade the plan or contact support.

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.