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

GitHub quickstart · 3 min read

Keep Octokit. Change one line.

Everything you need for your first call is on this screen. No account creation, no seed data, no mock server to maintain.

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

01 / Base URL

One host, provider paths.

Point your GitHub client at https://gh.sandboxapis.dev. Paths, JSON, headers, and status codes mirror api.github.com.

request.sh
curl https://gh.sandboxapis.dev/repos/olympus-labs/parthenon

02 / Drop in your client

Octokit works unmodified.

The only change is the base URL — Octokit and everything built on it work as-is.

javascript
import { Octokit } from "@octokit/rest";

const octokit = new Octokit({ baseUrl: "https://gh.sandboxapis.dev" });

const { data } = await octokit.repos.get({ owner: "olympus-labs", repo: "parthenon" });
console.log(data.full_name);        // "olympus-labs/parthenon"

const pulls = await octokit.pulls.list({ owner: "olympus-labs", repo: "parthenon", state: "all" });

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

03 / Conditional requests

A 304, and what it actually costs.

Reads carry an ETag. Send it back as If-None-Match and an unchanged resource answers 304 Not Modified with an empty body — smaller and faster, exactly as on real GitHub. It is also free of charge whenever our CDN answers it from its shared cache, which covers the anonymous reads of this host below. A request carrying your key returns private, never reaches that shared cache, and spends a unit even when the answer is a 304 — why, in full.

request.sh
# 1 — read the validator off a normal response
curl -sD- -o /dev/null https://gh.sandboxapis.dev/repos/olympus-labs/parthenon | grep -i '^etag:'
# etag: W/"153b66fcd19c7efe…"

# 2 — send it back: 304, empty body (anonymous here, so the CDN answers it free)
curl -i -H 'If-None-Match: W/"153b66fcd19c7efe…"' \
  https://gh.sandboxapis.dev/repos/olympus-labs/parthenon

Octokit rejects on a 304 rather than resolving, so catch it — the error carries status: 304:

javascript
const first = await octokit.repos.get({ owner: "olympus-labs", repo: "parthenon" });
const etag = first.headers.etag;

try {
  const next = await octokit.repos.get({
    owner: "olympus-labs",
    repo: "parthenon",
    headers: { "if-none-match": etag },
  });
  // changed — use next.data
} catch (err) {
  if (err.status === 304) {
    // unchanged — nothing to re-download
  } else throw err;
}

ETag is served wherever the real provider serves one: GitHub, GitLab and Azure DevOps use weak validators (W/"…"), Bitbucket uses strong ones. Providers whose real APIs send no validator — Jira, Linear, and the AI-tool hosts — send none here either.

04 / A real response

Live from the universe.

Every reference below — owner, branches, commits — resolves to a fetchable object.

200 · application/json
{
  "id": 273073411,
  "node_id": "UmVwb3NpdG9yeToyNzMwNzM0MTE",
  "name": "parthenon",
  "full_name": "olympus-labs/parthenon",
  "owner": {
    "login": "olympus-labs",
    "id": 674901807,
    "node_id": "T3JnYW5pemF0aW9uOjY3NDkwMTgwNw",
    "avatar_url": "https://gh.sandboxapis.dev/avatars/u/674901807?v=4",
    "gravatar_id": "",
    "url": "https://gh.sandboxapis.dev/users/olympus-labs",
    "html_url": "https://gh.sandboxapis.dev/olympus-labs",
    "followers_url": "https://gh.sandboxapis.dev/users/olympus-labs/followers",
    "following_url": "https://gh.sandboxapis.dev/users/olympus-labs/following{/other_user}",
    "gists_url": "https://gh.sandboxapis.dev/users/olympus-labs/gists{/gist_id}",
    "starred_url": "https://gh.sandboxapis.dev/users/olympus-labs/starred{/owner}{/repo}",
    "subscriptions_url": "https://gh.sandboxapis.dev/users/olympus-labs/subscriptions",
    "organizations_url": "https://gh.sandboxapis.dev/users/olympus-labs/orgs",
    "repos_url": "https://gh.sandboxapis.dev/users/olympus-labs/repos",
    "events_url": "https://gh.sandboxapis.dev/users/olympus-labs/events{/privacy}",
    "received_events_url": "https://gh.sandboxapis.dev/users/olympus-labs/received_events",
    "type": "Organization",
    "site_admin": false
  },
  "private": true,
  "description": "Monorepo for the Olympus Labs developer platform — the temple everything is built on.",
  "fork": false,
  "url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon",
  "html_url": "https://gh.sandboxapis.dev/olympus-labs/parthenon",
  "archive_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/{archive_format}{/ref}",
  "assignees_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/assignees{/user}",
  "blobs_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/git/blobs{/sha}",
  "branches_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/branches{/branch}",
  "collaborators_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/collaborators{/collaborator}",
  "comments_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/comments{/number}",
  "commits_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/commits{/sha}",
  "compare_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/compare/{base}...{head}",
  "contents_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/contents/{+path}",
  "contributors_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/contributors",
  "deployments_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/deployments",
  "downloads_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/downloads",
  "events_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/events",
  "forks_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/forks",
  "git_commits_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/git/commits{/sha}",
  "git_refs_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/git/refs{/sha}",
  "git_tags_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/git/tags{/sha}",
  "git_url": "git://gh.sandboxapis.dev/olympus-labs/parthenon.git",
  "hooks_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/hooks",
  "issue_comment_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/issues/comments{/number}",
  "issue_events_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/issues/events{/number}",
  "issues_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/issues{/number}",
  "keys_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/keys{/key_id}",
  "labels_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/labels{/name}",
  "languages_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/languages",
  "merges_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/merges",
  "milestones_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/milestones{/number}",
  "notifications_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/notifications{?since,all,participating}",
  "pulls_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/pulls{/number}",
  "releases_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/releases{/id}",
  "ssh_url": "git@gh.sandboxapis.dev:olympus-labs/parthenon.git",
  "stargazers_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/stargazers",
  "statuses_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/statuses/{sha}",
  "subscribers_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/subscribers",
  "subscription_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/subscription",
  "tags_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/tags",
  "teams_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/teams",
  "trees_url": "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/git/trees{/sha}",
  "clone_url": "https://gh.sandboxapis.dev/olympus-labs/parthenon.git",
  "svn_url": "https://gh.sandboxapis.dev/olympus-labs/parthenon",
  "homepage": null,
  "language": "TypeScript",
  "forks_count": 0,
  "forks": 0,
  "stargazers_count": 0,
  "watchers_count": 0,
  "watchers": 0,
  "size": 4096,
  "default_branch": "main",
  "open_issues_count": 37,
  "open_issues": 37,
  "is_template": false,
  "topics": [
    "developer-tools",
    "platform",
    "typescript",
    "monorepo"
  ],
  "has_issues": true,
  "has_projects": true,
  "has_wiki": false,
  "has_pages": false,
  "has_downloads": true,
  "has_discussions": false,
  "archived": false,
  "disabled": false,
  "visibility": "private",
  "mirror_url": null,
  "license": {
    "key": "mit",
    "name": "MIT License",
    "spdx_id": "MIT",
    "url": "https://gh.sandboxapis.dev/licenses/mit",
    "node_id": "MDc6TGljZW5zZTEz"
  },
  "allow_forking": true,
  "web_commit_signoff_required": false,
  "pushed_at": "2026-04-26T17:20:00Z",
  "created_at": "2026-04-26T17:20:00Z",
  "updated_at": "2026-04-26T17:20:00Z",
  "network_count": 0,
  "subscribers_count": 0
}

05 / Repository files

The repo has real files.

Repositories carry actual source — a README, a package.json, TypeScript modules, workflow YAML — served through GitHub's own file endpoints. The tree evolves with history: a file at an older commit is that file as it was.

files.sh
# the README, base64 like the real API
curl https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/readme

# a directory listing, then a single file
curl https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/contents/src
curl "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/contents/README.md?ref=main"

# the whole tree, and a blob by its sha
curl "https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/git/trees/HEAD?recursive=1"

The SHAs are real git object hashes: run git hash-object over the bytes you download and you get back the sha the API advertised. The same file, byte for byte, is served by GitLab's repository/files and Bitbucket's src — one canonical repository, three dialects.

06 / Clone the repo

git clone works.

The repositories are real remotes over git smart-HTTP, served from the same host as the API. There is no separate git hostname, so the clone URL your API base URL implies is the one that works — which is what makes tools that discover files by cloning drop in on a single env-var swap.

clone.sh
git clone https://gh.sandboxapis.dev/olympus-labs/parthenon.git
cd parthenon

git log --oneline -3
git fsck --full          # exits clean: a real object graph, not a stub

# the SHAs are the API's SHAs — one repository, two dialects
HEAD_SHA=$(git rev-parse HEAD)
curl -s https://gh.sandboxapis.dev/repos/olympus-labs/parthenon/commits/$HEAD_SHA

# shallow clones work too
git clone --depth 1 https://gh.sandboxapis.dev/olympus-labs/parthenon.git shallow

Supported: full and shallow clones (--depth, then fetch --deepen/--unshallow), git ls-remote, incremental git fetch, and the .git suffix with or without. Not supported: git push — this universe is read-only, so it answers 403 like every other write — partial clone (--filter=blob:none; git falls back to a full clone), protocol v2 (we speak v0 and every modern client downgrades silently), git archive, and the dumb HTTP protocol.

07 / Pin a snapshot

Deterministic CI.

Same env-var swap, a *.snap. host — the universe regenerates byte-identically on every request, so pinned tests never drift.

.env
# reproducible in CI
export GITHUB_API_URL=https://gh-2026-03.snap.sandboxapis.dev

Pins also preserve what GitHub has since removed: the original Copilot metrics endpoint (GET /orgs/{org}/copilot/metrics, retired upstream 2026-04-02) still answers on gh pins frozen before the closure, while the live host's 404 points you at its replacement, the Copilot metrics-reports family.

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