The minimum supported runtime, contributor toolchain, CI matrix, and release rules are documented in PYTHON_VERSION_POLICY.md. Changes to the minimum Python version must keep those surfaces synchronized and must include a release note naming the final compatible SDK release.
We use uv to manage Python, dependencies, and builds.
Install uv 0.12.1 or newer, Node.js at the version in .node-version, and
the exact pnpm version in package.json (npm install --global pnpm@11.19.0).
The Node toolchain is for repository development only, not SDK users or builds.
Then run:
$ ./scripts/bootstrapThis installs all SDK extras and Python development tools from uv.lock, plus
the contributor tools from pnpm-lock.yaml. Bootstrap requires an already
installed Node.js and pnpm; it does not download or switch those tools for you.
Run a
command with uv run --locked --all-extras, or activate .venv in your shell.
Use uv lock after changing dependencies, and commit the updated uv.lock.
It is the authoritative lockfile; uv export can produce a requirements file
for tools that need one.
For Node tooling updates, edit package.json, run
pnpm install --lockfile-only --ignore-scripts, review the dependency and
integrity changes, and commit pnpm-lock.yaml. Normal bootstrap uses a frozen
lockfile. pnpm rejects releases that have not cleared the eight-day cooldown,
including packages whose registry metadata omits their publication date.
Pyright runs the local Microsoft package and never invokes npm or
downloads a runtime. Do not use npx, pnpm dlx, or Corepack auto-downloads.
The default environment uses Pydantic v2. ./scripts/test also runs the
Pydantic-v1 suite in a separate, locked environment. To run that lane alone,
use ./scripts/test-pydantic-v1.
Routine Python, Node-tooling, and GitHub Actions updates have an eight-day cooldown. uv also excludes Python distribution artifacts uploaded within the last eight days. Dependabot security updates remain enabled and are exempt from Dependabot's version-update cooldown.
The committed uv.lock must remain usable outside a contributor's environment:
registry sources use https://pypi.org/simple, and distribution artifacts use
hashed https://files.pythonhosted.org/packages/ URLs. If a managed registry
rewrites those locations, keep its required local security checks enabled. Use
dependency-update automation or an approved public-lockfile repair that matches
each exact filename and SHA-256 against upstream metadata; do not substitute
hosts blindly or commit private registry URLs. The public-source regression test
in tests/test_uv_workflows.py checks this without making network requests.
Do not lower a security-fixed minimum or downgrade a patched lock entry to make
the cooldown pass. If an urgent fix is too new for uv, request SDK CODEOWNER
review of the advisory, exact fixed version, upstream provenance, artifact
hashes, and affected dependency paths. The reviewed PR may add a temporary,
package-specific tool.uv.exclude-newer-package cutoff using a fixed UTC
timestamp just after the approved artifacts were uploaded. Update only the
approved package (for example, uv lock --upgrade-package 'package==version'),
retain the security floor in published metadata where applicable, and review
the resulting lock diff. Record the advisory and an expiry/removal date in the
PR and remove the exception once those artifacts are eight days old. Do not
disable the global cutoff or exempt unrelated packages.
For an urgent Node-tooling security fix, obtain the same CODEOWNER review and
use a temporary, exact package@version entry in pnpm's
minimumReleaseAgeExclude. Record the public advisory, integrity/provenance,
and removal date in the PR. Do not lower an existing security-fixed version,
disable the global age policy, or enable lifecycle scripts globally.
See uv's package-specific cutoff documentation and Dependabot's cooldown policy.
Most of the SDK is generated code. Modifications to code will be persisted between generations, but may
result in merge conflicts between manual patches and changes from the generator. The generator will never
modify the contents of the src/openai/lib/ and examples/ directories.
- Never commit API or admin keys, bearer tokens, webhook secrets, cloud
credentials, private keys, publishing credentials, or
.envfiles. Load real credentials from environment variables such asOPENAI_API_KEY,OPENAI_ADMIN_KEY, andOPENAI_WEBHOOK_SECRET; use clearly fake values and sanitized data in examples, tests, fixtures, and recorded responses. - Redact
Authorizationandapi-keyheaders, other credentials, and customer request or response data from logs, exceptions, snapshots, and debug output. Prefer the mock server or mocked HTTP transport over live credentials in tests. - Review direct and transitive dependency changes, package provenance, build or
install hooks, and diffs to
pyproject.toml, optional extras,uv.lock, and the build dependency group. - Pin third-party GitHub Actions to reviewed full commit SHAs, minimize job permissions, and keep secrets and write-capable tokens away from untrusted pull-request code. Protect release-app credentials and preserve the separate build and upload jobs, protected publishing environment, and PyPI Trusted Publishing. Limit OIDC access to the trusted publishing job.
- Request SDK CODEOWNER review for authentication, X.509, webhook verification, network destinations, redirects, TLS, cloud metadata, file handling, serialization, dependency, CI, and release changes. Add synchronous and asynchronous regression tests as applicable, including credential redaction and invalid signatures.
- Report suspected vulnerabilities privately through the process in SECURITY.md, never through public issues or pull requests.
All files in the examples/ directory are not modified by the generator and can be freely edited or added to.
# add an example to examples/<your-example>.py
#!/usr/bin/env -S uv run python
…$ chmod +x examples/<your-example>.py
# run the example against your api
$ ./examples/<your-example>.pyIf you’d like to use the repository from source, you can either install from git or link to a cloned repository:
To install via git:
$ pip install git+ssh://git@github.com/openai/openai-python.gitAlternatively, you can build from source and install the wheel file:
Building this package will create two files in the dist/ directory, a .tar.gz containing the source files and a .whl that can be used to install the package efficiently.
To create a distributable version of the library, all you have to do is run this command:
$ ./scripts/buildThe build script exports hash-checked build requirements from uv.lock before
building the sdist and wheel. It does not install the development toolchain.
Then to install:
$ pip install ./path-to-wheel-file.whlMost tests require you to set up a mock server against the OpenAPI spec to run the tests.
./scripts/bootstrap installs the locked Steady package and its platform
binary. ./scripts/test starts it automatically when no mock server is running.
Neither ./scripts/test nor ./scripts/mock downloads Node tools. If the local
tool is missing, rerun bootstrap. TEST_API_BASE_URL and an already-running
mock server remain supported. To start the server yourself:
$ ./scripts/mock$ ./scripts/testThis repository uses Ruff to lint and format Python code.
To lint:
$ ./scripts/lintTo format and fix all ruff issues automatically:
$ ./scripts/formatChanges made to this repository via the automated release PR pipeline should publish to PyPI automatically. If the changes aren't made through the automated pipeline, you may want to make releases manually.
You can release to package managers by using the Publish PyPI GitHub action. PyPI publishing uses Trusted Publishing, so the PyPI project must trust this repository's GitHub Actions workflow and the publish environment.
If you need to retry a PyPI release, use the Publish PyPI GitHub action. Local manual publishing is not the standard release path because the GitHub workflow uses OIDC instead of a long-lived PyPI token.