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

# SDK

> TypeScript and Python SDKs for the Query API

Programmatically access and search your Raindrop data. Build dashboards, create eval sets, export data, or integrate Raindrop into your workflows.

## Installation

<CodeGroup>
  ```bash TypeScript theme={null}
  npm install @raindrop-ai/query
  ```

  ```bash Python theme={null}
  pip install raindrop-query
  ```
</CodeGroup>

## Quick Start

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { RaindropQuery } from "@raindrop-ai/query";

  const client = new RaindropQuery({
    apiKey: process.env.RAINDROP_QUERY_API_KEY,
  });

  // Semantic search user inputs for frustration
  const results = await client.events.search({
    query: "frustration about load times",
    mode: "semantic",
    searchIn: "user_input,assistant_output",
  });
  ```

  ```python Python theme={null}
  import os
  from raindrop_query import RaindropQuery

  client = RaindropQuery(api_key=os.environ["RAINDROP_QUERY_API_KEY"])

  # Semantic search user inputs for frustration
  results = client.events.search(
      query="frustration about load times",
      mode="semantic",
      search_in="user_input"
  )
  ```
</CodeGroup>

<Info>
  [Get your Query API key here](https://auth.raindrop.ai/org/api_keys) (this is different from the write key used for ingestion).
</Info>

<Info>
  Reads are scoped to a single [project](/platform/projects). Requests resolve to your org's **Production** project (slug `default`) by default, so single-project orgs need nothing extra. To target another project, send its slug in the `X-Raindrop-Project-Id` header. See the [Query API reference](/query-api/api-reference#projects).
</Info>

***

## Common Patterns

### List Signals

```typescript theme={null}
const response = await client.signals.list({ limit: 10 });

// Returns: { data: [...], meta: { cursor, has_more } }
const signals = response.data;
```

### Get Events for a Signal

```typescript theme={null}
const signal = signals[0];

// Get count
const count = await client.events.count({ signal: signal.id });

// Get the actual events
const events = await client.events.list({
  signal: signal.id,
  limit: 100,
});
```

### Event Counts Over Time

```typescript theme={null}
const timeseries = await client.events.timeseries({
  signal: signal.id,
  timestamp: { gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString() },
  interval: "day",
});
```

***

## Error Handling

```typescript theme={null}
import { RaindropQuery } from "@raindrop-ai/query";
import { SDKValidationError } from "@raindrop-ai/query/models/errors";

try {
  const events = await client.events.list();
} catch (error) {
  if (error instanceof SDKValidationError) {
    console.error("Invalid request:", error.message);
  }
}
```
