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

# TypeScript SDK

> Install @flowra/sdk with examples for tools, workflows, connections, chat, files, sandbox, and usage.

This guide walks through [`@flowra/sdk`](https://www.npmjs.com/package/@flowra/sdk) for Node.js backends. Overview: [SDKs](/guides/sdk). Full method map: [SDK namespaces](/guides/sdk-namespaces). Every method: [SDK method examples](/guides/sdk-method-examples). Source: [github.com/flowradev/sdk](https://github.com/flowradev/sdk).

## Install

Package on [npm](https://www.npmjs.com/package/@flowra/sdk).

```bash theme={null}
npm install @flowra/sdk
# or: pnpm add @flowra/sdk
```

From the [SDK repo](https://github.com/flowradev/sdk) (optional):

```bash theme={null}
pnpm --dir typescript install
pnpm --dir typescript build
```

Requires Node 18+.

## Create a client

```ts theme={null}
import { Flowra } from '@flowra/sdk';

const flowra = new Flowra({
  apiKey: process.env.FLOWRA_API_KEY!,
  // baseUrl: 'https://flowra.dev',
  // username: 'customer_alice',
  // throwOnError: true,
});
```

| Option | Meaning |
| - | - |
| `apiKey` | Project API key (`x-api-key`) — required |
| `baseUrl` | API origin (default `https://flowra.dev`) |
| `username` | Optional external user (`x-username`) |
| `throwOnError` | Throw on non-2xx (default `true`) |

Scope to another end user without rebuilding options:

```ts theme={null}
const alice = flowra.asUser('customer_alice');
await alice.connections.list();
await alice.knowledge.list();
```

See [Multi-tenancy](/guides/multi-tenancy).

## Profile and tools

Copy tool slugs from `tools.list`. Do not invent them. Catalog actions are typically `UPPER_SNAKE`.

```ts theme={null}
const profile = await flowra.getProfile();

const tools = await flowra.tools.list({
  limit: 10,
  toolkitSlug: 'slack',
  q: 'send message',
});

const tool = await flowra.tools.get(tools.items?.[0]?.id ?? 'TOOL_ID');

const slug = tools.data?.[0]?.slug ?? tools.items?.[0]?.slug ?? 'SLACK_SEND_MESSAGE';
const result = await flowra.tools.execute(slug, {
  arguments: {
    channel: '#general',
    text: 'Hello from @flowra/sdk',
  },
  // connectedAccountId: '...',
});

const logs = await flowra.tools.executionLogs({ limit: 20 });
```

List toolkits (with nested tools):

```ts theme={null}
const kits = await flowra.toolkits.listWithTools({ q: 'slack', limit: 5 });
const channels = await flowra.toolkits.messagingChannels();
const categories = await flowra.toolkits.listCategories();
```

## Run a workflow

```ts theme={null}
const list = await flowra.workflows.list({ limit: 10, q: 'support' });
const workflowId = list.items?.[0]?.id ?? 'WORKFLOW_ID';

const run = await flowra.workflows.run(workflowId, {
  input: { message: 'Summarize open tickets' },
});

const threadId = run.threadId as string;

// Poll until completed, failed, or paused
let status = await flowra.workflows.status(threadId);
while (status.status === 'running') {
  await new Promise((r) => setTimeout(r, 1500));
  status = await flowra.workflows.status(threadId);
}

if (status.status === 'paused') {
  await flowra.workflows.resume(threadId, {
    resumeValue: { approved: true },
  });
}

const detail = await flowra.workflows.execution(run.executionId);
const stats = await flowra.workflows.statistics(workflowId);
```

Recipe: [Run a workflow](/recipes/run-a-workflow). HITL: [Human in the loop](/guides/human-in-the-loop).

## Connect an account

```ts theme={null}
const configs = await flowra.authConfigs.list({ toolkitSlug: 'slack' });
const authConfigId = configs.items?.[0]?.id ?? 'AUTH_CONFIG_ID';

const link = await flowra.connections.createLink({
  toolkitSlug: 'slack',
  authConfigId,
});
// Open link.url (or equivalent) in a browser for OAuth

const accounts = await flowra.connections.list();
const grouped = await flowra.connections.listGrouped();
```

Per end user:

```ts theme={null}
const alice = flowra.asUser('customer_alice');
await alice.connections.createLink({ toolkitSlug: 'slack', authConfigId });
```

Recipe: [Connect an account](/recipes/connect-an-account).

## External users and triggers

```ts theme={null}
await flowra.users.create({ username: 'customer_alice' });
const user = await flowra.users.getByUsername('customer_alice');

await flowra.triggers.list();
await flowra.triggers.upsert('SOME_TRIGGER_SLUG', {
  // UpsertTriggerInstanceDto fields
});
const logs = await flowra.triggers.invocationLogs({ limit: 10 });
```

## Chat thread and stream

```ts theme={null}
const thread = await flowra.chat.createThread({
  metadata: { ticketId: 'T-100' },
});
const threadId = thread.thread_id as string;

await flowra.chat.stream(threadId, {
  input: {
    messages: [{ role: 'user', content: 'What can you help with?' }],
  },
});

const history = await flowra.chat.history(threadId, {});
const state = await flowra.chat.state(threadId);
const runs = await flowra.chat.listRuns(threadId);
```

SSE helpers and usage events: [Chat streaming](/guides/sdk-chat-streaming).

## Skills and MCP

```ts theme={null}
const skills = await flowra.skills.list();
await flowra.skills.registrySearch({ q: 'pdf' });
await flowra.skills.addToLibrary(skillId);

const servers = await flowra.mcp.list();
const server = await flowra.mcp.create({
  // CreateMcpServerDto
});
const installConfig = await flowra.mcp.config(server.id);
```

## Knowledge and database (per user)

```ts theme={null}
const alice = flowra.asUser('customer_alice');

const collection = await alice.knowledge.create({ name: 'Help center' });
await alice.knowledge.ingestUrl(collection.id, {
  url: 'https://docs.yoursite.com/faq',
});
const collections = await alice.knowledge.list();
const collectionId = collections[0]?.id ?? collection.id;
await alice.knowledge.search(collectionId, { query: 'refund policy' });
await alice.knowledge.chunks(collectionId, { limit: 20 });

const tables = await alice.database.list();
const tableId = tables[0]?.id ?? 'TABLE_ID';
await alice.database.documents(tableId, { limit: 50 });
await alice.database.createDocument(tableId, {
  // document fields
});
```

## Files

```ts theme={null}
const files = await flowra.files.list({ limit: 20 });
// Upload uses multipart; pass the body shape expected by the generated client
await flowra.files.upload('document', formDataBody as never);
const bytes = await flowra.files.download(fileId);
const storage = await flowra.files.storageBreakdown();
```

## Sandbox, browser, LLM

```ts theme={null}
const preview = await flowra.sandbox.runEphemeral({
  language: 'javascript',
  source: 'return { ok: true, n: 1 + 1 };',
  timeoutMs: 8000,
});

const session = await flowra.sandbox.createSession({});
await flowra.sandbox.execute(session.id, {
  language: 'python',
  source: 'print(2 + 2)',
});
await flowra.sandbox.releaseSession(session.id);

await flowra.browser.status(sessionId);
await flowra.browser.touch(sessionId);
await flowra.browser.view(sessionId, { /* query */ });
await flowra.browser.close(sessionId);

const models = await flowra.llm.models();
const chat = await flowra.llm.chat({
  messages: [{ role: 'user', content: 'Say hello in one sentence.' }],
});
const text = await flowra.llm.generate({
  // GenerateDto
});
```

## Usage and credits

```ts theme={null}
const balance = await flowra.usage.balance();
const ledger = await flowra.usage.list({
  threadId,
  from: '2026-08-01T00:00:00.000Z',
});
const runUsage = await flowra.usage.forExecution(executionId);
```

Details: [Usage and credits](/guides/usage-and-credits).

## Escape hatch: `flowra.raw`

Every API-key OpenAPI operation is on `flowra.raw` (generated). Pass the shared client:

```ts theme={null}
const res = await flowra.raw.toolsControllerGetTools({
  client: flowra.client,
  query: { limit: 5 },
});
```

Prefer the typed facade when it exists. Schemas: [API reference](/api-reference).

## Errors

With `throwOnError: true` (default), failed responses throw:

```ts theme={null}
try {
  await flowra.getProfile();
} catch (err) {
  console.error(err);
}
```

Set `throwOnError: false` if you want the generated `{ data, error }` shape on raw calls; facade helpers still unwrap and throw when using namespace methods with the default client config.

## Next

* [SDK method examples](/guides/sdk-method-examples) — Every facade method
* [Python SDK](/guides/sdk-python) — Parallel examples
* [Chat streaming](/guides/sdk-chat-streaming)
* [SDK namespaces](/guides/sdk-namespaces)
* [Run a workflow](/recipes/run-a-workflow)
* [Connect an account](/recipes/connect-an-account)
* [API reference](/api-reference)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.