# openai-python: the official Python client for the OpenAI API

> The openai package wraps the OpenAI REST API in typed Python clients for sync and async use, generated from the OpenAPI spec. Here is how it installs, how the Responses and Chat Completions paths differ, and where the docs stop short.

**openai/openai-python** — The official Python library for the OpenAI API

- Repository: https://github.com/openai/openai-python
- Website: https://pypi.org/project/openai/
- Stars: 31,715 · Forks: 6,603
- Language: Python
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/openai-openai-python

## What openai-python is for, and who ends up using it

The package solves one narrow problem: turning HTTP calls to the OpenAI REST API into typed Python objects. The README states that the library "provides convenient access to the OpenAI REST API from any Python 3.10+ application" and that it "includes type definitions for all request params and response fields." That is the whole pitch, and it is a real one. Without it you hand-roll requests, parse JSON yourself, and lose editor completion on response shapes.

The audience is Python developers who already have an API key or a cloud identity and want to call models from a script, a service, or a notebook. The repository layout supports that reading: examples/demo.py, examples/async_demo.py, examples/parsing.py, and examples/responses/ sit alongside a top-level api.md that the README calls "the full API of this library." There is also a bedrock.md and an examples/bedrock.py, so teams routing through Amazon Bedrock are a considered case rather than an afterthought.

What it is not is a model runtime. Nothing here runs inference locally. Every call leaves your process for a remote endpoint, and the library's job ends at serialization, transport, and typing. If you want an abstraction that can swap providers behind one interface, this is the wrong shape: the types are generated from OpenAI's own OpenAPI specification, which the README names as the source of generation.

## Two client styles, one generated surface

The library ships both synchronous and asynchronous clients, and the README attributes both to HTTPX2. The dependency list in pyproject.toml confirms the transport choice: httpx2>=2.7.0, <3 is a hard requirement, as are pydantic and anyio. The presence of anyio matters for anyone running under Trio rather than asyncio, since anyio is the compatibility layer that makes both possible.

The README describes two ways to generate text. The Responses API is called "the primary API for interacting with OpenAI models," while Chat Completions is described as "the previous standard (supported indefinitely)." That phrasing is worth reading carefully. It tells you new work should target responses.create, but it also commits to keeping chat.completions.create working, which is why the second example still appears in the README at all.

The generated-from-spec design has a consequence you should plan for. Because the client mirrors the OpenAPI document, its release cadence follows the API's. The repository shows v3.10.0, v3.11.0, and v3.12.0 all landing within two days in September 2026, and pyproject.toml carries version 3.13.0. Frequent minor bumps are normal here. Pin the version in your lockfile rather than tracking latest, or an unrelated deploy will pull in new request or response fields.

## Installing openai and making a first call

Installation is a single PyPI command. The README gives it directly, with no build step and no system packages.

```bash
# install from PyPI
pip install openai
```

After that, the package imports as openai. The README recommends keeping the key in a .env file rather than in source control, using python-dotenv, and points to platform.openai.com for key creation. The first example in the README constructs a client and calls the Responses API.

```python
import os
from openai import OpenAI

client = OpenAI(
    # This is the default and can be omitted
    api_key=os.environ.get("OPENAI_API_KEY"),
)

response = client.responses.create(
    model="gpt-5.5",
    instructions="You are a coding assistant that talks like a pirate.",
    input="How do I check if a Python object is an instance of a class?",
)

print(response.output_text)
```

The thing to notice is response.output_text. The Responses API returns a structured object, and the README's example reads the text through that convenience attribute rather than indexing into a content array. If you are porting from Chat Completions, that is the line that changes shape.

The older path is still documented and still short. Note that the system-style prompt uses the developer role here, not system.

```python
from openai import OpenAI

client = OpenAI()

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {"role": "developer", "content": "Talk like a pirate."},
        {
            "role": "user",
            "content": "How do I check if a Python object is an instance of a class?",
        },
    ],
)

print(completion.choices[0].message.content)
```

Both snippets pass model="gpt-5.5". That string is a live dependency on your account's access, not a constant. The library will import and construct the client fine with a model name your account cannot use; the failure arrives at call time.

## Workload identity: the part that is not about API keys

The most substantial section of the README is the one on workload identity, and it is the clearest signal of who the library is now built for. Instead of a long-lived key, you pass a workload_identity mapping containing an identity_provider_id, a service_account_id, and a provider. Three providers ship as documented imports: k8s_service_account_token_provider, azure_managed_identity_token_provider, and gcp_id_token_provider.

```python
from openai import OpenAI
from openai.auth import k8s_service_account_token_provider

client = OpenAI(
    workload_identity={
        "identity_provider_id": "idp-123",
        "service_account_id": "sa-456",
        "provider": k8s_service_account_token_provider(
            "/var/run/secrets/kubernetes.io/serviceaccount/token"
        ),
    },
)
```

The README states that tokens are exchanged lazily, cached, and refreshed automatically, with a default refresh buffer of 1200 seconds (20 minutes) before expiration, overridable through refresh_buffer_seconds. A custom provider is also allowed: you pass a dict with token_type and get_token instead of a built-in provider function.

X.509 mutual TLS is the most constrained mode, and the constraints are spelled out in detail. It defaults to https://mtls.api.openai.com/v1 when neither base_url nor OPENAI_BASE_URL is set. Requests must use HTTPS and stay on the configured API origin, and the effective HTTP Host authority must match that origin. Provider API-key and proxy-only headers cannot be sent alongside X.509 authentication, and token exchanges do not inherit API request hooks, authentication, or cookies. Identity settings are captured at client construction, so changing identity means constructing a new client. Azure clients do not support X.509 workload identity. These are not incidental footnotes; they are the operating envelope, and the README is unusually explicit about them.

## Where the documentation stops

The README is generous about X.509 and thin almost everywhere else. It points to api.md for "the full API of this library" and to platform.openai.com for REST semantics, which means the client-level documentation is largely a pointer. For anyone evaluating the library before writing code, that is a gap: you cannot learn retry behaviour, timeout defaults, or error class hierarchy from the README alone.

The versioning story is the other soft spot. The pyproject.toml in the repository declares version 3.13.0 while the most recent release listed is v3.12.0, which is normal for a repository between releases, but it does mean the file you read in the repo is not necessarily the artifact on PyPI. Confirm what you actually installed rather than trusting the repository's manifest.

Finally, the README's own examples use model="gpt-5.5" without saying whether that identifier is generally available, gated, or region-specific. It simply is not addressed. If your first call fails, the README gives you no troubleshooting section to work from, and the library's generated types will not tell you why a model name was rejected. That is a documentation boundary, not a code defect, but it will cost you time on day one.

## openai-python versus calling the REST API directly

The honest alternative is not another SDK. It is requests or httpx plus your own JSON handling, hitting the same REST endpoints the library wraps. The README is explicit that the REST API documentation lives on platform.openai.com and that this library is generated from the OpenAPI specification, so the direct-HTTP path is fully supported by OpenAI and always current.

The difference is what you give up. With direct HTTP you get no generated type definitions for request params and response fields, which is exactly what the README lists as the library's value. You also lose the sync and async client pair, so an async service needs its own concurrency handling rather than AsyncOpenAI. And you would implement workload identity token exchange, caching, and the refresh buffer yourself, including the X.509 constraints around origin matching and header restrictions.

Going direct makes sense in a few situations. If you need one endpoint and want zero dependencies, adding httpx2, pydantic, anyio, sniffio, and jiter to your tree is a poor trade. If your environment cannot install wheels from PyPI, direct HTTP sidesteps that entirely. But if you are calling several endpoints, handling streaming, or running in Kubernetes with service account tokens, the library is doing work you would otherwise duplicate and get subtly wrong.

## Licence, maintenance, and what upgrades cost you

The project is Apache-2.0, stated in pyproject.toml as license = "Apache-2.0" and echoed in the classifiers as "License :: OSI Approved :: Apache Software License." Apache-2.0 includes an explicit patent grant and permits commercial and closed-source use, but it also carries notice and attribution obligations. Read the LICENSE file in the repository rather than relying on the classifier string; that is the document that governs, and this is not legal advice.

On maintenance, the repository is not archived and the last push was on 2026-09-10. Releases v3.10.0, v3.11.0, and v3.12.0 all landed on 2026-09-09 and 2026-09-10. That is a tight cluster, and it is the pattern to expect from a spec-generated client.

The upgrade cost follows from that cadence. Minor versions can add request and response fields, and because the types are generated, a new field can change what your type checker accepts. Pin the version, run your type checker on upgrade, and read CHANGELOG.md rather than assuming a minor bump is inert. If you use optional extras, note that they are separate: realtime pulls websockets, datalib pulls numpy and pandas, voice_helpers pulls sounddevice and numpy, and bedrock pulls botocore and urllib3. Installing the base package does not install any of them, and the README does not document rollback for a version you have already deployed.

## Conclusion

Adopt openai-python if you are calling OpenAI models from Python 3.10+ and want typed request and response objects, a maintained sync and async client, and a documented path to workload identity instead of long-lived keys. Do not adopt it if your codebase is pinned below Python 3.10, if you need a client for a non-OpenAI endpoint that is not covered by the documented base_url and Bedrock paths, or if you want a library that does not track a hosted service's release cadence. Verify three things first: that pip install openai resolves to the version you expect, that your OPENAI_API_KEY is loaded from the environment rather than committed, and that the model name in your first call is one your account can actually reach, because the README's examples use gpt-5.5 and a wrong model name surfaces as a runtime error rather than an import error.

## FAQ

### How do I install the openai Python library?

Run pip install openai, which the README gives as the PyPI installation command. The package requires Python 3.10 or later, per the requires-python field in pyproject.toml.

### How do I use the openai Python library?

Import OpenAI, construct a client, and call an endpoint such as client.responses.create with a model, instructions, and input. The README's example prints response.output_text to read the generated text.

### What is the openai Python library?

It is the official Python library for the OpenAI API, offering typed request and response definitions plus synchronous and asynchronous clients powered by HTTPX2. It is generated from OpenAI's OpenAPI specification.

### How do I install openai in Python?

The README's installation section is a single command, pip install openai, with no additional build steps described. The README recommends loading OPENAI_API_KEY from a .env file rather than storing it in source control.

### How do I use Azure OpenAI with the openai Python library?

The README documents azure_managed_identity_token_provider as a workload identity provider, and the repository includes examples/azure.py and examples/azure_ad.py. The README also states that Azure clients do not support X.509 workload identity.

### Is the openai Python library free?

The library itself is licensed under Apache-2.0, so the code is free to use under that licence. The README does not describe pricing for the API calls the library makes; that is covered on platform.openai.com.

## Sources

- [License: Apache-2.0](https://github.com/openai/openai-python/blob/main/LICENSE)
- [openai/openai-python on GitHub](https://github.com/openai/openai-python)
- [Project website](https://pypi.org/project/openai/)
- [README](https://github.com/openai/openai-python/blob/main/README.md)
- [Releases](https://github.com/openai/openai-python/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/openai-openai-python
