Manage organization groups and who can access each project.
Project availability: ✅ Classic projects • ✅ Agentic projects
The Members and Groups API manages the same members, groups and project access you can set in Wren AI. Use it to keep project access in sync with your identity provider, for example with a nightly script.
A member can use a project in three ways:
- Organization admin: an admin is
OWNERon every project - Direct access: the member is added to the project with a role
- Group access: the member is in a group attached to the project with a role
When more than one applies, an organization admin comes first, then direct access, then the highest role among the member's groups. Roles are OWNER, CONTRIBUTOR and VIEWER.
Endpoints Overview
Organization Members
GET /v2/orgs/{orgId}/members: List organization members.GET /v2/orgs/{orgId}/access?email=: Show one member's groups and every project they can use.
Groups
GET /v2/orgs/{orgId}/groups: List groups.POST /v2/orgs/{orgId}/groups: Create a group.PATCH /v2/orgs/{orgId}/groups/{id}: Rename a group.DELETE /v2/orgs/{orgId}/groups/{id}: Delete a group. Add?force=trueto delete a group that is still attached to projects.
Group Members
GET /v2/orgs/{orgId}/groups/{id}/members: List group members.PUT /v2/orgs/{orgId}/groups/{id}/members: Replace the group's members.POST /v2/orgs/{orgId}/groups/{id}/members: Add group members.DELETE /v2/orgs/{orgId}/groups/{id}/members?email=: Remove a group member.
Project Members
GET /v2/projects/{projectId}/member-access: List the members added to the project directly.POST /v2/projects/{projectId}/member-access: Add up to 500 members.PATCH /v2/projects/{projectId}/member-access?email=: Change a member's role.DELETE /v2/projects/{projectId}/member-access?email=: Remove a member.
Project Groups
GET /v2/projects/{projectId}/group-access: List the groups attached to the project.POST /v2/projects/{projectId}/group-access: Attach a group.PATCH /v2/projects/{projectId}/group-access/{groupId}: Change a group's role.DELETE /v2/projects/{projectId}/group-access/{groupId}: Detach a group.
Project Access
GET /v2/projects/{projectId}/access: List everyone who can use the project, and why.
The Members and Groups API requires the Enterprise plan. On other plans every endpoint returns 403 PLAN_NOT_SUPPORTED. Project endpoints also accept that project's API key for reading.
Changes need an organization API key
Organization endpoints and every change require an organization API key. A project API key gets
403 ACTION_FORBIDDEN, on organization endpoints and on project changes.
Basic Usage
This example mirrors a Finance team from your identity provider and gives it VIEWER on project 42.
Create a Group
Request — POST /v2/orgs/7/groups
{ "name": "Finance" }Response
{
"id": 12,
"name": "Finance",
"memberCount": 0,
"createdAt": "2026-10-20T08:00:00.000Z"
}Set the Group's Members
PUT replaces the whole list, so a sync script can send the current team every time.
Request — PUT /v2/orgs/7/groups/12/members
{ "emails": ["[email protected]", "[email protected]"] }Attach the Group to a Project
Request — POST /v2/projects/42/group-access
{ "groupId": 12, "role": "VIEWER" }Offboard a Member
Find what the member can still use, then remove their direct access to each project.
Request — GET /v2/orgs/7/[email protected]
{
"email": "[email protected]",
"orgRole": "MEMBER",
"groups": [{ "id": 12, "name": "Finance" }],
"projects": [
{ "projectId": 42, "name": "Sales", "role": "VIEWER", "source": "group", "groupId": 12, "groupName": "Finance" },
{ "projectId": 57, "name": "Ops", "role": "CONTRIBUTOR", "source": "direct" }
]
}Request — DELETE /v2/projects/57/[email protected]
Sync Scripts
Every change is safe to send again:
- Adding a member or group that is already there skips it.
- Removing a member or group that is already gone does nothing.
- An email that appears more than once in a request counts once.
Emails are case-insensitive. The API never creates users, so every email must belong to an organization member.
Errors
Errors return a code and an error message. Some codes also include fields that name what went wrong, such as emails on NOT_AN_ORG_MEMBER or path on INVALID_INPUT.
| Status | Code | When |
|---|---|---|
| 400 | INVALID_INPUT | An id or a field in the request is invalid, or the body is not valid JSON. |
| 400 | INVALID_ROLE | A role is not OWNER, CONTRIBUTOR or VIEWER. |
| 400 | TOO_MANY_ENTRIES | The request has more than 500 entries. max gives the limit. |
| 400 | NOT_SAME_ORG | The group belongs to another organization. |
| 401 | UNAUTHORIZED_API_KEY | The API key is missing or invalid, or belongs to another organization. |
| 403 | PLAN_NOT_SUPPORTED | The organization is not on the Enterprise plan. |
| 403 | ACTION_FORBIDDEN | The endpoint or change needs an organization API key. |
| 403 | UNSUBSCRIBED_ACCESS | Adding, changing or removing project members needs an active subscription. |
| 404 | RESOURCE_NOT_FOUND | The project or group, or the member's or group's access to the project, does not exist. |
| 404 | NOT_AN_ORG_MEMBER | An email is not an organization member. |
| 405 | METHOD_NOT_ALLOWED | The endpoint does not support the HTTP method. |
| 409 | DUPLICATED_GROUP_NAME | The group name is already used. |
| 409 | IN_USE | The group is still attached to projects. Retry with ?force=true. |
| 409 | AMBIGUOUS_MEMBER | An email matches more than one user. |
| 413 | INVALID_INPUT | The request body is larger than 1 MB. |
How to create organization API keys
Visit Organization API Keys to learn more.
