List projects:

The API provides several filtering parameters for the listing methods:

  • archived: if True only archived projects will be returned
  • visibility: returns only projects with the specified visibility (can be public, internal or private)
  • search: returns project matching the given pattern

Results can also be sorted using the following parameters:

  • order_by: sort using the given argument. Valid values are id, name, path, created_at, updated_at and last_activity_at. The default is to sort by created_at
  • sort: sort order (asc or desc)
# Active projects
projects = gl.projects.list()
# Archived projects
projects = gl.projects.list(archived=1)
# Limit to projects with a defined visibility
projects = gl.projects.list(visibility='public')

# List owned projects
projects = gl.projects.owned()

# List starred projects
projects = gl.projects.starred()

# List all the projects
projects = gl.projects.all()

# Search projects
projects = gl.projects.list(search='keyword')

Get a single project:

# Get a project by ID
project = gl.projects.get(10)
# Get a project by userspace/name
project = gl.projects.get('myteam/myproject')

Create a project:

project = gl.projects.create({'name': 'project1'})

Create a project for a user (admin only):

alice = gl.users.list(username='alice')[0]
user_project = alice.projects.create({'name': 'project'})
user_projects = alice.projects.list()

Create a project in a group:

You need to get the id of the group, then use the namespace_id attribute to create the group:

group_id ='my-group')[0].id
project = gl.projects.create({'name': 'myrepo', 'namespace_id': group_id})

Update a project:

project.snippets_enabled = 1

Delete a project:

# or

Fork a project:

fork = project.forks.create({})

# fork to a specific namespace
fork = project.forks.create({'namespace': 'myteam'})

Create/delete a fork relation between projects (requires admin permissions):


Star/unstar a project:

Archive/unarchive a project:



Previous versions used archive_ and unarchive_ due to a naming issue, they have been deprecated but not yet removed.

Start the housekeeping job:


List the repository tree:

# list the content of the root directory for the default branch
items = project.repository_tree()

# list the content of a subdirectory on a specific branch
items = project.repository_tree(path='docs', ref='branch1')

Get the content and metadata of a file for a commit, using a blob sha:

items = project.repository_tree(path='docs', ref='branch1')
file_info = p.repository_blob(items[0]['id'])
content = base64.b64decode(file_info['content'])
size = file_info['size']

Get the repository archive:

# get the archive for the default branch
tgz = project.repository_archive()

# get the archive for a branch/tag/commit
tgz = project.repository_archive(sha='4567abc')


Archives are entirely stored in memory unless you use the streaming feature. See the artifacts example.

Get the content of a file using the blob id:

# find the id for the blob (simple search)
id = [d['id'] for d in p.repository_tree() if d['name'] == 'README.rst'][0]

# get the content
file_content = p.repository_raw_blob(id)


Blobs are entirely stored in memory unless you use the streaming feature. See the artifacts example.

Compare two branches, tags or commits:

result = project.repository_compare('master', 'branch1')

# get the commits
for commit in result['commits']:

# get the diffs
for file_diff in result['diffs']:

Get a list of contributors for the repository:

contributors = project.repository_contributors()

Get a list of users for the repository:

users = p.users.list()

# search for users
users = p.users.list(search='pattern')

Project custom attributes


List custom attributes for a project:

attrs = project.customattributes.list()

Get a custom attribute for a project:

attr = project.customattributes.get(attr_key)

Set (create or update) a custom attribute for a project:

attr = project.customattributes.set(attr_key, attr_value)

Delete a custom attribute for a project:

# or

Search projects by custom attribute:

project.customattributes.set('type': 'internal')
gl.projects.list(custom_attributes={'type': 'internal'})

Project files


Get a file:

f = project.files.get(file_path='README.rst', ref='master')

# get the base64 encoded content

# get the decoded content

Create a new file:

# v4
f = project.files.create({'file_path': 'testfile',
                          'branch': 'master',
                          'content': file_content,
                          'commit_message': 'Create testfile'})

# v3
f = project.files.create({'file_path': 'testfile',
                          'branch_name': 'master',
                          'content': file_content,
                          'commit_message': 'Create testfile'})

Update a file. The entire content must be uploaded, as plain text or as base64 encoded text:

f.content = 'new content''master', commit_message='Update testfile')  # v4'master', commit_message='Update testfile')  # v3

# or for binary data
# Note: decode() is required with python 3 for data serialization. You can omit
# it with python 2
f.content = base64.b64encode(open('image.png').read()).decode()'master', commit_message='Update testfile', encoding='base64')

Delete a file:

f.delete(commit_message='Delete testfile')

Project tags


List the project tags:

tags = project.tags.list()

Get a tag:

tag = project.tags.get('1.0')

Create a tag:

tag = project.tags.create({'tag_name': '1.0', 'ref': 'master'})

Set or update the release note for a tag:

tag.set_release_description('awesome v1.0 release')

Delete a tag:

# or

Project snippets

The snippet visibility can be definied using the following constants:



List the project snippets:

snippets = project.snippets.list()

Get a snippet:

snippets = project.snippets.list(snippet_id)

Get the content of a snippet:



The snippet content is entirely stored in memory unless you use the streaming feature. See the artifacts example.

Create a snippet:

snippet = project.snippets.create({'title': 'sample 1',
                                   'file_name': '',
                                   'code': 'import gitlab',

Update a snippet:

snippet.code = 'import gitlab\nimport whatever'

Delete a snippet:

# or


You can manipulate notes (comments) on the issues, merge requests and snippets.

  • ProjectIssue with ProjectIssueNote
  • ProjectMergeRequest with ProjectMergeRequestNote
  • ProjectSnippet with ProjectSnippetNote



List the notes for a resource:

i_notes = issue.notes.list()
mr_notes = mr.notes.list()
s_notes = snippet.notes.list()

Get a note for a resource:

i_note = issue.notes.get(note_id)
mr_note = mr.notes.get(note_id)
s_note = snippet.notes.get(note_id)

Create a note for a resource:

i_note = issue.notes.create({'body': 'note content'})
mr_note = mr.notes.create({'body': 'note content'})
s_note = snippet.notes.create({'body': 'note content'})

Update a note for a resource:

note.body = 'updated note content'

Delete a note for a resource:


Project members


List the project members:

members = project.members.list()

Search project members matching a query string:

members = project.members.list(query='bar')

Get a single project member:

member = project.members.get(1)

Add a project member:

member = project.members.create({'user_id':, 'access_level':

Modify a project member (change the access level):

member.access_level = gitlab.MASTER_ACCESS

Remove a member from the project team:

# or

Share the project with a group:

project.share(, gitlab.DEVELOPER_ACCESS)

Project hooks


List the project hooks:

hooks = project.hooks.list()

Get a project hook:

hook = project.hooks.get(1)

Create a project hook:

hook = gl.project_hooks.create({'url': 'http://my/action/url',
                                'push_events': 1},
# or
hook = project.hooks.create({'url': 'http://my/action/url', 'push_events': 1})

Update a project hook:

hook.push_events = 0

Delete a project hook:

# or

Project Services


Get a service:

# For v3
service ='asana', project_id=1)
# For v4
service ='asana')
# display its status (enabled/disabled)

List the code names of available services (doesn’t return objects):

services = gl.project_services.available()

Configure and enable a service:

service.api_key = 'randomkey'

Disable a service:


Issue boards

Boards are a visual representation of existing issues for a project. Issues can be moved from one list to the other to track progress and help with priorities.


Get the list of existing boards for a project:

boards = project.boards.list()

Get a single board for a project:

board = project.boards.get(board_id)

Board lists



List the issue lists for a board:

b_lists = board.lists.list()

Get a single list:

b_list = board.lists.get(list_id)

Create a new list:

# First get a ProjectLabel
label = get_or_create_label()
# Then use its ID to create the new board list
b_list = board.lists.create({'label_id':})

Change a list position. The first list is at position 0. Moving a list will set it at the given position and move the following lists up a position:

b_list.position = 2

Delete a list:


File uploads


Upload a file into a project using a filesystem path:

# Or provide a full path to the uploaded file
project.upload("filename.txt", filepath="/some/path/filename.txt")

Upload a file into a project without a filesystem path:

# Upload a file using its filename and filedata
project.upload("filename.txt", filedata="Raw data")

Upload a file and comment on an issue using the uploaded file’s markdown:

uploaded_file = project.upload("filename.txt", filedata="data")
issue = project.issues.get(issue_id)
    "body": "See the attached file: {}".format(uploaded_file["markdown"])

Upload a file and comment on an issue while using custom markdown to reference the uploaded file:

uploaded_file = project.upload("filename.txt", filedata="data")
issue = project.issues.get(issue_id)
    "body": "See the [attached file]({})".format(uploaded_file["url"])