Members · changeRole
Change a member's role
PATCH /v1/workspaces/{id}/members/{userId}
Owners only. Roles: owner (everything), decider (decides asks; manages agents, projects and threshold alerts), viewer (sees everything, decides nothing). The last Owner can't be demoted (409). Making someone an Owner counts for that person like creating a workspace does: they need a verified email (403 email_not_verified) and must own fewer shared workspaces than an account may (402 plan_limit or ceiling_reached).
- Who may call it
- humans: Owners and up
- Server
- https://api.logu.dev
Parameters#
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | required | The workspace's id (wsp_…). The request acts in this workspace (the Logu-Workspace header is ignored). · e.g. wsp_01K7D7Y8Z0B2D4F6H8K0M2P4R6 |
userId | path | string | required | The member's user id. · e.g. Hk9cW2vZpT4mQ6nJ |
Request body#
Content type application/json (required).
A member's new role. Strict.
| Field | Type | Required | Notes |
|---|---|---|---|
role | "owner" | "decider" | "viewer" | required |
{
"role": "decider"
}
Example#
curl -s -X PATCH "https://api.logu.dev/v1/workspaces/wsp_01K7D7Y8Z0B2D4F6H8K0M2P4R6/members/Hk9cW2vZpT4mQ6nJ" \
-H "Authorization: Bearer $LOGU_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"role":"decider"}'
Responses#
200
The member.
{
"id": "Hk9cW2vZpT4mQ6nJ",
"name": "Bruno",
"email": "bruno@example.com",
"role": "decider",
"joinedAt": "2026-10-03T10:00:00.000Z"
}
Response fields
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | required | |
name | string | required | |
email | string | required | |
role | "owner" | "decider" | "viewer" | required | |
joinedAt | string | required | date-time |
Errors#
Every error is {"error":{"code","message","hint","docUrl","requestId"}}: branch on code. See Errors.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | The request is malformed or a field is invalid (see issues). |
| 400 | unknown_field | The body has a field the endpoint doesn't know (often a typo or snake_case). |
| 401 | unauthorized | No credentials, or the API key or session is invalid or revoked. |
| 402 | plan_limit | This is over one of the workspace's plan quotas: asks, events or metric reports this month, stored images, projects or metric names (Free and Pro), or on Free its agents, members and webhook endpoints (only on servers that enforce plan limits), or a Free account that already owns its shared workspaces (always). |
| 402 | ceiling_reached | The workspace reached one of Logu's cost ceilings (asks, events, metric reports, test traffic or images this month, stored image bytes, projects, metric names or API keys). Unlike plan_limit, upgrading doesn't lift it. An account that already owns the most shared workspaces an account may own gets it too. |
| 403 | forbidden | The caller is authenticated but may not do this (wrong role, or an API key on a human-only endpoint). |
| 403 | email_not_verified | The signed-in human's email isn't verified yet, and this needs it (accepting an invitation, creating a shared workspace, or becoming the Owner of one). |
| 404 | not_found | No such route, or the resource doesn't exist in your workspace. |
| 409 | conflict | The resource isn't in a state that allows this: an ask that is no longer waiting (ask has its current state), an invitation no longer pending, the last Owner. |
| 500 | internal_error | Something went wrong on Logu's side. |