npm package: @findable-ai/sdk
Description: TypeScript client for the Findable Partner API
Latest version: 0.2.4

# @findable-ai/sdk

Zero-dependency TypeScript client for the [Findable](https://findable.ai) Partner API. Works in browsers, Node.js, and any runtime with native `fetch`.

[![npm version](https://img.shields.io/npm/v/@findable-ai/sdk)](https://www.npmjs.com/package/@findable-ai/sdk)

> **Full documentation**: [docs.findable.dev](https://docs.findable.dev/sdk)

## Installation

```bash
npm install @findable-ai/sdk
```

## Quick start

```typescript
import { FindableClient } from '@findable-ai/sdk';

const client = new FindableClient({
  apiKey: 'YOUR_API_KEY',
  buildingOwnerId: 'YOUR_BUILDING_OWNER_ID',
});

// Search documents
const results = await client.search({ query: 'fire safety', buildingId: 'bld-123' });
console.log(results.hits);

// Ask a question (non-streaming)
const answer = await client.ask({
  buildingId: 'bld-123',
  query: 'What are the fire safety requirements?',
});
console.log(answer.answer);
```

## Streaming

`askStream()` returns an async iterable with real-time server-sent events:

```typescript
const stream = client.askStream({
  buildingId: 'bld-123',
  query: 'Summarise the ventilation specs',
});

for await (const event of stream) {
  switch (event.event) {
    case 'text':
      process.stdout.write(event.text);
      break;
    case 'finish':
      console.log('\n\nCitations:', event.citations);
      break;
  }
}

// Cancel at any time
stream.abort();
```

### Stream events

| Event      | Fields                                                                     | Description                                             |
| ---------- | -------------------------------------------------------------------------- | ------------------------------------------------------- |
| `start`    | `threadId`                                                                 | Stream opened, thread created                           |
| `text`     | `text`                                                                     | Incremental answer text chunk                           |
| `thinking` | `text`                                                                     | Model reasoning text (when using high reasoning effort) |
| `finish`   | `answer`, `threadId`, `citations`, `citedDocuments`, `followUpSuggestions` | Complete response with metadata                         |
| `error`    | `message`                                                                  | Error occurred                                          |

## API reference

### `FindableClient`

```typescript
new FindableClient({ apiKey: string, buildingOwnerId: string, baseUrl?: string })
```

### Methods

| Method               | Returns                                       | Description                             |
| -------------------- | --------------------------------------------- | --------------------------------------- |
| `ask(options)`       | `Promise<AskResponse>`                        | Ask a question, get a complete response |
| `askStream(options)` | `AsyncIterable<AskStreamEvent> & { abort() }` | Ask with real-time streaming            |
| `search(options)`    | `Promise<SearchResult>`                       | Search documents                        |
| `listBuildings()`    | `Promise<Building[]>`                         | List all buildings                      |
| `getBuilding(id)`    | `Promise<Building>`                           | Get a single building                   |

### Options

```typescript
// Ask
{ buildingId: string, query: string, language?: 'en' | 'no' | 'nb' | 'nn',
  threadId?: string, attachedDocumentIds?: string[], reasoningEffort?: 'low' | 'medium' | 'high' }

// Search
{ query: string, buildingId?: string, maxResults?: number, startIndex?: number }
```

## Error handling

```typescript
import {
  FindableClient,
  AuthError,
  NotFoundError,
  FindableError,
} from '@findable-ai/sdk';

try {
  await client.ask({ buildingId: 'bld-123', query: 'Hello' });
} catch (err) {
  if (err instanceof AuthError) {
    // Invalid or missing API key (401/403)
  } else if (err instanceof NotFoundError) {
    // Building not found (404)
  } else if (err instanceof FindableError) {
    // Other API error — check err.status and err.message
  }
}
```

## React

For drop-in React components and hooks, see [`@findable-ai/react`](https://www.npmjs.com/package/@findable-ai/react).

## Documentation

- [Getting started](https://docs.findable.dev/getting-started)
- [SDK client reference](https://docs.findable.dev/sdk/client)
- [Streaming guide](https://docs.findable.dev/sdk/streaming)
- [API reference](https://docs.findable.dev/api)

## Licence

MIT