Skip to content

SDK Reference

Complete API reference for the Coherence JavaScript SDK.

Configuration

The SDK configuration comes from two sources:

  1. Backend Configuration: Set in your Coherence dashboard and automatically loaded by the SDK
  2. Frontend Configuration: Passed to Coherence.init() and used as fallback for any settings not configured in the backend

Backend Configuration

The following settings can be configured in your Coherence dashboard and will automatically override frontend defaults:

Setting Type Description
name string Assistant name shown in modal header (default: "Ask AI")
placeholderText string Help text shown in modal input (default: "How can I help you today?")
triggerConfig.showTriggerButton boolean Whether to show floating trigger button (default: true)
triggerConfig.triggerText string Text displayed on trigger button (default: "Open Chat")
triggerConfig.triggerClassName string CSS class for custom trigger styling (default: "")
triggerConfig.position string Trigger position: 'bottom-right', 'bottom-left', 'top-right', 'top-left' (default: "bottom-right")
triggerConfig.containerRef string Container reference for modal mounting (optional)
threadSuggestions string[] List of suggested conversation starters (default: [])
theme object Open-ended theme object for frontend customization (default: {})

Benefits of Backend Configuration: - Centralized configuration management - No code changes required for UI updates - Consistent settings across all SDK instances - Easy A/B testing and feature toggles

Initialization

Coherence.init(config)

Initializes the Coherence SDK with your configuration.

Parameters:

interface InitConfig {
  // OAuth Mode Configuration
  oauth?: {
    enabled: boolean;
    appId: string;
    getToken: () => Promise<string> | string;
    getHeaders?: () => Promise<Record<string, string>> | Record<string, string>;
    cookieNames?: string[];
    onTokenRefresh?: (result: TokenRefreshResult) => void;
    tokenHeaderName?: string;
  };

  // Backend SDK Mode Configuration
  // this is the route in your backend you added the Coherence interation to
  chatEndpoint?: string;
  // Optional: your app's backend URL if different from frontend host
  appBackendUrl?: string;

  // UI Configuration (Frontend Fallbacks)

  // Note: These are overridden by backend configuration when 
  // available (from the Coherence dashboard)
  name?: string;
  placeholderText?: string;
  threadSuggestions?: string[];
  triggerConfig?: {
    triggerText?: string;
    triggerClassName?: string;
    showTriggerButton?: boolean;
    position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
    headless?: boolean;
    containerRef?: string;
  };

  // Theme Configuration (also overriden by dashboard-set options)
  theme?: {
    primaryColor?: string;
    backgroundColor?: string;
    textColor?: string;
    borderRadius?: string;
    fontFamily?: string;
    customStyles?: string;
  };

  // Advanced Options
  extraContext?: Record<string, any>;
  getExtraContext?: () => Promise<Record<string, any>> | Record<string, any>;
  debug?: boolean;
  onError?: (error: CoherenceError) => void;
  onConnectionChange?: (connected: boolean) => void;
}

Returns: Promise<void>

Example:

await Coherence.init({
  oauth: {
    enabled: true,
    appId: 'app_123',
    getToken: async () => {
      const session = await getAuthSession();
      return session.token;
    }
  }
});

Core Methods

Coherence.show()

Shows the chat modal interface.

Returns: void

Example:

Coherence.show();

Coherence.hide()

Hides the chat modal interface.

Returns: void

Example:

Coherence.hide();

Coherence.toggle()

Toggles the chat modal visibility.

Returns: void

Example:

Coherence.toggle();

Coherence.isVisible()

Returns whether the chat modal is currently visible.

Returns: boolean

Example:

if (Coherence.isVisible()) {
  console.log('Chat is open');
}

Coherence.sendMessage(message, options)

Sends a message programmatically to the chat interface.

Parameters: - message: string | MessageContent[] - The message to send - options?: SendMessageOptions - Additional options

interface SendMessageOptions {
  autoShow?: boolean; // Whether to show chat modal (default: true)
  role?: 'user' | 'assistant'; // Message role (default: 'user')
  extraContext?: Record<string, any>; // Additional context for this message
}

Returns: Promise<{success: boolean}>

Example:

// Send a simple text message
await Coherence.sendMessage('Hello, how can you help me?');

// Send message with context without showing modal
await Coherence.sendMessage('Show me my analytics', {
  autoShow: false,
  extraContext: {
    currentPage: 'dashboard',
    selectedMetrics: ['revenue', 'users']
  }
});

// Send complex content
await Coherence.sendMessage([
  { type: 'text', text: 'Check this image:' },
  { type: 'image', url: 'https://example.com/chart.png' }
]);

Coherence.getInstance()

Returns the SDK instance for advanced usage.

Returns: CoherenceInstance

Example:

const instance = Coherence.getInstance();

Coherence.destroy()

Destroys the SDK instance and cleans up resources.

Returns: void

Example:

Coherence.destroy();

Instance Methods

Access these methods via Coherence.getInstance():

updateConfig(config)

Updates the SDK configuration dynamically.

Parameters: Partial InitConfig object

Returns: void

Example:

const instance = Coherence.getInstance();
instance.updateConfig({
  triggerText: 'Need Help?',
  theme: {
    primaryColor: '#10b981'
  }
});

getStore()

Returns the conversation store for custom UI implementations.

Returns: ConversationStore

Example:

const store = Coherence.getInstance().getStore();

Conversation Store API

Access via Coherence.getInstance().getStore():

State Management

getState()

Returns the current state of the conversation store.

Returns:

interface StoreState {
  conversations: Conversation[];
  activeConversation: Conversation | null;
  messages: Message[];
  loading: boolean;
  error: Error | null;
  user: User | null;
}

Example:

const state = store.getState();
console.log('Active conversation:', state.activeConversation);

subscribe(listener)

Subscribes to state changes.

Parameters: - listener: (state: StoreState) => void - Function called on state changes

Returns: () => void - Unsubscribe function

Example:

const unsubscribe = store.subscribe((state) => {
  console.log('New state:', state);
});

// Later: unsubscribe();

Conversation Management

getConversations()

Fetches all conversations for the current user.

Returns: Promise<Conversation[]>

Example:

const conversations = await store.getConversations();

createConversation(options)

Creates a new conversation.

Parameters:

interface CreateConversationOptions {
  title?: string;
  metadata?: Record<string, any>;
}

Returns: Promise<Conversation>

Example:

const conversation = await store.createConversation({
  title: 'Product Support'
});

setActiveConversation(conversationId)

Sets the active conversation and loads its messages.

Parameters: - conversationId: string - The conversation ID

Returns: Promise<void>

Example:

await store.setActiveConversation('conv_123');

updateConversation(conversationId, updates)

Updates a conversation's properties.

Parameters: - conversationId: string - The conversation ID - updates: Partial<Conversation> - Properties to update

Returns: Promise<Conversation>

Example:

await store.updateConversation('conv_123', {
  title: 'Resolved: Product Issue',
  status: 'archived'
});

deleteConversation(conversationId)

Deletes a conversation.

Parameters: - conversationId: string - The conversation ID

Returns: Promise<void>

Example:

await store.deleteConversation('conv_123');

Message Management

sendMessage(options)

Sends a message in the active conversation.

Parameters:

interface SendMessageOptions {
  content: MessageContent[];
  conversationId?: string; // Defaults to active conversation
  metadata?: Record<string, any>;
  extraContext?: Record<string, any>; // Additional context for AI
}

interface MessageContent {
  type: 'text' | 'image' | 'file';
  text?: string;
  url?: string;
  name?: string;
  size?: number;
}

Returns: Promise<Message>

Example:

// Send text message
await store.sendMessage({
  content: [{ type: 'text', text: 'Hello!' }]
});

// Send message with image
await store.sendMessage({
  content: [
    { type: 'text', text: 'Check this out:' },
    { type: 'image', url: 'https://example.com/image.jpg' }
  ]
});

// Send message with additional context for the AI
await store.sendMessage({
  content: [{ type: 'text', text: 'Help me analyze this data' }],
  extraContext: {
    currentPage: 'analytics',
    selectedMetrics: ['revenue', 'users'],
    timeRange: 'last-30-days'
  }
});

getMessages(conversationId)

Gets all messages for a conversation.

Parameters: - conversationId: string - The conversation ID

Returns: Promise<Message[]>

Example:

const messages = await store.getMessages('conv_123');

streamResponse(messageId)

Streams the AI response for a message.

Parameters: - messageId: string - The user message ID

Returns: EventSource - Server-sent events stream

Example:

const stream = store.streamResponse('msg_123');

stream.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  console.log('Partial response:', data);
});

stream.addEventListener('error', (error) => {
  console.error('Stream error:', error);
});

File Uploads

uploadFile(file)

Uploads a file for use in messages.

Parameters: - file: File - The file to upload

Returns: Promise<UploadedFile>

Example:

const input = document.getElementById('file-input');
const file = input.files[0];

const uploaded = await store.uploadFile(file);
console.log('File URL:', uploaded.url);

Data Types

Conversation

interface Conversation {
  id: string;
  title: string;
  status: 'regular' | 'archived';
  created_at: string;
  updated_at: string;
  last_message_at: string;
  metadata?: Record<string, any>;
}

Message

interface Message {
  id: string;
  conversation_id: string;
  role: 'user' | 'assistant';
  content: MessageContent[];
  created_at: string;
  metadata?: Record<string, any>;
}

User

interface User {
  id: string;
  app_id: string;
  created_at: string;
  metadata?: Record<string, any>;
}

Error Types

interface CoherenceError {
  type: 'AUTH_FAILED' | 'NETWORK_ERROR' | 'RATE_LIMIT' | 'VALIDATION_ERROR' | 'UNKNOWN';
  message: string;
  details?: any;
}

Events

The SDK emits various events you can listen to:

Window Events

// Chat opened
window.addEventListener('coherence:open', (event) => {
  console.log('Chat opened');
});

// Chat closed
window.addEventListener('coherence:close', (event) => {
  console.log('Chat closed');
});

// New message received
window.addEventListener('coherence:message', (event) => {
  console.log('New message:', event.detail);
});

// Error occurred
window.addEventListener('coherence:error', (event) => {
  console.error('Error:', event.detail);
});

Advanced Usage

Extra Context for AI

Provide additional context to help the AI understand the user's current situation and give more relevant responses.

Static Context (Initialization)

await Coherence.init({
  oauth: {
    enabled: true,
    appId: 'app_123',
    getToken: async () => getToken()
  },
  // Static context applied to all conversations
  extraContext: {
    userRole: 'admin',
    permissions: ['read', 'write', 'delete'],
    currentWorkspace: 'acme-corp'
  }
});

Dynamic Context (Callback)

For context that changes based on the current state of your application, use the getExtraContext callback. This function is called automatically for every message in both the default UI and when using sendMessage() without explicit context:

await Coherence.init({
  oauth: {
    enabled: true,
    appId: 'app_123',
    getToken: async () => getToken()
  },
  // Dynamic context callback - called for every message
  getExtraContext: async () => {
    // Fetch current application state
    const currentUser = await getCurrentUser();
    const currentPage = window.location.pathname;
    const selectedItems = getSelectedItems();

    return {
      userRole: currentUser.role,
      currentPage: currentPage,
      selectedItems: selectedItems,
      timestamp: new Date().toISOString(),
      // Any other dynamic context
      userPreferences: await getUserPreferences()
    };
  },
  // Static fallback context
  extraContext: {
    appVersion: '1.0.0',
    environment: 'production'
  }
});

When is getExtraContext called?

  • Default UI: Every time a user types a message and presses send
  • sendMessage() without context: When calling sendMessage() without providing extraContext in options
  • Error handling: If the callback throws an error, it falls back to static context

Benefits of dynamic context:

  • Real-time context based on current app state
  • No need to manually update context when user navigates or changes selection
  • Async support for API calls or complex state retrieval
  • Automatic fallback to static context if callback fails

Per-Message Context

const store = Coherence.getInstance().getStore();

// Context for specific message
await store.sendMessage({
  content: [{ type: 'text', text: 'Show me the quarterly report' }],
  extraContext: {
    quarter: 'Q3-2024',
    reportType: 'financial',
    department: 'sales'
  }
});

Context Precedence and Merging

When multiple context sources are provided, they are merged with the following precedence (higher precedence overwrites lower):

  1. Per-message context (highest precedence) - provided via sendMessage({ extraContext: ... })
  2. Dynamic context - returned by getExtraContext() callback
  3. Static context (lowest precedence) - provided via extraContext in initialization
// Static context from init
const staticContext = { userRole: 'admin', theme: 'dark', appVersion: '1.0.0' };

// Dynamic context from callback
const dynamicContext = { theme: 'light', currentPage: 'dashboard', timestamp: '2024-01-01' };

// Message context
const messageContext = { currentPage: 'analytics', customData: 'special' };

// Final context sent to AI: 
// { 
//   userRole: 'admin',        // from static (not overridden)
//   theme: 'light',           // from dynamic (overrides static)
//   appVersion: '1.0.0',      // from static (not overridden)
//   currentPage: 'analytics', // from message (overrides dynamic)
//   timestamp: '2024-01-01',  // from dynamic (not overridden)
//   customData: 'special'     // from message (new)
// }

Important Notes: - The getExtraContext callback is called for every message, allowing truly dynamic context - Dynamic context can be async and perform API calls or complex calculations - If getExtraContext throws an error, it falls back to static context - All context merging is shallow (nested objects are not deep merged)

Custom Authentication Headers

await Coherence.init({
  oauth: {
    enabled: true,
    appId: 'app_123',
    getToken: async () => {
      return localStorage.getItem('token');
    },
    getHeaders: async () => {
      // These headers are sent with every message request
      return {
        'X-API-Key': await getApiKey(),
        'X-User-Context': JSON.stringify({
          timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
          locale: navigator.language
        })
      };
    }
  }
});
await Coherence.init({
  oauth: {
    enabled: true,
    appId: 'app_123',
    getToken: async () => getToken(),
    cookieNames: ['sessionId', 'workspace', 'preferences'],
    // Cookies with these names will be automatically included
    // in message requests to your API
  }
});

Error Recovery

await Coherence.init({
  oauth: {
    enabled: true,
    appId: 'app_123',
    getToken: async () => getToken(),
    onTokenRefresh: (result) => {
      if (result.error) {
        // Token refresh failed
        if (result.error.type === 'AUTH_FAILED') {
          // Redirect to login
          window.location.href = '/login';
        }
      } else {
        // Token refreshed successfully
        console.log('Token refreshed');
      }
    }
  },
  onError: (error) => {
    // Global error handler
    switch(error.type) {
      case 'NETWORK_ERROR':
        showOfflineMessage();
        break;
      case 'RATE_LIMIT':
        showRateLimitMessage();
        break;
      default:
        console.error('Coherence error:', error);
    }
  }
});

Headless Mode

// Initialize without UI
await Coherence.init({
  modalConfig: {
    headless: true
  },
  oauth: {
    enabled: true,
    appId: 'app_123',
    getToken: async () => getToken()
  }
});

// Build your own UI using the store
const store = Coherence.getInstance().getStore();

// Example: Custom React hook
function useCoherence() {
  const [state, setState] = useState(store.getState());

  useEffect(() => {
    return store.subscribe(setState);
  }, []);

  return {
    ...state,
    sendMessage: (text) => store.sendMessage({
      content: [{ type: 'text', text }]
    })
  };
}

Browser Support

  • Chrome/Edge: Latest 2 versions
  • Firefox: Latest 2 versions
  • Safari: Latest 2 versions
  • Mobile browsers: iOS Safari 14+, Chrome Android

Performance

  • Initial bundle size: ~50KB gzipped
  • Lazy loads additional features as needed
  • Automatic connection management
  • Request debouncing and batching
  • Efficient DOM updates

Security

  • All data transmitted over HTTPS
  • JWT tokens expire after 1 hour
  • Automatic token refresh
  • XSS protection built-in
  • Content Security Policy compatible