GitLab token scopes explained: api vs read_api, and fine-grained tokens
Short answer
Give a token the least it needs. read_api lets a tool read through the API; api adds complete read and write access — enough to approve, merge, and push over HTTPS. Personal access tokens last at most 365 days by default and expire at midnight UTC. Since GitLab 19.2, fine-grained tokens can be limited to chosen groups and projects and individual permissions. For phone apps, keep the write token on the device and give any notification server a separate read_api key.
Every GitLab integration — a CI tool, a chatbot, a mobile app, an AI assistant — starts by asking for a token. The scope you pick decides what that tool can do with your account if it misbehaves or leaks. This guide covers the scopes that matter, how long tokens last, what changed with fine-grained tokens in 2026, and a safe setup for phone apps.
The scopes that matter
GitLab’s personal access tokens have 17 scopes. These are the ones most tools ask for:
| Scope | What it allows |
|---|---|
read_api |
Read the API: projects, merge requests, issues, pipelines, to-dos. For personal access tokens, also read the container and package registries |
api |
Complete read and write access to the API, including registries. For personal access tokens, also read and write Git over HTTPS |
read_user |
Read your own profile through the /user endpoint |
read_repository |
Pull repositories over HTTPS |
write_repository |
Pull and push repositories over HTTPS |
read_registry / write_registry |
Pull and push container registry images |
self_rotate |
Let the token rotate itself |
ai_features |
Use GitLab Duo features through the API |
The rest — create_runner, manage_runner, k8s_proxy, read_virtual_registry, write_virtual_registry, read_service_ping, admin_mode and sudo — are for runners, Kubernetes, virtual registries and administrators. A tool that is not one of those has no reason to ask for them.
api vs read_api, in practice
The line is simple: can the tool change anything?
read_apiis enough for dashboards, notification services, reporting and anything that only shows you things.apiis needed the moment a tool comments, approves, merges, retries a pipeline or creates an issue — and with it, it could also push code over HTTPS and touch registries.
With classic scopes there is no “api, but without push”. If a tool only needs to read, a read_api token is the strongest protection you have — and a fine-grained token, below, can narrow things further.
How long tokens last
- Leave the expiry date empty and GitLab sets it to 365 days — also the default maximum. (Self-managed instances can allow up to 400 days with a feature flag.)
- Tokens expire at midnight UTC on their expiry date.
- GitLab emails a warning 60, 30 and 7 days before.
- On self-managed GitLab Ultimate, administrators can set a shorter maximum lifetime for everyone.
Put the expiry in your calendar. A tool that stops working on a random Tuesday is usually an expired token.
Fine-grained personal access tokens
Classic tokens apply their scope to every project you can see. Fine-grained tokens fix that: you choose the groups and projects a token can reach, and individual permissions on each kind of resource.
- Beta in GitLab 18.10, generally available in GitLab 19.2, on Free, Premium and Ultimate — on gitlab.com, self-managed and Dedicated.
- Created from Generate token › Fine-grained token; the classic kind is now labelled Legacy token.
- A top-level group on gitlab.com, or a whole self-managed instance, can require fine-grained tokens.
- Not every tool understands them yet. Check before you switch an integration over; GitLab’s own MCP server, for example, accepts fine-grained tokens and OAuth but not legacy personal access tokens.
OAuth instead of a token
Apps that sign you in to gitlab.com with “Sign in with GitLab” use OAuth. Access tokens last two hours; the app swaps a refresh token for a new pair, and each refresh invalidates the old pair. A well-built app saves the new refresh token before using the new access token — otherwise one failed save signs you out. You can see and revoke every OAuth app under User settings › Applications.
A safe setup for a phone app
A mobile GitLab client usually needs two kinds of access, and they should never be the same key:
- The app itself needs
apito approve, merge and comment. That token should live only in the phone’s secure storage — the iPhone Keychain or the Android Keystore — and talk only to your GitLab. - Push notifications need a server that can check GitLab while your phone sleeps. That server should get a separate
read_apikey, so that even if it were compromised it could not change a line of code.
That is exactly how MergeBell is built. You sign in with GitLab’s OAuth page on gitlab.com, or a personal access token with api on self-managed GitLab, and that token never leaves the phone. Turning on alerts creates a second, read-only grant; the alert server checks every key’s scopes and refuses any key that goes beyond read_api and read_user, and reads GitLab only through the eight GET endpoints listed on the security page. Revoke either key in GitLab and it stops working at once.
Frequently asked questions
What is the difference between api and read_api in GitLab?
read_api grants read access to the API, plus the container and package registries for personal access tokens. api grants complete read and write access to the API, including registries, and for personal access tokens also read and write access to Git over HTTP.
What scope does a GitLab mobile app need?
An app that approves, merges or comments needs api. An app or server that only reads — for example to send notifications — needs only read_api, and should refuse anything more.
How long does a GitLab personal access token last?
If you leave the expiry date empty, GitLab sets it to 365 days, which is also the default maximum. Tokens expire at midnight UTC on their expiry date, and GitLab emails you 60, 30 and 7 days before.
What is a fine-grained personal access token in GitLab?
A token limited to the groups and projects you choose and to individual permissions, instead of broad scopes. It became generally available in GitLab 19.2 on all tiers; the older kind is now labelled a legacy token.
How do I revoke a GitLab token?
Personal access tokens: User settings → Access tokens → Revoke. OAuth access you granted to an app: User settings → Applications → Revoke. Revoking takes effect immediately.
Sources
- GitLab docs — Personal access tokens
- GitLab docs — Access token scopes
- GitLab docs — Fine-grained access tokens
- GitLab docs — GitLab as an OAuth 2.0 provider
- GitLab docs — OAuth 2.0 API
- GitLab docs — GitLab MCP server
Checked against these pages on 16 October 2026. GitLab changes quickly — if something here no longer matches, tell us and we will fix it.
Do this from your phone with MergeBell
Free for the whole review loop: the To-Do inbox, diffs and line comments, approve and merge, pipelines with retry, and push alerts for your To-Dos. Works with gitlab.com and self-managed GitLab 16.0+.
Get MergeBell for AndroidiPhone: email me at launch
On Google Play for Android 12 or later. The iPhone app is coming soon to the App Store. An independent app, not affiliated with GitLab Inc.