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

# Clients

> The official JavaScript SDK, the server-side proxy, and the embeddable Studio. Plus codegen recipes for other languages.

Runflow ships an official JavaScript surface as [`runflow-js`](https://github.com/runflow-io/runflow-js). Three packages, one for each integration shape. For other languages, generate a client from the public OpenAPI spec.

## JavaScript packages

| Package                                                                       | What it does                                                       | Where it runs                                           |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------- |
| [`@runflow-io/sdk`](/guides/javascript-sdk)                                   | Typed HTTP client and tool DSL for the API.                        | Node, Bun, Deno, browsers, edge workers.                |
| [`@runflow-io/proxy`](/guides/javascript-sdk#proxy-browser-calls-server-side) | Web Standards handler that injects your API key for browser calls. | Any server framework (Next.js, Hono, Workers, Express). |
| [`@runflow-io/studio`](/guides/embed-studio)                                  | Drop the Studio UI into a `<div>`.                                 | Browser, via npm.                                       |

All three packages target the same `api.runflow.io` REST surface documented in the [API reference](/api). They are MIT-licensed and published from [github.com/runflow-io/runflow-js](https://github.com/runflow-io/runflow-js).

<Tip>
  **Browsing without a key.** [`GET /v1/public/models`](https://api.runflow.io/v1/public/models) is an unauthenticated endpoint that returns the same model catalog the docs render from. Useful for client-side model pickers, IDE plugins, and discovery flows that should not ship an API key. Run dispatch + everything else still requires `Authorization: Bearer $RUNFLOW_API_KEY`.
</Tip>

<Warning>
  These packages are pre-1.0 (`0.0.x`). Patch releases may change types or runtime behavior. Pin exact versions in production until 1.0.
</Warning>

### Install

```bash theme={"dark"}
bun add @runflow-io/sdk
# or: npm install @runflow-io/sdk
# or: pnpm add @runflow-io/sdk
```

### One call, server-side

```ts theme={"dark"}
import { Runflow } from "@runflow-io/sdk";

const rf = new Runflow({ apiKey: process.env.RUNFLOW_API_KEY });
const dispatched = await rf.models.run("runflow/background-removal", {
  input: { image_url: "https://example.com/photo.jpg" },
});
// dispatched.id is the run id; same shape as the REST response.
const final = await rf.runs.wait(dispatched.id);
console.log(final.output);
```

Walk through every option in the [JavaScript SDK guide](/guides/javascript-sdk).

## Codegen for other languages

The public OpenAPI 3.1 spec is the same one that generates this site's API reference:

```
https://docs.runflow.io/api/openapi.public.json
```

### TypeScript types

```bash theme={"dark"}
npx openapi-typescript https://docs.runflow.io/api/openapi.public.json \
  -o src/runflow-types.ts
```

### Python client

```bash theme={"dark"}
pip install openapi-python-client
openapi-python-client generate --url https://docs.runflow.io/api/openapi.public.json
```

### Go client

```bash theme={"dark"}
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest
oapi-codegen -package runflow https://docs.runflow.io/api/openapi.public.json > runflow.go
```

## Hand-rolled HTTP

For most integrations a raw fetch or `requests` call is enough. Both snippets bound the network wait so a stuck connection never hangs the caller.

<CodeGroup>
  ```python Python theme={"dark"}
  import os, requests

  RUNFLOW_API_KEY = os.environ["RUNFLOW_API_KEY"]
  REQUEST_TIMEOUT = 30  # seconds

  def runflow_post(path, body):
      r = requests.post(
          f"https://api.runflow.io{path}",
          headers={"Authorization": f"Bearer {RUNFLOW_API_KEY}"},
          json=body,
          timeout=REQUEST_TIMEOUT,
      )
      r.raise_for_status()
      return r.json()
  ```

  ```javascript Node.js theme={"dark"}
  const RUNFLOW_API_KEY = process.env.RUNFLOW_API_KEY;
  const REQUEST_TIMEOUT_MS = 30_000;

  async function runflowPost(path, body) {
    const r = await fetch(`https://api.runflow.io${path}`, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${RUNFLOW_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(body),
      signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
    });
    if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
    return r.json();
  }
  ```
</CodeGroup>

## Related

<CardGroup cols={2}>
  <Card title="JavaScript SDK" icon="js" href="/guides/javascript-sdk">Server-side, browser, and the tool DSL.</Card>
  <Card title="Embed the Studio" icon="window" href="/guides/embed-studio">Drop the Studio into your site in three lines.</Card>
  <Card title="OpenAPI" icon="code" href="/agents/openapi">Spec details and codegen recipes.</Card>
  <Card title="Authentication" icon="key" href="/concepts/authentication">Bearer header.</Card>
</CardGroup>
