Python SDK
Use synchronous and asynchronous typed Python clients for the Openstead core API.
The Openstead Python SDK supports Python 3.10 and newer, with HTTPX transport and Pydantic models. Openstead and AsyncOpenstead expose the same public core resources.
Install
Install the Openstead SDK from the private Python repository. Your GitHub identity needs repository access and an authenticated Git credential helper. Contact Openstead support to request access if the repository is unavailable.
python -m pip install "git+https://github.com/Layerrail/openstead-python.git@32e1ccc913b2dd7ad3d964da46bd63f92e2a6de0"For a local checkout, run python -m pip install . from the repository directory. Pin a reviewed source commit in production dependency files. The SDK is not published on PyPI; never insert a GitHub token into an installation command or dependency file.
The examples below use the Openstead source version. Existing installations can keep using the runivo import and Runivo / AsyncRunivo compatibility aliases after upgrading. OPENSTEAD_API_KEY takes precedence, with RUNIVO_API_KEY retained as a fallback.
Read services
Set OPENSTEAD_API_KEY in your secret environment and OPENSTEAD_WORKSPACE_ID to its workspace UUID.
import os
from openstead import Openstead
with Openstead() as client:
workspace_id = os.environ["OPENSTEAD_WORKSPACE_ID"]
workspace = client.workspaces.get(workspace_id=workspace_id).workspace
print(workspace.name)
for service in client.services.iter(workspace_id=workspace_id):
print(service.name, service.status, service.url)The default API root is https://api.openstead.tech/api/v1. Pass api_key= explicitly to override the environment. Reuse a client in long-lived applications, and close it with a context manager or close().
Async usage
import asyncio
import os
from openstead import AsyncOpenstead
async def main() -> None:
async with AsyncOpenstead() as client:
async for project in client.projects.iter(
workspace_id=os.environ["OPENSTEAD_WORKSPACE_ID"],
):
print(project.id, project.name)
asyncio.run(main())Await endpoint methods; use async for for iterators. Use async with or aclose() to close an asynchronous client.
Create a project
This creates configuration and requires a write key:
import os
from openstead import Openstead
from openstead.models import ProjectCreate
with Openstead() as client:
response = client.projects.create(
workspace_id=os.environ["OPENSTEAD_WORKSPACE_ID"],
data=ProjectCreate(name="example-project", color="violet"),
idempotency_key="create-example-project-001",
)
print(response.project.id)data= accepts typed models or mappings with API field names. Models expose Python snake_case attributes, such as live_deployment_id. Serialize wire names with model_dump(by_alias=True, mode="json") when needed.
Resources and helpers
| Resource | Methods |
|---|---|
catalog | get() |
workspaces | get() |
projects | list(), iter(), get(), create(), update(), delete() |
services | list(), iter(), get(), create(), update(), delete(), archive(), restore(), action() |
variables | list(), iter(), create(), update(), delete(), reveal() |
deployments | list(), iter(), get(), create(), cancel(), rollback(), wait() |
operations | get(), wait() |
logs | list(), iter(), tail() |
Use client.get_openapi() to retrieve the public contract. Endpoint responses keep their named envelope; iterator and wait helpers yield or return the contained model.
Poll an existing deployment
import os
from openstead import DeploymentFailed, PollTimeout, Openstead
with Openstead() as client:
try:
deployment = client.deployments.wait(
workspace_id=os.environ["OPENSTEAD_WORKSPACE_ID"],
service_id=os.environ["OPENSTEAD_SERVICE_ID"],
deployment_id=os.environ["OPENSTEAD_DEPLOYMENT_ID"],
timeout=300.0,
poll_interval=2.0,
)
print(deployment.status)
except DeploymentFailed:
print("Review this deployment's logs before deploying again.")
except PollTimeout:
print("The wait ended. Read the existing deployment for its current state.")Waits default to 600 seconds and a two-second interval. A local cancellation or timeout ends observation, not the remote deployment. operations.wait() returns at complete and raises OperationFailed on failure.
Retry configuration and errors
The client defaults to a 20-second request timeout, at most two retries, and a 30-second retry window. Configure timeout, max_retries, and max_retry_elapsed at construction. Supported writes receive a key automatically; provide a durable idempotency_key for retries across separate calls.
import os
from openstead import APIError, Openstead, TransportError
try:
with Openstead(max_retries=2) as client:
client.projects.list(workspace_id=os.environ["OPENSTEAD_WORKSPACE_ID"], limit=100)
except APIError as exc:
print(exc.status_code, exc.code, exc.request_id)
except TransportError:
print("The API request could not complete within its retry limits.")Use APIError.errors only when you need the server's detailed messages. Do not log whole requests, responses, or secret models. Secret reveal is an explicit audited operation with no automatic retries. See retry rules and log reading.
Reveal a variable with an audit event POST
Developer role or above, plus protected-environment checks. This secret-bearing operation is explicitly excluded from idempotent replay; sending an idempotency key is rejected. Never log this response.
TypeScript SDK
Call the Openstead core API from Node.js with typed resources, async iterators, and cancellation.