Manage members using the Projects API
- Tier: Free, Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
Use this endpoint to interact with project members.
For information about group members, see the Group members API.
Roles
The role assigned to a user or group is defined
in the Gitlab::Access module as access_level.
- No access (
0) - Minimal access (
5) - Guest (
10) - Planner (
15) - Reporter (
20) - Developer (
30) - Maintainer (
40) - Owner (
50) - Admin (
60)
Known issues
- The
group_saml_identityandgroup_scim_identityattributes are only visible to group owners for SSO-enabled groups. - The
emailattribute is only visible to group owners for enterprise users of the group when an API request is sent to the group itself, or that group’s subgroups or projects.
List all members of a project
Gets a list of project members viewable by the authenticated user.
This function takes pagination parameters page and per_page to restrict the list of users.
GET /projects/:id/members| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer or string | yes | The ID or URL-encoded path of the project. |
query | string | no | Filters results based on a given name, email, or username. Use partial values to widen the scope of the query. |
user_ids | array of integers | no | Filter the results on the given user IDs. |
skip_users | array of integers | no | Filter skipped users out of the results. |
show_seat_info | boolean | no | Show seat information for users. |
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/:id/members"Example response:
[
{
"id": 1,
"username": "raymond_smith",
"name": "Raymond Smith",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"created_at": "2012-09-22T14:13:35Z",
"created_by": {
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
},
"expires_at": "2012-10-22",
"access_level": 30,
"group_saml_identity": null
},
{
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"created_at": "2012-09-22T14:13:35Z",
"created_by": {
"id": 1,
"username": "raymond_smith",
"name": "Raymond Smith",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
},
"expires_at": "2012-10-22",
"access_level": 30,
"email": "john@example.com",
"group_saml_identity": {
"extern_uid":"ABC-1234567890",
"provider": "group_saml",
"saml_provider_id": 10
}
}
]List all members of a project, including inherited and invited members
Gets a list of project members viewable by the authenticated user, including inherited members, invited users, and permissions through ancestor groups.
If a user is a member of this project and also of one or more ancestor groups,
only its membership with the highest access_level is returned.
This represents the effective permission of the user.
Members from an invited group are returned if either:
- The invited group is public.
- The requester is also a member of the invited group.
- The requester is a member of the shared group or project.
The invited group members have shared membership in the shared group or project. This means that if the requester is a member of a shared group or project, but not a member of an invited private group, then using this endpoint the requester can get all the shared group or project members, including the invited private group members.
This function takes pagination parameters page and per_page to restrict the list of users.
GET /projects/:id/members/all| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer or string | yes | The ID or URL-encoded path of the project. |
query | string | no | Filters results based on a given name, email, or username. Use partial values to widen the scope of the query. |
user_ids | array of integers | no | Filter the results on the given user IDs. |
show_seat_info | boolean | no | Show seat information for users. |
state | string | no | Filter results by member state, one of awaiting or active. Premium and Ultimate only. |
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/:id/members/all"Example response:
[
{
"id": 1,
"username": "raymond_smith",
"name": "Raymond Smith",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"created_at": "2012-09-22T14:13:35Z",
"created_by": {
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
},
"expires_at": "2012-10-22",
"access_level": 30,
"group_saml_identity": null
},
{
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"created_at": "2012-09-22T14:13:35Z",
"created_by": {
"id": 1,
"username": "raymond_smith",
"name": "Raymond Smith",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
},
"expires_at": "2012-10-22",
"access_level": 30,
"email": "john@example.com",
"group_saml_identity": {
"extern_uid":"ABC-1234567890",
"provider": "group_saml",
"saml_provider_id": 10
}
},
{
"id": 3,
"username": "foo_bar",
"name": "Foo bar",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"created_at": "2012-10-22T14:13:35Z",
"created_by": {
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
},
"expires_at": "2012-11-22",
"access_level": 30,
"group_saml_identity": null
}
]Get a member of a project
Gets a member of a project. Returns only direct members and not inherited members through ancestor groups.
GET /projects/:id/members/:user_id| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer or string | yes | The ID or URL-encoded path of the project. |
user_id | integer | yes | The user ID of the member. |
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/:id/members/:user_id"To update or remove a custom role from a group member, pass an empty member_role_id value:
# Updates a project membership
curl --request PUT --header "Content-Type: application/json" \
--header "Authorization: Bearer <your_access_token>" \
--data '{"member_role_id": null, "access_level": 10}' \
--url "https://gitlab.example.com/api/v4/projects/<project_id>/members/<user_id>"Example response:
{
"id": 1,
"username": "raymond_smith",
"name": "Raymond Smith",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"access_level": 30,
"email": "john@example.com",
"created_at": "2012-10-22T14:13:35Z",
"created_by": {
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
},
"expires_at": null,
"group_saml_identity": null
}Get a member of a project, including inherited and invited members
Gets a member of a project, including members inherited or invited through ancestor groups. See the corresponding endpoint to list all inherited members for details.
The invited group members have shared membership in the shared group or project. This means that if the requester is a member of a shared group or project, but not a member of an invited private group, then using this endpoint the requester can get all the shared group or project members, including the invited private group members.
GET /projects/:id/members/all/:user_id| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer or string | yes | The ID or URL-encoded path of the project. |
user_id | integer | yes | The user ID of the member. |
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/:id/members/all/:user_id"Example response:
{
"id": 1,
"username": "raymond_smith",
"name": "Raymond Smith",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"access_level": 30,
"created_at": "2012-10-22T14:13:35Z",
"created_by": {
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
},
"email": "john@example.com",
"expires_at": null,
"group_saml_identity": null
}Add a member to a project
Adds a member to a project.
POST /projects/:id/members| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer or string | yes | The ID or URL-encoded path of the project. |
user_id | integer or string | yes, if username is not provided | The user ID of the new member or multiple IDs separated by commas. |
username | string | yes, if user_id is not provided | The username of the new member or multiple usernames separated by commas. |
access_level | integer | yes | A valid access level. |
expires_at | string | no | A date string in the format YEAR-MONTH-DAY. |
invite_source | string | no | The source of the invitation that starts the member creation process. GitLab team members can view more information in this confidential issue: https://gitlab.com/gitlab-org/gitlab/-/issues/327120. |
member_role_id | integer | no | Ultimate only. The ID of a custom member role. |
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
--data "user_id=1&access_level=30" \
--url "https://gitlab.example.com/api/v4/projects/:id/members"Example response:
{
"id": 1,
"username": "raymond_smith",
"name": "Raymond Smith",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"created_at": "2012-10-22T14:13:35Z",
"created_by": {
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
},
"expires_at": "2012-10-22",
"access_level": 30,
"email": "john@example.com",
"group_saml_identity": null
}If administrator approval for role promotions is turned on, membership requests that promote existing users into a billable role require administrator approval.
To enable Manage Non-Billable Promotions,
you must first enable the enable_member_promotion_management application setting.
Example of queueing a single user:
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
--data "user_id=1&access_level=30" \
--url "https://gitlab.example.com/api/v4/projects/:id/members"{
"message":{
"username_1":"Request queued for administrator approval."
}
}Example of queueing multiple users:
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
--data "user_id=1,2&access_level=30" \
--url "https://gitlab.example.com/api/v4/projects/:id/members"{
"queued_users": {
"username_1": "Request queued for administrator approval.",
"username_2": "Request queued for administrator approval."
},
"status": "success"
}Edit a member of a project
Updates a member of a project.
PUT /projects/:id/members/:user_id| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer or string | yes | The ID or URL-encoded path of the project. |
user_id | integer | yes | The user ID of the member. |
access_level | integer | yes | A valid access level. |
expires_at | string | no | A date string in the format YEAR-MONTH-DAY. |
member_role_id | integer | no | Ultimate only. The ID of a custom member role. If no value is specified, removes all roles. |
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/:id/members/:user_id?access_level=40"Example response:
{
"id": 1,
"username": "raymond_smith",
"name": "Raymond Smith",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"created_at": "2012-10-22T14:13:35Z",
"created_by": {
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
},
"expires_at": "2012-10-22",
"access_level": 40,
"email": "john@example.com",
"group_saml_identity": null
}If administrator approval for role promotions is turned on, membership requests that promote existing users into a billable role require administrator approval.
To enable Manage non-billable promotions,
you must first enable the enable_member_promotion_management application setting.
Example response:
{
"message":{
"username_1":"Request queued for administrator approval."
}
}Remove a member from a project
Removes a user from a project where the user has been explicitly assigned a role.
The user needs to be a group member to qualify for removal. For example, if the user was added directly to a project in the group but not this group explicitly, you cannot use this endpoint to remove them. For more information, see Remove a billable member from a group.
DELETE /projects/:id/members/:user_id| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer or string | yes | The ID or URL-encoded path of the project. |
user_id | integer | yes | The user ID of the member. |
skip_subresources | boolean | false | Whether the deletion of direct memberships of the removed member in subgroups and projects should be skipped. Default is false. |
unassign_issuables | boolean | false | Whether the removed member should be unassigned from any issues or merge requests inside a given project. Default is false. |
Example request:
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/:id/members/:user_id"