> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Team seat quotas: manage seats and recover from TEAM_MEMBER_CAP_REACHED

> Operate your organization's seat quota — read live members plus pending invites from the dashboard, free a seat by revoking an invite or removing a member, recover the 422 TEAM_MEMBER_CAP_REACHED decline, and raise the quota through subaccount provisioning or a support change.

The [team seat quota concept page](/concepts/team-seat-quota-model) explains the model — a per-organization integer counting live members plus pending invites, enforced at invite time. This guide is the operational walkthrough: where to read the seat counters in the dashboard, how to free a seat when you reach the cap, the exact recovery steps when an invite is refused with `422 TEAM_MEMBER_CAP_REACHED`, and how to raise the quota when freeing a seat isn't enough.

Every control on this page is **tenant-owned**: the members, pending invites, and quota changes live in your organization and take effect immediately. The quota gates headcount only — it never touches message or call delivery.

## 1. Where seats are counted

Open **Settings → Team**. The seat math lives across the two cards at the top of the page:

* **Members table** — every live member. Each row of the full member list counts as one occupied seat. Soft-deleted members no longer hold a seat.
* **Pending invitations card** — every outstanding invitation. Each pending invite reserves a not-yet-seated spot, so a pending seat can't be promised to two people at once.

The effective usage is `live members + pending invites`, and that sum is compared against the organization's quota (2 seats on the default self-serve plan) on every invite-create request. The page is gated to **owner** and **admin** roles; other roles see the Settings hub instead. See the full day-to-day walkthrough in [Team members, invitations, and roles](/guides/organization-team-management).

To read the same usage from the API:

```bash theme={null}
curl -s https://api.orbit.devotel.io/api/v1/settings/team \
  -H "Authorization: Bearer $ORBIT_API_KEY"
```

Use the `pagination.total` in the response to see how many live members you hold, and cross it against:

```bash theme={null}
curl -s https://api.orbit.devotel.io/api/v1/settings/team/invites \
  -H "Authorization: Bearer $ORBIT_API_KEY"
```

The pending-invites list returns each invite's `email`, `role`, `invitedAt`, and `invitedBy` — you never receive the secure token, only the human-readable fields. Sum `total` from the members endpoint plus the length of this invite list for your occupied seats.

## 2. Free a seat

Two actions release a seat, and either one can immediately unblock an invite:

**Revoke a pending invite.** From the Pending invitations card press **Cancel** on the invite, or call the API with the invitee email (not the token — the API never discloses tokens):

```bash theme={null}
curl -X DELETE \
  "https://api.orbit.devotel.io/api/v1/settings/team/invites/alice%2Bonboarding%40acme.com" \
  -H "Authorization: Bearer $ORBIT_API_KEY"
```

The accept link in the original email stops working immediately, and the reserved seat returns to the pool before the invitee ever accepts. Re-invite later with the same address if you want it back.

**Remove a live member.** Removing a member is **owner-only** — admins can invite, resend, revoke, and change roles, but the Remove control and its API path are restricted to the owner. From the Members table press **Remove**, or:

```bash theme={null}
curl -X DELETE \
  "https://api.orbit.devotel.io/api/v1/settings/team/9d3cce49-…-user-id" \
  -H "Authorization: Bearer $ORBIT_API_KEY"
```

The seat is available immediately. Historical audit-log entries for the removed member are preserved.

## 3. Recover from 422 TEAM\_MEMBER\_CAP\_REACHED

The seat check runs before the invite is persisted, the dedup token is minted, or the email is sent — a refused invite never leaves a partial row behind. When the check trips, the whole batch item is declined:

```json theme={null}
{
  "error": {
    "code": "TEAM_MEMBER_CAP_REACHED",
    "message": "Your workspace includes 2 team seats and all are in use. Remove a member or cancel a pending invite to free a seat.",
    "details": {
      "resource": "invite",
      "max_team_members": 2,
      "live_members": 2,
      "pending_invites": 0
    }
  }
}
```

`details` tells you which counter tripped and how many seats the organization includes, so you know whether to clear a pending invite or a live member. The code is stable — map it on your integration's error handler (not the message text, which reads as guidance for the operator).

Recovery steps:

1. **List pending invites.** The usable window to clear is usually one of the outstanding invites, since revoking pending seats needs no owner role:

   ```bash theme={null}
   curl -s https://api.orbit.devotel.io/api/v1/settings/team/invites \
     -H "Authorization: Bearer $ORBIT_API_KEY"
   ```

2. **Free one seat.** Revoke a pending invite (Section 2) or, if you're the owner, remove a live member. If all seats are live members and no pending invite exists, only the member-removal path (owner-only) applies.

3. **Re-send the invite.** A revoked pending invite frees the seat immediately, so re-submit the invite create request:

   ```bash theme={null}
   curl -X POST https://api.orbit.devotel.io/api/v1/settings/team/invite \
     -H "Authorization: Bearer $ORBIT_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"email": "teammate@acme.com", "role": "developer"}'
   ```

   Roles accepted at invite time: `admin`, `supervisor`, `developer`, `viewer`, `billing`. The `owner` role is never assignable — ownership transfer is a separate, support-mediated flow.

If no seat can be freed — every live member is needed — raise the quota (next section).

## 4. Raise the quota

Three surfaces can raise the per-organization integer, in increasing order of privilege:

**Subaccount provisioning.** A parent organization creating or updating a subaccount passes `max_team_members` explicitly (1–500) in the request body. This is the self-serve path for resellers:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/subaccounts \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Sandbox",
    "slug": "acme-sandbox",
    "plan": "growth",
    "max_team_members": 25
  }'
```

To adjust an existing subaccount's cap, update the subaccount with the new value:

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/subaccounts/9d3cce49-…-subaccount-id \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "max_team_members": 25 }'
```

The parent's own quota is unaffected — each organization in the tree opens its own counter.

**Support-level raise.** When a quota raise exceeds what any plan assigns (or the parent is a direct org with no subaccount tree), platform staff patch the tenant's editable `maxTeamMembers` field directly (1–10000). Open a support request from your organization and reference the workspace — the change applies at the tenant level without touching any other organization setting.

**Default behavior.** A missing or null value never blocks you: any read of the quota falls back to the self-serve plan default (2), so a workspace row without the field behaves exactly like a fresh account.

This is deliberately a parent-scope or support-level control: a member of the organization cannot raise their own ceiling — the quota is a tenant-level guard, not a self-service flag.

## 5. Quota vs RBAC — heads, not capabilities

The quota counts heads only. The role hierarchy answers a different question at a different layer:

* **The quota decides whether one more member may join.** It is consulted once, at invite-create time.
* **Roles decide what each member can do once seated.** They are consulted on every request.

Assigning a seat to a `viewer` vs an `admin` consumes the same one seat; the seat check says nothing about which role the invite carries. Read the full capability matrix on [Team members, invitations, and roles](/guides/organization-team-management) and the role model on [Roles, teams, and permissions](/concepts/roles-teams-permissions). The numeric quota itself lives on [Team seat quota and invite enforcement](/concepts/team-seat-quota-model).

## Cross-references

* [Team seat quota and invite enforcement](/concepts/team-seat-quota-model) — the concept page this guide operationalizes.
* [Team members, invitations, and roles](/guides/organization-team-management) — the day-to-day Settings → Team console walkthrough.
* [Roles, teams, and permissions](/concepts/roles-teams-permissions) — the capability sibling; the quota counts heads, roles gate capabilities.
* [The subaccount organization model](/concepts/subaccount-organization-model) — where each organization's own quota sits in the tenant tree.
