Skip to main content

platinum-sdk (Python)

Python client for Platinum — hardware-isolated sandbox microVMs (one Cloud Hypervisor VM per sandbox, sub-second boots via a warm pool).

pip install platinum-sdk     # import name: platinum

Python ≥ 3.9, typed (PEP 561 — ships py.typed; mypy --strict clean). Sync and async clients. Server-side use only — never ship an API key into client-side code.

Quickstart

from platinum import Platinum

dn = Platinum(token="pt_live_...", api_url="https://api.platinum.dev")
# or: PT_TOKEN / PT_API_URL env vars

# Pick a template that exists on YOUR deployment first:
print(dn.templates.list())

sbx = dn.sandboxes.create(template="pt-base", wait_for_running=True)
r = sbx.exec(["uname", "-a"]).check()     # .check() raises on non-zero exit
print(r.stdout)
sbx.delete()

Async — a full 1:1 mirror of the sync surface:

from platinum import AsyncPlatinum

async with AsyncPlatinum(token="pt_live_...", api_url="https://api.platinum.dev") as dn:
    sbx = await dn.sandboxes.create(template="pt-base", wait_for_running=True)
    r = await sbx.exec("uname -a")        # argv list or plain string
    print(r.stdout)
    await sbx.delete()

Expose a port at create time (URL comes back in the same response):

sbx = dn.sandboxes.create(
    template="pt-base",
    expose=[{"port": 8080, "public": True}],
    wait_for_running=True,
)
print(sbx.exposed_url(8080))

Build a custom image inline (cache-hit on repeat, built on first use):

from platinum import Platinum, Template

dn = Platinum()
image = (Template.from_python_image("3.12-slim")
                 .pip_install(["fastapi", "uvicorn"])
                 .workdir("/app"))
sbx = dn.sandboxes.create(image=image, wait_for_running=True, wait_timeout_ms=600_000)

Configuration

Arg / env Default Meaning
token / PT_TOKEN — (required) API key pt_live_…, org-scoped bearer token
api_url / PT_API_URL http://127.0.0.1:3000 Control-plane URL
timeout 60.0 Per-request timeout in seconds (file transfer calls override per call)
transport — httpx transport override (e.g. httpx.MockTransport in tests)

Errors

Everything the SDK raises extends PlatinumError (.status, .body, .code — the API's machine-readable error code, also folded into str(err)):

from platinum import NotFoundError, ConflictError, RateLimitError

try:
    sbx.exec("true")
except NotFoundError:            # sandbox gone
    ...
except ConflictError as e:       # e.g. e.code == "sandbox_not_running"
    ...
except RateLimitError as e:      # back off e.retry_after_seconds — the SDK never retries
    ...

Subclasses: ValidationError (400) · AuthenticationError (401) · ForbiddenError (403) · NotFoundError (404) · ConflictError (409) · RateLimitError (429) · ServerError (5xx) · PlatinumTimeoutError / PlatinumConnectionError (client-side, status == 0). No automatic retries, ever — a 429 or a failed create is surfaced, never silently retried.

Surface (at parity with the TypeScript SDK)

The two SDKs expose the same operations — enforced in CI by verify/sdk-parity.sh (name-level) and the offline unit suites (behaviour). The async client mirrors the sync surface 1:1 (enforced by tests/test_unit.py::test_async_mirrors_sync_surface).

Area Methods
Sandboxes sandboxes.create(...) · get · connect · list · iter (auto-pagination) · rename · delete
Lifecycle stop/start (optional server-side wait) · pause/resume · kill · resize · fork · clone · snapshot · list_snapshots · delete_snapshot · restore · restore_from_backup · archive · backup · wait_running · wait_state · refresh
Run exec(argv | str) · sh(script) · run_code(code, lang=None) — defaults to the sandbox's create-time language
Processes process.start(cmd, cwd=, env=, pty=, cols=, rows=, timeout_ms=) · process.list() · process.get(handle) — the handle has logs · stream · stdin/close_stdin · signal · kill · resize · wait · refresh
Files (vsock) files.read/write/delete/list/stat/mkdir/exists · find (glob) · grep (content) · replace (bulk sed) · watch (generator of change events)
Networking expose(port, public=, ttl_seconds=) · unexpose · exposed_url · revoke_expose_token · set_egress_policy · add_ssh_keys
Observability metrics() (live cpu/mem/disk) · usage() (billed usage)
Platform templates.list/get/delete · Template builder · webhooks.* · regions.list() · me() · health.check()
Results ExecResult(stdout, stderr, exit_code, duration_ms, lang) with .check()

Run something that outlives the call — exec kills its process group the moment it returns, process.start does not:

p = sbx.process.start(["python", "-m", "http.server", "8000"], cwd="/workspace")
print(p.handle, p.pid)

for chunk in p.stream():            # resumes at the last byte if the socket drops
    if chunk.type in ("stdout", "stderr"):
        if chunk.dropped:           # the ring buffer evicted bytes — a HOLE, not a stat
            print(f"[{chunk.dropped} bytes lost]")
        print(chunk.data, end="")   # str, decoded here — a split emoji arrives whole
    elif chunk.type == "reconnect":  # incl. the server's 30-min cap: it keeps going
        print(f"[resumed at {chunk.stdout_offset}: {chunk.reason}]")
    elif chunk.type == "exit":      # the only terminal event — the loop ends here
        print("exit", chunk.exit_code)

p.signal("SIGTERM")                 # or p.kill() — the record (logs + exit code) is kept

Reconnect to it later from anywhere — reads are by absolute byte offset, so nothing is replayed and nothing is lost:

p = sbx.process.get(handle)
out = p.logs(stdout_offset=my_last_offset)
print(out.stdout, out.stdout_offset, out.running, out.exit_code)

raw = p.logs(encoding="base64").stdout       # bytes, not str — binary-safe

Interactive PTY (stdin also delivers control characters), and a server-side wait:

sh = sbx.process.start("bash -i", pty=True, cols=120, rows=40)
sh.stdin("ls -la\n")
sh.resize(100, 30)
sh.stdin(b"\x03")                   # ^C

done = sbx.process.start(["make", "build"]).wait(timeout_ms=600_000)
print(done.exit_code)

Async is the same surface with await / async for (await sbx.process.start(...), async for chunk in p.stream()). Managed processes need an in-VM agent that implements them; an older guest answers 409 managed_procs_unsupported and exec still works.

Watch for file changes:

for ev in sbx.files.watch("/workspace", max_seconds=60):
    if ev["event"] == "change":
        print(ev["data"]["type"], ev["data"]["path"])

Not wrapped yet: interactive terminal (WebSocket), cross-host migrate (admin-only), API-key management, audit-log queries, billing.

Limits worth knowing

  • files.write bodies must stay ≤ 16 MiB — larger writes currently truncate and fail through the vsock path. Split big files into ≤ 16 MiB chunks, or fetch them directly inside the sandbox (exec with wget).
  • exec/run_code are buffered, not streaming — output arrives after the command exits (default timeout 30 s via timeout_ms). run_code source is capped at 1 MiB.
  • Template names and minimums are per-deployment. pt-base (busybox — no git/pip/node/httpd inside; nc/wget available) exists on default installs; hosted deployments may only offer other templates with higher cpu/ram minimums. Call templates.list() first; a below-minimum create fails with a clear 400.
  • Background processes are reaped when their exec call returns. Use sbx.process.start(...) for anything that has to keep running — it is owned by the guest agent, not by the request, and its output and exit code stay readable. The old workaround (setsid sh -c '<server loop>' >/dev/null 2>&1 < /dev/null &, see examples/02_expose_service.py) still works but loses both.

Testing

pip install -e '.[test]' && pytest runs the offline unit suite (httpx.MockTransport, no network). The live e2e is opt-in: PT_E2E=1 PT_API_URL=… PT_TOKEN=… pytest test_e2e.py.

Examples

Runnable scripts in examples/:

pip install platinum-sdk
PT_API_URL=… PT_TOKEN=… python packages/sdk-py/examples/01_create_exec_delete.py

License

MIT

Release files for platinum-sdk 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for platinum-sdk 0.5.0
File Size Uploaded
platinum_sdk-0.5.0.tar.gz 98.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for platinum-sdk 0.5.0
File Interpreter ABI Platform
platinum_sdk-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 169.7 kB

Release files / platinum_sdk-0.5.0.tar.gz

Download URL platinum_sdk-0.5.0.tar.gz
Size 98.5 kB
Tags Source
SHA-256 checksum
How to use checksums
f4e9b85558c2350f06342cdd491534708d582d81faca4d22e205853446223f9f
BLAKE2b-256 checksum
How to use checksums
eb21d479bc510e05e7823e0c84ba79de5fa52dc31f97c0c93b91c5187d1262b7
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 Sep 25, 2026.

Transparency log

Release files / platinum_sdk-0.5.0-py3-none-any.whl

Download URL platinum_sdk-0.5.0-py3-none-any.whl
Size 71.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
59390e22086fbb8532a318692f7c84d854abf34a56976bfc8e79b65c52aa61ec
BLAKE2b-256 checksum
How to use checksums
9e497e3fb8ade91aeab6ffabd1ba1d9f7e36940f3bf656d9de708f3a2d36ed63
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 Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release 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