> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ns.rocks/llms.txt
> Use this file to discover all available pages before exploring further.

# API Reference

> Use the Nullspace HTTP API directly from curl, JavaScript, or any language without a first-party SDK.

# API Reference

Use this page when you are integrating from a language without a first-party
SDK. The generated endpoint reference is built from `openapi.yaml`, which is a
symlink to the repository's canonical `specs/openapi.yaml` contract.

<Note>
  For JavaScript or TypeScript, prefer the first-party
  [TypeScript SDK](./guides/typescript-sdk/overview) (`@nullspace/sdk`). The
  `fetch` examples below are for languages without a first-party SDK, or when you
  want to call the raw HTTP contract directly.
</Note>

## Setup

```bash theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
export NULLSPACE_API_KEY=ns_live_...
export NULLSPACE_API_URL=https://api.your-nullspace-domain
```

The API expects a bearer token on customer-facing routes:

```text theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
Authorization: Bearer ${NULLSPACE_API_KEY}
```

## Create A Machine

```bash theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
MACHINE_JSON="$(
  curl -fsS -X POST "${NULLSPACE_API_URL}/v1/machines" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
    -H "Content-Type: application/json" \
    --data '{"template":"base","timeout_ms":300000}'
)"

MACHINE_ID="$(printf '%s' "${MACHINE_JSON}" | jq -r '.id')"
echo "${MACHINE_ID}"
```

```javascript theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
const apiUrl = process.env.NULLSPACE_API_URL;
const apiKey = process.env.NULLSPACE_API_KEY;

const createResponse = await fetch(`${apiUrl}/v1/machines`, {
  method: "POST",
  headers: {
    authorization: `Bearer ${apiKey}`,
    "content-type": "application/json",
  },
  body: JSON.stringify({ template: "base", timeout_ms: 300_000 }),
});

if (!createResponse.ok) {
  throw new Error(await createResponse.text());
}

const machine = await createResponse.json();
console.log(machine.id);
```

## Execute A Command

```bash theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
curl -fsS -X POST "${NULLSPACE_API_URL}/v1/machines/${MACHINE_ID}/exec" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  --data '{"command":"echo hello from nullspace","shell":true,"timeout_secs":30}'
```

```javascript theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
const execResponse = await fetch(`${apiUrl}/v1/machines/${machine.id}/exec`, {
  method: "POST",
  headers: {
    authorization: `Bearer ${apiKey}`,
    "content-type": "application/json",
  },
  body: JSON.stringify({
    command: "echo hello from nullspace",
    shell: true,
    timeout_secs: 30,
  }),
});

const execResult = await execResponse.json();
console.log(execResult.stdout);
```

## Expose A Port

Start a background process, then request signed preview URL metadata for the
port:

```bash theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
curl -fsS -X POST "${NULLSPACE_API_URL}/v1/machines/${MACHINE_ID}/exec" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  --data '{"command":"cd /workspace && python3 -m http.server 8080","shell":true,"background":true}'

curl -fsS -X POST "${NULLSPACE_API_URL}/v1/machines/${MACHINE_ID}/host" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  --data '{"port":8080}'
```

```javascript theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
await fetch(`${apiUrl}/v1/machines/${machine.id}/exec`, {
  method: "POST",
  headers: {
    authorization: `Bearer ${apiKey}`,
    "content-type": "application/json",
  },
  body: JSON.stringify({
    command: "cd /workspace && python3 -m http.server 8080",
    shell: true,
    background: true,
  }),
});

const hostResponse = await fetch(`${apiUrl}/v1/machines/${machine.id}/host`, {
  method: "POST",
  headers: {
    authorization: `Bearer ${apiKey}`,
    "content-type": "application/json",
  },
  body: JSON.stringify({ port: 8080 }),
});

const host = await hostResponse.json();
console.log(host.url ?? host.host);
```

## Destroy The Machine

```bash theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
curl -fsS -X DELETE "${NULLSPACE_API_URL}/v1/machines/${MACHINE_ID}" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}"
```

```javascript theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
await fetch(`${apiUrl}/v1/machines/${machine.id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${apiKey}` },
});
```

## Response And Error Shape

Successful responses are JSON unless the endpoint explicitly documents a
download stream or WebSocket upgrade. Errors use the standard error envelope
documented in [Error codes](./error-codes).

Use [API Reference Scope](./reference/api-scope) before building against
account, Auth, admin, or operator-only routes. Use the API Reference section in
the sidebar for endpoint schemas, generated examples, status codes, and field
constraints.

## Related

* [Supported clients](./reference/clients)
* [Environment variables](./reference/env-vars)
* [WebSocket protocol](./reference/websocket-protocol)
* [Hosted endpoints](./reference/hosted-endpoints)
