A Complete Python Client for the GitHub API
GitHub's REST API grants programmatic access to nearly everything a developer might do through the web interface or git client. This includes managing issues, pull requests, releases, tags, Actions workflows, webhooks, users, organizations and deployments. But fully exploiting those features has required juggling multiple technologies: direct HTTP calls are clunky with obscure status codes, vendor libraries cover only a subset of endpoints with inconsistent interfaces, GitHub's official gh CLI handles a small fraction of the API's capabilities, and building Actions extensions forces developers into TypeScript.
Today fast.ai is releasing ghapi, a Python library and CLI designed to offer complete, idiomatic access to the entire GitHub API with a single consistent interface. It grew out of the maintainers' own workflow needs—automating issue triage, bulk-closing with template responses, and managing Actions across many repositories from the terminal. The library powers GitHub CEO Nat Friedman's ghtop project, after an overhaul he described as a "tour de force".
The key enabler is GitHub's OpenAPI specification, a machine-readable catalog of every endpoint in the API. ghapi uses that spec to auto-generate its interface, guaranteeing full coverage and keeping method names and documentation in sync with GitHub's own reference materials.
Exploring the API
To create an issue, say after a failed CI run, a developer consults the categorized API reference to find the issues.create operation. Alternatively, in Python or the CLI, tab completion lets you browse operation names and parameter lists interactively. Typing the name of an operation group shows all its members with parameter details plus a direct link to the official GitHub documentation.

Responses arrive as plain JSON from GitHub, which is hard to scan quickly. ghapi reformats every JSON response automatically into a readable bulleted list, making a returned issue object legible at a glance:

Boilerplate is reduced throughout. For instance, arguments such as repository owner and name supplied at instantiation are inserted dynamically into later calls, and custom headers required by preview endpoints are added automatically.
Paginated Results and Integrated Methods
Most API calls that return lists are paginated. Normally that means writing a loop across REST endpoints while manually tracking page counts. ghapi instead treats paged results as native Python iterators, ready for a for loop, list comprehension, or any other idiom. A helper called paged converts any paged endpoint into an iterator. To list all repositories in an organization:

ghapi can also fetch all pages in parallel automatically and concatenates the results.
That capability benefits ghapi.event, a module wrapping GitHub's Events API with its notoriously tricky navigation and quota tracking. A generator called fetch_events provides a continuous deduplicated stream of events, optionally filtered to remove bot activity and other developers' chosen criteria.
Higher-level convenience methods wrap whole API features, so a single call performs what otherwise requires multiple REST interactions—for example, editing a file in the repository directly:

Same Features on the Command Line
The ghapi CLI exposes the same operations, parameter names, documentation, and tab-completion as the Python API, making it trivial to move between interactive exploration and scripted use. Full reference documentation is browsable at any time by passing --help on the command line:

Writing GitHub Actions in Python
GitHub Actions offer unlimited compute for open source projects, but building workflows with them can be painful. They run in a custom sandbox that's hard to reproduce locally, testing means generating real events then waiting minutes to see the result, and the YAML-plus-special-syntax approach lacks the flexibility of a programming language. Extending Actions requires TypeScript, which many Python-centric maintainers never use.
ghapi lets you author workflows entirely in Python and do most of the development locally. A single command scaffolds a new action:

The generated Python file is then edited to add the logic. A workflow that automatically replies "thank you" to new pull requests, for example, takes only a few lines:

That short script relies on the full GitHub API through ghapi's Pythonic interface rather than Actions-specific syntax. ghapi bundles example payloads for all supported event types, so the script can be tested with realistic data on any development machine before it is ever pushed to a repository. Extensive tutorials are available in the ghapi documentation covering both the CLI and Actions workflows.
From OpenAPI Spec to a Lean Client
The source of ghapi's reach is GitHub's own OpenAPI description. A machine-readable OpenAPI spec allows automated generation of client libraries, and GitHub's — covering a 12-year-old API with thousands of features — is notably complete and carefully organized. The effort put into its design is evident: operation naming is consistent and the API is thoroughly categorized.
ghapi is among the first OpenAPI-based clients for the GitHub API, and it exploits Python's dynamic features to avoid a common pitfall of such libraries: verbose code generation. The typical route, as seen in the experimental octo-go client for Go, is to generate explicit methods and data types for each endpoint. That works, but the result is enormous; the generated wrapper for just the repo operations in octo-go exceeds 20,000 lines of code. Static languages like Go require this approach because the compiler needs prior knowledge of every function and data type.
In contrast, the entire ghapi package is only about 40kB. Instead of generating code, ghapi ships a compact Python module containing the essential spec data, with classes that create methods on the fly by referencing that module. The implementation relies on several dynamic tricks to make it work, which the project will detail in a later post.



