Skip to content
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 that the server uses to validate requests. So it cannot drift from what the API accepts. On 25 October 2026, it described 190 operations on 149 paths. Every product is in one file. No key is needed to fetch it. Its info.version is the API version you are using, 0.2.0 on 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 scheme, or oauth2 for the same key got by OAuth sign-in, 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; oauth2: the same key, got by OAuth 2.1 sign-in
components.schemas.Error The one error shape: code, status, message, requestId, hint, retryable, retryAfterMs, 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

The schema itself gives the ranges. For example, the create body sets timeoutSeconds up to 86,400 seconds (24 hours). Its default is 0, which means no time limit. idlePauseSeconds ranges 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, call 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: {} });const { data: run } = await api.POST("/v1/sandboxes/{id}:exec", {  params: { path: { id: sbx.id } },  body: { command: "python3 -c 'print(sum([125, 250, 375]))'" },});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 script 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. They 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. It names every wrong field in one invalid_request response. 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 returns the first result. With a different body, the request is refused with 422.
  • Treating a listed route as switched on. A route in the spec can return 501 unavailable where a capability is off. Check the products page.
  • Calling 0.1.0 routes. They return 410 upgrade_required with details.replacement. See migration.

Sources

Checked 25 October 2026.

Facts on this page were checked on 25 October 2026.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card