vxcloud · Python SDK
Provision infrastructure, deploy applications, and manage running services on the vxcloud platform — straight from Python.
vxcloud is the official, brand-name distribution of the vxcloud Python SDK. It re-exports the entire vxsdk surface, so import vxcloud and import vxsdk are byte-for-byte identical — pick the name your team prefers. The sync client is stdlib-only (zero third-party dependencies); an optional async client is one extra away.
Installation · Quick start · What you can do · Async · Errors · Docs
Installation
pip install vxcloud # sync client — stdlib only, zero dependencies
pip install vxcloud[async] # adds httpx for the async client
Requires Python 3.9+. Tested on CPython 3.9 – 3.12.
Quick start
import vxcloud
# Reads ~/.vxcloud/credentials.json (written by `vxcli auth login`)
c = vxcloud.Client.load_from_vxcli()
# ...or pass credentials explicitly
# c = vxcloud.Client(api_key="xc_dev_...", username="alice")
# Provision a VM on AWS
vm = c.cloud.vm.provision(
name="api-vm", cloud="aws", region="us-east-1",
instance_type="t3.small", key_pair_name="AWSPRODKEY2",
)
print(vm["public_ip"])
# Deploy a Docker container onto it
result = c.deploy.container(
host=vm["public_ip"], ssh_user="ubuntu", key_pair_name="AWSPRODKEY1.PEM",
image="grafana/grafana:latest", name="grafana",
ports=["3000:3000"], restart_policy="unless-stopped",
)
print(result["session_id"], result.get("status"))
Pick the entry-point name you like
All four resolve to the same client class — there is no behavior difference:
import vxcloud
c = vxcloud.Client.load_from_vxcli() # canonical
c = vxcloud.VxCloud.load_from_vxcli() # PascalCase brand (matches the TS SDK)
c = vxcloud.vxcloud.load_from_vxcli() # lowercase brand
c = vxcloud.load_from_vxcli() # module-level convenience
What you can do
vxcloud is a thin, typed wrapper over the vxcloud FastAPI control plane. The
same JSON wire contract powers the Go and TypeScript SDKs.
| Area | Example | Backend |
|---|---|---|
| Compute | c.cloud.vm.provision(...), c.cloud.vm.status(...), c.cloud.vm.action(...) |
/api/v2/tenant/provision/vm |
| Containers | c.deploy.container(...), c.install.compose(...) |
/api/v2/tenant/container/deploy |
| App stacks | c.deploy.stack("golang", repo_url=..., ...), c.deploy.fastapi(...) |
/api/v2/infrastructure/services/<kind>/deploy |
| Storage & IAM | c.cloud.create_s3_bucket(...), c.cloud.create_iam_policy(...) |
/api/v2/tenant/provision/{storage,security} |
| Networking | c.cloud.create_vpc(...) |
/api/v2/tenant/provision/networks |
| Kubernetes | c.cloud.create_kubernetes_cluster(...), c.cloud.list_kubernetes_clusters() |
/api/v2/tenant/provision/kubernetes |
| Serverless | c.cloud.create_serverless_function(...) |
/api/v2/tenant/provision/serverless |
| CI/CD | c.cicd.pipelines.list(), c.cicd.pipelines.trigger(...) |
/api/v2/cicd/... |
| Marketplace | c.marketplace.agents.deploy(...), c.marketplace.models.list() |
/api/v2/marketplace/... |
| AI agents | c.agentcontrol.*, c.vxcomputer.run(...) |
/api/v2/{agentcontrol,vxcomputer}/... |
| Workflows | c.workflow.create(...), c.workflow.execute(...), c.vxchrono.launch_run(...) |
/api/v2/{workflow,vxchrono}/... |
| Sandboxes | c.sandboxes.create(...), c.sandboxes.wait_ready(...), c.sandboxes.extend(...) |
/api/v2/sandboxes/... |
| SalesShift | c.salesshift.search_leads(...), c.salesshift.send_email(...), c.salesshift.list_opportunities(...) |
/api/v1/salesshift/... |
| Custom scripts | c.install.script(host=..., script="#!/bin/bash\n...") |
/api/v2/tenant/install/script |
# Deploy a language stack straight from a public git repo
c.deploy.stack(
"golang",
host="54.197.71.181", ssh_user="ubuntu", key_pair_name="AWSPRODKEY1.PEM",
repo_url="https://github.com/joelwembo/va-sample-golang.git", branch="main",
git_provider="github", app_name="va-sample-golang",
http_port="80", app_port="8080", go_version="1.22",
)
# Trigger a CI/CD pipeline
for p in c.cicd.pipelines.list():
print(p["id"], p["name"])
build = c.cicd.pipelines.trigger(pipeline_id="abc...", branch="main")
# Deploy a marketplace agent
c.marketplace.agents.deploy(
"golang_url_status_agent",
host="54.197.71.181", ssh_user="ubuntu", key_pair_name="AWSPRODKEY1.PEM",
http_port="8094",
)
SalesShift — leads, CRM, campaigns and signals
SalesShift is the go-to-market layer of the platform: the global prospect pool,
the CRM it feeds, tracked email and campaigns, the cross-tenant opportunity
signal pool, tasks, social distribution, and the workspace's own billing. It all
hangs off c.salesshift.
import vxcloud
c = vxcloud.Client.load_from_vxcli()
ss = c.salesshift
# ── Prospect pool ────────────────────────────────────────────────────
# Search returns MASKED addresses (j•••@acme.com). A mask is not an
# address — revealing one spends quota, so price the batch first.
page = ss.search_leads(
filters={"seniority": ["c_level", "vp"], "country": ["AU"]},
limit=50,
)
ids = [p["pool_person_id"] for p in page["results"][:10]]
print(ss.reveal_quota()) # allowance / remaining / unlimited
print(ss.preview_reveal_cost(ids)) # what this batch WOULD cost
try:
print(ss.reveal_lead(ids[0])["email"])
except vxcloud.VxLeadQuotaExhaustedError:
print("allowance spent — you were NOT charged for this attempt")
except vxcloud.VxLeadErasedError:
print("erased at the person's request — terminal, never retry")
# ── Pool → lead → contact ────────────────────────────────────────────
ss.save_leads(ids)
report = ss.convert_from_pool(ids, lifecycle_stage="lead")
# A convert splits into buckets; a partial success reported as success is
# how duplicate contacts get created. Render every bucket.
print(vxcloud.describe_convert(report))
# ── Email, campaigns, signals, tasks ─────────────────────────────────
ss.send_email(to_email="ada@acme.com", subject="Quick question",
body_html="<p>Hi Ada…</p>")
print(ss.get_stats())
opps = ss.list_opportunities(source="hn", min_score=70)
ss.push_opportunity_to_lead(opps["results"][0]["id"])
ss.create_task("Follow up with Ada", goal="Book a 20-min call")
# ── Social distribution ──────────────────────────────────────────────
post = ss.create_social_post("Shipping vxcli 2026.8.13 today.")
job = ss.distribute_post(post["id"])
# Fan-out is one goroutine per network; `speedup` is measured, not claimed.
# `simulated` is true when the deployment holds no social API credentials —
# always surface it rather than reporting a simulated post as published.
for d in job["job"]["deliveries"]:
print(d["channel"], "SIMULATED" if d["simulated"] else "published")
# ── Billing (what the workspace pays for SalesShift) ─────────────────
sub = ss.billing_subscription()
for code, limit in sub["plan"]["quotas"].items():
# None means UNLIMITED. A plain 0 would read as "no allowance" — the
# exact opposite of what the API means.
print(code, "unlimited" if limit is None else limit)
The same surface is available from the CLI, with --output json|yaml on every
command and a confirmation prompt (--yes to skip) on anything that spends or
destroys:
vxcli salesshift leads search --seniority c_level --country AU --limit 25
vxcli salesshift leads quota
vxcli salesshift leads reveal <pool-id>
vxcli salesshift leads convert-from-pool <pool-id>… --lifecycle-stage lead
vxcli salesshift email send --to ada@acme.com --subject "…" --html "<p>…</p>"
vxcli salesshift campaigns report <campaign-id>
vxcli salesshift contacts list
vxcli salesshift opportunities list --source hn --min-score 70
vxcli salesshift tasks add --title "Follow up" --goal "Book a call"
vxcli salesshift social post --content "…"
vxcli salesshift billing plans
Async flavor
Install the extra and switch Client → AsyncClient. Same classes, same
method signatures — just add async/await. Ideal for FastAPI/aiohttp
services and concurrent fan-out (multi-host deploys, batch installs).
import asyncio
import vxcloud_async as vx
async def main():
async with await vx.AsyncClient.load_from_vxcli() as c:
# Three deploys in parallel — ~2.5× faster than sequential
await asyncio.gather(
c.deploy.container(host=h1, ssh_user="ubuntu", key_pair_name=K, image="redis:7", ports=["6381:6379"], name="r1"),
c.deploy.container(host=h2, ssh_user="ubuntu", key_pair_name=K, image="redis:7", ports=["6381:6379"], name="r2"),
c.deploy.container(host=h3, ssh_user="ubuntu", key_pair_name=K, image="redis:7", ports=["6381:6379"], name="r3"),
)
asyncio.run(main())
Error handling
try:
c.cicd.pipelines.list()
except vxcloud.VxAuthError: # 401 / 403
...
except vxcloud.VxValidationError: # 400 / 422
...
except vxcloud.VxRateLimitError as e: # 429 — inspect e.retry_after
...
except vxcloud.VxNotFoundError: # 404
...
except vxcloud.VxServerError: # 5xx
...
except vxcloud.VxNetworkError: # transport-level
...
except vxcloud.VxError: # base class — anything else
...
The client automatically retries transient failures (VxNetworkError,
VxServerError, VxRateLimitError) up to 3 times with exponential backoff,
and transparently refreshes an expired API key on 401 before replaying
the request — so application code rarely sees token expiration. Auth and
validation errors are surfaced immediately.
vxcloud vs. vxsdk
| Same code | vxcloud re-exports every public name from vxsdk — Client, VxCloud, all Vx* errors, every resource class, and the module-level load_from_vxcli() helper. |
| Versioning | Each vxcloud release pins the exact matching vxsdk release, so the surface is deterministic at install time. |
| Which to install | Prefer the brand name? pip install vxcloud. Prefer the canonical name? pip install vxsdk. They are interchangeable. |
SDKs for every stack
Same JSON wire contract, same auth model, same error taxonomy in every language.
| Language | Package | Install |
|---|---|---|
| Python | vxcloud · vxsdk |
pip install vxcloud |
| TypeScript / Node | @vxcloud/sdk |
npm install @vxcloud/sdk |
| Go | github.com/prodxcloud/vxcloud |
go get github.com/prodxcloud/vxcloud |
| C++ | cpp/ |
CMake or drop in two files (libcurl, C++17) |
| Java | java/ |
Maven, io.vxcloud:vxsdk (JDK 11+, zero deps) |
| CLI | vxcli |
curl -fsSL https://vxcloud.io/download/cli/install.sh | sh |
Links
- 📦 PyPI: pypi.org/project/vxcloud · pypi.org/project/vxsdk
- 📖 Documentation: vxcloud.io/docs/sdks
- 🛠️ Source & issues: github.com/prodxcloud/vxcloud
- 📝 Changelog: CHANGELOG.md
Author
Built and maintained by Joel O. Wembo — linkedin.com/in/joelwembo
License
Apache-2.0 © vxcloud / ProdXCloud
Metadata
Release files for vxcloud 2026.10.29
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 | Actions |
|---|---|---|---|---|
| vxcloud-2026.10.29.tar.gz | 10.4 kB | Without provenance | Details for vxcloud-2026.10.29.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| vxcloud-2026.10.29-py3-none-any.whl | Python 3 | none | any | Details for vxcloud-2026.10.29-py3-none-any.whl |
Total release size: 18.5 kB
Release files / vxcloud-2026.10.29.tar.gz
| Download URL | vxcloud-2026.10.29.tar.gz |
|---|---|
| Size | 10.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
24faaa6b729c044d874de1a4a2080af36c4844e6ab9f4be95cacf138cf5d6cb3
|
|
BLAKE2b-256 checksum How to use checksums |
e8c7a398a493269acc7e89eeae17500ffc0aed96950851c21ec54693792b4bbf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.0
|
Release files / vxcloud-2026.10.29-py3-none-any.whl
| Download URL | vxcloud-2026.10.29-py3-none-any.whl |
|---|---|
| Size | 8.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7eeb3e9b17d0e9c54f54d571bbdcee4b5356d319a8b0f02456faafb3e536dc7d
|
|
BLAKE2b-256 checksum How to use checksums |
647e91f2761defb820e9bbb52ba5d5ce316d43db26943872d7b86dddc36196e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.0
|
Security for vxcloud 2026.10.29
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.