Skip to main content

github-apiroute

CI Build

Python clients for GitHub's REST and GraphQL APIs, generated with apiroute and kept current by a weekly build. The REST client comes from GitHub's published OpenAPI description. The GraphQL client comes from GitHub's schema plus a set of operations written in this repository.

  • Two layers: every call works with plain dicts (gh.repos.get("octocat", "Hello-World")), and .models takes and returns typed pydantic models (gh.repos.models.get(...)).
  • Sync and async: add .aio to any call for the async version.
  • Lazy loading: only the sections and models you use are imported. The REST client covers about 1,250 endpoints and 4,100 models, and a script that calls one of them stays fast.
  • Typed: the package ships py.typed, and mypy checks the generated code.

Installation

pip install github-apiroute    # or: uv add github-apiroute

It needs Python 3.10 or newer.

Authentication

Both clients take a token: a personal access token, a GitHub App installation token, or a function that returns the current token (so a refreshing helper can be passed directly). It is sent as Authorization: Bearer <token>. Without a token, the REST API allows a few anonymous calls and the GraphQL API none.

For GitHub Enterprise Server, pass base_url: https://HOST/api/v3 for REST and https://HOST/api for GraphQL.

REST API

import os
from github_apiroute.rest import GitHubRestApi

gh = GitHubRestApi(token=os.environ["GITHUB_TOKEN"])

repo = gh.repos.get("octocat", "Hello-World")  # a dict
repo = gh.repos.models.get("octocat", "Hello-World")  # FullRepository
print(repo.full_name, repo.stargazers_count)

issues = gh.issues.list_for_repo("octocat", "Hello-World", state="open", per_page=100)
issues = await gh.issues.aio.list_for_repo("octocat", "Hello-World")

Sections follow GitHub's REST documentation (repos, issues, pulls, actions and so on), and each method is named after its operation. Every call sends X-GitHub-Api-Version: 2022-11-28; pass api_version= to request another version. REST list endpoints are paged with page and per_page.

GraphQL API

The GraphQL client runs the operations in operations/graphql/: a practical starter set. Each one becomes a typed method, and its result models contain exactly the fields the operation selects.

from github_apiroute.graphql import GitHubGraphQLApi

gh = GitHubGraphQLApi(token=os.environ["GITHUB_TOKEN"])

me = gh.models.viewer().viewer
print(me.login, me.created_at)  # created_at is a datetime

for issue in gh.repos.models.issues(owner="octocat", name="Hello-World"):  # every page
    print(issue.number, issue.title)

for repo in gh.search.models.search_repositories(query="apiroute language:python"):
    print(repo.name_with_owner)

await gh.mutations.models.aio.add_star(starrable_id=repo.id)
Section Operations
(root) viewer, rate_limit
repos repository, issue, and paginated issues, pull_requests, releases, stargazers
users user, paginated user_repositories
search paginated search_repositories, search_issues
mutations create_issue, add_comment, add_star, remove_star

Paginated operations return an iterator that follows pageInfo.endCursor until the last page. A response with errors raises apiroute.graphql.GraphQLError.

To add an operation, write it in a .graphql file under operations/graphql/ and regenerate (see Development). The generator checks every operation against GitHub's schema.

APIs

API Import Docs
REST API from github_apiroute.rest import GitHubRestApi docs
GraphQL API from github_apiroute.graphql import GitHubGraphQLApi docs

Errors raise apiroute.UnexpectedResponse, which carries the .response. For retries, transports and other client options, see apiroute's README.

Retries are off unless you turn them on, for example with gh.with_options(retries=3). Once on, failed connections are always retried. After a read timeout, though, only calls that are safe to repeat are retried: REST GET, PUT and DELETE (GitHub's PUTs set state, such as starring a repository), and GraphQL queries. REST POSTs and GraphQL mutations aren't, so an issue or a comment can't be created twice.

How this repository stays up to date

Nothing under src/github_apiroute/ is written by hand except auth.py and __init__.py. Everything else is generated from the sources listed in apis.yaml:

  1. Every Monday, the Build workflow does the following:
    • Upgrades apiroute to its newest release.
    • Downloads GitHub's REST description and introspects the GraphQL schema into specs/.
    • Regenerates the clients with apiroute generate.
    • Runs the lint and tests, then the live tests: read-only calls that check the typed models against what GitHub actually sends.
  2. If anything changed, it commits the result to main:
    • feat(specs): ... when GitHub changed a spec or schema, which produces a minor release.
    • fix(codegen): ... when only a newer apiroute changed the generated code, which produces a patch release.
  3. Release (release-please) then updates its release PR, tests it, merges it and publishes the new version to PyPI. No one has to do anything.

CI checks every push. It lints, runs the tests on Python 3.10 to 3.14, and regenerates from the committed specs to confirm the committed code matches them exactly.

Because specs/ is committed, git log -p specs/ shows exactly what GitHub changed and when.

Development

uv sync
GITHUB_TOKEN="$(gh auth token)" uv run python scripts/generate.py --fetch   # latest specs, regenerate
uv run python scripts/generate.py --only graphql   # regenerate one API from its committed spec
uv run pytest
GITHUB_TOKEN="$(gh auth token)" uv run pytest tests/live   # read-only calls against api.github.com
uv run ruff check . && uv run ruff format --check .

Fetching the GraphQL schema needs a token in GITHUB_TOKEN; regenerating from the committed specs doesn't. The live tests in tests/live check the typed models against what GitHub actually sends: they only read, keep lists to a few items, and are skipped without a token. Auth lives in src/github_apiroute/auth.py, which the generated clients extend.

License

MIT

Metadata

Release files for github-apiroute 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for github-apiroute 0.4.0
File Size Uploaded Provenance
github_apiroute-0.4.0.tar.gz 918.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for github-apiroute 0.4.0
File Interpreter ABI Platform
github_apiroute-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 4.7 MB

Release files / github_apiroute-0.4.0.tar.gz

Download URL github_apiroute-0.4.0.tar.gz
Size 918.6 kB
Tags Source
SHA-256 checksum
How to use checksums
5915eb664fa3ebe4bcbf7b895fba069089d04062e480b3cf03d14897cc9c614a
BLAKE2b-256 checksum
How to use checksums
cde797e64655dca957b7a170af15ed0c35aa530cc2db37036b6a7ece4ebb7042
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / github_apiroute-0.4.0-py3-none-any.whl

Download URL github_apiroute-0.4.0-py3-none-any.whl
Size 3.8 MB
Tags Python 3
SHA-256 checksum
How to use checksums
a0fb11bbda71ea34a8cd776960fe5ec54d1c6d3cc2e12fc300eb5459163d3ba5
BLAKE2b-256 checksum
How to use checksums
fe02d299f260027856e395b3c76ffe46a967c321b2ed2e5b91125932da4e784b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for github-apiroute 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page