delete_orgs_by_id

Changes data · you confirm first Idempotent

Calls DELETE /api/orgs/{id} as the signed-in person · REST reference

Soft-delete one organization, cascading, and report what was removed

One DAL transaction soft-deletes the organization, its groups, and the memberships into them (stamped REMOVED, never deleted). Each member who belongs to NO other live organization is soft-deleted and their DynamoDB auth row suspended; each member of another live organization is kept and loses only this one's memberships. The body's report is exactly what GET /api/orgs/{id}/deletion-preview showed. REFUSED (409) when the deletion would leave no live holder of the PFF_SUPERADMIN role — the platform organization, whatever its type. Requires execute:DeleteOrgCommand. The caller's own token is forwarded, so the DAL re-checks the permission and records the caller as deletedBy.

Arguments

ArgumentTypeDescription
idpathstring (uuid)required

Example call

A client sends this over the MCP session; Claude and other agents build it for you. The values are placeholders — the shape is real.

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "delete_orgs_by_id",
    "arguments": {
      "id": "11111111-1111-4111-8111-111111111111"
    }
  }
}
Confirmation
The client shows the person the exact request and waits. Nothing runs until they tick Make this change. See Reading and changing.

Result

On success (HTTP 200) the tool returns one text item holding the API's JSON, pretty-printed.

Deleted. Bare object, no envelope.

json
{
  "id": "string",
  "message": "Organization deleted successfully",
  "report": {
    "blocked": true,
    "blockedReason": "string",
    "blockers": [
      {}
    ],
    "groupsRemoved": [
      {}
    ],
    "membershipsRemoved": 1,
    "orgId": "string",
    "orgName": "string",
    "permissionsRetired": 1,
    "rolesRemoved": [
      {}
    ],
    "usersDeactivated": [
      {}
    ],
    "usersKept": [
      {}
    ]
  }
}

Fields

FieldTypeDescription
idstringThe deleted organization's id, as the DAL reports it.
messagestring
reportobjectWhat deleting ONE organization removes, deactivates and keeps. The preview and the delete answer the SAME shape, because the DAL computes it once — the delete writes exactly the plan the preview showed, in one transaction. blocked is the verdict, and blockers every reason for it: a deletion that would leave no live holder of the PFF_SUPERADMIN role is refused, whichever organization that is (no property of the org decides it — the platform org is type NETWORK with no parentId, the same as an ordinary partner — so the guard counts the role's live holders instead), and so is the deletion of an organization that still holds money, a clawback, vouchers in flight, recurring gifts or live child organizations.
report.blockedboolean
report.blockedReasonstring | null
report.blockersarray of objectEvery reason this organization may not be deleted yet; empty when it may.
report.blockers[].amountCentsinteger | nullThe money involved, in cents, where there is one.
report.blockers[].code"LAST_SUPERADMIN" | "OPEN_CLAWBACK" | "PAYOUTS_PAUSED_BY_CLAWBACK" | "CLAWBACK_WINDOW_OPEN" | "BALANCE_OWED" | "PAYOUT_TRANSFER_UNSETTLED" | … (13 values)
report.blockers[].countintegerHow many of the thing the code names.
report.blockers[].messagestringThe sentence a person reads — what holds the deletion and what clears it.
report.blockers[].untilinteger | nullEpoch milliseconds the blocker lifts by itself, where it does (the clawback window).
report.groupsRemovedarray of objectThe organization's live groups — its OWNER and MEMBER groups among them; each is soft-deleted.
report.groupsRemoved[].idstring
report.groupsRemoved[].namestring | null
report.membershipsRemovedintegerCurrent (non-REMOVED) memberships into those groups; each is stamped REMOVED.
report.orgIdstring
report.orgNamestring
report.permissionsRetiredintegerThe organization's per-org permissions. Not written: every grant path requires a live organization, so they confer nothing once it is deleted.
report.rolesRemovedarray of objectThe organization's own live roles (its OWNER and ORG_USER roles); each is soft-deleted.
report.rolesRemoved[].idstring
report.rolesRemoved[].namestring | null
report.usersDeactivatedarray of objectMembers who belong to no other live organization. Each is soft-deleted and their DynamoDB auth row suspended, so they cannot sign in by either path.
report.usersDeactivated[].emailstring | null
report.usersDeactivated[].idstring
report.usersKeptarray of objectMembers of another live organization. Kept, and lose only this organization's memberships; keptBy names the organization(s) that keep them.
report.usersKept[].emailstring | null
report.usersKept[].idstring
report.usersKept[].keptByarray of object

When it fails

A failed call returns isError: true with the API's message as text. A change the person declines, or lets time out, also comes back this way and nothing changes.

400

The id is not a UUID.

403

Authenticated, but the caller holds none of the required permissions.

404

No such organization, or it is already deleted.

409

The guard refused — the deletion would leave no live PFF_SUPERADMIN holder — or the graph changed between the plan and the write. Nothing was deleted.

What the model is shown

This is the tool exactly as the server lists it in tools/list. The description starts with the REST call it makes.

json
{
  "name": "delete_orgs_by_id",
  "description": "DELETE /api/orgs/{id} — One DAL transaction soft-deletes the organization, its groups, and the memberships into them (stamped REMOVED, never deleted). Each member who belongs to NO other live organization is soft-deleted and their DynamoDB auth row suspended; each member of another live organization is kept and loses only this one's memberships. The body's `report` is exactly what `GET /api/orgs/{id}/deletion-preview` showed. REFUSED (409) when the deletion would leave no live holder of the `PFF_SUPERADMIN` role — the platform organization, whatever its type. Requires `execute:DeleteOrgCommand`. The caller's own token is forwarded, so the DAL re-checks the permission and records the caller as `deletedBy`.\n\nThis changes data. The person is asked to confirm it before it runs, and nothing happens if they decline.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "id": {
        "type": "string"
      }
    },
    "required": [
      "id"
    ]
  },
  "annotations": {
    "readOnlyHint": false,
    "destructiveHint": true,
    "idempotentHint": true,
    "openWorldHint": false
  }
}