delete_orgs_by_id
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
| Argument | Type | Description | |
|---|---|---|---|
idpath | string (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.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "delete_orgs_by_id",
"arguments": {
"id": "11111111-1111-4111-8111-111111111111"
}
}
}Result
On success (HTTP 200) the tool returns one text item holding the API's JSON, pretty-printed.
Deleted. Bare object, no envelope.
{
"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
| Field | Type | Description |
|---|---|---|
id | string | The deleted organization's id, as the DAL reports it. |
message | string | |
report | object | What 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.blocked | boolean | |
report.blockedReason | string | null | |
report.blockers | array of object | Every reason this organization may not be deleted yet; empty when it may. |
report.blockers[].amountCents | integer | null | The 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[].count | integer | How many of the thing the code names. |
report.blockers[].message | string | The sentence a person reads — what holds the deletion and what clears it. |
report.blockers[].until | integer | null | Epoch milliseconds the blocker lifts by itself, where it does (the clawback window). |
report.groupsRemoved | array of object | The organization's live groups — its OWNER and MEMBER groups among them; each is soft-deleted. |
report.groupsRemoved[].id | string | |
report.groupsRemoved[].name | string | null | |
report.membershipsRemoved | integer | Current (non-REMOVED) memberships into those groups; each is stamped REMOVED. |
report.orgId | string | |
report.orgName | string | |
report.permissionsRetired | integer | The organization's per-org permissions. Not written: every grant path requires a live organization, so they confer nothing once it is deleted. |
report.rolesRemoved | array of object | The organization's own live roles (its OWNER and ORG_USER roles); each is soft-deleted. |
report.rolesRemoved[].id | string | |
report.rolesRemoved[].name | string | null | |
report.usersDeactivated | array of object | Members 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[].email | string | null | |
report.usersDeactivated[].id | string | |
report.usersKept | array of object | Members of another live organization. Kept, and lose only this organization's memberships; keptBy names the organization(s) that keep them. |
report.usersKept[].email | string | null | |
report.usersKept[].id | string | |
report.usersKept[].keptBy | array 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.
400The id is not a UUID.
403Authenticated, but the caller holds none of the required permissions.
404No such organization, or it is already deleted.
409The 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.
{
"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
}
}