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/sdkThe 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
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | — | Your Chatsby API key. Required. |
baseUrl | string | https://api.chatsby.co/v1 | Override the base URL (useful for testing against a proxy or mock server). |
timeout | number | 30000 | Request timeout in milliseconds. |
maxRetries | number | 2 | Number 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 objectsParameters:
| Parameter | Type | Description |
|---|---|---|
page_size | number | Results per page (1-100). Default: 20. |
status | string | Filter by status: active, paused. |
cursor | string | Pagination 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Agent display name. |
model | string | No | AI model. Default: gpt-4o. |
system_prompt | string | No | Behavioral instructions. |
temperature | number | No | Randomness (0.0-2.0). Default: 0.7. |
max_tokens | number | No | Max 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 timestampagents.delete()
Permanently deletes an agent and all its associated sources and conversations.
await chatsby.agents.delete('agent_1a2b3c4d5e');
// No return value — throws on errorDeleting 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:
| Parameter | Type | Description |
|---|---|---|
page_size | number | Results per page (1-100). Default: 20. |
status | string | Filter: pending, processing, trained, failed. |
type | string | Filter: website, text, file, qa. |
cursor | string | Pagination 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); // 24580sources.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
| Class | HTTP Status | Description |
|---|---|---|
ChatsbyError | Any | Base class for all Chatsby API errors. |
AuthenticationError | 401 | Invalid or missing API key. |
ForbiddenError | 403 | Key lacks required permissions. |
NotFoundError | 404 | Resource does not exist. |
RateLimitError | 429 | Rate limit exceeded. Has retryAfter property. |
ValidationError | 422 | Request failed validation. Has errors array. |
ServerError | 500, 503 | Server-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.
On this page
- Installation
- Configuration
- Configuration Options
- Environment Variables
- Agents
- agents.list()
- agents.create()
- agents.get()
- agents.update()
- agents.delete()
- Sources
- sources.list()
- sources.create()
- sources.get()
- sources.delete()
- sources.refresh()
- Conversations
- conversations.create()
- conversations.stream()
- conversations.list()
- conversations.get()
- conversations.delete()
- Error Handling
- Error Classes
- TypeScript Support
- Pagination Helpers
- Complete Example: Custom Chat Interface