cvh-client
Python API client for the Community Visualization Hub (CVH) — a platform for creating and sharing interactive genomic, spatial, and single-cell visualizations powered by Gosling.js and Vitessce. Designed for use in Jupyter notebooks.
Source lives in the CVH monorepo under python-client/. File issues at hms-dbmi/cvh/issues.
Installation
Requires Python 3.10+.
pip install cvh-client
With Vitessce widget support:
pip install "cvh-client[vitessce]"
Quick start
from cvh_client import CVHClient
# Authenticate against the hosted CVH via Auth0 (opens a browser
# for the device-authorization flow). Swap `base_url`, `domain`,
# `client_id`, and `audience` for your own deployment's values if
# you're self-hosting.
client = CVHClient.from_login(
base_url="https://api.visualizationhub.org",
domain="auth.visualizationhub.org",
client_id="BlOrQcABtV8FrluOQnIO3bWCG1MQU9bx",
audience="cvh-api-prod-id",
)
# List workspaces
workspaces = client.list_workspaces()
ws = workspaces.items[0]
# List datasets and visualizations in a workspace
datasets = client.list_datasets(ws.uuid)
visualizations = client.list_visualizations(ws.uuid)
# Get a single visualization with its config
viz = client.get_visualization(visualizations[0].uuid)
# Update a visualization, then publish it
client.update_visualization(viz.uuid, name="New name", conf={...})
client.publish_visualization(viz.uuid)
Token expiration is handled automatically — if the client was created via from_login(), it will re-authenticate when the token expires.
API methods
Workspaces
| Method | Description |
|---|---|
create_workspace(name, description, *, private) |
Create a workspace you administer |
list_workspaces(limit, offset) |
List workspaces the user has access to |
get_workspace(uuid) |
Get a single workspace |
update_workspace(uuid, **fields) |
Update workspace metadata |
delete_workspace(uuid) |
Delete a workspace |
Datasets
| Method | Description |
|---|---|
create_dataset(workspace_uuid, name, file_type, *, source_url, tool, description, **fields) |
Register a dataset by URL |
list_datasets(workspace_uuid, *, tags, assembly, file_type, name, tool, page, page_size) |
List datasets in a workspace with optional filters |
get_dataset(uuid) |
Get a single dataset |
update_dataset(uuid, **fields) |
Update dataset metadata |
set_dataset_tags(uuid, tags) |
Replace a dataset's tags |
list_dataset_tags(workspace_uuid) |
List tags used by datasets in a workspace |
list_dataset_field_values(workspace_uuid, field) |
List distinct assembly or file_type values |
delete_dataset(uuid) |
Delete a dataset |
Visualizations
| Method | Description |
|---|---|
create_visualization(workspace_uuid, name, *, description, author, tool) |
Create a new visualization |
list_visualizations(workspace_uuid, *, tags, name, uuids) |
List visualizations in a workspace |
get_visualization(uuid) |
Get a visualization with its full config |
update_visualization(uuid, **fields) |
Update visualization metadata or config |
publish_visualization(uuid) |
Make a visualization viewable by anyone |
unpublish_visualization(uuid) |
Make a published visualization private again |
set_visualization_tags(uuid, tags) |
Replace a visualization's tags |
list_visualization_tags(workspace_uuid) |
List tags used by visualizations in a workspace |
delete_visualization(uuid) |
Delete a visualization |
Public
The visualization methods work without signing in, so CVHClient(base_url="https://api.visualizationhub.org") is enough. list_public_workspaces requires sign-in.
| Method | Description |
|---|---|
list_public_visualizations(*, tags, uuids, limit, offset) |
List published visualizations |
get_public_visualization(uuid) |
Get a published visualization with its config |
list_public_workspaces(limit, offset) |
List public workspaces (requires sign-in) |
All methods return typed Pydantic models (Workspace, Dataset, Visualization, etc.).
Error handling
API errors raise descriptive exceptions:
from cvh_client import NotFoundError, AuthorizationError, CVHAPIError
try:
client.get_visualization("nonexistent-uuid")
except NotFoundError as e:
print(e.status_code) # 404
print(e.detail) # {"detail": "..."}
except AuthorizationError:
print("Check your permissions")
except CVHAPIError as e:
print(f"API error {e.status_code}: {e}")
Examples
See the examples/ directory for Jupyter notebooks:
getting_started.ipynb— Authentication, listing workspaces/datasets/visualizations, basic CRUDvitessce_workflow.ipynb— End-to-end Vitessce workflow: create a visualization with the Codeluppi et al. osmFISH config, retrieve it, view it with the Vitessce widget, modify and update
Development
Run these from inside python-client/ (checkout the monorepo first).
uv sync # Install dependencies
uv run pytest # Run tests
uv run ruff check src/ tests/ # Lint
uv run ruff format src/ tests/ # Format
Releasing
Published to PyPI via manual GitHub Actions dispatch. To cut a release:
- Bump the version in
VERSION.txt,pyproject.tomlandsrc/cvh_client/__init__.py(the workflow refuses to publish if they differ), and move the[Unreleased]changelog entries under the new version. - Merge to
main. - In the CVH repo's Actions tab → Publish cvh-client → Run workflow, entering the same version string as confirmation. Choose
testpypifirst to rehearse the release on TestPyPI, then run it again withpypi.
PyPI never accepts the same version twice, so a mistake can't be fixed by re-uploading; it needs a new version. That's what the TestPyPI rehearsal is for.
After publishing, the workflow installs the new version and smoke-tests it against the matching backend (dev for TestPyPI, production for PyPI).
The workflow uses trusted publishing (OIDC — no long-lived token). Trust is configured on each index as:
- Repository:
hms-dbmi/cvh - Workflow:
publish-client.yml - Environment:
testpypion TestPyPI,pypion PyPI
Metadata
Release files for cvh-client 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cvh_client-0.4.0.tar.gz | 15.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cvh_client-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.3 kB
Release files / cvh_client-0.4.0.tar.gz
| Download URL | cvh_client-0.4.0.tar.gz |
|---|---|
| Size | 15.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9425e19c3fd48751b136021abaadba39fefc29d4ed1a56da5ff79302b51eb0bc
|
|
BLAKE2b-256 checksum How to use checksums |
caa9f32197f03a2276c6f49d0bcc66335f540044b66624d5c9df92877d189f85
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 9, 2026.
Transparency logRelease files / cvh_client-0.4.0-py3-none-any.whl
| Download URL | cvh_client-0.4.0-py3-none-any.whl |
|---|---|
| Size | 18.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
97da95af4a55c2607c4eac59bb540a84ac2ed9b76be8322176bda70a1196b15b
|
|
BLAKE2b-256 checksum How to use checksums |
adf4729f6024ccfa3a2323f1b0e9aeb3cd6673bf4f1c19f5f39ae6ec616c4a04
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 9, 2026.
Transparency log