Skip to content

TypeScript / JavaScript SDK

The official SDK for browsers and Node.js applications.

Terminal window
npm install @uchara/sdk
# or
yarn add @uchara/sdk
# or
pnpm add @uchara/sdk
  • Node.js 16+ (for backend)
  • Modern browsers (Chrome 90+, Firefox 88+, Safari 14+)
  • TypeScript 4.5+ (optional, types included)

The SDK provides tree-shakeable exports:

// Import only what you need
import { VisitorSDK } from '@uchara/sdk/visitor';
import { AgentSDK } from '@uchara/sdk/agent';
import { ServerSDK } from '@uchara/sdk/server';
// Or import everything
import { VisitorSDK, AgentSDK, ServerSDK } from '@uchara/sdk';

For embedding chat widget in customer applications.

import { VisitorSDK } from '@uchara/sdk/visitor';
const visitor = new VisitorSDK({
apiURL: 'https://api.uchara.com',
widgetToken: 'wgt_your_token',
contactMetadata: {
user_id: 'user_123',
email: 'customer@example.com',
},
autoConnect: true, // Auto-connect WebSocket after init
});
await visitor.init();
// Get widget config (colors, welcome message)
const config = await visitor.getConfig();
// Get or start conversation
const conv = await visitor.getActiveConversation();
const newConv = await visitor.startConversation({
message: 'Hello!',
});
// Get messages
const messages = await visitor.getMessages(conv.id, { limit: 50 });
// Send message
const message = await visitor.sendMessage(conv.id, {
content: 'I need help with my order',
});
// Upload file
const { url } = await visitor.uploadFile(conv.id, file);
await visitor.sendMessage(conv.id, {
content: 'Here is my receipt',
attachments: [{ url, name: file.name, mime_type: file.type, size: file.size }],
});
// Close conversation
await visitor.closeConversation(conv.id);
visitor.on('message.new', (event) => {
console.log('New message:', event.payload.content);
});
visitor.on('message.delta', (event) => {
// Streaming bot response
if (event.payload.done) {
console.log('Complete:', event.payload.content);
} else {
process.stdout.write(event.payload.delta);
}
});
visitor.on('typing', (event) => {
console.log('Agent is typing...');
});
// Typing indicators
visitor.sendTyping(conv.id);
visitor.stopTyping(conv.id);
import { VisitorSDK } from '@uchara/sdk/visitor';
import { useEffect, useState } from 'react';
function ChatWidget() {
const [sdk] = useState(() => new VisitorSDK({
apiURL: 'https://api.uchara.com',
widgetToken: 'wgt_abc123',
}));
const [messages, setMessages] = useState([]);
useEffect(() => {
sdk.init().then(() => {
sdk.connect();
sdk.on('message.new', (event) => {
setMessages(prev => [...prev, event.payload]);
});
});
return () => sdk.disconnect();
}, []);
const sendMessage = async (content: string) => {
const convId = sdk.getActiveConversationId()
|| (await sdk.startConversation()).id;
await sdk.sendMessage(convId, { content });
};
return (
<div>
{messages.map(msg => <div key={msg.id}>{msg.content}</div>)}
</div>
);
}

For building custom agent dashboards.

import { AgentSDK } from '@uchara/sdk/agent';
const agent = new AgentSDK({
apiURL: 'https://api.uchara.com',
});
// Login
await agent.login({
email: 'agent@company.com',
password: 'your_password',
});
// List conversations
const conversations = await agent.listConversations({
status: 'open',
limit: 20,
});
// Send reply
await agent.sendMessage(conversations[0].id, {
content: 'Hi! How can I help?',
});
// Assign conversation
await agent.assignConversation(convId, { assigned_to: agentId });
// Update workflow
await agent.updateWorkflow(convId, {
status: 'open',
priority: 'high',
waiting_for: 'customer',
});
// Resolve
await agent.resolveConversation(convId);
// Internal notes
await agent.addNote(convId, 'Customer is VIP, handle with care');
// Real-time events
agent.on('conversation.new', (event) => {
console.log('New conversation:', event.payload);
});

For backend-to-backend integration.

import { ServerSDK } from '@uchara/sdk/server';
const server = new ServerSDK({
apiURL: 'https://api.uchara.com',
apiKey: process.env.UCHARA_API_KEY,
});
// Send notification from your backend
await server.sendMessage('conversation_id', {
content: 'Your order #12345 has shipped! 🚚',
sender_type: 'bot',
});
// Upsert contact
const contact = await server.upsertContact({
external_id: 'user_123',
name: 'John Doe',
email: 'john@example.com',
});
// List conversations
const conversations = await server.listConversations({
status: 'open',
});
import { HTTPError } from '@uchara/sdk';
try {
await agent.sendMessage(conversationId, { content: 'Hello' });
} catch (error) {
if (error instanceof HTTPError) {
console.error(`HTTP ${error.status}: ${error.body?.error}`);
if (error.status === 401) {
// Token expired, re-login
} else if (error.status === 429) {
// Rate limited, retry with backoff
}
}
}

All types are exported:

import type {
Message,
Conversation,
Contact,
Member,
Channel,
WSEvent,
} from '@uchara/sdk';
interface VisitorSDKConfig {
apiURL: string;
widgetToken: string;
contactMetadata?: Record<string, unknown>;
autoConnect?: boolean;
}
interface AgentSDKConfig {
apiURL: string;
accessToken?: string;
autoConnect?: boolean;
}
interface ServerSDKConfig {
apiURL: string;
apiKey?: string;
workspaceId?: string;
}