Topolo Docs Topolo Platform
Open workspace

Get organization billable seats

Read the billable seat summary for one organization.

Outcome

Read the billable seat summary for one organization.

Full examples below were captured from isolated actual Auth handlers and repository SQL with disclosed simulations.

Before you start

  • Verify the intended credential identity and pinned context; discover the exact organization id and published target authority. Display labels and synthetic fixture ids do not authorize a live call.

  • Keep directory user counts, computed membership seats and application-resource authority separate.

Discover the authorized organization

topolo whoami --json
topolo context ls --json
topolo actions get app_topolo_auth.organizations.billable_seats.get --detail --json
topolo actions get app_topolo_auth.organizations.list --detail --json

Organization directory discovery itself requires platform authority. An ordinary manager must use the organization already resolved from its credential context; directory refusal does not justify switching context.

Input fields

FieldRequiredMeaning
orgIdYesExact organization id from the verified credential context or authorized organization discovery. A display name/slug is not an id and this field does not switch credentials.

Response fields

A success contains success=true, message, data and an ISO timestamp. Refusals contain success=false and error instead. Directory/detail responses use camelCase projections; export preserves selected raw snake_case fields and JSON text.

The handler checks hydrated membership in this exact organization: owner/admin or verified platform authority. A token role alone is not sufficient. An ordinary member receives HTTP 403 FORBIDDEN; the local fixture simulates hydrated membership lookup explicitly.

billableSeatCount requires active membership, active user, a returned billableRole and a principal type other than service_local, agent_employee or external_agent. activeMemberCount excludes agent_employee but includes service_local; guestCount counts active guests excluding agent_employee. These counts can differ from each other and from directory userCount.

updatedAt is the current read-time epoch seconds. This read computes stored membership counts, changes no seats and contacts no commerce provider. seatCommitment is the effective trusted Pay or One manual-grant capacity and revision. An active Stripe subscription or unexpired trial takes precedence; commercialGrant records manual provenance and expiry without a Stripe ID. availableHumanSeats is zero for blocked or expired commitments and never includes agents. This read is not an invoice, payment confirmation or resource grant.

An empty organization produces zero counts for platform authority. The summary query does not separately require an existing organization row, so zero counts do not establish that an organization exists; verify organizations.get when existence matters.

Worked examples

Every identifier, address and stored record below is synthetic. Resolve live identifiers and runtime authority before validating and planning the unchanged read. The CLI/MCP connection supplies its own credential; fixture token scenarios are not input fields. Empty fixture collections do not prove production feature coverage or provider parity.

Stored organization membership determines billable seats; agent and service principals are excluded

Input · payload.json:

{
  "orgId": "org_read_fixture"
}

CLI:

topolo actions validate app_topolo_auth.organizations.billable_seats.get --data @payload.json --json
topolo actions plan app_topolo_auth.organizations.billable_seats.get --data @payload.json --json
topolo actions call app_topolo_auth.organizations.billable_seats.get --data @payload.json --detail --json

MCP read after topolo_validate_action and topolo_plan_action on the same input:

{
  "tool": "topolo_read_action",
  "arguments": {
    "actionId": "app_topolo_auth.organizations.billable_seats.get",
    "input": {
      "orgId": "org_read_fixture"
    }
  }
}

Captured local handler response · HTTP 200:

{
  "success": true,
  "message": "Billable seat summary retrieved successfully",
  "data": {
    "seatSummary": {
      "organizationId": "org_read_fixture",
      "seatCommitment": null,
      "billableSeatCount": 1,
      "activeMemberCount": 2,
      "guestCount": 1,
      "billableRoles": [
        "platform_super_admin",
        "platform_admin",
        "owner",
        "super_admin",
        "admin",
        "member"
      ],
      "updatedAt": 1790985600
    }
  },
  "timestamp": "2026-10-03T00:00:00.000Z"
}

Platform authority reads an empty organization seat summary

Input · payload.json:

{
  "orgId": "org_read_other"
}

CLI:

topolo actions validate app_topolo_auth.organizations.billable_seats.get --data @payload.json --json
topolo actions plan app_topolo_auth.organizations.billable_seats.get --data @payload.json --json
topolo actions call app_topolo_auth.organizations.billable_seats.get --data @payload.json --detail --json

MCP read after topolo_validate_action and topolo_plan_action on the same input:

{
  "tool": "topolo_read_action",
  "arguments": {
    "actionId": "app_topolo_auth.organizations.billable_seats.get",
    "input": {
      "orgId": "org_read_other"
    }
  }
}

Captured local handler response · HTTP 200:

{
  "success": true,
  "message": "Billable seat summary retrieved successfully",
  "data": {
    "seatSummary": {
      "organizationId": "org_read_other",
      "seatCommitment": null,
      "billableSeatCount": 0,
      "activeMemberCount": 0,
      "guestCount": 0,
      "billableRoles": [
        "platform_super_admin",
        "platform_admin",
        "owner",
        "super_admin",
        "admin",
        "member"
      ],
      "updatedAt": 1790985600
    }
  },
  "timestamp": "2026-10-03T00:00:00.000Z"
}

Verify the result

  • Match data.seatSummary.organizationId to the authorized input and interpret each counter separately. Read organizations.get if organization existence must be established.

Errors and recovery

Missing credential is refused

Input:

{
  "orgId": "org_read_fixture"
}

Captured local refusal · HTTP 401:

{
  "success": false,
  "error": {
    "message": "Access token required",
    "code": "AUTH_ERROR",
    "details": null,
    "timestamp": "2026-10-03T00:00:00.000Z"
  }
}

Non-admin membership cannot read the seat summary

Input:

{
  "orgId": "org_read_fixture"
}

Captured local refusal · HTTP 403:

{
  "success": false,
  "error": {
    "message": "Organization admin access required",
    "code": "FORBIDDEN",
    "details": null,
    "timestamp": "2026-10-03T00:00:00.000Z"
  }
}

Published recovery guidance

  • AUTH_ERROR (HTTP 401): Verify the same pinned credential and exact refusal. For directory/detail/export this code also reports denied authority; do not change context or assume expiry.

  • FORBIDDEN (HTTP 403): Stop and report the missing owner/admin membership in this exact organization. Do not substitute a token role, endpoint or broader context.

  • SERVER_ERROR (HTTP 500): Preserve sanitized request/status evidence for an authorized Auth maintainer. These reads do not write; after the underlying store/parser issue is resolved, review a fresh read of the same target.

Recovery boundary

This read has no rollback. Keep the same discovered organization and credential context; respect authority refusal and preserve sanitized evidence for store failures. Re-read only after the underlying issue is resolved.

Discovery and evidence

Actual isolated organization handlers and repository SQL; no live identity, membership, billing or export was changed.

Real: Organization read/billing/privacy handlers; Organization directory/service and seat summary SQL; Portable export field selection and database routing; Canonical migration-created tables and SQLite engine; Response serialization and permission helpers. Simulated: Verified token identities and hydrated membership lookup; Empty application icon catalog; Clock, synthetic records and deliberate malformed settings; All split bindings co-located in isolated SQLite; no multi-D1 provider parity. No live organization, identity, membership, export, billing or seat changed.