POST /api/org/admin/groups/{id}/members {memberId} — add a member. 409 GROUP_EXTERNALLY_MANAGED if the group's source isn't "kiban" (the single-writer invariant).
POST /api/org/admin/positions/{id}/assignments {memberId} — assign-NOW (server-dated).
POST /api/org/admin/companies/{companyId}/groups {code,name} — companyId comes from the PATH only; the group is always created with source="kiban" (the only source this surface can create).
POST /api/org/admin/companies/{companyId}/positions {code,title} — companyId comes from the PATH only; org-unit defaults to the company root.
POST /api/org/admin/assignments/{id}/end — end-NOW, no body (server-dated).
GET /api/org/admin/groups/{id}/members — the Groups admin page's own member-list read, needed to render a remove button per current member (add/remove alone can't drive a UI without knowing WHO to remove).
GET /api/org/admin/companies/{companyId}/groups — list, each row carrying its member count and source (externally-sourced groups render read-only with a source badge).
Optionalpage: numberOptionalpageSize: numberGET /api/org/admin/companies/{companyId}/positions — list, each row carrying its CURRENT assignment (assignmentId/memberId/holderDisplayName — null when unassigned).
Optionalpage: numberOptionalpageSize: numberDELETE /api/org/admin/groups/{id}/members/{memberId} — remove a member. Same 409 GROUP_EXTERNALLY_MANAGED refusal as adminAddGroupMember.
GET /api/org/me/companies — companies where the CALLER (kcSub-injected by the gateway) has an active membership in an active company; the company-switcher source.
GET /api/org/companies/{companyId}/members — the gateway-exposed, least-disclosure member picker (share-with/assign-to). q is an optional case-insensitive substring filter over displayName/email.
Optionalq: stringOptionalpage: numberOptionalpageSize: number
Typed client over org's gateway-exposed HTTP surface:
meCompanies,memberDirectory, and the superadmin-onlyadmin*position/group methods.