# 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](/docs/api)). ## Fetch it ```bash no-run curl -sS https://api.withruntime.com/v1/openapi.json -o runtime-openapi.json jq -r '.info.version' runtime-openapi.json # 0.2.0 jq -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 `. ## 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](https://openapi-ts.dev/introduction) reads OpenAPI 3.0 and 3.1 and writes a `.d.ts` file: ```bash no-run npx openapi-typescript https://api.withruntime.com/v1/openapi.json -o ./runtime-api.d.ts npm install openapi-fetch ``` Then [openapi-fetch](https://openapi-ts.dev/openapi-fetch/) makes typed calls. In TypeScript, call `createClient(...)`, with `paths` imported from the generated file. Plain JavaScript looks like this: ```js import 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: ```python check import json import urllib.request from collections import defaultdict with 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](/docs/products). - **Calling 0.1.0 routes.** They return 410 `upgrade_required` with `details.replacement`. See [migration](/docs/migrate). ## Related - [How to call the REST API with curl](/how-to/call-the-rest-api-with-curl) - [Runtime Cloud MCP](/docs/mcp), whose tools the spec also lists - [Model Context Protocol](/glossary/model-context-protocol) - [JavaScript SDK](/docs/javascript) and [Python SDK](/docs/python) ## Sources Checked 25 October 2026. - [Runtime OpenAPI document](https://api.withruntime.com/v1/openapi.json), fetched and counted that day - [openapi-typescript introduction](https://openapi-ts.dev/introduction) - [openapi-fetch](https://openapi-ts.dev/openapi-fetch/) and its [API](https://openapi-ts.dev/openapi-fetch/api) Facts on this page were checked on 25 October 2026.