Organisations
Organisation and member management
List organisations the current user can switch into
List organisations the current user can switch into. Each row is an organisation the caller holds an ACTIVE membership for, and the acting tenant's organisation comes first. Organisations in tenants that are not ACTIVE are omitted β including the acting one: PLT-477 gates both membership resolvers on tenant status, so a non-ACTIVE tenant can no longer be acted in at all and the earlier acting-tenant exemption is gone. The list is empty when the acting tenant contributes no visible organisation, even if other tenants did produce rows, so a foreign tenant can never occupy the first position. The payload is deliberately the switch-target projection (`id` and `name` only); use `GET /api/organisations/{id}` for the full organisation record.
Create a new organisation β a full workspace: the tenant, its 1:1 organisation, the creating userβs record and their ACTIVE membership are bootstrapped together, then the default roles are seeded (with the caller assigned Admin)
Create a new organisation β a full workspace: the tenant, its 1:1 organisation, the creating userβs record and their ACTIVE membership are bootstrapped together, then the default roles are seeded (with the caller assigned Admin). The endpoint is IDEMPOTENT PER SLUG FOR ITS CREATOR (PLT-960): when a prior attempt bootstrapped the tenant but failed before role seeding, retrying the same slug as the same user RESUMES that tenant β the 201 carries the original tenant id and the PERSISTED organisation record (a changed name in the retry body is not applied) and seeding is re-run. Seeding is serialized per tenant, so concurrent same-slug submissions are safe: the loser resumes or receives the member-aware 409.
Get organisation details
Get organisation details. This is the full organisation record, and the endpoint to use for the fields `GET /api/organisations` does not return β that list is the switch-target projection (`id` and `name` only). Access is the same audience as that list: the handler gates on an ACTIVE membership in the organisation (`resolveOrgAccess`), and the list only ever returns organisations you are an ACTIVE member of β so every caller affected by the narrowing can call this. The `org.settings.view` marker below describes the intended administrative permission; the GET handler does not currently enforce it.
Update organisation name
Update organisation name. Slug lives on identity.tenants and logo is not yet wired, so only the name field is persisted by this endpoint.
List organisation members
List organisation members. Rows are membership records enriched with user fields; cross-tenant operators β members whose user account lives in another organisation β carry `isCrossTenant: true` and their home tenant in `userTenantId` (INF-322). Membership status is not filtered.
Add a member to the organisation
Add a member to the organisation
Remove a member from the organisation
Remove a member from the organisation
List roles in the organisation
List roles in the organisation. Requires an active membership; permissions and roles are resolved against that membership's TENANT, not the path organisation id, which the Directory schema does not guarantee to be equal. Callers with `org.roles.manage` receive full role objects (including permissions). Callers with only `org.invitations.manage` receive a minimal `{id, name}` projection suitable for role assignment in invitation flows.
Create a custom role
Create a custom role
Update a role (name, description, and/or permissions)
Update a role (name, description, and/or permissions)
Delete a non-system role
Delete a non-system role
List invitations for the organisation
List invitations for the organisation
Send an invitation
Send an invitation. With a `projectId` this invites an external collaborator onto that one project, accepts either `projects.collaborators.manage` or `org.invitations.manage`, and additionally requires that the caller can reach the project. Without a `projectId` it adds a member to the organisation and requires `org.invitations.manage` alone.
Revoke a pending invitation
Revoke a pending invitation