SDKs

Node.js SDK

Complete reference for the official Chatsby Node.js SDK — installation, configuration, all methods, TypeScript support, error handling, and streaming.

The official Chatsby Node.js SDK provides a typed, idiomatic wrapper around the Chatsby REST API. It handles authentication, request formatting, error parsing, pagination, and streaming so you can focus on building your integration.

Installation

Install the SDK using your preferred package manager:

# npm
npm install @chatsby/sdk
 
# yarn
yarn add @chatsby/sdk
 
# pnpm
pnpm add @chatsby/sdk

The SDK requires Node.js 18 or later and supports both CommonJS and ES Modules.

Configuration

Initialize the client with your API key and optional configuration:

import { Chatsby } from '@chatsby/sdk';
 
const chatsby = new Chatsby({
  apiKey: process.env.CHATSBY_API_KEY,
});

Configuration Options

OptionTypeDefaultDescription
apiKeystringYour Chatsby API key. Required.
baseUrlstringhttps://api.chatsby.co/v1Override the base URL (useful for testing against a proxy or mock server).
timeoutnumber30000Request timeout in milliseconds.
maxRetriesnumber2Number of automatic retries on network errors and 5xx responses.
const chatsby = new Chatsby({
  apiKey: process.env.CHATSBY_API_KEY,
  baseUrl: 'https://api.chatsby.co/v1',
  timeout: 60000,    // 60 seconds for long operations
  maxRetries: 3,
});

Environment Variables

The SDK automatically reads the CHATSBY_API_KEY environment variable if no apiKey is provided in the constructor:

# .env
CHATSBY_API_KEY=chtb_live_abc123def456
// API key is read from CHATSBY_API_KEY automatically
const chatsby = new Chatsby();

Agents

agents.list()

Retrieves a paginated list of agents in your account.

const { data, has_more, next_cursor } = await chatsby.agents.list({
  page_size: 10,
  status: 'active',
});
 
console.log(data); // Array of Agent objects

Parameters:

ParameterTypeDescription
page_sizenumberResults per page (1-100). Default: 20.
statusstringFilter by status: active, paused.
cursorstringPagination cursor.

agents.create()

Creates a new agent.

const agent = await chatsby.agents.create({
  name: 'Customer Support Bot',
  model: 'gpt-4o',
  system_prompt: 'You are a helpful customer support agent for Acme Corp.',
  temperature: 0.5,
  max_tokens: 1024,
});
 
console.log(agent.id); // "agent_f7g8h9i0j1"

Parameters:

ParameterTypeRequiredDescription
namestringYesAgent display name.
modelstringNoAI model. Default: gpt-4o.
system_promptstringNoBehavioral instructions.
temperaturenumberNoRandomness (0.0-2.0). Default: 0.7.
max_tokensnumberNoMax response tokens (1-4096). Default: 1024.

agents.get()

Retrieves a single agent by ID.

const agent = await chatsby.agents.get('agent_1a2b3c4d5e');
console.log(agent.name);         // "Customer Support Bot"
console.log(agent.status);       // "active"
console.log(agent.system_prompt);

agents.update()

Updates one or more fields on an agent. Only include the fields you want to change.

const updated = await chatsby.agents.update('agent_1a2b3c4d5e', {
  system_prompt: 'Updated instructions: Be concise and always provide links.',
  temperature: 0.3,
});
 
console.log(updated.updated_at); // New timestamp

agents.delete()

Permanently deletes an agent and all its associated sources and conversations.

await chatsby.agents.delete('agent_1a2b3c4d5e');
// No return value — throws on error

Deleting an agent is irreversible. All sources and conversations belonging to the agent are permanently removed. If you want to temporarily disable an agent, use agents.update() to set status: 'paused'.

Sources

sources.list()

Lists all sources for a given agent.

const { data, has_more, next_cursor } = await chatsby.sources.list('agent_1a2b3c4d5e', {
  page_size: 50,
  status: 'trained',
  type: 'website',
});
 
for (const source of data) {
  console.log(`${source.id}: ${source.type}${source.status} (${source.character_count} chars)`);
}

Parameters:

ParameterTypeDescription
page_sizenumberResults per page (1-100). Default: 20.
statusstringFilter: pending, processing, trained, failed.
typestringFilter: website, text, file, qa.
cursorstringPagination cursor.

sources.create()

Adds a new source to an agent. Processing begins immediately.

// Website source
const websiteSource = await chatsby.sources.create('agent_1a2b3c4d5e', {
  type: 'website',
  content: 'https://acme.com/help',
  crawl_subpages: true,
});
 
// Text source
const textSource = await chatsby.sources.create('agent_1a2b3c4d5e', {
  type: 'text',
  content: 'Acme Corp was founded in 2020 and is headquartered in San Francisco.',
});
 
// Q&A source
const qaSource = await chatsby.sources.create('agent_1a2b3c4d5e', {
  type: 'qa',
  content: JSON.stringify([
    { question: 'What are your business hours?', answer: 'Monday to Friday, 9 AM to 6 PM EST.' },
    { question: 'How do I reset my password?', answer: 'Click Forgot Password on the login page.' },
  ]),
});
 
console.log(websiteSource.status); // "pending"

sources.get()

Retrieves a single source by ID.

const source = await chatsby.sources.get('src_abc123defg');
console.log(source.status);          // "trained"
console.log(source.character_count);  // 24580

sources.delete()

Permanently removes a source from the agent's knowledge base.

await chatsby.sources.delete('src_abc123defg');

sources.refresh()

Re-crawls a website source to pick up content changes. Only works for website type sources.

const refreshed = await chatsby.sources.refresh('src_abc123defg');
console.log(refreshed.status); // "processing"

Conversations

conversations.create()

Sends a message to an agent and receives a response. Creates a new conversation or continues an existing one.

// New conversation
const result = await chatsby.conversations.create({
  agent_id: 'agent_1a2b3c4d5e',
  message: 'What is your return policy?',
  metadata: {
    user_id: 'usr_12345',
    plan: 'premium',
  },
});
 
console.log(result.reply);           // "Our return policy allows..."
console.log(result.conversation_id); // "conv_xyz789abcd"
console.log(result.sources_used);    // [{ id: "src_...", title: "..." }]
 
// Continue the conversation
const followUp = await chatsby.conversations.create({
  agent_id: 'agent_1a2b3c4d5e',
  message: 'Does that include sale items?',
  conversation_id: result.conversation_id,
});

conversations.stream()

Sends a message and returns an async iterator that yields streaming events.

const stream = await chatsby.conversations.stream({
  agent_id: 'agent_1a2b3c4d5e',
  message: 'Explain your pricing plans in detail.',
});
 
let fullResponse = '';
 
for await (const event of stream) {
  if (event.type === 'token') {
    process.stdout.write(event.content);
    fullResponse += event.content;
  }
 
  if (event.type === 'done') {
    console.log('\n\nConversation:', event.conversation_id);
  }
 
  if (event.type === 'error') {
    console.error('Error:', event.message);
    break;
  }
}

conversations.list()

Lists conversations for an agent with optional filtering.

const { data, has_more, next_cursor } = await chatsby.conversations.list('agent_1a2b3c4d5e', {
  page_size: 20,
  created_after: '2025-03-01T00:00:00Z',
  metadata: { plan: 'premium' },
});
 
for (const conversation of data) {
  console.log(`${conversation.id}${conversation.created_at}`);
}

conversations.get()

Retrieves a conversation with its full message history.

const conversation = await chatsby.conversations.get('conv_xyz789abcd');
 
console.log(`Messages: ${conversation.messages.length}`);
 
for (const msg of conversation.messages) {
  console.log(`[${msg.role}] ${msg.content}`);
}

conversations.delete()

Permanently deletes a conversation and all its messages.

await chatsby.conversations.delete('conv_xyz789abcd');

Error Handling

The SDK throws typed errors that you can catch and inspect:

import { Chatsby, ChatsbyError, AuthenticationError, NotFoundError, RateLimitError } from '@chatsby/sdk';
 
const chatsby = new Chatsby({ apiKey: process.env.CHATSBY_API_KEY });
 
try {
  const agent = await chatsby.agents.get('agent_nonexistent');
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log('Agent not found:', error.message);
    console.log('Status:', error.status);   // 404
    console.log('Code:', error.code);       // "resource_not_found"
  } else if (error instanceof AuthenticationError) {
    console.log('Invalid API key:', error.message);
  } else if (error instanceof RateLimitError) {
    console.log('Rate limited. Retry after:', error.retryAfter, 'seconds');
  } else if (error instanceof ChatsbyError) {
    // Catch-all for any Chatsby API error
    console.log('API error:', error.message);
    console.log('Type:', error.type);
    console.log('Status:', error.status);
  } else {
    // Network error, timeout, etc.
    throw error;
  }
}

Error Classes

ClassHTTP StatusDescription
ChatsbyErrorAnyBase class for all Chatsby API errors.
AuthenticationError401Invalid or missing API key.
ForbiddenError403Key lacks required permissions.
NotFoundError404Resource does not exist.
RateLimitError429Rate limit exceeded. Has retryAfter property.
ValidationError422Request failed validation. Has errors array.
ServerError500, 503Server-side error.

TypeScript Support

The SDK is written in TypeScript and exports all types:

import {
  Chatsby,
  Agent,
  Source,
  Conversation,
  Message,
  CreateAgentParams,
  UpdateAgentParams,
  CreateSourceParams,
  CreateConversationParams,
  ListParams,
  PaginatedResponse,
  StreamEvent,
} from '@chatsby/sdk';
 
const chatsby = new Chatsby({ apiKey: process.env.CHATSBY_API_KEY! });
 
// All methods are fully typed
const agent: Agent = await chatsby.agents.create({
  name: 'Support Bot',
  model: 'gpt-4o',
});
 
const sources: PaginatedResponse<Source> = await chatsby.sources.list(agent.id);
 
const stream: AsyncIterable<StreamEvent> = await chatsby.conversations.stream({
  agent_id: agent.id,
  message: 'Hello',
});

Pagination Helpers

For list endpoints, you can iterate through all pages automatically:

// Manual pagination
let cursor = null;
const allAgents = [];
 
do {
  const page = await chatsby.agents.list({ page_size: 100, cursor });
  allAgents.push(...page.data);
  cursor = page.has_more ? page.next_cursor : null;
} while (cursor);
 
console.log(`Total agents: ${allAgents.length}`);
// Helper: collect all pages into an array
async function listAll(listFn, params = {}) {
  const all = [];
  let cursor = null;
 
  do {
    const page = await listFn({ ...params, page_size: 100, cursor });
    all.push(...page.data);
    cursor = page.has_more ? page.next_cursor : null;
  } while (cursor);
 
  return all;
}
 
const allAgents = await listAll((p) => chatsby.agents.list(p));
const allSources = await listAll((p) => chatsby.sources.list('agent_1a2b3c4d5e', p));

Complete Example: Custom Chat Interface

This example builds a simple chat server using Express that proxies requests to the Chatsby API with streaming:

import express from 'express';
import { Chatsby } from '@chatsby/sdk';
 
const app = express();
app.use(express.json());
 
const chatsby = new Chatsby({
  apiKey: process.env.CHATSBY_API_KEY,
});
 
const AGENT_ID = process.env.CHATSBY_AGENT_ID;
 
// Send a message and stream the response
app.post('/api/chat', async (req, res) => {
  const { message, conversation_id, user_id } = req.body;
 
  if (!message) {
    return res.status(400).json({ error: 'Message is required' });
  }
 
  // Set SSE headers
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');
 
  try {
    const stream = await chatsby.conversations.stream({
      agent_id: AGENT_ID,
      message,
      conversation_id,
      metadata: conversation_id ? undefined : { user_id: user_id || 'anonymous' },
    });
 
    for await (const event of stream) {
      res.write(`event: ${event.type}\n`);
      res.write(`data: ${JSON.stringify(event)}\n\n`);
    }
  } catch (error) {
    res.write(`event: error\n`);
    res.write(`data: ${JSON.stringify({ message: error.message })}\n\n`);
  }
 
  res.end();
});
 
// Get conversation history
app.get('/api/conversations/:id', async (req, res) => {
  try {
    const conversation = await chatsby.conversations.get(req.params.id);
    res.json(conversation);
  } catch (error) {
    if (error.status === 404) {
      return res.status(404).json({ error: 'Conversation not found' });
    }
    res.status(500).json({ error: 'Internal server error' });
  }
});
 
// List conversations for a user
app.get('/api/users/:userId/conversations', async (req, res) => {
  try {
    const conversations = await chatsby.conversations.list(AGENT_ID, {
      metadata: { user_id: req.params.userId },
      page_size: 20,
    });
    res.json(conversations);
  } catch (error) {
    res.status(500).json({ error: 'Internal server error' });
  }
});
 
app.listen(3000, () => {
  console.log('Chat server running on http://localhost:3000');
});

This server provides three endpoints:

  • POST /api/chat — Sends a message and streams the response via SSE.
  • GET /api/conversations/:id — Retrieves a conversation with full message history.
  • GET /api/users/:userId/conversations — Lists conversations for a specific user using metadata filtering.

This example is a starting point. For production use, add input validation, authentication middleware for your own users, rate limiting, and proper error logging.