Skip to content

GitHub API Guide: REST, GraphQL, Authentication and Automation

6 min readGitHub Engineering · GitHub API

The bridge from GitHub user workflows to programmable developer automation.

Everything in the previous three clusters is available over HTTP. Repositories, pull requests, reviews, Issues, releases, rulesets, checks — all of it is readable and writable by a program.

This cluster is where GitHub stops being a product you use and becomes infrastructure you build on.

Start with Lesson 1

GitHub exposes REST and GraphQL, and they are genuinely different systems rather than two syntaxes for the same thing. They have different endpoints, different authentication scopes in some cases, different rate-limit accounting, and different coverage — a few features exist in only one.

Neither is the successor to the other. Choosing between them is a per-task decision, covered in both API lessons and summarised here:

RESTGraphQL
ShapeOne endpoint per resourceOne endpoint, queries describe the shape
Fetching related dataMultiple requestsOne request
Over-fetchingCommon — you get the whole objectYou request exactly what you need
Rate limitingPer requestPer query complexity
DiscoverabilityDocumented endpoints, easy to curlIntrospectable schema
Best forSimple known operations, scriptingRelated data, avoiding N+1 requests

Claims that GraphQL is always more efficient or REST always simpler are both wrong. A single repository lookup is trivial in REST and needlessly ceremonious in GraphQL. Fetching a hundred pull requests with their authors, reviews and labels is one GraphQL query and several hundred REST requests.

More engineering time is lost to choosing the wrong credential than to any other part of GitHub automation, so this cluster treats it as a first-class subject rather than a prerequisite.

ScenarioLikely pattern
Personal CLI usegh auth
Short personal scriptFine-grained personal access token
Organisation automationGitHub App — usually preferable
User-authorised applicationApp or OAuth model
GitHub Actions workflowWorkflow token, or an App for cross-repository work
Public read-only queryAuthentication may not be required

That table is a starting point, not a rule. The reasoning behind it — least privilege, expiry, ownership, revocability — is in API Authentication, and the reason organisation automation should usually not use somebody’s personal token is in GitHub Apps.

The two APIs. REST and GraphQL in depth — requests, authentication, versioning, pagination, rate limits, error handling, and when each is the right choice.

Credentials. The authentication decision framework, fine-grained tokens in detail, and GitHub Apps as the identity model for anything organisational.

Events. Webhooks — being told when something changes rather than asking repeatedly. This is the rung of the automation ladder most teams never reach, and it is the one that removes polling entirely.

Applied automation. Repositories, pull requests and Issues, then a small maintainable Python client that pulls the whole cluster together.

GitHub’s API reference is large and the parts that matter are not always obvious. Three habits make it usable.

Read the permissions line. Every REST endpoint states which fine-grained permission it requires. That line is the fastest way to work out what a token needs, and it removes the usual approach of granting broadly and hoping.

Check both APIs. Coverage differs in both directions. Before concluding something is impossible, check whether the other API has it — Discussions are largely GraphQL-only, and some administrative endpoints are REST-only.

Watch the examples’ identity. Some endpoints behave differently depending on whether the caller is a user, an App installation, or the Actions token. The documentation says which are supported, and a 403 on an endpoint you believe you can reach is often an identity mismatch rather than a missing permission.

Most of the difficulty in API work is not the successful path.

StatusWhat it usually means here
401The credential is missing, malformed, expired or revoked
403Insufficient permission — or a rate limit; check the headers
404Missing, or present and invisible to your token
409A state conflict — an empty repository, or a merge race
422Valid JSON, invalid content; the body names the field
5xxGitHub’s problem; retry with backoff

Two of those are ambiguous by design and worth internalising now, because they cause more wasted debugging than anything else in this cluster.

404 is a privacy feature. GitHub returns “not found” rather than “forbidden” for private resources your token cannot see, so the API does not disclose which private repositories exist. While developing against a narrowly-scoped token, “not found” almost always means “not permitted”.

403 is overloaded. It covers genuine permission failures and some rate-limit rejections. Check x-ratelimit-remaining before concluding your token is wrong.

Only 4xx responses other than 403 and 429 are worth failing fast on. Rate limits and 5xx should back off and retry; everything else will fail identically however many times you try.

You should be able toCovered in
Explain HTTP methods, status codes and headers
Read and write JSON
Use gh api for one-off callsgh api
Describe what a pull request storesPull Requests Explained
Write a script with error handlingGitHub CLI Scripting

The Python lesson assumes basic Python. Everything else is language-agnostic and demonstrated with curl and gh api.

A recurring source of confusion is that the same request can succeed or fail depending purely on who is asking — and “who” has more possible answers than people expect.

CallerSeesRate limitActs as
NobodyPublic data60/hour
A user tokenWhat that user can reach5,000/hourThe person
An App installationWhere the App is installed5,000+, scalingThe App
An App user tokenIntersection of App and userThe user’sThe person, via the App
The Actions tokenIts own repository1,000/hour per repositoryThe workflow

The intersection row is worth dwelling on. An App with Issues write, used by someone with read-only access to a repository, cannot write there. That property is what makes Apps safe to install in organisations: the App cannot escalate a user beyond what they already have.

The consequence for debugging: before investigating a permission problem, establish which of these five you are. gh api user tells you for a token; an App installation token has no user at all, and calling /user with one returns an error that looks alarming and is simply the wrong endpoint for that identity.

REST endpoints and GraphQL fields are removed only after a deprecation period, announced through response headers and schema metadata rather than only in release notes. Watching for them is cheap and turns a future outage into scheduled work — the REST and GraphQL lessons each cover how.

  1. Lesson 1: 01. GitHub REST APIGitHub REST API from first request to production script: authentication, API versioning, pagination, rate limits and error handling — with curl and gh api examples that run.Intermediate13 min read
  2. Lesson 2: 02. GitHub GraphQL APIQuery exactly the data you need in one request. Learn the schema, nodes and edges, cursor pagination, mutations, node IDs, rate-limit cost and when REST is the better choice.Intermediate → Advanced13 min read
  3. Lesson 3: 03. API AuthenticationFine-grained tokens, classic PATs, GitHub App tokens, OAuth and the Actions token — which credential for which job, with a decision framework and the trade-offs of each.Intermediate13 min read
  4. Lesson 4: 04. Fine-Grained PATsResource owner, repository selection, per-permission grants, expiry and organisation approval — how fine-grained PATs work and when a GitHub App is the better answer.Intermediate12 min read
  5. Lesson 5: 05. GitHub AppsA GitHub App is an integration identity with explicit permissions and per-installation access. JWTs, installation tokens, webhooks, and when an App beats a token.Intermediate → Advanced13 min read
  6. Lesson 6: 06. GitHub WebhooksWebhooks push events to your system instead of you polling. Learn payloads, signature verification, retries and redelivery, idempotency and safe local development.Intermediate → Advanced13 min read
  7. Lesson 7: 07. Repository AutomationCreate and configure repositories, manage branches, labels, collaborators and releases through the API — with pagination, idempotency, dry-run and safe destructive operations.Intermediate → Advanced11 min read
  8. Lesson 8: 08. Pull Request AutomationAutomate pull requests through the GitHub API: list, read changed files, request reviewers, check status and merge safely — including the calls that stop a bot merging a red build.Intermediate → Advanced11 min read
  9. Lesson 9: 09. Issue AutomationList, create, label, assign and close Issues through the API — with search, pagination, triage patterns, rate-limit awareness and the pull-request overlap that skews counts.Intermediate11 min read
  10. Lesson 10: 10. Python + GitHub APIBuild a maintainable Python client for GitHub — sessions, timeouts, retries, pagination, rate limits and error handling — organised into modules you can actually keep.Intermediate → Advanced10 min read
This cluster covers the top three rungs

A vertical progression: manual web interface, GitHub CLI, Bash automation, REST and GraphQL APIs, GitHub Apps with webhooks, and production integrations. The last three are the subject of this cluster.

Manual web interfaceCovered in FundamentalsGitHub CLICovered in the CLI clusterBash automationCovered in the CLI clusterREST / GraphQL APIThis clusterGitHub Apps + webhooksThis clusterProduction integrationsThis cluster

The step that changes most is the last but one. Scripts ask GitHub what happened; webhooks mean GitHub tells you. That inversion removes polling, removes latency, and removes the rate-limit budget spent on asking whether anything changed — which is usually most of it.

Least privilege. Every credential should be able to do the minimum the task requires, on the smallest set of repositories, for the shortest useful time. Broad tokens are convenient in development and are the reason incidents become large.

Handle pagination. The API returns pages. Automation that ignores this works during testing with twenty objects and silently misses data in production with four hundred. It is the most common correctness bug in GitHub automation.

Prefer events to polling. Asking every minute whether a pull request merged is a webhook problem being solved with a rate-limit budget. It is slower, more expensive, and less reliable than being told.

This is the final cluster of GitHub Engineering. What follows it — GitHub Actions, security, and AI-assisted engineering — builds directly on it: workflows authenticate the way this cluster describes, security tooling consumes these endpoints, and integrations are Apps.

For now, the practical endpoint is that you should be able to take any operation from the previous three clusters and perform it from code.

Begin: GitHub REST API