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

# Overview

> Get started with the CloudCruise TypeScript/JavaScript SDK

# TS/JS SDK Overview

Contributions are welcome at [https://github.com/CloudCruise/cloudcruise-js](https://github.com/CloudCruise/cloudcruise-js).

Report bugs via [GitHub issues](https://github.com/CloudCruise/cloudcruise-js/issues) or [Discord](https://discord.com/invite/MHjbUqedZF).

The CloudCruise TypeScript/JavaScript SDK provides a simple way to integrate browser automation workflows into your applications. Execute workflows, manage credentials, and monitor runs programmatically.

## Installation

Install the latest version:

```bash theme={null}
npm install cloudcruise
```

Get your keys at [CloudCruise Settings](https://app.cloudcruise.com/settings/api-keys).

```javascript theme={null}
import { CloudCruise } from 'cloudcruise';

const client = new CloudCruise({
  apiKey: "your-api-key",
  encryptionKey: "your-encryption-key",
});
```

## 1. Creating a Run

```javascript theme={null}
const run = await client.runs.start({
  workflow_id: "workflow-123",
  run_input_variables: {
    variable_1: "https://example.com",
    variable_2: "john_doe",
  },
});

console.log("Session ID:", run.sessionId);
```

## 2. Listening to run events

Use typed per-event listeners for the best DX. Alternatively, you can attach a single `'run.event'` listener and switch on `message.data.event`.

```ts theme={null}
import { EventType } from 'cloudcruise';

const handle = await client.runs.start({
  workflow_id: "workflow-123",
  run_input_variables: { target: "https://example.com" },
});

handle.on(EventType.ExecutionStep, ({ data: { payload }, timestamp }) => {
  const { current_step, next_step } = payload;
  console.log(`[SESSION: ${handle.sessionId}] STEP: ${current_step} -> ${next_step} @ ${timestamp}`);
});

handle.on(EventType.ExecutionStart, ({ data, timestamp }) => {
  console.log(`[SESSION: ${handle.sessionId}] START: ${data.payload.workflow_id} @ ${timestamp}`);
});

handle.on('error', (error) => {
  const msg = error instanceof Error ? error.message : String(error);
  console.error(`[SESSION: ${handle.sessionId}] ERROR:`, msg);
});

handle.on('end', ({ type }) => {
  console.log(`[SESSION: ${handle.sessionId}] Workflow completed${type ? ` with status: ${type}` : ''}!`);
  handle.close();
});

// Alternatively, a single catch-all:
// handle.on('run.event', (message) => {
//   if (message.event !== 'run.event') return;
//   const { event, payload, timestamp } = message.data;
//   switch (event) {
//     case EventType.ExecutionStep: {
//       const { current_step, next_step } = payload;
//       console.log(`[SESSION: ${handle.sessionId}] STEP: ${current_step} -> ${next_step} @ ${timestamp}`);
//       break;
//     }
//     default: {
//       console.log(`[SESSION: ${handle.sessionId}] EVENT:`, JSON.stringify(message, null, 2));
//     }
//   }
// });
```

### Other available events

* **'open'**: connection established
* **'ping'**: heartbeat messages
* **'reconnect'**: reconnect attempts with `{ attemptDelayMs }`
* **'message'**: catch-all mirror of `'run.event'` and `'ping'`
* **'close'**: connection closed (informational)
* **'error'**: SSE errors
* **'end'**: terminal status for the session

Example:

```ts theme={null}
handle.on('ping', (e) => console.log('ping:', e));
handle.on('reconnect', ({ attemptDelayMs }) => console.log('reconnect in', attemptDelayMs, 'ms'));
```

### Async iteration (streaming)

If you prefer a loop:

```ts theme={null}
for await (const msg of handle) {
  if (msg.event !== 'run.event') continue;
  console.log('Received:', msg.data.event);
  if (msg.data.event === EventType.ExecutionSuccess) break;
}
```

* **Tip**: Use Option A for strongly-typed handlers when you know the events you care about. Use Option B for centralized routing/logging. Both can be combined (e.g., typed listeners for your primary events plus a catch-all logger).

## 3. Wait for Completion

You can wait for the run to finish, but **keep in mind if your run is long, this can be a very long time:**

```javascript theme={null}
const run = await client.runs.start({
  workflow_id: "workflow-123",
  run_input_variables: { target: "https://example.com" },
});

// This will block until completion - use with caution for long workflows
const result = await run.wait();
console.log("Run completed:", result.status);
console.log("Output data:", result.data);
```

## Watching a Live Session

While a session is running, fetch a viewer URL to watch its browser stream:

```typescript theme={null}
const { url } = await client.runs.getLiveViewConnection(run.sessionId);
console.log("Watch live:", url);
```

The auth token embedded in `url` is **single-use** — reopening a previously used viewer link (reloading the tab, or opening it later) fails to connect. Call `getLiveViewConnection` again to mint a fresh link instead of reusing the old one. This only works while the session is still active.

## Next Steps

* Explore the [Run API](/run-api/start-a-run) for detailed workflow execution options
* Learn about [Vault API](/vault-api/create-vault-entry) for secure credential management
* Check out [Workflow API](/workflow-api/get-workflows) to manage your workflows
* Set up [Webhooks](/webhooks-api/replay-webhooks) for event notifications
