SDKs
raw.computer has an SDK for TypeScript and one for Python. Both are generated from the API's
OpenAPI document, so every operation of the HTTP API is a typed
method of theirs, named by its operationId, and both behave the same way: the version they were made from on every
request, an Idempotency-Key on every POST, retries as Retry-After says, and one typed error.
Early access: the packages are not on npm or PyPI yet. They will be
npm install rawcomputerandpip install rawcomputer. Until then, use the HTTP API or the CLI, which do the same.
TypeScript
For Node 20 or later, Bun, Deno, Workers and browsers: anywhere fetch runs.
import { Raw, RawError } from 'rawcomputer';
const raw = new Raw(); // RAW_API_KEY, or RAW_TOKEN with RAW_WORKSPACE
const me = await raw.getMe();
const acting = me.workspace ? `${me.workspace.code} (${me.workspace.id})` : 'no workspace';
console.log(
`me: ${me.user.email} with a ${me.api_key.kind} key, in ${acting}, API version ${me.raw_version}`
);
for (const workspace of (await raw.listWorkspaces()).data)
console.log(
`workspace: ${workspace.code} · ${workspace.name} (${workspace.id}) as ${workspace.relation}`
);
console.log(`sandboxes: ${(await raw.listSandboxes()).data.length}`);
try {
await raw.createSandbox({ body: { class: 'std', size: '4x8' } });
} catch (e) {
if (!(e instanceof RawError)) throw e;
console.log(`createSandbox: RawError ${e.status} ${e.code}: ${e.message}`);
console.log(` next step: ${e.next_step.message} ${e.next_step.url ?? ''}`.trimEnd());
console.log(` docs: ${e.docs}`);
}
me: ada@example.com with a workspace key, in default (ws_01m6zbey4kf5db2f5qbn7fwppy), API version 2026-11-08
workspace: default · Default (ws_01m6zbey4kf5db2f5qbn7fwppy) as developer
sandboxes: 0
createSandbox: RawError 503 capacity_unavailable: No cell serves std yet: raw.computer is in early access.
next step: Read the early-access note; sandbox creates open when the first cell does. https://raw.computer/docs/limits#early-access
docs: https://raw.computer/docs/errors#capacity_unavailable
A method takes one object with the parts its operation has: body, path (raw.getSandbox({ path: { id } })),
query (raw.listSandboxes({ query: { limit: 10 } })) and headers. Its answer and its body are typed from the
document; every type is exported (import type { Sandbox } from 'rawcomputer').
Python
For Python 3.11 or later. AsyncRaw is the same client with every method awaited.
from rawcomputer import Raw, RawError
from rawcomputer.models import SandboxCreate
raw = Raw() # RAW_API_KEY, or RAW_TOKEN with RAW_WORKSPACE
me = raw.get_me()
acting = f"{me.workspace.code} ({me.workspace.id})" if me.workspace else "no workspace"
print(f"me: {me.user.email} with a {me.api_key.kind} key, in {acting}, API version {me.raw_version}")
for workspace in raw.list_workspaces().data:
print(f"workspace: {workspace.code} · {workspace.name} ({workspace.id}) as {workspace.relation}")
print(f"sandboxes: {len(raw.list_sandboxes().data)}")
try:
raw.create_sandbox(body=SandboxCreate(class_="std", size="4x8"))
except RawError as e:
print(f"create_sandbox: RawError {e.status} {e.code}: {e.message}")
print(f" next step: {e.next_step.message} {e.next_step.url or ''}".rstrip())
print(f" docs: {e.docs}")
me: ada@example.com with a personal key, in default (ws_01m6zbey4kf5db2f5qbn7fwppy), API version 2026-11-08
workspace: default · Default (ws_01m6zbey4kf5db2f5qbn7fwppy) as admin
sandboxes: 0
create_sandbox: RawError 503 capacity_unavailable: No cell serves std yet: raw.computer is in early access.
next step: Read the early-access note; sandbox creates open when the first cell does. https://raw.computer/docs/limits#early-access
docs: https://raw.computer/docs/errors#capacity_unavailable
Methods are the operationIds in snake_case (get_me, list_workspaces, create_sandbox). A path parameter comes
first (raw.get_sandbox("sbx_…")), everything else by keyword (body=, limit=, raw_workspace=). Request and answer
classes are in rawcomputer.models; a field the API may leave out is UNSET.
Credentials
| What | TypeScript | Python |
|---|---|---|
A workspace API key (rc_live_…) |
new Raw({ apiKey }) |
Raw(api_key) |
A personal token (rc_pat_…) and its workspace |
new Raw({ apiKey: token, workspace }) |
Raw(token, workspace="ws_…") |
| Another origin | new Raw({ baseUrl }) |
Raw(base_url=…) |
Left out, they are read from the environment as the CLI reads it: RAW_TOKEN, else RAW_API_KEY;
RAW_WORKSPACE; RAW_API_URL. Make a key in the console under API keys; a personal token is what raw login
keeps. A token acts as its person in the workspace it names (sent as Raw-Workspace) and in none without it; one call
can name another (headers: { 'Raw-Workspace': … } in TypeScript, raw_workspace= in Python). A credential of
neither kind is refused before any request is sent.
Versions
Every request names the API version the SDK was made from in Raw-Version (RAW_VERSION, today 2026-11-08), so
an answer has the shape the SDK reads whatever version the key is pinned to. A value the API adds later (a new state,
a new error code) is read as it came, never refused.
Idempotency and retries
- Every POST carries an
Idempotency-Key, made by the SDK unless the call names its own, and each retry sends the same one: a POST that reached the API is answered as the first time and never done twice (Idempotency). - 429 and a 5xx with
Retry-Afterare sent again after it, when the wait is at mostmaxRetryWait/max_retry_wait(60 seconds); a longer wait is yours to choose, and the error'sretry_atsays when. - 500, 502 and 504 without
Retry-After, and a request that got no answer, are sent again after 0.5, 1, 2… seconds, when they are safe to repeat: a GET, or a POST with its key. - At most
maxRetries/max_retries(3) times. Anything else is yours at once: a 4xx, and a 503capacity_unavailable, which no wait mends.
Errors
Every answer that is not a success throws (TypeScript) or raises (Python) a RawError:
| Field | Holds |
|---|---|
status |
the HTTP status |
code |
the stable code to branch on: one of Errors |
message |
what happened, in one sentence |
next_step |
what to do: message, and where one helps, url, api ("POST /v1/api_keys") and cli |
docs |
the code on the Errors page |
retry_at |
when a retry is expected to succeed, on capacity_full and rate_limited; else null / None |
A request that got no answer at all, after its retries, throws what fetch or httpx2 threw.