Skip to main content

Remove User (admin)

Requires admin-scoped API key

This tool is only available when authenticated with an admin-scoped Phoenix API key. User-scoped keys never see it in tools/list and receive 403 forbidden_admin_scope if they try to call it directly. See Admin operations overview for details.

Destructive

Removes the user from the org and revokes all of their API keys and OAuth tokens for this org. This cannot be undone — the user must be re-invited if they're added back.

Hard-deletes the user's team memberships in the calling org and revokes their access. The user's public.users record is preserved so historical attribution (audit log targets, conversation creators, etc.) stays intact.

Tool key: admin_remove_user

Parameters

NameTypeRequiredDescription
user_idUUIDYesID of the user to remove. Snake_case to match MCP convention.

Required Integrations

None.

How It Works

The org slug is derived from the API key. Then:

  1. Self-removal guard. If user_id matches the calling user, the tool returns cannot_remove_self.
  2. Membership pre-flight. If the user has no active membership in this org, the tool returns user_not_found. (Also returned for cross-org user_id values, so cross-org probes are indistinguishable from "user does not exist.")
  3. Owner protection. If the user is the org owner, the tool returns cannot_remove_owner.
  4. Tenant transaction with advisory lock. Inside a tenant transaction, a Postgres advisory lock keyed on the org slug serializes concurrent removals. Distinct admin user_ids are counted; removing this user must leave at least one other admin in the org or the tool returns last_admin.
  5. Tenant deletes. team_memberships and tenant apiKeys rows for this user are deleted inside the transaction.
  6. Public deletes. webapp_api_keys_registry rows for (userId, organizationSlug) are deleted (this is what actually invalidates the key — validate() is a single public-schema join), followed by oauth_tokens rows for the same (userId, organizationSlug).
  7. Cache invalidation. Org-access cache and MCP org-context cache are flushed so a stale tools/list for the removed user's keys doesn't keep serving from cache.
  8. An audit row is written with action remove_user, target_type user, target_id = userId, metadata = { removedMembershipsCount }.

Use Cases

  • Offboarding workflow: HR system fires when an employee leaves; a Power Automate flow calls this tool to revoke Phoenix access in lockstep.
  • AI-assisted admin: "Remove bob@acme.com from Phoenix" via Claude Desktop with an admin-scoped MCP key (after a admin_get_consumption call to look up the user_id).

Example Usage

MCP JSON-RPC

{
"jsonrpc": "2.0",
"id": "1",
"method": "tools/call",
"params": {
"name": "admin_remove_user",
"arguments": {
"user_id": "9a3a9b40-3a6f-4f0a-9f8e-1b7f0b2c0d10"
}
}
}

Response

{
"userId": "9a3a9b40-3a6f-4f0a-9f8e-1b7f0b2c0d10",
"removedAt": "2026-04-29T16:42:11.000Z",
"removedMembershipsCount": 1
}

Error codes

CodeTrigger
invalid_user_iduser_id is not a UUID.
cannot_remove_selfuser_id matches the calling user.
cannot_remove_owneruser_id is the org owner. Transfer ownership first.
last_adminRemoving this user would leave the org with zero active admins.
user_not_foundNo active membership for that user_id in this org.
forbidden_admin_scopeKey is user-scoped or the user is no longer an org admin.

See also