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

# SDK Usage Guide

> Complete guide to using the Orchata TypeScript SDK

Learn how to use the Orchata SDK to manage spaces, documents, and query your knowledge base.

## Client Configuration

Create a client instance with optional configuration:

```typescript theme={null}
import { Orchata } from '@orchata-ai/sdk';

const client = new Orchata({
  // Required: Your API key
  apiKey: 'oai_xxx',

  // Optional: Custom base URL (default: https://api.orchata.ai/api)
  baseUrl: 'https://api.orchata.ai/api',

  // Optional: Request timeout in ms (default: 30000)
  timeout: 30000,

  // Optional: Custom fetch implementation
  fetch: customFetch
});
```

## Spaces

Spaces are knowledge bases that contain your documents.

### List Spaces

```typescript theme={null}
const { spaces, total } = await client.spaces.list();

console.log(`Found ${total} spaces`);
spaces.forEach(space => {
  console.log(`${space.name}: ${space.id}`);
});
```

Filter spaces by metadata:

```typescript theme={null}
const { spaces } = await client.spaces.list({
  metadata: { team: 'engineering' }
});
```

### Create a Space

```typescript theme={null}
const { space } = await client.spaces.create({
  name: 'Documentation',
  description: 'Product documentation and guides',
  icon: 'book', // Optional: 'folder', 'book', 'file-text', 'database', etc.
  metadata: { // Optional
    team: 'engineering',
    project: 'api-v2'
  }
});

console.log(`Created space: ${space.id}`);
```

### Get a Space

```typescript theme={null}
const { space } = await client.spaces.get('space_123');
console.log(space.name, space.description);
```

### Update a Space

```typescript theme={null}
const { space } = await client.spaces.update('space_123', {
  name: 'Updated Name',
  description: 'New description',
  icon: 'database',
  metadata: { team: 'product', priority: 'high' }
});
```

### Delete a Space

```typescript theme={null}
await client.spaces.delete('space_123');
```

<Note>
  Deleting a space archives it (soft delete). The space and its documents remain accessible but hidden.
</Note>

### Get Space Limits

Check document usage and limits for a space based on your plan:

```typescript theme={null}
const limits = await client.spaces.getLimits('space_123');

console.log(`${limits.documents.current} / ${limits.documents.max} documents`);
console.log(`${limits.documents.remaining} remaining`);
```

## Documents

Documents contain the content in your spaces. Orchata automatically handles chunking and embedding.

### List Documents

```typescript theme={null}
const { documents, total } = await client.documents.list({
  spaceId: 'space_123'
});

documents.forEach(doc => {
  console.log(`${doc.filename} - Status: ${doc.status}`);
});
```

Filter documents by metadata:

```typescript theme={null}
const { documents } = await client.documents.list({
  spaceId: 'space_123',
  metadata: { category: 'docs', version: '2.0' }
});
```

### Upload a Document

```typescript theme={null}
const { document } = await client.documents.upload({
  spaceId: 'space_123',
  content: '# Getting Started\n\nWelcome to our product!',
  filename: 'getting-started.md',
  metadata: { // Optional
    category: 'docs',
    version: '1.0'
  }
});

console.log(`Document ID: ${document.id}`);
```

<Warning>
  Documents start with `status: "processing"`. Wait a few seconds for embedding to complete before querying.
</Warning>

### Upload Multiple Documents

Upload multiple documents in a single operation:

```typescript theme={null}
const result = await client.documents.batchUpload({
  spaceId: 'space_123',
  documents: [
    { filename: 'doc1.md', content: '# Doc 1\n\nContent...' },
    { filename: 'doc2.md', content: '# Doc 2\n\nContent...' }
  ]
});

console.log(`Uploaded: ${result.totalSuccessful}, Failed: ${result.totalFailed}`);
```

### Get Document Content

Retrieve the full processed content of a document:

```typescript theme={null}
const { content } = await client.documents.getContent('doc_123', 'space_123');
console.log(content);
```

### Upsert a Document

Create a document if it doesn't exist, or update it if a document with the same filename already exists in the space:

```typescript theme={null}
const { document, created } = await client.documents.upsert({
  spaceId: 'space_123',
  filename: 'readme.md',
  content: '# Updated README\n\nNew content...',
  metadata: { version: '2.0' }
});

console.log(created ? 'Created' : 'Updated', document.id);
```

### Append to a Document

Add content to the end of an existing document:

```typescript theme={null}
const { document } = await client.documents.append('doc_123', {
  spaceId: 'space_123',
  content: '## New Section\n\nAdditional content...',
  separator: '\n\n---\n\n' // Optional, defaults to double newline
});
```

### Get Document by Filename

Look up a document by its filename within a space:

```typescript theme={null}
const doc = await client.documents.getByFilename({
  spaceId: 'space_123',
  filename: 'readme.md'
});

console.log(doc.content);
```

### Update a Document

```typescript theme={null}
const { document } = await client.documents.update('doc_123', {
  spaceId: 'space_123',
  metadata: { category: 'updated' }
});
```

### Delete a Document

```typescript theme={null}
await client.documents.delete('doc_123', 'space_123');
```

## Queries

Query your knowledge base using semantic search.

### Simple Query

```typescript theme={null}
const { results } = await client.query({
  spaceIds: 'space_123',
  query: 'How do I authenticate?'
});

results.forEach(result => {
  console.log(`Score: ${result.similarity}`);
  console.log(`Content: ${result.chunk.content}`);
  console.log(`Document: ${result.document.filename}`);
});
```

### Query Multiple Spaces

```typescript theme={null}
const { results } = await client.query({
  spaceIds: ['space_123', 'space_456'],
  query: 'authentication',
  topK: 5 // Return top 5 results
});
```

### Filter by Metadata

```typescript theme={null}
const { results } = await client.query({
  spaceIds: 'space_123',
  query: 'API reference',
  metadata: { category: 'docs' }
});
```

### Group Results by Space

```typescript theme={null}
const { groupedBySpace } = await client.query({
  spaceIds: ['space_123', 'space_456'],
  query: 'authentication',
  groupBySpace: true
});

// Access results grouped by space
for (const [spaceId, results] of Object.entries(groupedBySpace)) {
  console.log(`Space ${spaceId}: ${results.length} results`);
}
```

### Query Options

<ParamField body="spaceIds" type="string | string[]" required>
  One or more space IDs to search.
</ParamField>

<ParamField body="query" type="string" required>
  Natural language search query.
</ParamField>

<ParamField body="topK" type="integer" default="10">
  Maximum number of results to return (1-100).
</ParamField>

<ParamField body="threshold" type="number" default="0.0">
  Minimum similarity score (0-1). Higher values return more relevant but fewer results.
</ParamField>

<ParamField body="metadata" type="object">
  Filter results by document metadata key-value pairs.
</ParamField>

<ParamField body="groupBySpace" type="boolean" default="false">
  Group results by space ID instead of returning a flat array.
</ParamField>

## Smart Query

Discover which spaces are most relevant for a query without knowing which spaces to search.

### Find Relevant Spaces

```typescript theme={null}
const { relevantSpaces } = await client.smartQuery({
  query: 'How do I authenticate users?',
  maxSpaces: 3
});

relevantSpaces.forEach(rec => {
  console.log(`${rec.space.name}: ${rec.relevanceScore}`);
});
```

### Relevance Methods

Choose how spaces are matched to your query:

```typescript theme={null}
// Keyword matching
const { relevantSpaces } = await client.smartQuery({
  query: 'authentication',
  relevanceMethod: 'keyword'
});

// Embedding-based similarity
const { relevantSpaces } = await client.smartQuery({
  query: 'authentication',
  relevanceMethod: 'embedding'
});

// Hybrid (default) - combines both methods
const { relevantSpaces } = await client.smartQuery({
  query: 'authentication',
  relevanceMethod: 'hybrid',
  keywordWeight: 0.5 // Weight for keyword vs embedding (0-1)
});
```

### Complete Workflow

Use Smart Query to discover spaces, then query them:

```typescript theme={null}
// Step 1: Discover relevant spaces
const { relevantSpaces } = await client.smartQuery({
  query: 'user authentication'
});

// Step 2: Query the recommended spaces
const { results } = await client.query({
  spaceIds: relevantSpaces.map(rec => rec.space.id),
  query: 'user authentication'
});
```

<Tip>
  Smart Query is especially useful for AI agents that need to discover which knowledge bases to search without hardcoded space IDs.
</Tip>

## Runtime Support

The SDK works across different JavaScript runtimes:

| Runtime            | Supported | Notes                   |
| ------------------ | --------- | ----------------------- |
| Node.js 18+        | ✅         | Uses native `fetch`     |
| Node.js 16-17      | ⚠️        | Requires fetch polyfill |
| Deno               | ✅         | Full support            |
| Bun                | ✅         | Full support            |
| Browsers           | ✅         | Modern browsers         |
| Cloudflare Workers | ✅         | Full support            |

## Next Steps

<CardGroup cols={2}>
  <Card title="AI Integration" icon="sparkles" href="/sdk/ai-integration">
    Integrate with Vercel AI SDK for AI-powered applications.
  </Card>

  <Card title="Error Handling" icon="triangle-alert" href="/sdk/errors">
    Handle errors gracefully with typed error classes.
  </Card>

  <Card title="Quickstart" icon="rocket" href="/sdk/quickstart">
    Review the quickstart guide.
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Explore the REST API documentation.
  </Card>
</CardGroup>
