patch_orgs_by_id
Calls PATCH /api/orgs/{id} as the signed-in person · REST reference
Update an organization's DAL-backed fields
Platform staff pass; everyone else must hold execute:UpdateOrgCommand IN the org named in the path (requireOrgPermission), which the DAL checks again in this org against the caller's own token: an org owner edits their own org only, and a read-only member is refused 403. An owner edits the org's RECORD — name, address, phone, email, website — and a service provider's payoutCadence. What the org IS — type, status, parentId — only platform staff may change: any of them from anyone else is refused 403 before anything is written, and the DAL refuses the same fields to an org-bound caller. A type change REBUILDS the org's permission set in the same DAL transaction: the org ends with exactly the new type's entitlements, its owner holds all of them, and every permission beyond them is removed with every role's and person's grant of it. The response then carries permissionSetChange — the features added and removed. Any other key is ignored without comment. parentId: null (or "") detaches the org to the top level; the DAL refuses a move that would make an org its own ancestor, an unknown type, a payout cadence for an org that is not a service provider, and a donor organization becoming a service provider — those refusals answer 400, 404 or 409 with the DAL's wording.
Arguments
| Argument | Type | Description | |
|---|---|---|---|
idpath | string (uuid) | required | |
bodyJSON | object | required | The request body, as a JSON object. Its fields are listed below. |
Fields of body
| Field | Type | Description | |
|---|---|---|---|
address | string | ||
email | string (email) | ||
name | string | ||
parentId | string (uuid) | null | Platform staff only. null or "" detaches to the top level. Setting it to this org's own id is rejected with 400. | |
payoutCadence | "MANUAL" | "DAILY" | "WEEKLY" | "MONTHLY" | How often a SERVICE_PROVIDER is paid out: MANUAL on request only (the clinic's own pay out today, or platform staff); DAILY, WEEKLY (from Monday) and MONTHLY (from the 1st) by the payout schedule, in UTC. The owner's to change. null clears it, which reads as MANUAL. Any cadence for an organization of another type is refused with 400. | |
phone | string | ||
status | string | Platform staff only. Written as given; POST /{id}/approve and POST /{id}/suspend are the dedicated routes for the two common changes. | |
type | string | Platform staff only. One of the DAL's org types (any casing); an unknown type is rejected with 400, and a DONOR organization — or one ever credited with a donation — becoming a SERVICE_PROVIDER is refused with 409. | |
website | string | An absolute http(s) URL — the DAL refuses anything else. "" clears it. A service provider's website is also what its payout account sends Stripe. |
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": "patch_orgs_by_id",
"arguments": {
"id": "11111111-1111-4111-8111-111111111111",
"body": {
"address": "string",
"email": "name@example.org",
"name": "string",
"parentId": "11111111-1111-4111-8111-111111111111",
"payoutCadence": "MANUAL",
"phone": "string",
"status": "string",
"type": "string",
"website": "string"
}
}
}
}Result
On success (HTTP 200) the tool returns one text item holding the API's JSON, pretty-printed.
The updated organization as the DAL answered the write: the Org model's save assigns the DAL's entity back onto the model, so EVERY timestamp — createdAt included — is epoch milliseconds, unlike GET /api/orgs/{id}, whose createdAt is ISO-8601. A no-op edit skips the write and answers the stored entity, the same way.
{
"createdAt": 1,
"id": "11111111-1111-4111-8111-111111111111",
"name": "string",
"status": "string",
"type": "string",
"parentId": "11111111-1111-4111-8111-111111111111",
"payoutCadence": "MANUAL",
"permissionSetChange": {
"added": [
"string"
],
"grantsRemoved": 1,
"orgType": "string",
"removed": [
"string"
]
},
"updatedAt": 1
}Fields
| Field | Type | Description |
|---|---|---|
createdAt | integer | Epoch milliseconds, straight off the DAL entity. |
id | string (uuid) | |
name | string | |
parentId | string (uuid) | null | |
payoutCadence | "MANUAL" | "DAILY" | "WEEKLY" | "MONTHLY" | Null when the organization never chose one (paid like MANUAL). |
permissionSetChange | object | Present only when the update changed the org's type: how its permission set was rebuilt to the new type's entitlements, in the same transaction. |
permissionSetChange.added | array of string | Feature ids instantiated for the org and granted to its owner. |
permissionSetChange.grantsRemoved | integer | Role GRANTS and direct grants that went with the removed permissions. |
permissionSetChange.orgType | string | |
permissionSetChange.removed | array of string | Feature ids removed from the org, each with every grant of it. |
status | string | |
type | string | |
updatedAt | integer | null |
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.
400parentIdequals this org's own id, the DAL refused the hierarchy move (cycle / "its own parent" / depth),typeis not an org type, orpayoutCadenceis not a cadence or was set on an organization that is not a service provider. The DAL's wording is forwarded verbatim.403Not platform staff and not holding
execute:UpdateOrgCommandin the organization ("Access denied to this organization." when the caller has no standing there at all), ortype,statusorparentIdwas supplied by a caller who is not platform staff (the message names the fields and what an owner may edit instead), or a donor-realm bearer.404No such organization, or the DAL reported the named parent as missing.
409A platform caller asked to make a DONOR organization, or one credited with a donation, a SERVICE_PROVIDER — refused by the DAL, whose wording (naming the org) is forwarded.
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": "patch_orgs_by_id",
"description": "PATCH /api/orgs/{id} — Platform staff pass; everyone else must hold `execute:UpdateOrgCommand` IN the org named in the path (`requireOrgPermission`), which the DAL checks again in this org against the caller's own token: an org owner edits their own org only, and a read-only member is refused 403. An owner edits the org's RECORD — `name`, `address`, `phone`, `email`, `website` — and a service provider's `payoutCadence`. What the org IS — `type`, `status`, `parentId` — only platform staff may change: any of them from anyone else is refused 403 before anything is written, and the DAL refuses the same fields to an org-bound caller. A `type` change REBUILDS the org's permission set in the same DAL transaction: the org ends with exactly the new type's entitlements, its owner holds all of them, and every permission beyond them is removed with every role's and person's grant of it. The response then carries `permissionSetChange` — the features added and removed. Any other key is ignored without comment. `parentId: null` (or `\"\"`) detaches the org to the top level; the DAL refuses a move that would make an org its own ancestor, an unknown `type`, a payout cadence for an org that is not a service provider, and a donor organization becoming a service provider — those refusals answer 400, 404 or 409 with the DAL's wording.\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"
},
"body": {
"type": "string",
"description": "The JSON request body: { address: string; email: string; name: string; parentId: string (Platform staff only.); payoutCadence: one of \"MANUAL\" | \"DAILY\" | \"WEEKLY\" | \"MONTHLY\" (How often a SERVICE_PROVIDER is paid out: MANUAL on request only (the clinic's own pay ...); phone: string; status: string (Platform staff only.); type: string (Platform staff only.); website: string (An absolute http(s) URL — the DAL refuses anything else.) }"
}
},
"required": [
"id",
"body"
]
},
"annotations": {
"readOnlyHint": false,
"destructiveHint": true,
"idempotentHint": false,
"openWorldHint": false
}
}