Founding keys are opena year free at 6,000 req/hour, for the first 1,000 developersClaim yours
Documentation 29

GitLab quickstart · 3 min read

Keep python-gitlab. Change one line.

Everything you need for your first call is on this screen. Paths mirror gitlab.com/api/v4, so your client code stays exactly where it is.

01Point the base URL at gl.
02Call it exactly as before
03Pin a snapshot for CI

01 / Base URL

One host, provider paths.

Point your GitLab client at https://gl.sandboxapis.dev. Paths mirror gitlab.com/api/v4.

request.sh
curl https://gl.sandboxapis.dev/api/v4/projects/olympus-labs%2Fparthenon

02 / Drop in your client

Point python-gitlab at the base URL.

The only change is the base URL — the v4 paths and response shapes it expects are validated against GitLab's official OpenAPI spec.

python
import gitlab

gl = gitlab.Gitlab("https://gl.sandboxapis.dev")

project = gl.projects.get("olympus-labs/parthenon")
print(project.path_with_namespace)   # "olympus-labs/parthenon"

mrs = project.mergerequests.list(state="all")

Two clients on this host are proved end to end rather than described: python-gitlab and @gitbeaker/rest, whose exact snippets a script executes against https://gl.sandboxapis.dev and checks the output of. Verified quickstarts →

03 / A real response

Live from the universe.

200 · application/json
{
  "id": 4411,
  "description": "Monorepo for the Olympus Labs developer platform — the temple everything is built on.",
  "name": "parthenon",
  "name_with_namespace": "Olympus Labs / parthenon",
  "path": "parthenon",
  "path_with_namespace": "olympus-labs/parthenon",
  "created_at": "2026-04-26T17:20:00.000Z",
  "default_branch": "main",
  "tag_list": [
    "developer-tools",
    "platform",
    "typescript",
    "monorepo"
  ],
  "topics": [
    "developer-tools",
    "platform",
    "typescript",
    "monorepo"
  ],
  "ssh_url_to_repo": "git@gl.sandboxapis.dev:olympus-labs/parthenon.git",
  "http_url_to_repo": "https://gl.sandboxapis.dev/olympus-labs/parthenon.git",
  "web_url": "https://gl.sandboxapis.dev/olympus-labs/parthenon",
  "readme_url": "https://gl.sandboxapis.dev/olympus-labs/parthenon/-/blob/main/README.md",
  "forks_count": 0,
  "star_count": 0,
  "last_activity_at": "2026-04-26T17:20:00.000Z",
  "namespace": {
    "id": 72807,
    "name": "Olympus Labs",
    "path": "olympus-labs",
    "kind": "group",
    "full_path": "olympus-labs",
    "web_url": "https://gl.sandboxapis.dev/groups/olympus-labs"
  },
  "visibility": "private",
  "archived": false,
  "empty_repo": false,
  "issues_enabled": true,
  "merge_requests_enabled": true,
  "wiki_enabled": false,
  "jobs_enabled": true,
  "snippets_enabled": false,
  "can_create_merge_request_in": true
}

04 / Repository files

The project has real files.

Projects carry actual source — a README, a package.json, TypeScript modules, CI YAML — through GitLab's own file endpoints, headers included (X-Gitlab-Blob-Id, X-Gitlab-Content-Sha256, X-Gitlab-Last-Commit-Id).

files.sh
# file metadata (base64 content + content_sha256), ref is required
curl "https://gl.sandboxapis.dev/api/v4/projects/olympus-labs%2Fparthenon/repository/files/README.md?ref=main"

# the raw bytes
curl "https://gl.sandboxapis.dev/api/v4/projects/olympus-labs%2Fparthenon/repository/files/README.md/raw?ref=main"

# the tree, recursively
curl "https://gl.sandboxapis.dev/api/v4/projects/olympus-labs%2Fparthenon/repository/tree?recursive=1"

Paths are url-encoded exactly as GitLab requires (src%2Fauth%2Fmod0.ts), and last_commit_id points at the commit that actually last touched the file. The same bytes are served by GitHub's contents and Bitbucket's src — one canonical repository, three dialects.

05 / Pin a snapshot

Deterministic CI.

Same env-var swap, a *.snap. host — byte-identical on every request.

.env
# reproducible in CI
export CI_API_V4_URL=https://gl-v4.snap.sandboxapis.dev/api/v4

Tour the universe → · Coverage manifest → · Versioning & pinning →