Group-level protected branches API

  • Tier: Premium, Ultimate
  • Offering: GitLab Self-Managed
History

Use the protected branches API for groups to manage protected branch rules. It provides endpoints to list, create, update, and delete protected branch rules that apply to projects belonging to a group.

Protected branch settings for groups are restricted to top-level groups only.

Valid access levels

The access levels are defined in the ProtectedRefAccess.allowed_access_levels method. These levels are recognized:

Copy to clipboard
0  => No access
30 => Developer access
40 => Maintainer access
60 => Admin access

List protected branches

Gets a list of protected branches from a group. If a wildcard is set, it is returned instead of the exact name of the branches that match that wildcard.

Copy to clipboard
GET /groups/:id/protected_branches
AttributeTypeRequiredDescription
idinteger or stringyesThe ID or URL-encoded path of the group.
searchstringnoName or part of the name of protected branches to be searched for.
Copy to clipboard
curl --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/groups/5/protected_branches"

Example response:

Copy to clipboard
[
  {
    "id": 1,
    "name": "main",
    "push_access_levels": [
      {
        "id":  1,
        "access_level": 40,
        "user_id": null,
        "group_id": 1234,
        "access_level_description": "Maintainers"
      }
    ],
    "merge_access_levels": [
      {
        "id":  1,
        "access_level": 40,
        "user_id": null,
        "group_id": 1234,
        "access_level_description": "Maintainers"
      }
    ],
    "allow_force_push":false,
    "code_owner_approval_required": false
  },
  {
    "id": 1,
    "name": "release/*",
    "push_access_levels": [
      {
        "id":  1,
        "access_level": 40,
        "user_id": null,
        "group_id": null,
        "access_level_description": "Maintainers"
      }
    ],
    "merge_access_levels": [
      {
        "id":  1,
        "access_level": 40,
        "user_id": null,
        "group_id": 1234,
        "access_level_description": "Maintainers"
      }
    ],
    "allow_force_push":false,
    "code_owner_approval_required": false
  },
  ...
]

Get a single protected branch or wildcard protected branch

Gets a single protected branch or wildcard protected branch.

Copy to clipboard
GET /groups/:id/protected_branches/:name
AttributeTypeRequiredDescription
idinteger or stringyesThe ID or URL-encoded path of the group.
namestringyesThe name of the branch or wildcard.
Copy to clipboard
curl --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/groups/5/protected_branches/main"

Example response:

Copy to clipboard
{
  "id": 1,
  "name": "main",
  "push_access_levels": [
    {
      "id":  1,
      "access_level": 40,
      "user_id": null,
      "group_id": null,
      "access_level_description": "Maintainers"
    }
  ],
  "merge_access_levels": [
    {
      "id":  1,
      "access_level": null,
      "user_id": null,
      "group_id": 1234,
      "access_level_description": "Example Merge Group"
    }
  ],
  "allow_force_push":false,
  "code_owner_approval_required": false
}

Protect repository branches

Protects a single repository branch using a wildcard protected branch.

Copy to clipboard
POST /groups/:id/protected_branches
Copy to clipboard
curl --request POST \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/groups/5/protected_branches?name=*-stable&push_access_level=30&merge_access_level=30&unprotect_access_level=40"
AttributeTypeRequiredDescription
idinteger or stringyesThe ID or URL-encoded path of the group.
namestringyesThe name of the branch or wildcard.
allow_force_pushbooleannoAllow all users with push access to force push. Default: false.
allowed_to_mergearraynoArray of access levels allowed to merge, with each described by a hash of the form {user_id: integer}, {group_id: integer}, or {access_level: integer}.
allowed_to_pusharraynoArray of access levels allowed to push, with each described by a hash of the form {user_id: integer}, {group_id: integer}, or {access_level: integer}.
allowed_to_unprotectarraynoArray of access levels allowed to unprotect, with each described by a hash of the form {user_id: integer}, {group_id: integer}, or {access_level: integer}.
code_owner_approval_requiredbooleannoPrevent pushes to this branch if it matches an item in the CODEOWNERS file. Default: false.
merge_access_levelintegernoAccess levels allowed to merge. Defaults: 40, Maintainer role.
push_access_levelintegernoAccess levels allowed to push. Defaults: 40, Maintainer role.
unprotect_access_levelintegernoAccess levels allowed to unprotect. Defaults: 40, Maintainer role.

Example response:

Copy to clipboard
{
  "id": 1,
  "name": "*-stable",
  "push_access_levels": [
    {
      "id":  1,
      "access_level": 30,
      "user_id": null,
      "group_id": null,
      "access_level_description": "Developers + Maintainers"
    }
  ],
  "merge_access_levels": [
    {
      "id":  1,
      "access_level": 30,
      "user_id": null,
      "group_id": null,
      "access_level_description": "Developers + Maintainers"
    }
  ],
  "unprotect_access_levels": [
    {
      "id":  1,
      "access_level": 40,
      "user_id": null,
      "group_id": null,
      "access_level_description": "Maintainers"
    }
  ],
  "allow_force_push":false,
  "code_owner_approval_required": false
}

Example with user and group access

Elements in the allowed_to_push / allowed_to_merge / allowed_to_unprotect array should take the form {user_id: integer}, {group_id: integer}, or {access_level: integer}. Each user must have access to the project and each group must have this project shared. These access levels allow more granular control over protected branch access.

Copy to clipboard
curl --request POST \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/groups/5/protected_branches?name=*-stable&allowed_to_push%5B%5D%5Buser_id%5D=1"

Example response:

Copy to clipboard
{
  "id": 1,
  "name": "*-stable",
  "push_access_levels": [
    {
      "id":  1,
      "access_level": null,
      "user_id": 1,
      "group_id": null,
      "access_level_description": "Administrator"
    }
  ],
  "merge_access_levels": [
    {
      "id":  1,
      "access_level": 40,
      "user_id": null,
      "group_id": null,
      "access_level_description": "Maintainers"
    }
  ],
  "unprotect_access_levels": [
    {
      "id":  1,
      "access_level": 40,
      "user_id": null,
      "group_id": null,
      "access_level_description": "Maintainers"
    }
  ],
  "allow_force_push":false,
  "code_owner_approval_required": false
}

Example with allow to push and allow to merge access

Example request:

Copy to clipboard
curl --request POST \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "main",
    "allowed_to_push": [{"access_level": 30}],
    "allowed_to_merge": [{
        "access_level": 30
      },{
        "access_level": 40
      }
    ]}'
    --url "https://gitlab.example.com/api/v4/groups/5/protected_branches"

Example response:

Copy to clipboard
{
    "id": 5,
    "name": "main",
    "push_access_levels": [
        {
            "id": 1,
            "access_level": 30,
            "access_level_description": "Developers + Maintainers",
            "user_id": null,
            "group_id": null
        }
    ],
    "merge_access_levels": [
        {
            "id": 1,
            "access_level": 30,
            "access_level_description": "Developers + Maintainers",
            "user_id": null,
            "group_id": null
        },
        {
            "id": 2,
            "access_level": 40,
            "access_level_description": "Maintainers",
            "user_id": null,
            "group_id": null
        }
    ],
    "unprotect_access_levels": [
        {
            "id": 1,
            "access_level": 40,
            "access_level_description": "Maintainers",
            "user_id": null,
            "group_id": null
        }
    ],
    "allow_force_push":false,
    "code_owner_approval_required": false
}

Unprotect repository branches

Unprotects the given protected branch or wildcard protected branch.

Copy to clipboard
DELETE /groups/:id/protected_branches/:name
Copy to clipboard
curl --request DELETE \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/groups/5/protected_branches/*-stable"
AttributeTypeRequiredDescription
idinteger or stringyesThe ID or URL-encoded path of the group.
namestringyesThe name of the branch.

Example response:

Copy to clipboard
{
   "name": "main",
   "push_access_levels": [
      {
         "id": 12,
         "access_level": 40,
         "access_level_description": "Maintainers",
         "user_id": null,
         "group_id": null
      }
   ]
}

Update a protected branch

Updates a protected branch.

Copy to clipboard
PATCH /groups/:id/protected_branches/:name
Copy to clipboard
curl --request PATCH \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/groups/5/protected_branches/feature-branch?allow_force_push=true&code_owner_approval_required=true"
AttributeTypeRequiredDescription
idinteger or stringyesThe ID or URL-encoded path of the group.
namestringyesThe name of the branch.
allow_force_pushbooleannoWhen enabled, members who can push to this branch can also force push.
allowed_to_pusharraynoArray of push access levels, with each described by a hash.
allowed_to_mergearraynoArray of merge access levels, with each described by a hash.
allowed_to_unprotectarraynoArray of unprotect access levels, with each described by a hash.
code_owner_approval_requiredbooleannoPrevent pushes to this branch if it matches an item in the CODEOWNERS file. Default: false.

Elements in the allowed_to_push, allowed_to_merge and allowed_to_unprotect arrays should:

  • Be one of user_id, group_id, or access_level.
  • Take the form {user_id: integer}, {group_id: integer}, or {access_level: integer}.

To update:

  • user_id: Ensure the updated user has access to the project. You must also pass the id of the access_level in the respective hash.
  • group_id: Ensure the updated group has this project shared. You must also pass the id of the access_level in the respective hash.

To delete:

  • You must pass _destroy set to true. See the following examples.

Example: create a push_access_level record

Copy to clipboard
curl --header 'Content-Type: application/json' --request PATCH \
  --data '{"allowed_to_push": [{access_level: 40}]}' \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/groups/22034114/protected_branches/main"

Example response:

Copy to clipboard
{
   "name": "main",
   "push_access_levels": [
      {
         "id": 12,
         "access_level": 40,
         "access_level_description": "Maintainers",
         "user_id": null,
         "group_id": null
      }
   ]
}

Example: update a push_access_level record

Copy to clipboard
curl --header 'Content-Type: application/json' --request PATCH \
  --data '{"allowed_to_push": [{"id": 12, "access_level": 0}]' \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/groups/22034114/protected_branches/main"

Example response:

Copy to clipboard
{
   "name": "main",
   "push_access_levels": [
      {
         "id": 12,
         "access_level": 0,
         "access_level_description": "No One",
         "user_id": null,
         "group_id": null
      }
   ]
}

Example: delete a push_access_level record

Copy to clipboard
curl --header 'Content-Type: application/json' --request PATCH \
  --data '{"allowed_to_push": [{"id": 12, "_destroy": true}]}' \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/groups/22034114/protected_branches/main"

Example response:

Copy to clipboard
{
   "name": "main",
   "push_access_levels": []
}