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.
  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
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. Auth lives in src/github_apiroute/auth.py, which the generated clients extend.

License

MIT

Metadata

Release files for github-apiroute 0.2.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.2.0
File Size Uploaded Provenance
github_apiroute-0.2.0.tar.gz 912.2 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 4.7 MB

Release files / github_apiroute-0.2.0.tar.gz

Download URL github_apiroute-0.2.0.tar.gz
Size 912.2 kB
Tags Source
SHA-256 checksum
How to use checksums
79a0a6d10aa26ac5f03bdbe6c29ffd574c12d55ceb4200123ddb534e2e93f7ad
BLAKE2b-256 checksum
How to use checksums
fe94c0ada86fe2c536fc796a11b0d53e445b95e2463efbfba4e38a33c6a28be9
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.2.0-py3-none-any.whl

Download URL github_apiroute-0.2.0-py3-none-any.whl
Size 3.8 MB
Tags Python 3
SHA-256 checksum
How to use checksums
3f36a15fe1b9c5e90367544b45782b6674cbaa01542af236ab092b397359c061
BLAKE2b-256 checksum
How to use checksums
8b482a6007aba2c00095d63a1b0d9f35c662e68ddd4b0d68cda4ea4c866dbd1b
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.2.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