GitLab CLI & REST API
The glab CLI brings GitLab into the terminal. The REST API enables automation, scripting, and integrations. Both use personal access tokens or project/group tokens for authentication.
glab CLI
# Install glab
brew install glab # macOS
curl -sL https://raw.githubusercontent.com/cli/cli/main/scripts/bootstrap.sh | bash # Linux
# Authenticate
glab auth login # Interactive login
glab auth login --token $GITLAB_TOKEN # With PAT
# Merge Requests
glab mr create # Interactive MR creation
glab mr list # List open MRs
glab mr list --state merged --author @me
glab mr view 42 # View MR #42
glab mr checkout 42 # Checkout MR branch locally
glab mr approve 42
glab mr merge 42 --squash --delete-source-branch
# Issues
glab issue create --title "Bug: ..." --label "bug"
glab issue list --label "high-priority"
glab issue close 99
glab issue view 99
# Pipelines
glab pipeline list # List recent pipelines
glab pipeline view # View pipeline for current branch
glab pipeline run --ref main # Trigger pipeline
glab pipeline status # Status of latest pipeline
glab pipeline cancel <id>
glab pipeline retry <id>
# Job logs
glab pipeline ci view # Interactive pipeline trace
glab pipeline job trace <job-name> # Stream job logs
# Repo
glab repo clone mygroup/myproject
glab repo create --name new-project --group mygroup --visibility private
glab repo fork mygroup/myprojectREST API with curl
# Authentication: pass token in header or query param
# Header (preferred): --header "PRIVATE-TOKEN: <token>"
# Query param: ?private_token=<token>
GITLAB_TOKEN="glpat-xxxxxxxxxxxxxxxxxxxx"
PROJECT_ID="mygroup%2Fmyproject" # URL-encode the / as %2F (or use numeric ID)
BASE="https://gitlab.com/api/v4"
# Get project info
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "$BASE/projects/$PROJECT_ID"
# List merge requests
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "$BASE/projects/$PROJECT_ID/merge_requests?state=opened&per_page=20"
# Create an issue
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" --data '{"title": "Fix login bug", "labels": "bug,high-priority"}' "$BASE/projects/$PROJECT_ID/issues"
# Pagination — GitLab returns X-Next-Page, X-Total-Pages headers
# Fetch all pages with a loop:
page=1
while true; do
response=$(curl -sI --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "$BASE/projects/$PROJECT_ID/issues?per_page=100&page=$page")
next=$(echo "$response" | grep -i "x-next-page:" | tr -d "[:space:]" | cut -d: -f2)
[ -z "$next" ] && break
page=$next
done
# Trigger pipeline
curl --request POST --form "token=<trigger-token>" --form "ref=main" "$BASE/projects/$PROJECT_ID/trigger/pipeline"
# Get pipeline jobs
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "$BASE/projects/$PROJECT_ID/pipelines/12345/jobs"Access Tokens & Webhooks
# Token types:
# Personal Access Token (PAT): tied to a user; use for personal automation
# Project Access Token: scoped to a project; rotate without affecting user
# Group Access Token: scoped to a group and all subgroups/projects
# Create a project access token (API)
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --data "name=ci-bot&scopes[]=api&scopes[]=read_repository&expires_at=2025-01-01" "$BASE/projects/$PROJECT_ID/access_tokens"
# Webhooks — GitLab POSTs JSON to your URL on events
# Events: Push, Tag Push, Merge Request, Issue, Pipeline, Deployment, etc.
# Create webhook via API
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" --data '{
"url": "https://myapp.example.com/webhooks/gitlab",
"push_events": true,
"merge_requests_events": true,
"pipeline_events": true,
"token": "my-secret-webhook-token"
}' "$BASE/projects/$PROJECT_ID/hooks"
# Verify webhook authenticity (in your handler)
# GitLab sends X-Gitlab-Token header matching the token you set above
# List webhooks
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "$BASE/projects/$PROJECT_ID/hooks"Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free