This release is a pre-release and may not be stable for production use.
UpCloud's Python API Client (v3 alpha)
This v3-dev branch is the generated OpenAPI client for UpCloud's HTTP API (/1.3/...). It is a breaking major relative to the handwritten 2.x CloudManager client on main. “v3” is the Python package major version, not a new HTTP API version.
Please test thoroughly before production use. A separate UpCloud account for development is recommended.
Installation
Stable 2.x remains the default on PyPI. Once a v3 alpha is published, select it explicitly:
pip install upcloud-api # latest 2.x (currently 2.9.x)
pip install "upcloud-api==3.0.0a1" # this generated v3 alpha
Do not rely on a blanket pip install --pre. That would also pull pre-releases of other dependencies.
upcloud-api>=2.9,<3 stays on 2.x: under PEP 440, <3 excludes 3.0.0a1 even with --pre. To opt into the v3 alpha, pin upcloud-api==3.0.0a1.
The distribution name is upcloud-api. The import package is upcloud_api.
Supported Python versions
- Python 3.11
- Python 3.12
- Python 3.13
- Python 3.14
- PyPy 3.11
Usage
import os
from upcloud_api import AuthenticatedClient
client = AuthenticatedClient(
base_url="https://api.upcloud.com",
token=os.environ["UPCLOUD_TOKEN"],
)
# Call generated operations, for example:
# from upcloud_api.api.server import list_servers
# with client as client:
# servers = list_servers.sync(client=client)
This is not a drop-in replacement for CloudManager. See generated helpers under upcloud_api/ and examples under examples/.
Regenerating the client
The client is produced by openapi-python-client from the public OpenAPI spec:
mise trust .config/mise.toml
mise install
mise run generate
The mise configuration pins openapi-python-client,
speakeasy, the ruff its post-hooks use (the same version as the pre-commit hook),
jq, and uv.
The generate task runs generator/scripts/generate.sh on the checked-in
generator/openapi/spec.json (no download). It refuses to overwrite uncommitted
changes in upcloud_api/ unless you pass mise run generate --force.
mise run regenerate runs generate, then check, and stops at the
first failure with a non-zero exit. The generated changes stay in place for
investigation. Neither task changes pyproject.toml or uv.lock. A stale lock
fails the uv commands, and only mise run lock and mise run version:set update it.
generate.sh applies generator/openapi/overlay.yaml with
speakeasy overlay apply --strict, runs the jq filter in
generator/scripts/strip_schema_titles.jq to remove collision-prone schema titles,
and writes the result to generator/openapi/spec.patched.json,
then recreates only upcloud_api/. Spec fixes go in the overlay. Do not hand-edit
upcloud_api/ except via the overlay, generator templates, or
the title filter. mise run check:generated fails
if regenerating changes either output.
Development
Install mise, then set up the locked environment (Python 3.14 by default):
mise trust .config/mise.toml
mise install
mise run setup
mise run lint
mise run check
mise run build
Local development and CI use the same task entry points and mise-pinned tools.
Every uv command runs with UV_LOCKED=1, so it fails on a stale uv.lock.
Python is selected by UV_PYTHON, or .python-version when no override is supplied.
For example:
UV_PYTHON=3.11 mise run test:unit
UV_PYTHON=pypy3.11 mise run test:unit
Task reference
| Task | Purpose |
|---|---|
setup |
Install locked development dependencies. |
lint |
Run pre-commit: ruff, shellcheck, and actionlint. |
test:tools |
Test the shell scripts offline with bats. |
test:preprocess |
Test schema-title filtering, overlay fixes, and the endpoint checker. |
test:unit |
Run offline unit tests for the SDK and Wiretap test cases. |
check:generated |
Regenerate and fail if upcloud_api/ or spec.patched.json changes. |
check:endpoints |
Check that every spec operation has generated code. |
test:contract |
Run generated sync/async SDK calls against a local Wiretap mock. |
check |
Run required checks: lint, test:tools, test:preprocess, test:unit, check:generated. Alias: test. |
findings |
Run check:endpoints and test:contract (fails on known spec and generator issues). |
validate |
Run check and findings, even if check fails. |
build |
Build a wheel and source distribution into dist/, then run twine check. |
generate [--force] |
Regenerate the SDK from the checked-in spec. |
regenerate |
Run generate, then check, and stop at the first failure. |
lock |
Update uv.lock. |
version:set <version> |
Set [project].version in pyproject.toml and uv.lock with uv version --no-sync. |
spec:download <version> <asset_url> |
Download a released spec using SPECS_ACCESS_PAT (used by the regeneration workflow). |
examples [name...] |
Run live mdtest examples, all four by default. |
Checks and contract tests
check runs the required static, unit, and generation checks. It blocks builds,
releases, and regeneration PRs.
findings runs check:endpoints and test:contract to report known spec and
generator issues without blocking releases. Regeneration PRs are opened as
drafts when findings fails.
mise install installs every pinned tool, including wiretap, bats,
shellcheck, actionlint, twine, and mdtest (built with the pinned Go).
Wiretap runs as a local binary in mock mode and doesn't need Docker or Podman.
No task except examples needs UpCloud credentials or makes real UpCloud requests,
but the first run needs network access to install tools and dependencies.
generator/scripts/wiretap.sh starts Wiretap, sends an invalid probe request to
verify validation is active, runs the Python tests, and fails if the report is
missing or contains any other violation. It writes wiretap.log,
wiretap-report.json, and coverage.json to validation-artifacts/ (override
with VALIDATION_ARTIFACTS).
Shared scripts across SDK repositories
The task names are shared across the Python, Go, and PHP SDK repositories:
setup, lint, generate, test:tools, test:preprocess, test:unit,
check:generated, check:endpoints, test:contract, check, findings,
build, spec:download, regenerate, examples, and version:set. Only the
run commands are language-specific.
Scripts with the header line Copied unchanged into each UpCloud SDK repository
don't depend on the SDK language. They need only bash, git, curl, tar, and
mise-pinned tools, and their bats tests in generator/scripts/tests/ travel with
them:
generator/scripts/wiretap.sh SPEC COMMAND...runsCOMMANDwithWIRETAP_URLpointing at a local Wiretap mock (WIRETAP_PORT, default 9090) and writes its artifacts toVALIDATION_ARTIFACTS. The exit code is the result.generator/scripts/check_generated.sh PATH... -- CMD...runsCMDand fails, listing the files, if it changed anyPATH.generator/scripts/download_spec.shdownloads and validates a release spec.generator/scripts/run_examples.sh NAME...runsexamples/<name>/test_<name with - as _>.mdwith mdtest.
The rest is specific to this Python repository: uv, generate.sh,
generator/openapi/overlay.yaml, strip_schema_titles.jq, check_endpoint_coverage.py,
the spec-derived Wiretap cases
in tests/wiretap_cases.py, and the SDK calls in tests/test_wiretap.py.
Local generation always uses the checked-in generator/openapi/spec.json.
spec:download is only needed by the CI regeneration workflow, or when you
deliberately want a newer released spec.
Downloading a spec and preparing a package version
Downloading is optional. Set SPECS_ACCESS_PAT in your shell before downloading a
release asset. The URL
must be a GitHub API release-asset URL. --spec-file selects the tarball member and
defaults to upcloud-public-openapi.json:
mise run spec:download 0.0.107 \
https://api.github.com/repos/UpCloudLtd/upcloud-openapi-spec/releases/assets/123 \
--spec-file upcloud-public-openapi.json
mise run regenerate
Downloading replaces generator/openapi/spec.json only after the selected member
has been downloaded and checked as an OpenAPI JSON document. The token is sent only
to api.github.com. curl doesn't forward it when the asset redirects to another
host. Use an actual release asset
ID rather than the placeholder above. Package version changes are separate and explicit:
mise run version:set 3.0.0a1
mise run build
Publishing, GitHub releases, PR creation, artifact handling, CodeQL, and Scorecard remain GitHub Actions responsibilities, not local tasks.
Live examples
The root is the distributable upcloud-api package. Set UPCLOUD_TOKEN for a
separate development account before running a live example. mise install
provides mdtest:
mise run examples tag
# Explicitly run all four live resource tests:
mise run examples
These tasks create real UpCloud resources and can incur charges. They run
generator/scripts/run_examples.sh, which maps each name to
examples/<name>/test_<name>.md (with - replaced by _ in the file name),
checks the token and mdtest availability before invocation, and sets the absolute
UPCLOUD_SDK_PATH so mdtest imports the local SDK from its temporary
working directory. CI runs mise run examples for same-repository PRs and manual
dispatches. Fork PRs are skipped because they cannot read the token.
SPEC_VERSION follows the OpenAPI spec, while the package version is tracked in the root
pyproject.toml and uv.lock. The v3 release
workflows update it from the release tag or manual TestPyPI input (for example,
3.0.0a1) via mise run version:set before building.
The root pyproject.toml, README, and license are not overwritten by regeneration.
Changelog
- Changelog is available in its own file
Bugs, Issues, Problems, Ideas
Please report issues and feature requests through the issues page.
Metadata
Release files for upcloud-api 3.0.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| upcloud_api-3.0.0a1.tar.gz | 553.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| upcloud_api-3.0.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.3 MB
Release files / upcloud_api-3.0.0a1.tar.gz
| Download URL | upcloud_api-3.0.0a1.tar.gz |
|---|---|
| Size | 553.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a1b662e4007008bf869e75ffd31b0df97306dd2b78f17ab4258ac608f467b9d3
|
|
BLAKE2b-256 checksum How to use checksums |
13154ee9f667b98d507626106278a338f760ed312745c8b5de78c3837c1220d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / upcloud_api-3.0.0a1-py3-none-any.whl
| Download URL | upcloud_api-3.0.0a1-py3-none-any.whl |
|---|---|
| Size | 1.8 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8cf4e7223b966a3a57cb06c15737fcdd9526d6d439d2ab0c355519e2d7ca584c
|
|
BLAKE2b-256 checksum How to use checksums |
4a3aa8f1fbc8965a647977bae6aeb2b2df5ad5e2832a071e2c790159914d4891
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logSecurity for upcloud-api 3.0.0a1
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for upcloud_api-3.0.0a1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logA 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.