Skip to main content

Cyberdesk Python SDK

The official Python SDK for Cyberdesk API. This SDK provides a clean, type-safe interface for interacting with all Cyberdesk resources including machines, workflows, runs, connections, and trajectories.

Installation

# Basic SDK installation
pip install cyberdesk

# With testing utilities
pip install "cyberdesk[testing]"

# All development dependencies (for SDK contributors)
pip install "cyberdesk[all]"

Quick Start

The most common use case is to execute workflows that you've created in the Cyberdesk Dashboard.

from cyberdesk import CyberdeskClient, RunCreate
import time

# Initialize the client
client = CyberdeskClient(api_key="your-api-key")

# Create a run for your workflow
run_data = RunCreate(
    workflow_id="your-workflow-id",
    machine_id="your-machine-id",
    input_values={
        # Your workflow-specific input data
        "patient_id": "12345",
        "patient_first_name": "John",
        "patient_last_name": "Doe"
    }
)

response = client.runs.create_sync(run_data)
if response.error:
    print(f"Error creating run: {response.error}")
else:
    run = response.data
    
    # Wait for the run to complete
    while run.status in ["scheduling", "running"]:
        time.sleep(5)  # Wait 5 seconds
        response = client.runs.get_sync(run.id)
        run = response.data
    
    # Get the output data
    if run.status == "success":
        print("Result:", run.output_data)
    else:
        print("Run failed:", ", ".join(run.error or []))

Desktop Parameters

Configure machine-specific values that automatically populate workflows running on specific desktops:

from cyberdesk import MachineUpdate

# Set desktop parameters for a machine
client.machines.update_sync(
    machine_id="machine-id",
    data=MachineUpdate(
        machine_parameters={
            "username": "machine_specific_user",
            "api_url": "https://api-region-east.example.com",
            "config_path": "C:\\MachineA\\config.json"
        },
        machine_sensitive_parameters={
            "password": "actual_secret_value",  # Stored securely in Basis Theory
            "api_key": "actual_api_key_123"
        }
    )
)

Use in workflows with standard syntax:

Log in to {api_url} using {username} and password {$password}.
Then open the config at {config_path}.

Desktop parameters automatically override run-level inputs and persist across runs. See the Desktop Parameters docs for more details.

Full Documentation

For complete documentation including async/sync usage, error handling, and all available methods, visit:

https://docs.cyberdesk.io/sdk-guides/python

Async Support

The SDK provides both synchronous and asynchronous methods for all operations:

import asyncio
from cyberdesk import CyberdeskClient

async def main():
    client = CyberdeskClient(api_key="your-api-key")
    
    # Async method
    response = await client.machines.list()
    if response.data:
        for machine in response.data.items:
            print(f"Machine: {machine.name}")

asyncio.run(main())

Resources

Machines

# List machines
response = client.machines.list_sync(
    skip=0,
    limit=10,
    status=MachineStatus.ACTIVE
)

# Get a specific machine
response = client.machines.get_sync("machine-id")

# Create a machine
from cyberdesk import MachineCreate

machine = MachineCreate(
    name="My Machine",
    provider="azure",
    region="eastus"
)
response = client.machines.create_sync(machine)

# Update a machine
from cyberdesk import MachineUpdate

update = MachineUpdate(name="Updated Name")
response = client.machines.update_sync("machine-id", update)

# Delete a machine
response = client.machines.delete_sync("machine-id")

Workflows

# List workflows
response = client.workflows.list_sync()

# Get a workflow
response = client.workflows.get_sync("workflow-id")

# Create a workflow
from cyberdesk import WorkflowCreate

workflow = WorkflowCreate(
    name="My Workflow",
    description="Description"
)
response = client.workflows.create_sync(workflow)

# Update a workflow
from cyberdesk import WorkflowUpdate

update = WorkflowUpdate(description="New description")
response = client.workflows.update_sync("workflow-id", update)

# Delete a workflow
response = client.workflows.delete_sync("workflow-id")

Runs

# List runs with filtering
response = client.runs.list_sync(
    workflow_id="workflow-id",
    machine_id="machine-id",
    status=RunStatus.RUNNING
)

# Create a run
from cyberdesk import RunCreate

run = RunCreate(
    workflow_id="workflow-id",
    machine_id="machine-id"
)
response = client.runs.create_sync(run)

# Get run details
response = client.runs.get_sync("run-id")

# Update run status
from cyberdesk import RunUpdate

update = RunUpdate(status=RunStatus.COMPLETED)
response = client.runs.update_sync("run-id", update)

Connections

# List connections
response = client.connections.list_sync(
    machine_id="machine-id",
    status=ConnectionStatus.ACTIVE
)

# Create a connection
from cyberdesk import ConnectionCreate

connection = ConnectionCreate(
    machine_id="machine-id",
    connection_type="vnc"
)
response = client.connections.create_sync(connection)

Trajectories

# List trajectories
response = client.trajectories.list_sync(workflow_id="workflow-id")

# Create a trajectory
from cyberdesk import TrajectoryCreate

trajectory = TrajectoryCreate(
    workflow_id="workflow-id",
    trajectory_data=[{"action": "click", "x": 100, "y": 200}]
)
response = client.trajectories.create_sync(trajectory)

# Get latest trajectory for a workflow
response = client.trajectories.get_latest_for_workflow_sync("workflow-id")

# Update a trajectory
from cyberdesk import TrajectoryUpdate

update = TrajectoryUpdate(
    trajectory_data=[{"action": "type", "text": "Hello"}]
)
response = client.trajectories.update_sync("trajectory-id", update)

Error Handling

All methods return an ApiResponse object with data and error attributes:

response = client.machines.get_sync("invalid-id")
if response.error:
    print(f"Error: {response.error}")
else:
    print(f"Machine: {response.data.name}")

Context Manager

The client can be used as a context manager:

with CyberdeskClient(api_key="your-api-key") as client:
    response = client.machines.list_sync()
    # Client will be properly closed when exiting the context

Configuration

You can specify a custom API base URL:

client = CyberdeskClient(
    api_key="your-api-key",
    base_url="https://custom-api.cyberdesk.io"
)

Type Safety

The SDK is fully typed and exports all request/response models:

from cyberdesk import (
    MachineCreate,
    MachineUpdate,
    MachineResponse,
    MachineStatus,
    WorkflowCreate,
    WorkflowResponse,
    RunCreate,
    RunStatus,
    # ... and more
)

Webhooks

Handling Webhooks

Cyberdesk sends webhooks when important events occur (e.g., workflow completion). To handle webhooks:

import json
import os
from fastapi import FastAPI, Request, HTTPException
from svix.webhooks import Webhook, WebhookVerificationError
from openapi_client.cyberdesk_cloud_client.models.run_completed_event import RunCompletedEvent
from openapi_client.cyberdesk_cloud_client.models.run_response import RunResponse
from typing import cast

app = FastAPI()

@app.post("/webhooks/cyberdesk")
async def cyberdesk_webhook(request: Request):
    secret = os.environ["SVIX_WEBHOOK_SECRET"]
    wh = Webhook(secret)
    
    payload = await request.body()
    headers = {
        "svix-id": request.headers.get("svix-id"),
        "svix-timestamp": request.headers.get("svix-timestamp"),
        "svix-signature": request.headers.get("svix-signature"),
    }
    
    try:
        wh.verify(payload, headers)
        data = json.loads(payload)
        # IMPORTANT: Use from_dict() for attrs classes, NOT model_validate()
        evt = RunCompletedEvent.from_dict(data)
        run: RunResponse = cast(RunResponse, evt.run)
        
        # Process the run based on status
        if run.status == "success":
            print(f"Run {run.id} completed successfully!")
            print(f"Output: {run.output_data}")
        
        return {"ok": True}
    except WebhookVerificationError:
        raise HTTPException(status_code=400, detail="Invalid signature")

Important: The SDK uses attrs classes (not Pydantic), so use RunCompletedEvent.from_dict(data) instead of model_validate(data).

Testing Webhooks Locally

See tests/webhooks/WEBHOOK_TESTING.md for a complete guide on testing webhooks locally without exposing your server to the internet.

Quick start:

# Install SDK with testing dependencies
pip install "cyberdesk[testing]"

# Set up .env file
cp .env.example .env
# Edit .env with your SVIX_WEBHOOK_SECRET

# Run the example webhook handler
python -m uvicorn tests.webhooks.example_webhook_handler:app --reload

# In another terminal, test it
python -m tests.webhooks.test_webhook_local

Example Files

All webhook testing resources are in the tests/webhooks/ directory:

  • tests/webhooks/example_webhook_handler.py - Complete, production-ready webhook handler
  • tests/webhooks/test_webhook_local.py - Utility to test webhooks locally
  • tests/webhooks/test_webhook_integration.py - pytest integration tests
  • tests/webhooks/WEBHOOK_TESTING.md - Comprehensive testing guide
  • tests/webhooks/WEBHOOK_QUICKSTART.md - Quick reference guide

Testing

The SDK includes comprehensive testing utilities:

Quick Test

# Install with test dependencies
pip install ".[testing]"

# Set up environment
cp .env.example .env
# Edit .env with your credentials

# Run all tests
pytest tests/ -v

Test Categories

  • Webhook Tests (tests/webhooks/) - Test webhook handlers locally, no real API
  • Integration Tests (tests/integration/) - Test SDK with real API calls

See TESTING.md for complete testing documentation.

Limitations

  • Screenshot API: The /v1/computer/{machine_id}/display/screenshot endpoint is not included in the generated client due to limitations with binary (PNG) responses in the openapi-python-client generator. This can be added manually if needed - see the TODO comment in client.py.

Requirements

  • Python 3.8+
  • httpx
  • attrs (used by the auto-generated OpenAPI client)

License

MIT License - see LICENSE file for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cyberdesk-2.2.67.tar.gz (162.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cyberdesk-2.2.67-py3-none-any.whl (476.6 kB view details)

Uploaded Python 3

File details

Details for the file cyberdesk-2.2.67.tar.gz.

File metadata

  • Download URL: cyberdesk-2.2.67.tar.gz
  • Upload date:
  • Size: 162.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cyberdesk-2.2.67.tar.gz
Algorithm Hash digest
SHA256 156d994bb893f8acf03d6057cee2cd623fb2e54789fcf45bb5c1f2957ff647f9
MD5 6ea67002ef5120a54fc5c1d079a75315
BLAKE2b-256 8889965094b3fdee75cce86126dd38372e49cf767bbf72e4d2d9e80008175989

See more details on using hashes here.

Provenance

The following attestation bundles were made for cyberdesk-2.2.67.tar.gz:

Publisher: publish-sdks.yml on cyberdesk-hq/cyberdesk-new

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cyberdesk-2.2.67-py3-none-any.whl.

File metadata

  • Download URL: cyberdesk-2.2.67-py3-none-any.whl
  • Upload date:
  • Size: 476.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cyberdesk-2.2.67-py3-none-any.whl
Algorithm Hash digest
SHA256 36825b26bb44c3e27b1ed2c29b4711f11ff6ba7a90fe7d11158f70aea739da7c
MD5 70c4856ffe036f216a9ef5b69336aca5
BLAKE2b-256 7403a3e9c39ce85e84443432f3871d845217ab846125a4b0cc6b5e4b0802396b

See more details on using hashes here.

Provenance

The following attestation bundles were made for cyberdesk-2.2.67-py3-none-any.whl:

Publisher: publish-sdks.yml on cyberdesk-hq/cyberdesk-new

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

2.2.67 This release

2 files

2.2.66

2 files

2.2.64

2 files

2.2.62

2 files

2.2.61

2 files

2.2.60

2 files

2.2.59

2 files

2.2.58

2 files

2.2.57

2 files

2.2.56

2 files

2.2.53

2 files

2.2.52

2 files

2.2.50

2 files

2.2.49

2 files

2.2.48

2 files

2.2.47

2 files

2.2.46

2 files

2.2.45

2 files

2.2.44

2 files

2.2.43

2 files

2.2.42

2 files

2.2.41

2 files

2.2.40

2 files

2.2.39

2 files

2.2.38

2 files

2.2.37

2 files

2.2.36

2 files

2.2.35

2 files

2.2.34

2 files

2.2.33

2 files

2.2.32

2 files

2.2.31

2 files

2.2.30

2 files

2.2.29

2 files

2.2.28

1 file

2.2.27

2 files

2.2.26

2 files

2.2.25

2 files

2.2.24

2 files

2.2.22

2 files

2.2.21

2 files

2.2.20

2 files

2.2.19

2 files

2.2.18

2 files

2.2.17

2 files

2.2.16

2 files

2.2.15

2 files

2.2.14

2 files

2.2.13

2 files

2.2.12

2 files

2.2.11

2 files

2.2.10

2 files

2.2.9

2 files

2.2.8

2 files

2.2.7

2 files

2.2.6

2 files

2.2.5

2 files

2.2.4

2 files

2.2.3

2 files

2.2.2

2 files

2.2.1

2 files

2.2.0

2 files

2.1.21

2 files

2.1.20

2 files

2.1.19

2 files

2.1.18

2 files

2.1.17

2 files

2.1.16

2 files

2.1.15

2 files

2.1.14

2 files

2.1.13

2 files

2.1.12

2 files

2.1.11

2 files

2.1.10

2 files

2.1.9

2 files

2.1.8

2 files

2.1.7

2 files

2.1.6

2 files

2.1.5

2 files

2.1.4

2 files

2.1.3

2 files

2.1.2

2 files

2.1.1

2 files

2.1.0

2 files

2.0.0

2 files

1.11.0

2 files

1.10.0

2 files

1.9.0

2 files

1.8.0

2 files

1.7.0

2 files

1.6.0

2 files

1.5.0

2 files

1.4.1

2 files

1.4.0

2 files

1.3.0

2 files

1.2.0

2 files

1.0.0

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page