Runtime

How to use Runtime's OpenAPI spec

Download https://api.withruntime.com/v1/openapi.json, an OpenAPI 3.1 document of every route, and feed it to a client generator.

Runtime's OpenAPI document is generated from the same route definitions the server validates requests with, so it cannot drift from what the API accepts. On 25 September 2026 it described 143 operations on 116 paths, every product in one file, with no key needed to fetch it. Its info.version is the API version you are talking to, 0.2.0 that day (API reference).

Fetch it

Terminalcurl -sS https://api.withruntime.com/v1/openapi.json -o runtime-openapi.jsonjq -r '.info.version' runtime-openapi.json          # 0.2.0jq -r '.paths | keys[]' runtime-openapi.json | head  # /v1/me, /v1/usage, /v1/sandboxes ...

The document needs no authentication. The API it describes does: the document's default security is the bearer security scheme, so send Authorization: Bearer <key>.

What is in it

Part What you find
openapi 3.1.0
info.version The API version, 0.2.0
servers https://api.withruntime.com
components.securitySchemes bearer: HTTP bearer auth
components.schemas.Error The one error shape: code, status, message, requestId, hint, details
paths Every route, with operationId such as sandboxes.create or audit.list
Operation tags One per product: sandboxes, files, commands, images, volumes and the rest
Parameters Idempotency-Key on writes, with the pattern it must match
Request schemas Every field with its default, range and a description, unknown fields refused
x-mcp-tools The MCP server's tools, each with its name, description and input schema

Ranges are in the schema itself. The create body, for instance, gives timeoutSeconds from 60 to 3600 with a default of 1800, and idlePauseSeconds from 0 to 86,400.

Generate TypeScript types

openapi-typescript reads OpenAPI 3.0 and 3.1 and writes a .d.ts file:

Terminalnpx openapi-typescript https://api.withruntime.com/v1/openapi.json -o ./runtime-api.d.tsnpm install openapi-fetch

Then openapi-fetch makes typed calls. In TypeScript, write createClient<paths>(...) with paths imported from the generated file; plain JavaScript looks like this:

JavaScriptimport createClient from "openapi-fetch";const api = createClient({  baseUrl: "https://api.withruntime.com",  headers: { Authorization: `Bearer ${process.env.RUNTIME_API_KEY}` },});const { data: sbx } = await api.POST("/v1/sandboxes", { body: { funding: "trial" } });const { data: run } = await api.POST("/v1/sandboxes/{id}:exec", {  params: { path: { id: sbx.id } },  body: { command: "python3 -c 'print(6 * 7)'" },});console.log(run.stdout);await api.POST("/v1/sandboxes/{id}:stop", { params: { path: { id: sbx.id } } });

Read it from a script

The spec is plain JSON, so any language can list what the API offers. This prints each product and its operations:

Pythonimport jsonimport urllib.requestfrom collections import defaultdictwith urllib.request.urlopen("https://api.withruntime.com/v1/openapi.json") as response:    spec = json.load(response)by_tag = defaultdict(list)for path, methods in spec["paths"].items():    for method, op in methods.items():        for tag in op.get("tags", []):            by_tag[tag].append(f"{method.upper()} {path}  ({op['operationId']})")print(spec["info"]["version"])for tag in sorted(by_tag):    print(tag, len(by_tag[tag]))

Prefer the SDKs where there is one

For JavaScript, TypeScript and Python, the official SDKs are thin layers over this same API and add what a generated client lacks: an idempotency key on every write and retries with it, a create that waits for capacity, streaming, resumable uploads and typed errors. A generated client is the right tool for Go, Rust, Java, a language with no SDK, or an API gateway that imports OpenAPI.

Mistakes and how Runtime handles them

  • Generating once and never again. New products add paths. Regenerate on each upgrade and compare info.version.
  • Adding fields the schema does not list. The server refuses unknown fields and names every wrong one in one invalid_request answer, so a typo fails loudly instead of being ignored.
  • Retrying writes from a generated client with no key. Send your own Idempotency-Key header on writes. The same key with the same body answers the first result; with a different body it is refused with 422.
  • Treating a listed route as switched on. A route in the spec can answer 503 unavailable where a capability is off. Check the products page.
  • Calling 0.1.0 routes. They answer 410 upgrade_required with details.replacement; see migration.

Sources

Checked 25 September 2026.

Facts on this page were checked on 25 September 2026.