post_orgs
Calls POST /api/orgs as the signed-in person · REST reference
Create an organization together with its one owner
Requires execute:CreateOrgCommand (org.create, a platform feature no organization holds); platform staff are admitted as on every gate. The owner of the new org holds everything its TYPE is entitled to. owner is REQUIRED and names exactly one owner: an EXISTING user by email (404 when no user has it), or a newUser created with the org in both the graph and the auth store (409 when the email already belongs to a user). One DAL transaction creates the Org, its per-org permissions, its OWNER and MEMBER groups and roles, the new owner when there is one, and the owner's membership of the OWNER group — there is no window in which an org exists without its owner. parentOrgId places the new org under an existing organization — its parentId, written in that same transaction. It is checked before anything is written: an id that names no live organization is a 404 and creates nothing. Placing an org in the hierarchy is platform authority, which creating one already requires; PATCH /api/orgs/{id} (parentId) moves it later. type takes the Title_Case values from GET /api/orgs/types.
Arguments
| Argument | Type | Description | |
|---|---|---|---|
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 | required | |
owner | object | required | Exactly one of email (an existing user) and newUser (a user created with the org). |
owner.email | string (email) | ||
owner.newUser | object | ||
owner.newUser.email | string (email) | required | |
owner.newUser.firstName | string | required | |
owner.newUser.lastName | string | required | |
owner.newUser.phone | string | E.164, e.g. +15035550100. | |
parentOrgId | string (uuid) | The existing organization to create this one under (its parentId). | |
phone | string | ||
taxId | string | ||
type | "Network" | "Partner" | "Distributor" | "Service_Provider" | "Donor" | 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": "post_orgs",
"arguments": {
"body": {
"name": "string",
"owner": {
"email": "name@example.org",
"newUser": {
"email": "name@example.org",
"firstName": "string",
"lastName": "string",
"phone": "string"
}
},
"type": "Network",
"address": "string",
"email": "name@example.org",
"parentOrgId": "11111111-1111-4111-8111-111111111111",
"phone": "string",
"taxId": "string"
}
}
}
}Result
On success (HTTP 201) the tool returns one text item holding the API's JSON, pretty-printed.
The created organization, as the Org model wrapper serialises it. Bare object, no envelope.
{
"createdAt": "2026-01-15T12:00:00Z",
"id": "11111111-1111-4111-8111-111111111111",
"name": "string",
"status": "string",
"type": "string",
"address": "string",
"email": "string",
"parentId": "11111111-1111-4111-8111-111111111111",
"phone": "string",
"taxId": "string",
"updatedAt": 1
}Fields
| Field | Type | Description |
|---|---|---|
address | string | null | |
createdAt | string (date-time) | ISO-8601 — coerced by the model, unlike every other timestamp here. |
email | string | null | |
id | string (uuid) | |
name | string | |
parentId | string (uuid) | null | |
phone | string | null | |
status | string | The status the DAL assigns on create, 'active' (this route sends none). A free string, not the DAL's OrgStatus set (ACTIVE | INACTIVE | SUSPENDED). |
taxId | string | null | |
type | string | |
updatedAt | integer | null | Epoch milliseconds, passed through untouched. |
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.
400name,typeorownermissing;ownernaming both or neither form; aparentOrgIdthat is not an id; or a field the DAL refuses (an invalid type, email or E.164 phone, a name out of range).403The caller does not hold
execute:CreateOrgCommandand is not platform staff, or the bearer is donor-realm and refused byauthenticate.404owner.emailnames no user, orparentOrgIdnames no live organization. Nothing is created.409owner.newUser.emailalready belongs to a user — name them byowner.email.
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": "post_orgs",
"description": "POST /api/orgs — Requires `execute:CreateOrgCommand` (`org.create`, a platform feature no organization holds); platform staff are admitted as on every gate. The owner of the new org holds everything its TYPE is entitled to. `owner` is REQUIRED and names exactly one owner: an EXISTING user by `email` (404 when no user has it), or a `newUser` created with the org in both the graph and the auth store (409 when the email already belongs to a user). One DAL transaction creates the Org, its per-org permissions, its OWNER and MEMBER groups and roles, the new owner when there is one, and the owner's membership of the OWNER group — there is no window in which an org exists without its owner. `parentOrgId` places the new org under an existing organization — its `parentId`, written in that same transaction. It is checked before anything is written: an id that names no live organization is a 404 and creates nothing. Placing an org in the hierarchy is platform authority, which creating one already requires; `PATCH /api/orgs/{id}` (`parentId`) moves it later. `type` takes the Title_Case values from `GET /api/orgs/types`.\n\nThis changes data. The person is asked to confirm it before it runs, and nothing happens if they decline.",
"inputSchema": {
"type": "object",
"properties": {
"body": {
"type": "string",
"description": "The JSON request body: { address: string; email: string; name*: string; owner*: { email: string; newUser: object } (Exactly one of `email` (an existing user) and `newUser` (a user created with the org).); parentOrgId: string (The existing organization to create this one under (its `parentId`).); phone: string; taxId: string; type*: one of \"Network\" | \"Partner\" | \"Distributor\" | \"Service_Provider\" | \"Donor\" }"
}
},
"required": [
"body"
]
},
"annotations": {
"readOnlyHint": false,
"destructiveHint": true,
"idempotentHint": false,
"openWorldHint": false
}
}