Official SDK for consuming Unthread webhook events from unthread-webhook-server.
This SDK provides a general-purpose, storage-agnostic, platform-agnostic client for any integrator that wants to consume webhooks from the Unthread platform via unthread-webhook-server.
Target users:
- WG Tech Labs bots (Discord, Telegram) - will wire with Nuvex for storage
- Companies building custom dashboards
- Developers building integrations (Slack, Teams, custom apps)
- Any application that needs Unthread webhook data
unthread-webhook-server (queues events to Redis)
│
▼
@wgtechlabs/unthread-webhook-sdk (this package)
│
▼
Integrator's Application (brings their own storage)
npm install @wgtechlabs/unthread-webhook-sdk redisNote: redis is a peer dependency. You must install it separately.
import { UnthreadWebhook } from '@wgtechlabs/unthread-webhook-sdk';
// Create client
const client = new UnthreadWebhook({
redisUrl: 'redis://localhost:6379',
});
// Register event handlers
client
.on('message_created', async (event) => {
console.log('New message:', event.data.message.body);
// Save to your database
})
.on('conversation_created', async (event) => {
console.log('New conversation:', event.data.friendlyId);
})
.on('conversation_updated', async (event) => {
console.log('Conversation updated:', event.data.status);
})
.onError(async (error) => {
console.error('Error processing event:', error);
});
// Connect and start consuming
await client.connect();
await client.start();
// Graceful shutdown
process.on('SIGINT', async () => {
await client.disconnect();
process.exit(0);
});interface UnthreadWebhookConfig {
/** Redis connection URL (required) */
redisUrl: string;
/** Queue name to consume from (default: 'unthread-events') */
queueName?: string;
/** Poll interval in milliseconds (default: 1000) */
pollInterval?: number;
/** Validate events before passing to handlers (default: true) */
validateEvents?: boolean;
/** Custom logger instance */
logger?: Logger;
}const client = new UnthreadWebhook({
redisUrl: 'redis://localhost:6379',
queueName: 'my-custom-queue',
pollInterval: 2000,
validateEvents: true,
logger: {
info: (msg, ...args) => console.log(msg, ...args),
warn: (msg, ...args) => console.warn(msg, ...args),
error: (msg, ...args) => console.error(msg, ...args),
debug: (msg, ...args) => console.debug(msg, ...args),
},
});Main client class for consuming webhook events.
Creates a new instance of the webhook client.
Connects to Redis. Must be called before start().
Starts consuming events from the Redis queue.
Stops consuming events from the queue.
Stops consuming and disconnects from Redis.
Registers a handler for message_created events.
Registers a handler for conversation_created events.
Registers a handler for conversation_updated events.
Registers a handler that receives all event types.
Registers an error handler for processing errors.
Returns true if connected to Redis, false otherwise.
Triggered when a new message is created in a conversation.
{
type: 'message_created',
platform: Platform,
targetPlatform: Platform,
sourcePlatform: 'dashboard' | 'api' | 'unknown',
timestamp: string, // ISO 8601
data: {
conversationId: string,
messageId: string,
message: {
id: string,
body: string,
authorType: 'agent' | 'customer' | 'system',
author?: {
id: string,
name: string,
email?: string,
},
createdAt: string, // ISO 8601
},
customer?: {
id: string,
name?: string,
email?: string,
},
},
}Triggered when a new conversation is created.
{
type: 'conversation_created',
platform: Platform,
targetPlatform: Platform,
sourcePlatform: 'dashboard' | 'api' | 'unknown',
timestamp: string, // ISO 8601
data: {
id: string,
conversationId: string,
friendlyId: string,
title?: string,
status: 'open' | 'closed' | 'pending' | 'resolved',
priority?: 'low' | 'medium' | 'high' | 'urgent',
customer?: {
id: string,
name?: string,
email?: string,
},
assignee?: {
id: string,
name: string,
email?: string,
},
createdAt: string, // ISO 8601
},
}Triggered when a conversation is updated.
{
type: 'conversation_updated',
platform: Platform,
targetPlatform: Platform,
sourcePlatform: 'dashboard' | 'api' | 'unknown',
timestamp: string, // ISO 8601
data: {
id: string,
conversationId: string,
friendlyId: string,
status: 'open' | 'closed' | 'pending' | 'resolved',
previousStatus?: 'open' | 'closed' | 'pending' | 'resolved',
updatedFields: string[],
updatedAt: string, // ISO 8601
},
}import { UnthreadWebhook } from '@wgtechlabs/unthread-webhook-sdk';
const client = new UnthreadWebhook({
redisUrl: process.env.REDIS_URL!,
});
client.onAny(async (event) => {
console.log(`Received ${event.type} event`);
});
await client.connect();
await client.start();import { UnthreadWebhook } from '@wgtechlabs/unthread-webhook-sdk';
import { MyDatabase } from './database'; // Your storage layer
const db = new MyDatabase();
const client = new UnthreadWebhook({
redisUrl: process.env.REDIS_URL!,
});
client.on('message_created', async (event) => {
// Save to YOUR database (MongoDB, PostgreSQL, etc.)
await db.messages.create({
id: event.data.messageId,
conversationId: event.data.conversationId,
body: event.data.message.body,
authorType: event.data.message.authorType,
createdAt: event.data.message.createdAt,
});
});
client.on('conversation_created', async (event) => {
// Save to YOUR database
await db.conversations.create({
id: event.data.conversationId,
friendlyId: event.data.friendlyId,
status: event.data.status,
customerId: event.data.customer?.id,
});
});
await client.connect();
await client.start();import { UnthreadWebhook, ValidationError, ConnectionError } from '@wgtechlabs/unthread-webhook-sdk';
const client = new UnthreadWebhook({
redisUrl: process.env.REDIS_URL!,
});
client.on('message_created', async (event) => {
// Your handler logic
await processMessage(event);
});
client.onError(async (error) => {
if (error instanceof ValidationError) {
console.error('Invalid event received:', error.eventData);
} else if (error instanceof ConnectionError) {
console.error('Redis connection error:', error.message);
// Implement reconnection logic
} else {
console.error('Unexpected error:', error);
}
});
await client.connect();
await client.start();import { UnthreadWebhook, Platform } from '@wgtechlabs/unthread-webhook-sdk';
const client = new UnthreadWebhook({
redisUrl: process.env.REDIS_URL!,
});
client.on('message_created', async (event) => {
if (event.platform === Platform.DISCORD) {
// Handle Discord-specific logic
await sendToDiscordBot(event);
} else if (event.platform === Platform.TELEGRAM) {
// Handle Telegram-specific logic
await sendToTelegramBot(event);
}
});
await client.connect();
await client.start();Base error class for all SDK errors.
class UnthreadError extends Error {
code: string;
cause?: Error;
}Thrown for Redis connection errors.
class ConnectionError extends UnthreadError {
// Extends UnthreadError with code: 'CONNECTION_ERROR'
}Thrown when an event fails validation.
class ValidationError extends UnthreadError {
eventData?: unknown;
// Extends UnthreadError with code: 'VALIDATION_ERROR'
}npm run buildnpm testnpm run typecheck- unthread-webhook-server - The webhook server that queues events to Redis
GPL-3.0 © Waren Gonzaga
Waren Gonzaga
- Website: warengonzaga.com
- Email: [email protected]
- GitHub: @warengonzaga
Made with ❤️ by WG Tech Labs