Skip to main content

Wonderful SDK for TypeScript

A TypeScript SDK for integrating Wonderful’s contact center capabilities into your mobile apps and web clients. Supports real-time WebSocket chat, JWT authentication, session recovery, and communication history.

Installation

Add the Wonderful registry to your project’s .npmrc:
echo '@wonderful-sdk:registry=https://wonderfulcx.jfrog.io/artifactory/api/npm/npm-local-prod/' >> .npmrc
Then install with your package manager:
npm install @wonderful-sdk/contact-center
# or
yarn add @wonderful-sdk/contact-center
# or
pnpm add @wonderful-sdk/contact-center

Quick Start

import { WonderfulSDK } from '@wonderful-sdk/contact-center';

// Initialize the SDK
const sdk = new WonderfulSDK({
  baseUrl: 'https://api.wonderful.ai',
  token: 'your-jwt-token'
});

// Start a chat session
const session = await sdk.chat.start({
  from: 'user-123',
  fromType: 'phone'
});

// Send a message
await session.send({ type: 'text', text: 'Hello!' });

// Listen for events
const unsubscribe = session.onEvent((event) => {
  switch (event.type) {
    case 'message':
      console.log(`${event.data.speaker}: ${event.data.data.text}`);
      break;
    case 'connected':
      console.log('Connected to session:', event.data.sessionId);
      break;
    case 'disconnected':
      if (event.data.willRetry) {
        console.log('Connection lost, reconnecting...');
      }
      break;
    case 'reconnected':
      console.log('Reconnected!');
      break;
    case 'error':
      console.error('Error:', event.data.message);
      break;
    case 'ended':
      console.log('Session ended by:', event.data.endedBy);
      break;
  }
});

// End the session
await session.end();

SDK Initialization

import { WonderfulSDK } from '@wonderful-sdk/contact-center';

const sdk = new WonderfulSDK(config: SDKConfig);

SDKConfig

interface SDKConfig {
  /** Base URL for the Wonderful API */
  baseUrl: string;
  /** Auth token (JWT) - use this OR apiKey */
  token?: string;
  /** SDK-signed JWT - use this with refreshToken for frontend apps */
  signedToken?: string;
  /** API key - use this OR token (recommended for server-side) */
  apiKey?: string;
  /** Request timeout in milliseconds (default: 30000) */
  timeout?: number;
  /** Enable debug logging */
  debug?: boolean;
  /**
   * Async callback to refresh the JWT when it expires.
   * Called automatically on 401 responses.
   */
  refreshToken?: (entityId: string) => Promise<string>;
}
Provide one of token, signedToken, or apiKey. Use apiKey on the backend only; use signedToken (with refreshToken) on the frontend.

Initialization Examples

// Using JWT token (for browser/mobile apps)
const sdk = new WonderfulSDK({
  baseUrl: 'https://api.wonderful.ai',
  token: 'your-jwt-token',
  timeout: 30000,
  debug: false
});

// Using signed token with refresh (recommended for frontend)
const sdk = new WonderfulSDK({
  baseUrl: 'https://api.wonderful.ai',
  signedToken: tokenFromBackend,
  refreshToken: async (entityId) => {
    const response = await fetch('/api/refresh-sdk-token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ entityId }),
    });
    const { token } = await response.json();
    return token;
  }
});

// Using API key (for server-side integrations)
const sdk = new WonderfulSDK({
  baseUrl: 'https://api.wonderful.ai',
  apiKey: 'your-api-key',
  timeout: 30000,
  debug: false
});

Default Behavior

SettingDefaultDescription
Request timeout30,000msHTTP request timeout
Max retries3Automatic retry on network errors
Retry delay1,000msInitial delay (exponential backoff)
WebSocket ping30,000msKeep-alive interval
Max reconnect attempts5WebSocket reconnection limit

Modules

ModuleDescriptionDocs
sdk.authSign JWTs for end-user authentication (backend only, requires apiKey)Authentication
sdk.chatStart, recover, and manage real-time chat sessions via WebSocketChat
sdk.communicationsQuery communication history with filtering and paginationCommunications

Additional Methods

Property / MethodDescription
sdk.configCurrent SDK configuration (read-only copy)
sdk.setToken(token)Update the authentication token at runtime
sdk.clearAuth()Clear all auth credentials from the SDK
WonderfulSDK.versionSDK version string
// Update token at runtime
const newToken = await fetchNewToken();
sdk.setToken(newToken);

// Check SDK version
console.log(WonderfulSDK.version); // '0.2.0'

Backend Integration

The SDK uses a backend + frontend architecture. Your backend signs JWTs using an API key (never exposed to browsers), and your frontend uses those tokens to connect.

Express.js Token Endpoint

import express from 'express';
import { WonderfulSDK } from '@wonderful-sdk/contact-center';

const app = express();
app.use(express.json());

const sdk = new WonderfulSDK({
  baseUrl: process.env.WONDERFUL_API_URL,
  apiKey: process.env.WONDERFUL_API_KEY  // Keep secret — server-side only
});

// Endpoint for frontend to get SDK tokens
app.post('/api/sdk-token', async (req, res) => {
  const { userId } = req.user; // From your auth middleware

  const { jwt, expiresAt, id } = await sdk.auth.sign({
    id: userId,  // Ties communications to this user
    metadata: {
      email: req.user.email,
      plan: req.user.subscription
    }
  });

  res.json({ token: jwt, expiresAt, id });
});

Frontend Connection

import { WonderfulSDK } from '@wonderful-sdk/contact-center';

async function getToken(entityId: string): Promise<string> {
  const res = await fetch('http://localhost:3001/auth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ entityId }),
  });
  const { token } = await res.json();
  return token;
}

const entityId = 'user-123';
const token = await getToken(entityId);

const sdk = new WonderfulSDK({
  baseUrl: 'https://api.wonderful.ai',
  signedToken: token,
  refreshToken: async (id) => getToken(id), // Auto-refresh on 401
});

const session = await sdk.chat.start({
  from: entityId,
  fromType: 'phone',
});

Complete Example

import { WonderfulSDK, SessionEvent, Message } from '@wonderful-sdk/contact-center';

// Initialize
const sdk = new WonderfulSDK({
  baseUrl: 'https://api.wonderful.ai',
  signedToken: tokenFromBackend,
  refreshToken: async (entityId) => fetchNewToken(entityId),
});

// Start session
const session = await sdk.chat.start({
  from: '+1234567890',
  fromType: 'phone',
  agentId: 'support-agent-uuid',
  metadata: { name: 'John Doe', gender: 'male', platform: 'app' }
});

console.log('Session started:', session.sessionId);

// Subscribe to events
const unsubscribe = session.onEvent((event: SessionEvent) => {
  switch (event.type) {
    case 'message':
      const msg = event.data;
      if (msg.speaker === 'agent') {
        displayAgentMessage(msg.data.text);
      }
      break;

    case 'disconnected':
      if (event.data.willRetry) {
        showToast('Connection lost. Reconnecting...');
      }
      break;

    case 'reconnected':
      showToast('Reconnected!');
      break;

    case 'error':
      if (!event.data.recoverable) {
        showError(event.data.message);
      }
      break;

    case 'ended':
      showToast(`Chat ended by ${event.data.endedBy}`);
      navigateToHome();
      break;
  }
});

// Send messages
await session.send({ type: 'text', text: 'Hi, I need help with my order' });

// Later: end session
await session.end();
unsubscribe();

Mobile App Recovery Pattern

// On app launch
async function initChat() {
  const savedSessionId = await storage.get('currentSessionId');

  if (savedSessionId) {
    try {
      const session = await sdk.chat.recover(savedSessionId);

      if (session.status === 'in-progress') {
        // Show existing messages
        renderMessages(session.messages);

        // Subscribe to new events
        session.onEvent(handleEvent);

        return session;
      }
    } catch (error) {
      // Session not found or expired
      await storage.remove('currentSessionId');
    }
  }

  // Start new session
  const session = await sdk.chat.start({
    from: await getUserIdentifier(),
    fromType: 'phone'
  });
  await storage.set('currentSessionId', session.sessionId);

  session.onEvent(handleEvent);
  return session;
}

Error Handling

import { SDKError } from '@wonderful-sdk/contact-center';

try {
  await session.send({ type: 'text', text: 'Hello' });
} catch (error) {
  if (error instanceof SDKError) {
    console.log('Error code:', error.code);
    console.log('Recoverable:', error.recoverable);

    switch (error.code) {
      case 'AUTH_EXPIRED':
        // If refreshToken is configured, the SDK retries automatically
        break;
      case 'NETWORK_ERROR':
        // SDK will auto-retry WebSocket connections
        break;
      case 'SESSION_NOT_FOUND':
        // Session ended or invalid — start a new one
        break;
    }
  }
}

Error Codes

CodeDescriptionRecoverable
INVALID_REQUESTMissing required field or invalid parameterNo
MISSING_PARTICIPANTfrom and fromType are requiredNo
SESSION_NOT_FOUNDSession does not exist or was not initializedNo
SESSION_ENDEDSession has already endedNo
PII_MASKING_ENABLEDLive streaming blocked due to PII maskingNo
NETWORK_ERRORNetwork request failedYes
AUTH_ERRORMissing or invalid authentication credentialsNo
AUTH_EXPIREDJWT token expiredYes (refresh)
UNAUTHORIZEDInvalid or missing API keyNo
FORBIDDENInsufficient permissions (HTTP 403)No
VALIDATION_ERRORRequest validation failed (invalid params, metadata too large)No
RATE_LIMITEDToo many requestsYes (retry)
UNKNOWN_ERRORUnexpected error occurredDepends

Exported Types

All types are exported for TypeScript users:
import {
  // Main SDK
  WonderfulSDK,

  // Auth types
  type AuthClient,
  type SignRequest,
  type SignResponse,
  AUTH_VALIDATION,

  // Chat types
  type ChatClient,
  type ChatSession,
  type ChatStartParams,
  type SDKConfig,
  type SessionParticipant,

  // Message types
  type ChatMessage,
  type Message,
  type MessageData,
  type MessageDataType,
  type MessageAction,
  type ActionType,
  type SendResponse,
  type Speaker,
  type IdentityType,

  // Event types
  type SessionEvent,
  type SessionEventCallback,
  type Unsubscribe,
  type MessageEvent,
  type ConnectedEvent,
  type DisconnectedEvent,
  type ReconnectingEvent,
  type ReconnectedEvent,
  type ErrorEvent,
  type SessionEndedEvent,
  type ConnectionState,
  type SessionStatus,
  type DisconnectReason,
  type EndedReason,

  // Communications types
  type CommunicationsClient,
  type Communication,
  type CommunicationType,
  type CommunicationStatus,
  type CommunicationDirection,
  type CommunicationInteractor,
  type ListCommunicationsParams,
  type ListCommunicationsResponse,

  // Error types
  SDKError,
  type SDKErrorCode,
  type SDKErrorDetails,
} from '@wonderful-sdk/contact-center';

Feature Support

FeatureStatusNotes
Text messagesSupportedSend and receive
Image messagesSupportedVia mediaUrl
Document messagesSupportedVia mediaUrl + fileName
Voice/Audio messagesReceive onlyCannot send via SDK
Location messagesReceive onlyCannot send via SDK
Session metadataSupportedCustom key-value pairs on start
Message metadataSupportedCustom data per message
Session recoverySupportedsdk.chat.recover(sessionId)
Session forwardingSupportedsession.forward(destination)
Auto-reconnectSupportedExponential backoff (max 5 attempts)
Token refreshSupportedVia refreshToken callback
Typing indicatorsNot availablePlatform feature only
Read receiptsNot availablePlatform feature only
Presence statusNot availableNot implemented