Python SDK
The official Python SDK for the WAYSCloud API. One client, nine services, typed exceptions, automatic retries, and connection pooling.
bash
pip install wayscloudRequires Python 3.10+. PyPI page.
Authentication
python
from wayscloud import WaysCloudClient
# Personal Access Token
client = WaysCloudClient(token="wayscloud_pat_xxx...")
# API key
client = WaysCloudClient(api_key="wayscloud_api_xxx...")
# Environment variables (no args needed)
# Set WAYSCLOUD_TOKEN or WAYSCLOUD_API_KEY
client = WaysCloudClient()Priority: explicit arguments > environment variables.
| Parameter | Environment variable | Default |
|---|---|---|
token | WAYSCLOUD_TOKEN | — |
api_key | WAYSCLOUD_API_KEY | — |
base_url | WAYSCLOUD_API_URL | https://api.wayscloud.services |
timeout | — | 30.0 |
Services
| Service | Property | Description |
|---|---|---|
| VPS | client.vps | Virtual private servers |
| DNS | client.dns | DNS zones and records |
| Storage | client.storage | S3-compatible object storage |
| Database | client.database | Managed PostgreSQL & MariaDB |
| Redis | client.redis | Managed Redis |
| Apps | client.apps | App Platform (containers) |
| IoT | client.iot | IoT device management |
| SMS | client.sms | SMS messaging |
| Account | client.account | Profile and SSH keys |
Examples
VPS
python
# List instances
for vm in client.vps.list():
print(vm["hostname"], vm["status"])
# Create
vps = client.vps.create(
hostname="web01.example.com",
plan="vps-medium",
region="no",
os_template="ubuntu-24.04",
)
# Lifecycle
client.vps.start(vps["id"])
client.vps.stop(vps["id"])
client.vps.delete(vps["id"])DNS
python
client.dns.create_zone("example.com")
client.dns.create_record(
"example.com",
record_type="A",
name="www",
value="192.0.2.1",
ttl=3600,
)Database
python
db = client.database.create(name="prod", db_type="postgresql")
creds = client.database.credentials("postgresql", "prod")
print(creds["connection_string"])Storage
python
client.storage.create_bucket("my-bucket")
creds = client.storage.credentials()Redis
python
instance = client.redis.create(name="cache", plan="redis-starter")
creds = client.redis.credentials(instance["id"])Apps
python
app = client.apps.create(name="my-app", region="eu", port=8080)
client.apps.deploy(app["id"], image="ghcr.io/org/app:latest")IoT
python
device = client.iot.create_device(
device_id="sensor-01",
name="Temperature Sensor",
)
creds = client.iot.device_credentials("sensor-01")SMS
python
client.sms.send(to="+4712345678", message="Hello from WAYSCloud")Error handling
python
from wayscloud import NotFoundError, AuthenticationError, ValidationError, ServerError
try:
client.vps.get("nonexistent")
except NotFoundError:
print("Resource not found")
except AuthenticationError:
print("Invalid or expired credentials")
except ValidationError:
print("Invalid request parameters")
except ServerError:
print("Server error — retry later")All exceptions inherit from WaysCloudError with status_code, message, and detail.
| Exception | HTTP Status |
|---|---|
AuthenticationError | 401, 403 |
NotFoundError | 404 |
ValidationError | 422 |
ServerError | 5xx |
Connection management
The SDK uses a persistent HTTP client for connection pooling:
python
with WaysCloudClient(token="wayscloud_pat_xxx...") as client:
zones = client.dns.zones()
vps = client.vps.list()
# Connections released hereOr close manually:
python
client = WaysCloudClient()
try:
data = client.vps.list()
finally:
client.close()Retries
Automatic retries on 429, 502, 503, 504 — up to 3 attempts with exponential backoff. Respects Retry-After headers.
Next steps
- CLI — command-line interface built on this SDK
- Terraform Provider — infrastructure as code
- Python examples — using the REST API directly
Kubernetes
client.kubernetes manages Managed Kubernetes clusters (PAT with kubernetes:read / kubernetes:write). Create and delete are asynchronous — use wait().
python
# Catalogue
client.kubernetes.plans(region="no", kind=None)
client.kubernetes.regions()
client.kubernetes.versions()
client.kubernetes.estimate(plan_code, node_pools, currency="NOK", region="no")
# Clusters
client.kubernetes.list()
client.kubernetes.get(cluster_id)
client.kubernetes.create(name, node_pools, plan_code="k8s-cluster-dev", region="no",
version="1.34", api_ip_filter=None, ssh_key_ids=None)
client.kubernetes.wait(cluster_id, timeout=1800, interval=15)
client.kubernetes.delete(cluster_id, confirm_name)
client.kubernetes.history(cluster_id)
# Node pools
client.kubernetes.add_node_pool(cluster_id, name, plan_code, count, labels=None, taints=None)
client.kubernetes.scale_node_pool(cluster_id, pool_name, count)
client.kubernetes.delete_node_pool(cluster_id, pool_name)
# Access
client.kubernetes.kubeconfig(cluster_id) # YAML text — a secret
client.kubernetes.set_api_access(cluster_id, cidrs)
# Public IPs and reverse DNS
client.kubernetes.allocate_ip(cluster_id)
client.kubernetes.release_ip(cluster_id, address)
client.kubernetes.set_ptr(cluster_id, address, ptr_record)
# Backups
client.kubernetes.backup_policy(cluster_id)
client.kubernetes.set_backup_policy(cluster_id, enabled=True, schedule_cron="0 3 * * *",
retention_days=14, include_volumes=True, namespaces=None)
client.kubernetes.backups(cluster_id)
client.kubernetes.backup_now(cluster_id, namespaces=None)
client.kubernetes.restore(cluster_id, backup_id, namespaces=None)
# Upgrades
client.kubernetes.available_upgrades(cluster_id)
client.kubernetes.upgrade(cluster_id, version)Full reference: Kubernetes API.