Documentation
DocsAPI reference

Members

The people in the organization, their status, and their permissions.

Updated Oct 6, 2026

A member's direct access is a predefined role: owner, admin, reviewer or auditor. List the roles to see what each one holds, and change a member's role to replace all of their direct permissions with that role. Their team access doesn't change. Only an owner can grant the owner role. On the hosted edition, a member can instead hold custom permission policies, and team permissions are inherited by every member of the team.

Suspension pauses access while keeping the member's role and permissions. Removal revokes the member's sessions and personal API keys in the organization, disables their personal agents' instances, and keeps the record as deprovisioned for past decisions and audit events.

See Membership management for the member list, status changes and directory-managed members, or Permissions for roles and access.

List members

GET/api/v1/membersSession or API keyRequires membership.read

Returns every member of the organization, with their status and the roles they hold, directly or through their teams.

Request

Parameters

ParameterTypeDescription
limitquery · integer

How many members to return. Defaults to 200.

Response

Response codes

StatusBodyDescription
200object

The members

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot read members

Response body200

membersarray<Member>required

Example

GET /api/v1/members
curl -X GET "$WITHHUMAN_URL/api/v1/members" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "members": [
    {
      "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "display_name": "Ada Lovelace",
      "email": "[email protected]",
      "status": "active",
      "assignments": [
        {
          "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
          "organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
          "principal_kind": "membership",
          "principal_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
          "scope_kind": "organization",
          "scope_id": "string",
          "scope_name": "string",
          "source": "manual",
          "source_key": "string",
          "granted_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
          "via_team_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
          "via_team_name": "string",
          "created_at": "2026-09-08T12:02:11Z",
          "permissions": [
            "string"
          ],
          "is_owner": true,
          "built_in_role": "owner",
          "permission_policy_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71"
        }
      ],
      "admission_source": "manual",
      "directory_managed": true,
      "team_ids": [
        "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71"
      ],
      "created_at": "2026-09-08T12:02:11Z"
    }
  ]
}

List predefined roles

GET/api/v1/rolesSession or API keySelf-service

The predefined roles a person can be invited with or given, owner first, with the permissions each holds. They are the same in every organization.

Request

No parameters or body.

Response

Response codes

StatusBodyDescription
200object

The predefined roles

401ErrorResponse

You are not signed in

Response body200

rolesarray<Role>required

Example

GET /api/v1/roles
curl -X GET "$WITHHUMAN_URL/api/v1/roles" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "roles": [
    {
      "key": "owner",
      "name": "Reviewer",
      "description": "string",
      "permissions": [
        "string"
      ],
      "dangerous": true
    }
  ]
}

Give a member a predefined role

PUT/api/v1/members/{id}/roleSession cookieRequires permission_policy.write

Gives the member one predefined role everywhere in the organization, replacing every permission they hold directly, custom permission policies included. What they inherit from teams and what your directory manages stay.

You cannot change your own role. Only an owner may grant the owner role or change a member who holds it, the organization must keep at least one active owner, and a role holding a sensitive permission needs a fresh sign-in.

Request

Parameters

ParameterTypeDescription
idrequiredpath · uuid

The membership's id.

Request body

roleenumrequired

A predefined role. owner is full control and only an owner may grant it; admin manages agents, pipelines, paths, members and teams; reviewer decides the requests routed to them; auditor reads everything without changing anything.

One of owner, admin, reviewer, auditor

Response

Response codes

StatusBodyDescription
200object

The updated membership

400ErrorResponse

The role is unknown

403ErrorResponse

You cannot change permissions, this is your own membership, the role or the member is an owner and you are not, or the role needs a fresher sign-in

404ErrorResponse

No such member

409ErrorResponse

The member is managed by your directory, or is the last active owner

Response body200

A person's membership of the organization, as stored.

Example

PUT /api/v1/members/{id}/role
curl -X PUT "$WITHHUMAN_URL/api/v1/members/{id}/role" \
  -b "withhuman_session=$WITHHUMAN_SESSION" \
  -H "Content-Type: application/json" \
  -d '{
  "role": "owner"
}'
200 response
{
  "member": {
    "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "user_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "status": "active",
    "admission_source": "manual",
    "directory_managed": true,
    "assignments": [
      {
        "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "principal_kind": "membership",
        "principal_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "scope_kind": "organization",
        "scope_id": "string",
        "scope_name": "string",
        "source": "manual",
        "source_key": "string",
        "granted_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "via_team_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "via_team_name": "string",
        "created_at": "2026-09-08T12:02:11Z",
        "permissions": [
          "string"
        ],
        "is_owner": true,
        "built_in_role": "owner",
        "permission_policy_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71"
      }
    ],
    "team_ids": [
      "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71"
    ],
    "created_at": "2026-09-08T12:02:11Z",
    "updated_at": "2026-09-08T12:02:11Z"
  }
}

Suspend or reactivate a member

PATCH/api/v1/members/{id}Session or API keyRequires membership.write

Sets a member's status to suspended or active. A suspended member cannot sign in or act until reactivated. Permissions are changed through PUT /api/v1/members/{id}/role or, where the edition offers custom permissions, the member's permission policies.

You cannot change your own membership. Changing a member who holds the owner role requires holding it yourself. Members managed by your directory cannot be changed here, and the organization must keep at least one active owner.

Suspending a member that an active escalation path or team escalation policy still targets is refused with membership_in_escalation_path; the paths are listed in details.escalation_paths and the policies in details.team_escalation_policies. Pass force to suspend anyway. Those targets then reach nobody until the path or policy is edited.

Request

Parameters

ParameterTypeDescription
idrequiredpath · uuid

The membership's id.

Request body

statusenumrequired

active or suspended.

One of active, suspended

forceboolean

Suspend even while an active escalation path targets the member.

Response

Response codes

StatusBodyDescription
200object

The updated membership

400ErrorResponse

status is not active or suspended

403ErrorResponse

You cannot change members, this is your own membership, or the member holds the owner role and you do not

404ErrorResponse

No such member

409ErrorResponse

The member is managed by your directory, is already removed, or is the last active owner. Or an active escalation path targets the member: error.code is membership_in_escalation_path and error.details.escalation_paths lists the paths

Response body200

A person's membership of the organization, as stored.

Example

PATCH /api/v1/members/{id}
curl -X PATCH "$WITHHUMAN_URL/api/v1/members/{id}" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "active",
  "force": true
}'
200 response
{
  "member": {
    "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "user_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "status": "active",
    "admission_source": "manual",
    "directory_managed": true,
    "assignments": [
      {
        "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "principal_kind": "membership",
        "principal_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "scope_kind": "organization",
        "scope_id": "string",
        "scope_name": "string",
        "source": "manual",
        "source_key": "string",
        "granted_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "via_team_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
        "via_team_name": "string",
        "created_at": "2026-09-08T12:02:11Z",
        "permissions": [
          "string"
        ],
        "is_owner": true,
        "built_in_role": "owner",
        "permission_policy_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71"
      }
    ],
    "team_ids": [
      "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71"
    ],
    "created_at": "2026-09-08T12:02:11Z",
    "updated_at": "2026-09-08T12:02:11Z"
  }
}

Remove a member

DELETE/api/v1/members/{id}Session or API keyRequires membership.write

Removes a member from the organization. Their sessions are revoked at once. The membership record is kept with status deprovisioned, because decisions and audit events refer to it.

You cannot remove yourself. Removing a member who holds the owner role requires holding it yourself, and the organization must keep at least one active owner.

Removing a member that an active escalation path or team escalation policy still targets is refused with membership_in_escalation_path; the paths are listed in details.escalation_paths and the policies in details.team_escalation_policies. Pass force=true to remove anyway. Those targets then reach nobody until the path or policy is edited, and the audit event records which paths and policies were left behind.

Request

Parameters

ParameterTypeDescription
idrequiredpath · uuid

The membership's id.

forcequery · boolean

Remove even while an active escalation path targets the member.

Response

Response codes

StatusBodyDescription
204

The member is removed

403ErrorResponse

You cannot change members, this is your own membership, or the member holds the owner role and you do not

404ErrorResponse

No such member

409ErrorResponse

The member is managed by your directory or is the last active owner. Or an active escalation path targets the member: error.code is membership_in_escalation_path and error.details.escalation_paths lists the paths

Example

DELETE /api/v1/members/{id}
curl -X DELETE "$WITHHUMAN_URL/api/v1/members/{id}" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"

List permissions

GET/api/v1/permissionsSession or API keySelf-service

Human permission vocabulary. Requires permission-policy read or write access at any scope.

Request

No parameters or body.

Response

Response codes

StatusBodyDescription
200object

The permissions

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot read roles

Response body200

Example

GET /api/v1/permissions
curl -X GET "$WITHHUMAN_URL/api/v1/permissions" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "permissions": [
    {
      "key": "request.decide",
      "area": "request",
      "description": "Approve or deny requests routed to you",
      "holders": [
        "human"
      ],
      "resource": "organization",
      "dangerous": true
    }
  ]
}

Get members permission policies

GET/api/v1/members/{id}/permission_policiesSession or API keySelf-service

Request

Parameters

ParameterTypeDescription
idrequiredpath · uuid

Response

Response codes

StatusBodyDescription
200PermissionPoliciesPage

Policy operation completed

400ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

401ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

403ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

404ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

409ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

Response body200

namestringrequired
can_createbooleanrequired
is_ownerbooleanrequired

Example

GET /api/v1/members/{id}/permission_policies
curl -X GET "$WITHHUMAN_URL/api/v1/members/{id}/permission_policies" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "name": "string",
  "policies": [
    {
      "scope_kind": "organization",
      "resource_ids": [
        "string"
      ],
      "permissions": [
        "string"
      ],
      "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "revision": 1,
      "resources": [
        {
          "id": "string",
          "name": "string",
          "kind": "organization"
        }
      ],
      "source": "manual",
      "via_team_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "via_team_name": "string",
      "can_edit": true,
      "read_only_reason": "string"
    }
  ],
  "resources": [
    {
      "id": "string",
      "name": "string",
      "kind": "organization"
    }
  ],
  "permissions": [
    {
      "key": "request.decide",
      "area": "request",
      "description": "Approve or deny requests routed to you",
      "holders": [
        "human"
      ],
      "resource": "organization",
      "dangerous": true
    }
  ],
  "can_create": true,
  "is_owner": true,
  "read_only_reason": "string"
}

Post members permission policies

POST/api/v1/members/{id}/permission_policiesSession cookieRequires permission_policy.write

Refused with 403 custom_permissions_unavailable where the edition offers predefined roles alone (custom_permissions_enabled false).

Request

Parameters

ParameterTypeDescription
idrequiredpath · uuid
Idempotency-Keyrequiredheader · string

Request body

scope_kindenumrequired

One of organization, team, agent

resource_idsarray<string>required

Empty for organization scope; otherwise the selected team IDs or agent slugs.

permissionsarray<string>required

Response

Response codes

StatusBodyDescription
201PermissionPolicy

Policy operation completed

400ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

401ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

403ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

404ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

409ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

Response body201

scope_kindenumrequired

One of organization, team, agent

resource_idsarray<string>required

Empty for organization scope; otherwise the selected team IDs or agent slugs.

permissionsarray<string>required
iduuidrequired
revisionint64required
sourceenumrequired

One of manual, directory

can_editbooleanrequired

Example

POST /api/v1/members/{id}/permission_policies
curl -X POST "$WITHHUMAN_URL/api/v1/members/{id}/permission_policies" \
  -b "withhuman_session=$WITHHUMAN_SESSION" \
  -H "Idempotency-Key: string" \
  -H "Content-Type: application/json" \
  -d '{
  "scope_kind": "organization",
  "resource_ids": [
    "string"
  ],
  "permissions": [
    "string"
  ]
}'
201 response
{
  "scope_kind": "organization",
  "resource_ids": [
    "string"
  ],
  "permissions": [
    "string"
  ],
  "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "revision": 1,
  "resources": [
    {
      "id": "string",
      "name": "string",
      "kind": "organization"
    }
  ],
  "source": "manual",
  "via_team_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "via_team_name": "string",
  "can_edit": true,
  "read_only_reason": "string"
}

Get members permission policy

GET/api/v1/members/{id}/permission_policies/{policy_id}Session or API keySelf-service

Request

Parameters

ParameterTypeDescription
idrequiredpath · uuid
policy_idrequiredpath · uuid

Response

Response codes

StatusBodyDescription
200PermissionPolicy

Policy operation completed

400ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

401ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

403ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

404ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

409ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

Response body200

scope_kindenumrequired

One of organization, team, agent

resource_idsarray<string>required

Empty for organization scope; otherwise the selected team IDs or agent slugs.

permissionsarray<string>required
iduuidrequired
revisionint64required
sourceenumrequired

One of manual, directory

can_editbooleanrequired

Example

GET /api/v1/members/{id}/permission_policies/{policy_id}
curl -X GET "$WITHHUMAN_URL/api/v1/members/{id}/permission_policies/{policy_id}" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "scope_kind": "organization",
  "resource_ids": [
    "string"
  ],
  "permissions": [
    "string"
  ],
  "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "revision": 1,
  "resources": [
    {
      "id": "string",
      "name": "string",
      "kind": "organization"
    }
  ],
  "source": "manual",
  "via_team_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "via_team_name": "string",
  "can_edit": true,
  "read_only_reason": "string"
}

Put members permission policy

PUT/api/v1/members/{id}/permission_policies/{policy_id}Session cookieRequires permission_policy.write

Refused with 403 custom_permissions_unavailable where the edition offers predefined roles alone (custom_permissions_enabled false).

Request

Parameters

ParameterTypeDescription
idrequiredpath · uuid
policy_idrequiredpath · uuid
Idempotency-Keyrequiredheader · string

Request body

scope_kindenumrequired

One of organization, team, agent

resource_idsarray<string>required

Empty for organization scope; otherwise the selected team IDs or agent slugs.

permissionsarray<string>required
revisionint64required

Required when updating an existing policy.

Response

Response codes

StatusBodyDescription
200PermissionPolicy

Policy operation completed

400ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

401ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

403ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

404ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

409ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

Response body200

scope_kindenumrequired

One of organization, team, agent

resource_idsarray<string>required

Empty for organization scope; otherwise the selected team IDs or agent slugs.

permissionsarray<string>required
iduuidrequired
revisionint64required
sourceenumrequired

One of manual, directory

can_editbooleanrequired

Example

PUT /api/v1/members/{id}/permission_policies/{policy_id}
curl -X PUT "$WITHHUMAN_URL/api/v1/members/{id}/permission_policies/{policy_id}" \
  -b "withhuman_session=$WITHHUMAN_SESSION" \
  -H "Idempotency-Key: string" \
  -H "Content-Type: application/json" \
  -d '{
  "scope_kind": "organization",
  "resource_ids": [
    "string"
  ],
  "permissions": [
    "string"
  ],
  "revision": 1
}'
200 response
{
  "scope_kind": "organization",
  "resource_ids": [
    "string"
  ],
  "permissions": [
    "string"
  ],
  "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "revision": 1,
  "resources": [
    {
      "id": "string",
      "name": "string",
      "kind": "organization"
    }
  ],
  "source": "manual",
  "via_team_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "via_team_name": "string",
  "can_edit": true,
  "read_only_reason": "string"
}

Delete members permission policy

DELETE/api/v1/members/{id}/permission_policies/{policy_id}Session cookieRequires permission_policy.write

Refused with 403 custom_permissions_unavailable where the edition offers predefined roles alone (custom_permissions_enabled false).

Request

Parameters

ParameterTypeDescription
idrequiredpath · uuid
policy_idrequiredpath · uuid
Idempotency-Keyrequiredheader · string
revisionrequiredquery · integer

Response

Response codes

StatusBodyDescription
204

Policy operation completed

400ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

401ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

403ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

404ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

409ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

Example

DELETE /api/v1/members/{id}/permission_policies/{policy_id}
curl -X DELETE "$WITHHUMAN_URL/api/v1/members/{id}/permission_policies/{policy_id}?revision=1" \
  -b "withhuman_session=$WITHHUMAN_SESSION" \
  -H "Idempotency-Key: string"