Skip to content

List members of a project.

GET
/v1/projects/{projectId}/members
Code sample: Shell / cURL
curl --request GET \
--url 'https://stratum.example.com/v1/projects/example/members?limit=100' \
--header 'Authorization: Bearer <token>'

The canonical “who has access to this project” list. Returns the union of:

  • project-scoped role bindings on this project, and
  • inherited org-scoped role bindings on the project’s parent organization (org-owner / org-admin / org-member / org-billing implicitly reach every project in the org)

Install-scope principals (bootstrap-admin / platform-admin) are NOT listed — they’re global operators, not project members.

One row per user; the bindings array carries every binding that grants this user access. inherited=true marks org-scoped bindings so the UI can render an “inherited from org” badge.

Each item embeds the user (displayName / email / state) so the UI needs no second call. Gated by iam:ListProjectMembers on the project resource — any principal with a project-scoped role OR an org-scoped role on the parent org passes.

projectId
required
string
/^p-[a-z0-9-]+$/
limit
integer
default: 100 >= 1 <= 500
page_token
string

Opaque cursor from a previous response’s nextPageToken; omit for the first page. A token that cannot be parsed is treated as no token, so a client gets the first page rather than a 400.

Cursor-paginated. Ordered email, userId. The page unit is the MEMBER, not the role binding: each member carries ALL of its bindings, because a page cut across binding rows would return a member whose binding list is silently incomplete.

This endpoint returned every matching row with no limit of any kind until.

Members.

Media typeapplication/json
object
items
required
Array<object>
object
userId
required
string
email
required
string format: email
displayName
required
string
state
required
string
Allowed values: pending active suspended deleted
bindings
required

Every binding granting this user access to the project, in stable order (scope_type, scope_id, role). Either a project-scoped binding on this exact project, OR an org-scoped binding on the project’s parent organization (marked inherited: true).

Array<object>
object
id
required
string
role
required
string
scopeType
required
string
Allowed values: organization project
scopeId
required
string
inherited
required

True when the binding is at organization scope (inherited into every project under that org). The UI badges these as “via org”.

boolean
createdAt
required
string format: date-time
createdBy
required
string
nextPageToken
string

Example

{
"items": [
{
"state": "pending",
"bindings": [
{
"scopeType": "organization"
}
]
}
]
}

Authenticated but not authorized.

Media typeapplication/problem+json
object
type
required
string format: uri
title
required
string
status
required
integer
>= 400 <= 599
detail
string
instance
string format: uri-reference
requestId
required
string
code
required
string
issues

The findings of a rejected IAM policy document (custom and resource policies).

Array<object>

One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.

object
code
required

The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.

string
statement
required

Index of the statement at fault; -1 for the document as a whole.

integer
>= -1
detail
required
string
action

The offending action, where one is at fault (ACTION_NOT_APPLICABLE).

string
errors

Field errors, for codes that carry them: each problem at its field (see FieldError). Documented on the responses that set it, e.g. approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED. Absent otherwise.

Array<object>

One field’s problem, the stage-2 installer API’s shape. field is the field’s path, message what is wrong with it.

object
field
required

The field’s path, e.g. links[0].interface, disks[1].confirm, mgmt.address or role; empty for the whole request.

string
message
required
string
details

Structured facts about the refusal, for codes that carry them. The shape is fixed per code and documented on the response that answers it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and IMAGE_IN_USE. Absent for codes that carry none.

object
key
additional properties
any

Example

{
"issues": [
{
"code": "ACTION_NOT_APPLICABLE",
"action": "compute:CreateVpc"
}
]
}

Resource not found.

Media typeapplication/problem+json
object
type
required
string format: uri
title
required
string
status
required
integer
>= 400 <= 599
detail
string
instance
string format: uri-reference
requestId
required
string
code
required
string
issues

The findings of a rejected IAM policy document (custom and resource policies).

Array<object>

One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.

object
code
required

The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.

string
statement
required

Index of the statement at fault; -1 for the document as a whole.

integer
>= -1
detail
required
string
action

The offending action, where one is at fault (ACTION_NOT_APPLICABLE).

string
errors

Field errors, for codes that carry them: each problem at its field (see FieldError). Documented on the responses that set it, e.g. approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED. Absent otherwise.

Array<object>

One field’s problem, the stage-2 installer API’s shape. field is the field’s path, message what is wrong with it.

object
field
required

The field’s path, e.g. links[0].interface, disks[1].confirm, mgmt.address or role; empty for the whole request.

string
message
required
string
details

Structured facts about the refusal, for codes that carry them. The shape is fixed per code and documented on the response that answers it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and IMAGE_IN_USE. Absent for codes that carry none.

object
key
additional properties
any

Example

{
"issues": [
{
"code": "ACTION_NOT_APPLICABLE",
"action": "compute:CreateVpc"
}
]
}