npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

amazon-connect-chatjs

v5.4.1

Published

Provides chat support to AmazonConnect customers

Readme

Amazon Connect ChatJS

npm TypeScript Apache License package size

A browser-based JavaScript library to build custom chat interfaces for Amazon Connect. Includes TypeScript support, fully managed WebSocket connections, and simplified API calls with internal AWS SDK integration. The Amazon Connect Chat javascript library (ChatJS) gives you the power to customize your chat experience and build your own chat widget or agent chat UI.

This stand-alone library supports customer chat sessions by default. For agent chat sessions and Custom Contact Control Panel (CCP), please integrate with the Amazon Connect Streams library.

📌 New to Amazon Connect? First, explore the Amazon Connect User Guide to understand its features and capabilities. We recommend trying out the pre-built Omnichannel Hosted Widget (Voice, Chat, Video) before customizing with this library. For step-by-step guidance, check out our "Getting Started with Amazon Connect Chat Open Source" guide

ChatJS README Diagram

Table of Contents

📢 Announcements

  • 2026-10-07: v5.3.0 - Added useDualStack in setGlobalConfig(), to call the dual-stack (IPv4 + IPv6) Participant Service endpoint participant.connect.{region}.api.aws. Off by default
  • 2026-09-23: v5.2.0 - Added customChatClient, to replace the bundled AWS transport with your own. TypeScript: GetTranscriptResult.NextToken is now optional, so strict-mode consumers assigning it to string must widen to string | undefined
  • 2025-05-29: Migrated baked-in dependency from AWS SDK v2 to AWS SDK v3: src/client/aws-sdk-connectparticipant.js
  • 2024-04-02: Connection Acknowledgement (ConnAck) has migrated from SendEvent API to the CreateParticipant API. Please upgrade to amazon-connect-chatjs@^1.4.0 by Dec 31, 2024
  • 2023-03-30: v1.5.0 - Added support for React Native environments
  • 2023-12-23: v1.3.0 - Added Message Receipts feature, enabled by default
  • 2022-11-08: v1.2.0 - Added Client Side Metrics (CSM) feature, enabled by default
  • 2020-12-13: Added support for TypeScript (requires typescript@^3.0.1 or higher)

Examples

Getting Started

Prerequisites

Installation

npm install amazon-connect-chatjs
# or
yarn add amazon-connect-chatjs
# or
pnpm add amazon-connect-chatjs

Importing ChatJS

This library supports ESModule (ES6) imports. This will make the window.connect variable available in the current context.

import 'amazon-connect-chatjs';

TypeScript Support

This package includes built-in TypeScript type definitions (requires typescript@>=3.0.1). No additional @types packages needed.

import 'amazon-connect-chatjs'; // loads dist/index.d.ts

Importing from CDN

<!-- Using unpkg with semver range -->
<script src="https://unpkg.com/amazon-connect-chatjs@^3.0.0"></script>

<!-- Using unpkg with latest version -->
<script src="https://unpkg.com/amazon-connect-chatjs@latest"></script>

<!-- Using jsDelivr with specific version -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/amazon-connect-chat.js"></script>

<!-- Using with CORS -->
<script crossorigin src="https://unpkg.com/amazon-connect-chatjs"></script>

Using the AWS SDK and ChatJS

If your project also uses the AWS SDK, ensure you import ChatJS before the AWS SDK to prevent conflicts. This is because ChatJS includes its own bundled version of AWS SDK for JavaScript V3 (in src/client/aws-sdk-connectparticipant.js).

import 'amazon-connect-chatjs';
// Baked-in ChatJS dependency (AWS SDK v3)
// import { ConnectParticipantClient } from './client/aws-sdk-connectparticipant.js'; // v3.x.x

// Custom AWS SDK import, must be second
import { ConnectParticipantClient, StartAttachmentUploadCommand } from '@aws-sdk/client-connectparticipant'; // v3.x.x
// your code ...

Configuration

Set the global configuration to use. This method should be called before connect.ChatSession.create(). For all supported options, see connect.ChatSession.create().

connect.ChatSession.setGlobalConfig({
  region: "<AWS-REGION>", // (optional), defaults to: "us-west-2"
  loggerConfig: { // (optional)
    advancedLogWriter: null,
    customizedLogger: {
      debug: (...msg) => console.log(...msg),
      info: (...msg) => console.log(...msg),
      warn: (...msg) => console.log(...msg),
      error: (...msg) => console.log(...msg)
    },
    level: connect.ChatSession.LogLevel.INFO, // (optional), default 10 (DEBUG, INFO, WARN, ERROR, ADVANCED_LOG)
  },
  webSocketManagerConfig: { // (optional) for React Native environments
    isNetworkOnline: () => bool, // default: `() => navigator.onLine` (will break in React Native)
  },
  features: { // (optional)
    messageReceipts: {
      shouldSendMessageReceipts: true, // enabled by default, set to false to disable Read/Delivered receipts
      throttleTime: 5000 // default: 5000, customize time to wait before sending Read/Delivered receipts
    }
  },
  // NOTE: Message receipts are enabled by default on the first setGlobalConfig() call.
  // If you explicitly configure messageReceipts (enable or disable), subsequent setGlobalConfig()
  // calls that omit `features` will preserve your configuration. To send receipts manually with
  // full control over timing, use the `sendMessageReceipt()` method instead of `sendEvent()`.
  // Pass in a user agent suffix used to configure the AWS SDK client in Amazon Connect ChatJS.
  // This will be appended to the x-amz-user-agent custom header used in outgoing API requests
  customUserAgentSuffix: "", // (optional)
  // (optional) Route every Participant Service call through your own transport instead of the
  // bundled AWS SDK client. See `connect.ChatSession.ChatClient`
  customChatClient: null,
  // (optional) Call the dual-stack (IPv4 + IPv6) Participant Service endpoint,
  // https://participant.connect.{region}.api.aws, instead of the IPv4-only
  // https://participant.connect.{region}.amazonaws.com. Default: false. Ignored when `endpoint` is set.
  // Must be a boolean; any other value is ignored (with a warning) and the current setting is kept.
  useDualStack: false,
});

Usage

Customer Session

Create and join a new customer chat session.

To initialize ChatJS, you'll need chat details ({ ContactId, ParticipantId, ParticipantToken }) returned from a StartChatContact API request.

We recommend deploying this startChatContactAPI CloudFormation stack for your chat proxy backend.

import "amazon-connect-chatjs"; // imports the "window.connect"

connect.ChatSession.setGlobalConfig({ region: "us-west-2" });

// Step 1: Get chat details from your backend
// Boilerplate endpoint: https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/cloudformationTemplates/startChatContactAPI
const response = await fetch("<url-to-personal-chat-backend>", { method: "POST" });
const chatDetails = await response.json();

// Step 2: Connect to the chat session
const customerChatSession = connect.ChatSession.create({
  chatDetails: {
    contactId: chatDetails.ContactId,
    participantId: chatDetails.ParticipantId,
    participantToken: chatDetails.ParticipantToken,
  },
  options: { region: "us-west-2" }, // optional
  type: "CUSTOMER",
  disableCSM: true
});
await customerChatSession.connect();

// Step 3: Send messages and events
await customerChatSession.sendMessage({ contentType: "text/plain", message: "Hello World!" });
await customerChatSession.sendEvent({ contentType: "application/vnd.amazonaws.connect.event.typing" });

// Step 4: Handle incoming websocket events
customerChatSession.onMessage(event => { /* ... */ });
customerChatSession.onConnectionBroken(event => { /* ... */ });
customerChatSession.onEnded(event => { /* ... */ });
customerChatSession.onTyping(event => { /* ... */ });
customerChatSession.onConnectionEstablished(event => { /* ... */ });

// Step 5: End chat gracefully
await customerChatSession.disconnectParticipant();

ChatJS Customer Chat Session diagram

sequenceDiagram
    participant Client as Customer Chat UI<br/>[ChatJS Client]
    participant Proxy as startChatContactAPI<br/>[Lambda]
    participant Connect as Amazon Connect<br/>Backend
    participant Instance as Connect Instance
    participant Agent as Agent

    Client->>Proxy: POST /start-chat
    Note over Proxy: Returns:<br/>- ContactId<br/>- ParticipantId<br/>- ParticipantToken
    Proxy-->>Client: Return chat credentials

    Client->>Connect: customerChatSession.connect()
    Connect->>Instance: Initiate chat
    Instance->>Agent: Notify new chat
    Connect-->>Client: Return connection details

    Client->>Connect: subscribe to WebSocket connection

    rect rgb(240, 240, 240)
        Note over Client,Agent: Bi-directional WebSocket Communication
        Client->>Connect: WebSocket events
        Connect->>Instance: Internal routing
        Instance->>Agent: Agent interface
        Agent->>Instance: Agent responses
        Instance->>Connect: Internal routing
        Connect->>Client: WebSocket events
    end

    Client->>Connect: customerChatSession.disconnectParticipant()
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <!--
  Alternative import method:
  <script src="https://unpkg.com/[email protected]"></script>
  -->
</head>
<body>
  <div id="chat-container">
    <!-- Chat UI elements would go here -->
  </div>

  <script type="module">
    import "https://unpkg.com/[email protected]";
    const REGION = "us-west-2";

    window.onload = async function () {
      // Configure ChatJS
      connect.ChatSession.setGlobalConfig({ region: REGION });

      // Step 1: Get chat details from your backend
      const response = await fetch("<url-to-personal-chat-backend>", { method: "POST" });
      const chatDetails = await response.json();

      // Step 2: Connect to the chat session
      const customerChatSession = connect.ChatSession.create({
        chatDetails: {
          contactId: chatDetails.ContactId,
          participantId: chatDetails.ParticipantId,
          participantToken: chatDetails.ParticipantToken,
        },
        options: { region: REGION }, // optional
        type: "CUSTOMER",
        disableCSM: true
      });
      await customerChatSession.connect();

      // Step 3: Send messages and events
      // These would typically be triggered by user actions
      // await customerChatSession.sendMessage({ contentType: "text/plain", message: "Hello World!" });
      // await customerChatSession.sendEvent({ contentType: "application/vnd.amazonaws.connect.event.typing" });

      // Step 4: Handle incoming websocket events
      customerChatSession.onMessage(event => { /* ... */ });
      customerChatSession.onConnectionBroken(event => { /* ... */ });
      customerChatSession.onEnded(event => { /* ... */ });
      customerChatSession.onTyping(event => { /* ... */ });
      customerChatSession.onConnectionEstablished(event => { /* ... */ });

      // Step 5: End chat gracefully
      // This would typically be triggered by a user action
      // await customerChatSession.disconnectParticipant();
    };
  </script>
</body>
</html>

Agent Session

For agent chat sessions and Custom Custom Contact Control Panel (CCP), please integrate ChatJS with the Amazon Connect Streams library.

StreamJS will provide the ChatJS agentChatSession via agentConnection.getMediaController(). This supports the same event listeners and methods as customer chat sessions, with the exception of disconnectParticipant().

Note: for Custom CCP, you must to allow-list your domain before using StreamsJS, including http://localhost:PORT for local testing. More details here. Update your instance settings in the Amazon Connect AWS Console.

<html>
<!-- OPTIONAL: hide the pre-built CCP UI
<style>#ccp-iframe-root iframe{display:none}</style>
-->
<body>
  <div id="ccp-iframe-root"></div>
  <script type="module">
    import 'https://unpkg.com/[email protected]';  // StreamJS must be imported first

    // To allow-list your domain, see: https://github.com/amazon-connect/amazon-connect-streams#allowlisting
    const INSTANCE_URL = "https://<INSTANCE_NAME>.my.connect.aws/ccp-v2/";
    const REGION = '<AWS-REGION>'; // "us-west-2"

    // Step 1: Initialize CCP
    // <div id="ccp-iframe-root" />
    var containerElement = document.getElementById("ccp-iframe-root");
    await connect.core.initCCP(containerElement, {
      ccpUrl: INSTANCE_URL,
      region: REGION,
      loginPopup: true,
    });

    // Step 2: Handle incoming chat contacts
    connect.contact((contact) => {
      if (contact.getType() !== connect.ContactType.CHAT) return;
      // Auto-accept the incoming chat contact
      contact.accept();

      contact.onAccepted(async () => {
        const agentConnection = contact.getConnections().find(conn => conn.getType() === connect.ConnectionType.AGENT);

        // Configure ChatJS (optional)
        connect.ChatSession.setGlobalConfig({ /* ... */ });

        // Step 3: Initialize ChatJS and subscribe to WebSocket connection
        const agentChatSession = await agentConnection.getMediaController();

        // Fetch the transcript
        const awsSDKResponse = await agentChatSession.getTranscript({
          sortOrder: "ASCENDING",
          maxResults: 100, // default: 15
          metadata: { foo: "bar" }, // optional
          // scanDirection: "BACKWARD", (optional) default: BACKWARD
          // nextToken?: nextToken - OPTIONAL, for pagination
        });
        const { InitialContactId, NextToken, Transcript } = awsSDKResponse.data;

        // Set up event listeners
        agentChatSession.onConnectionEstablished((event) => {
          // Handle connection established
        });

        agentChatSession.onMessage((event) => {
          const message = event.data?.Content;
          // Handle incoming message
        });

        // Send messages
        await agentChatSession.sendMessage({ contentType: "text/plain", message: "Hello World!" });

        // NOTE: disconnectParticipant() is not available in agentChatSession
        // To leave an agent chat session, run:
        // contact.destroy()
      });
    });
  </script>
</body>
</html>
<!-- chatjs-streamsjs-example.html -->
<!--
# Amazon Connect Custom Agent Chat UI

## Overview
Custom Agent Chat UI integrating ChatJS and StreamsJS for Amazon Connect Chat

- StreamsJS: https://github.com/amazon-connect/amazon-connect-streams
- ChatJS: https://github.com/amazon-connect/amazon-connect-chatjs
- AWS Documentation: https://docs.aws.amazon.com/connect/latest/adminguide/chat-with-connect-contacts.html

## Prerequisites
- Amazon Connect Instance
- Access to Agent Contact Control Panel (CCP): https://<instance-alias>.my.connect.aws/ccp-v2
  - Requires: Security Profile = "CCP: Access CCP"

## Configuration Steps
1. Allowlisting
   - Login to your AWS Account, then navigate to the Amazon Connect console.
   - Click the instance name of the instance for which you would like to allowlist pages to load the settings page for your instance.
   - Click the "Application integration" link on the left.
   - Click "Add Origin", then enter a domain URL: http://localhost:8080

2. Configuration Updates
   - Update the following values in the script:
     * `INSTANCE_URL`: Your Amazon Connect instance URL
     * `REGION`: Your AWS region

## Local Testing Instructions
1. Host the HTML file in a local browser
   ``
   npx live-server --port=8080 chatjs-streamsjs-example.html
   ``
   - Access URL: http://localhost:8080

2. Login Process
   - Open Contact Control Panel (CCP)
   - Login with your Agent username/password

3. Chat Interaction
   - Keep CCP tab open
   - In a second browser tab, launch Amazon Connect Test Chat Page: https://<instance-alias>.my.connect.aws/test-chat
   - Open the Customer widget
   - Back on CCP tab, wait for an incoming chat contact, click "Accept"
-->
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Agent Chat UI [Amazon Connect]</title>
  <style>
    body {
      display: flex;
    }

    #prebuilt-agent-ui-iframe,
    #chat-ui-container {
      width: 400px;
      height: 800px;
    }

    #chat-ui-container {
      font-family: Arial, sans-serif;
      border: 1px solid #ddd;
      padding: 15px;
      border-radius: 5px;
      margin: 20px auto;
    }

    #custom-agent-chat-transcript {
      height: 300px;
      overflow-y: auto;
      background-color: #f8f8f8;
      padding: 10px;
      margin-top: 20px;
      width: 100%;
      box-sizing: border-box;
    }

    #custom-agent-chat-transcript::after {
      content: "";
      display: table;
      clear: both;
    }

    .message {
      margin: 5px 0;
      padding: 8px;
      border-radius: 5px;
      max-width: 80%;
      word-wrap: break-word;
      clear: both;
    }

    .incoming-message {
      background-color: #f0f0f0;
      border: 1px solid #ddd;
      float: left;
      text-align: left;
    }

    .outgoing-message {
      background-color: #0084ff;
      color: white;
      border: 1px solid #0073e6;
      float: right;
      text-align: right;
    }

    #message-input-container {
      display: flex;
      margin-top: 15px;
    }

    #messageInput {
      flex-grow: 1;
      margin-right: 5px;
      padding: 8px;
      border: 1px solid #ccc;
      border-radius: 4px;
    }

    button {
      padding: 8px 15px;
      border-radius: 4px;
      cursor: pointer;
      background-color: #0084ff;
      color: white;
      border: none;
    }

    button:disabled {
      background-color: #ccc;
    }
  </style>
</head>

<body>
  <div id="prebuilt-agent-ui-iframe"></div>
  <div id="chat-ui-container">
    <h3>Custom Agent Chat UI (ChatJS + StreamsJS)</h3>
    <div id="custom-agent-chat-transcript"></div>
    <div id="message-input-container" style="display: none">
      <input type="text" id="messageInput" placeholder="Type your message..." disabled>
      <button id="sendMessageButton" disabled>Send</button>
    </div>
  </div>

  <script type="module">
    // Option 1: import ChatJS and StreamJS directly from npm (order is important)
    import "https://unpkg.com/[email protected]"; // imports `window.connect.*`
    import "https://unpkg.com/[email protected]"; // also imports `window.connect.*`

    // Option 2: Import bundle files
    // import "amazon-connect-streams.js";
    // import "amazon-connect-chat.js";

    const INSTANCE_URL = "https://{INSTANCE-ALIAS}.my.connect.aws/ccp-v2?visual-refresh=true";
    const REGION = 'us-west-2';
    const MAX_TRANSCRIPT_MESSAGES = 15;

    window.onload = async function () {
      // DOM element references
      const elements = {
        prebuiltAgentUI: document.getElementById("prebuilt-agent-ui-iframe"),
        transcript: document.getElementById("custom-agent-chat-transcript"),
        messageInput: document.getElementById("messageInput"),
        sendButton: document.getElementById("sendMessageButton"),
        inputContainer: document.getElementById("message-input-container"),
      };

      // Initialize Connect CCP and set up handlers
      await connect.core.initCCP(elements.prebuiltAgentUI, {
        ccpUrl: INSTANCE_URL,
        region: REGION,
        loginPopup: true,
      });

      connect.ChatSession.setGlobalConfig({
        loggerConfig: { useDefaultLogger: true },
        region: REGION,
      });

      // Handle new contacts
      connect.contact(contact => {
        if (contact.getType() === connect.ContactType.CHAT) {
          // Automatically accept chat
          contact.accept();
        }

        contact.onAccepted(() => initializeChatContact(contact));
      });

      // Check for existing contacts
      connect.agent(agent => {
        agent.onRefresh(() => {
          agent.getContacts().forEach(contact => {
            const contactStatus = contact.getStatus().type;
            const isActiveChat =
              contact.getType() === connect.ContactType.CHAT &&
              (contactStatus === connect.ContactStateType.CONNECTED ||
                contactStatus === connect.ContactStateType.ACCEPTED);

            if (isActiveChat) initializeChatContact(contact);
          });
        });
      });

      /**
       * Initialize a chat contact and set up the UI
       */
      async function initializeChatContact(contact) {
        if (contact.getType() !== connect.ContactType.CHAT) return;

        const agentConnection = contact.getConnections().find(
          conn => conn.getType() === connect.ConnectionType.AGENT
        );

        let chatSession;
        try {
          chatSession = await agentConnection.getMediaController();

          if (!chatSession) {
            chatSession = connect.ChatSession.create({
              chatDetails: agentConnection.getMediaInfo(),
              options: { region: REGION },
              type: connect.ChatSession.SessionTypes.AGENT,
              websocketManager: connect.core.getWebSocketManager()
            });
            await chatSession.connect();
          }

          // To end an Agent Chat Session, equiv to customerChatSession.disconnectParticipant()
          // await contact.destroy({
          //     success: () => console.log("Contact ended successfully"),
          //     failure: (err) => console.error("Failed to end contact:", err)
          // });

          setupChat(chatSession, elements);
        } catch (error) {
          console.error('Error getting chat session:', error);
        }
      }

      /**
       * Set up the chat UI and handlers
       */
      function setupChat(chatSession, elements) {
        if (!chatSession) return;

        // Show and enable UI elements
        elements.transcript.style.display = "block";
        elements.transcript.style.visibility = "visible";
        elements.inputContainer.style.display = "flex";
        elements.messageInput.disabled = false;
        elements.sendButton.disabled = false;

        // Set up message sending
        const sendMessage = async () => {
          const message = elements.messageInput.value.trim();
          if (message) {
            try {
              await chatSession.sendMessage({ contentType: "text/plain", message });
              elements.messageInput.value = '';
            } catch (error) {
              console.error('Error sending message:', error);
            }
          }
        };

        elements.sendButton.addEventListener('click', sendMessage);
        elements.messageInput.addEventListener('keypress', e => {
          if (e.key === 'Enter') sendMessage();
        });

        // Set up chat session handlers
        chatSession.onConnectionEstablished(() => {
          // Load previous messages
          chatSession.getTranscript({
            scanDirection: "BACKWARD",
            sortOrder: "ASCENDING",
            maxResults: MAX_TRANSCRIPT_MESSAGES
          }).then(response => {
            if (response.data?.Transcript) {
              response.data.Transcript.forEach(msg => renderMessage(msg, chatSession, elements));
            }
          }).catch(error => console.error("Error loading transcript:", error));
        });

        /**
         * Subscribes an event handler that triggers whenever a message or an event (except for `application/vnd.amazonaws.connect.event.typing`) is created by any participant.
         * @param {
            chatDetails: Object,
            data: {
              AbsoluteTime: string,
              Content?: string,
              ContentType: string,
              DisplayName?: string,
              Id: string,
              ParticipantId?: string,
              ParticipantRole?: "AGENT" | "CUSTOMER" | "SYSTEM",
              Type: "MESSAGE" | "EVENT" | "ATTACHMENT" | "CONNECTION_ACK",
              ContactId?: string,
              InitialContactId?: string
            }
        } event
        */
        chatSession.onMessage(event => {
          if (event.data) renderMessage(event.data, chatSession, elements);
        });

        /**
         * Subscribes an event handler that triggers whenever a "application/vnd.amazonaws.connect.event.typing" event is created by any participant.
         * @param {
            AbsoluteTime?: string,
            ContentType: "application/vnd.amazonaws.connect.event.typing",
            Type?: string,
            ParticipantId?: string,
            DisplayName?: string,
            ParticipantRole?: "AGENT" | "CUSTOMER" | "SYSTEM",
            InitialContactId?: string
        } event.data
        */
        chatSession.onTyping((event) => {
          // Handle typing indicator
          renderMessage({
            "AbsoluteTime": "2025-05-23T06:01:24.287Z",
            "ContentType": "text/plain",
            "Content": "...",
            "Id": "e69634e9-2b31-4598-923e-5b2be62d436b",
            "Type": "EVENT",
            "ParticipantId": "5b370166-c0ee-4e23-ac1b-87ceffa611c4",
            "DisplayName": "Customer",
            "ParticipantRole": "CUSTOMER",
            "InitialContactId": "3358be3e-368d-4cde-ae92-352f44c35440"
          }, chatSession, elements);
        })

        /**
         * Subscribes an event handler that triggers when a read message event is received from the customer or agent.
         * @param {
            AbsoluteTime?: string,
            ContentType: "application/vnd.amazonaws.connect.event.message.read",
            Type?: string,
            ParticipantId?: string,
            DisplayName?: string,
            ParticipantRole?: "AGENT" | "CUSTOMER" | "SYSTEM",
            InitialContactId?: string
         } event.data
         */
        chatSession.onReadReceipt((event) => {
          // handle message receipt
        })

        /**
         * Subscribes an event handler that triggers when a delivered message event is received from the customer or agent.
         * @param {
            AbsoluteTime?: string,
            ContentType: "application/vnd.amazonaws.connect.event.message.delivered",
            Type?: string,
            ParticipantId?: string,
            DisplayName?: string,
            ParticipantRole?: "AGENT" | "CUSTOMER" | "SYSTEM",
            InitialContactId?: string
         } event.data
         */
        chatSession.onDeliveredReceipt((event) => {
          // handle message receipt
        })
      }

      /**
       * Render a message in the chat UI
       */
      function renderMessage(message, chatSession, elements) {
        if (message.ContentType === "text/plain" || message.ContentType === "text/markdown") {
          const messageElement = document.createElement("div");
          messageElement.className = "message";

          const isFromAgent = message.ParticipantId === chatSession.getChatDetails().participantId;
          messageElement.classList.add(isFromAgent ? "outgoing-message" : "incoming-message");

          const displayName = message.DisplayName || (isFromAgent ? 'Agent' : 'Customer');
          const content = document.createElement("div");
          const messageContent = message.Content || message.content;
          content.textContent = `${displayName}: ${messageContent}`;
          messageElement.appendChild(content);

          messageElement.id = `msg-${message.Id}`;
          messageElement.title = new Date(message.AbsoluteTime).toLocaleTimeString();

          elements.transcript.appendChild(messageElement);
          elements.transcript.scrollTop = elements.transcript.scrollHeight;
        }
      }
    };
  </script>
</body>

</html>
sequenceDiagram
  participant ChatJS
  participant ConnectAPI
  participant WebSocket
  participant AgentUI
  participant StreamsJS

  rect rgb(200, 230, 200)
    Note over AgentUI, WebSocket: 1. Initialize + Subscribe
    AgentUI ->> core.initCCP: core.initCCP
    StreamsJS ->> AgentUI: initConnection success
    AgentUI ->> StreamsJS: agent.onRefresh(handleAgentData)
    AgentUI ->> StreamsJS: contact.onIncoming(handleContact)
  end

  rect rgb(230, 200, 230)
    Note over AgentUI, WebSocket: 2. Incoming Chat Contact
    ConnectAPI ->> StreamsJS: New CHAT contact
    StreamsJS ->> AgentUI: contact.onIncoming event
    Note right of AgentUI: Check contact.getType() === "chat"
  end

  rect rgb(200, 200, 230)
    Note over AgentUI, WebSocket: 3. Accept Chat
    AgentUI ->> StreamsJS: contact.accept()
    StreamsJS ->> ConnectAPI: AcceptContact API
    ConnectAPI -->> StreamsJS: Contact accepted
    StreamsJS ->> AgentUI: contact.onAccepted event
    Note over AgentUI: Initialize ChatJS
    AgentUI ->> ChatJS: new ChatSession(chatDetails);
    ChatJS ->> WebSocket: Connect with participantToken
    WebSocket -->> ChatJS: Connection established
    ChatJS ->> AgentUI: onConnectionEstablished event
  end

  rect rgb(240, 240, 240)
    Note over AgentUI, WebSocket: 4. Chat Operations
    WebSocket ->> ChatJS: Incoming message
    ChatJS ->> AgentUI: onMessage callback
    AgentUI ->> ChatJS: sendMessage("Hello")
    ChatJS ->> WebSocket: Send via WebSocket
    WebSocket -->> ChatJS: Message delivered
    ChatJS -->> AgentUI: Success callback
    AgentUI ->> ChatJS: getTranscript()
    ChatJS ->> WebSocket: Request transcript
    WebSocket -->> ChatJS: Return transcript
    ChatJS -->> AgentUI: Transcript data
  end

  rect rgb(230, 230, 200)
    Note over AgentUI, WebSocket: 5. End Chat
    AgentUI ->> StreamsJS: contact.destroy()
    StreamsJS ->> ConnectAPI: StopContact API
    ConnectAPI -->> StreamsJS: Contact ended
    StreamsJS ->> AgentUI: contact.onEnded event
    WebSocket ->> ChatJS: Connection closed
    ChatJS ->> AgentUI: onConnectionLost event
  end

API

Global Properties

window.connect.ChatSession

window.connect.ChatSession = {
  create: ({ /* ... */ }) => {},
  setGlobalConfig: (config) => {},
  LogLevel: { /* ... */ },
  Logger: { /* ... */ },
  SessionTypes: { /* ... */ },
  ChatClient: class { /* ... */ },
};

This is the main entry point to amazon-connect-chatjs. All your interactions with the library start here.

window.connect.ChatSession.LogLevel

connect.ChatSession.LogLevel = {
  DEBUG,
  INFO,
  WARN,
  ERROR,
  ADVANCED_LOG,
};

Enumerates the logging levels.

ChatSession Class

connect.ChatSession.create()

const chatSession = await connect.ChatSession.create({
  chatDetails: {
    contactId: "...", // REQUIRED
    participantId: "...", // REQUIRED
    participantToken: "...", // REQUIRED, unless a `customChatClient` holds it instead
  },
  options: {
    region: "us-east-1", // (optional) defaults to `region` set in `.setGlobalConfig()`
    customChatClient: new MyChatClient(), // (optional); use null to ignore a globally configured client
  },
  type: window.connect.ChatSession.SessionTypes.CUSTOMER, // REQUIRED - options: `CUSTOMER`, `AGENT`
  disableCSM: true
});

ContactId, ParticipantId, and ParticipantToken must be generated on your backend and passed to the client. Make a request to StartChatContact API (see #Usage) for more details.

participantToken may be omitted only when you supply a customChatClient that holds the token on your backend, since nothing in the browser then needs it.

connect.ChatSession.setGlobalConfig()

connect.ChatSession.setGlobalConfig({
  // AWS Region (optional, defaults to "us-west-2")
  region: "<AWS-REGION>",

  // Logger Configuration (optional)
  loggerConfig: {
    advancedLogWriter: null,
    customizedLogger: {
      debug: (...msg) => console.log(...msg),
      info: (...msg) => console.log(...msg),
      warn: (...msg) => console.log(...msg),
      error: (...msg) => console.log(...msg)
    },
    // Log levels: DEBUG, INFO, WARN, ERROR, ADVANCED_LOG
    level: connect.ChatSession.LogLevel.INFO
  },

  // WebSocket Manager Config (optional, for React Native environments)
  webSocketManagerConfig: {
    // Default: `() => navigator.onLine` (will break in React Native)
    isNetworkOnline: () => bool
  },

  // Features Configuration (optional)
  features: {
    messageReceipts: {
      // Enable/disable Read/Delivered receipts (enabled by default)
      shouldSendMessageReceipts: true,
      // Time to wait before sending Read/Delivered receipts (default: 5000ms)
      throttleTime: 5000
    }
  },

  // User agent suffix for AWS SDK client (optional)
  // Appended to x-amz-user-agent custom header in API requests
  customUserAgentSuffix: "",

  // (optional) Route every session's Participant Service calls through your own transport
  // instead of the bundled AWS SDK client. See `connect.ChatSession.ChatClient`
  customChatClient: null,

  // (optional) Use the dual-stack (IPv4 + IPv6) Participant Service endpoint
  // (participant.connect.{region}.api.aws). Default: false. `endpoint` takes precedence.
  useDualStack: false
});

Set the global configuration to use. If this method is not called, the defaults of loggerConfig and region are used. This method should be called before connect.ChatSession.create().

Note on useDualStack: this option applies to the Amazon Connect Participant Service API calls that ChatJS makes. The WebSocket URL is not affected: it is returned by the CreateParticipantConnection API and depends on your Amazon Connect instance. For clients on IPv6-only networks, confirm that your Amazon Connect instance supports IPv6 for chat as well as setting useDualStack: true; otherwise API calls can succeed while the WebSocket fails to connect, and incoming messages are not delivered in real time.

Note on features: the features block (including messageReceipts) is only re-evaluated when you pass it explicitly. If a subsequent setGlobalConfig call omits features, the previously configured message-receipts settings (shouldSendMessageReceipts and throttleTime) are preserved. This keeps wrapping libraries that only update unrelated fields like loggerConfig or region from unintentionally re-enabling receipts.

connect.ChatSession.ChatClient

The transport contract between ChatJS and the Amazon Connect Participant Service. By default ChatJS calls that service directly using its bundled AWS SDK client; extend ChatClient and pass the instance as customChatClient to route every call through your own backend instead, so tokens need not reach the browser. Methods resolve to { data: <response body, PascalCase keys unchanged> }, except downloadAttachment (a Blob) and getAttachmentURL (a string). A client passed to create() takes precedence over one registered with setGlobalConfig(). Pass { customChatClient: null } on create() to opt one session out of the globally configured client.

class MyChatClient extends connect.ChatSession.ChatClient {
  // REQUIRED - no chat works without these five
  createParticipantConnection(participantToken, type, acknowledgeConnection) {} // -> { data: { Websocket, ConnectionCredentials? } }
  disconnectParticipant(connectionToken) {} // -> { data: {} }
  sendMessage(connectionToken, content, contentType, clientToken) {} // -> { data: { Id, AbsoluteTime } }
  sendEvent(connectionToken, contentType, content, clientToken) {} // -> { data: { Id, AbsoluteTime } }
  getTranscript(connectionToken, args) {} // -> { data: { InitialContactId, Transcript, NextToken } }

  // (optional) only needed for the Connect features that use them
  sendAttachment(connectionToken, attachment, metadata) {} // -> { data: {} }
  downloadAttachment(connectionToken, attachmentId) {} // -> Blob
  getAttachmentURL(connectionToken, attachmentId) {} // -> string
  describeView(viewToken, connectionToken) {} // -> { data: { View } } (note: viewToken first)
  getAuthenticationUrl(connectionToken, redirectUri, sessionId) {} // -> { data: { AuthenticationUrl } }
  cancelParticipantAuthentication(connectionToken, sessionId) {} // -> { data: {} }
}

const chatSession = connect.ChatSession.create({
  chatDetails: { contactId, participantId }, // `participantToken` no longer required
  options: { customChatClient: new MyChatClient() },
  type: "CUSTOMER",
});

Implementing a custom chat client

  • Return ConnectionCredentials from createParticipantConnection, or omit it to run tokenless. ChatJS never reads ConnectionToken. It only passes the value back as the connectionToken argument of every other method, so it can be any string your backend recognizes. Keep the ConnectionToken that CreateParticipantConnection returned on your backend.
  • Set ConnectionCredentials.Expiry to the Expiry your backend received from CreateParticipantConnection (e.g. "2026-09-29T21:00:00.000Z"). ChatJS calls createParticipantConnection again 1 minute before this time. If the value is missing or unparseable, ChatJS logs a warning and stops refreshing. If it's in the past, ChatJS refreshes at most once a minute.
  • Return Websocket unchanged from CreateParticipantConnection. The browser opens this WebSocket itself. ConnectionToken is the only field you may replace with your own value.
  • Return Id from sendMessage. ChatJS uses it to match the message it displayed optimistically. Without it, the message can appear twice.
  • Reject on failure. Don't throw synchronously. Use async methods or return a rejected promise, so ChatJS can roll back its transcript state.
  • Map getTranscript args to the service request. They arrive in camelCase (maxResults, nextToken, scanDirection, sortOrder, startPosition: { id, absoluteTime, mostRecent }, contactId). startPosition may be an empty object.
  • sendAttachment does the whole upload: start the upload, send the file to the returned URL, then complete the upload.
  • Throttle typing events yourself if needed. The bundled client throttles them, but a custom client replaces it.

ChatJS checks the client when the session is created. If logging is configured, it logs an error for a missing required method (createParticipantConnection, disconnectParticipant, sendMessage, sendEvent, getTranscript) and a warning for a missing optional one. The session is still created, and ChatJS doesn't fall back to the bundled client:

  • A missing createParticipantConnection makes connect() reject with connectSuccess: false.
  • Calling any other missing method throws an UnImplementedMethod error synchronously, so .catch() on the call doesn't catch it. Use await inside try/catch.

Unless the session is created with disableCSM: true, ChatJS records a client-side metric count for each customer session that uses a custom client, and for each one that runs tokenless. The counts don't include tokens or message content.

Your backend

  1. Call StartChatContact. Keep ParticipantToken and return only ContactId and ParticipantId to the browser.
  2. For createParticipantConnection, call CreateParticipantConnection with Type: ["WEBSOCKET", "CONNECTION_CREDENTIALS"]. Store the returned ConnectionToken and return the Websocket block with your stand-in ConnectionCredentials, or with no ConnectionCredentials in tokenless mode.
    • ChatJS calls this on connect(), again 1 minute before Expiry, and whenever the WebSocket reconnects. Every call refreshes both the WebSocket and the token, so handle each call the same way. Call CreateParticipantConnection again, replace the stored ConnectionToken, and return the new Websocket object together with your stand-in ConnectionCredentials (carrying the new Expiry).
    • On refresh calls, acknowledgeConnection is null. In that case, leave ConnectParticipant out of the CreateParticipantConnection request.
  3. For every other method, authenticate the request with your own credentials. Then look up the stored ConnectionToken and call the matching Participant Service API.

Two things still reach the browser: the WebSocket URL, and the pre-signed attachment URLs if your client uploads or downloads from the browser. If your client uploads or downloads attachments from the browser, your instance's attachment S3 bucket must allow your site's origin in its CORS configuration (PUT and GET). Otherwise uploads fail with Failed to fetch.

Keeping both tokens in your backend (tokenless mode)

Your backend can hold the participantToken and connectionToken and never send either to the browser. To do this, have createParticipantConnection resolve with only the websocket:

// -> { data: { Websocket: { Url, ConnectionExpiry } } }   (no ConnectionCredentials)

When a customChatClient returns no ConnectionCredentials, ChatJS runs the session tokenless:

  • connectionToken is null on every other ChatClient method, and chatSession.getChatDetails().connectionDetails.connectionToken is null. Your backend attaches the real token.
  • participantToken is whatever you passed in chatDetails, so omit it there to keep it off the browser. It is then null on every createParticipantConnection call, including websocket refreshes.
  • ChatJS does not poll to refresh the connection token. Your backend owns token refresh.
  • ChatJS logs a WARN once, when the session goes tokenless. If you didn't intend it, check that your backend forwards ConnectionCredentials.
  • Tokenless mode lasts for the rest of the session. If a later createParticipantConnection response includes ConnectionCredentials, ChatJS ignores it and connectionToken stays null. Return credentials on every call, or on none.

Websocket.Url is still required. The bundled AWS client is unaffected: a response without ConnectionCredentials still fails as a malformed response.

connect.ChatSession.Logger

connect.ChatSession.Logger = {
    debug(data) {}
    info(data) {}
    warn(data) {}
    error(data) {}
    advancedLog(data) {}
}
const logger = connect.ChatSession.Logger;
logger.info('foobar')
// INFO [2025-04-08T03:29:35.423Z] ChatJS: foobar

Exposes the internal ChatJS logger. Group your logs and use consistent format for easier debugging.

connect.ChatSession.SessionTypes

connect.ChatSession.SessionTypes = {
  AGENT,
  CUSTOMER,
};

Enumerates the session types.

chatSession Methods

Amazon Connect Participant Service API wrappers

Metadata Usage
  • Most functions accept an optional metadata argument
  • metadata is not used by amazon-connect-chatjs internally
  • The metadata value is copied to the response object
  • Developers can use metadata for their own purposes

Example:

chatSession.getTranscript({ metadata: "foo" })
  .then(({ data, metadata }) => {
    console.log(metadata); // "foo"
  })
  .catch(({ error, metadata}) => {
     console.error(metadata); // "foo"
  })

chatSession.connect()

const { connectCalled, connectSuccess } = await chatSession.connect();
// connectCalled: indicates whether the Amazon Connect Participant Service was called
// connectSuccess: indicates whether the operation succeeded

Wraps the CreateParticipantConnection API.

Note: If the operation fails, the Promise will reject, but the error will have the same schema as a successful response.

chatSession.sendMessage()

const awsSdkResponse = await chatSession.sendMessage({
  contentType: "text/plain",
  message: "Hello World!",
  metadata: { foo: "bar" }, // optional
});
const { AbsoluteTime, Id, MessageMetadata } = awsSdkResponse.data;
const metadata = awsSdkResponse.metadata;

Wraps the SendMessage API.

The arguments are based on the API request body with the following differences:

  • Fields are in camelCase.
  • ClientToken cannot be specified.

The response data is the same as the API response body.

chatSession.getTranscript()

const awsSDKResponse = await chatSession.getTranscript({
    sortOrder: "ASCENDING",
    maxResults: 100, // default: 15
    metadata: { foo: "bar" }, // optional
    // scanDirection: "BACKWARD", (optional) default: BACKWARD
    // nextToken?: nextToken - OPTIONAL, for pagination
});
const { InitialContactId, NextToken, Transcript } = awsSDKResponse.data;
// see: https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_GetTranscript.html#API_GetTranscript_ResponseSyntax

Fetch the chat transcript (uses ConnectionToken). Wraps the GetTranscript API

Important note: In order to specify scanDirection as FORWARD, you need to explicitly include a startPosition. This is because the default startPosition is at the most recent update to the transcript, so requesting a transcript in the FORWARD direction from the default startPosition is equivalent to asking for a transcript containing only messages more recent than the present (you are asking for messages in the future!).

chatSession.sendEvent()

const awsSdkResponse = await chatSession.sendEvent({
  contentType: "application/vnd.amazonaws.connect.event.typing",
  metadata: { foo: "bar" }, // optional
});
const { AbsoluteTime, Id } = awsSdkResponse.data;

Wraps the SendEvent API.

The arguments are based on the API request body with the following differences:

  • Fields are in camelCase.
  • ClientToken cannot be specified.
  • ContentType allows the following values:
    • "application/vnd.amazonaws.connect.event.typing"
    • "application/vnd.amazonaws.connect.event.connection.acknowledged"
    • "application/vnd.amazonaws.connect.event.message.delivered"
    • "application/vnd.amazonaws.connect.event.message.read"
    • "application/vnd.amazonaws.connect.event.participant.invited"

The response data is the same as the API response body.

Manual message receipts with sendMessageReceipt

When automatic message receipts are disabled (by setting features.messageReceipts.shouldSendMessageReceipts to false in setGlobalConfig), sendEvent calls with a Read or Delivered content type are rejected. To emit receipts manually from a custom UI, use the dedicated sendMessageReceipt method:

await chatSession.sendMessageReceipt({
  event: "delivered", // or "read"
  messageId: "<INCOMING_MESSAGE_ID>"
});

// Or pass a transcript item directly:
await chatSession.sendMessageReceipt({
  event: "read",
  message: transcriptItem // object with an Id property
});

Notes:

  • event must be "delivered" or "read".
  • Provide either messageId (string) or message (a transcript item with an Id field).
  • This method bypasses the automatic receipt gate and throttle entirely — the receipt is sent immediately regardless of the shouldSendMessageReceipts setting.
  • Aligns with the sendMessageReceipt API exposed by the Amazon Connect mobile SDKs.

chatSession.sendAttachment()

Important: an administrator must enable attachments for your Connect instance

await chatSession.sendAttachment({
  attachment: attachment // type: File [HTML file object, see https://developer.mozilla.org/en-US/docs/Web/API/File]
  metadata: { foo: "bar" }, // optional
});
// supported files: .csv, .doc, .docx, .jpeg, .jpg, .pdf, .png, .ppt, .pptx, .txt, .wav, .xls, .xlsx
// max size: 20MB
// source: https://docs.aws.amazon.com/connect/latest/adminguide/feature-limits.html#feature-limits-chat

// Example usage
var input = document.createElement('input');
input.type = 'file';
input.addEventListener('change', (e) => {
  const file = e.target.files[0];
  chatSession.sendAttachment({ attachment: file })
});

Wraps the StartAttachmentUpload and CompleteAttachmentUpload API. The arguments are based on the StartAttachmentUpload and CompleteAttachmentUpload API request body with the following differences:

The response data is the same as the StartAttachmentUpload and CompleteAttachmentUpload API response body. chatSession.sendAttachment() invokes the StartAttachmentUpload API, uploads the Attachment to the S3 bucket using the pre-signed URL received in the StartAttachmentUpload API response and invokes the CompleteAttachmentUpload API to finish the Attachment upload process.

chatSession.downloadAttachment()

chatSession.onMessage(event => {
  // event.contentType === "application/vnd.amazonaws.connect.message.attachment"
  if (event.data && event.data.Type === "ATTACHMENT") {
    const attachmentItem = event.data.Attachments[0];

    console.log(event.data);
    //  {
    //     "AbsoluteTime": "2025-05-24T21:42:55.867Z",
    //     "Attachments": [
    //         {
    //             "ContentType": "image/png",
    //             "AttachmentId": "asdfasdfasdfsadf",
    //             "AttachmentName": "Screenshot 2025-05-24 at 2.42.48 PM.png",
    //             "Status": "APPROVED"
    //         }
    //     ],
    //     "Id": "86a061a2-f99c-4691-a63e-47d145628a80",
    //     "Type": "ATTACHMENT",
    //     "ParticipantId": "4393212f-4481-4c7d-8184-5be9d811d7ce",
    //     "DisplayName": "Spencer",
    //     "ParticipantRole": "CUSTOMER",
    //     "InitialContactId": "f50e4cc0-b825-4da7-849a-27fa75f993de",
    //     "ContactId": "7d007f43-a0cc-4efb-abc9-628fc216e6d5"
    // }
  }

  // ...
});

chatSession.downloadAttachment({
  attachmentId: attachmentItem.AttachmentId
}).then((awsSDKResponse) => {
  const attachmentBlob = awsSDKResponse;  // Blob
  /*
    Attachment Object - This is the actual file that will be downloaded by either agent or end-customer.
    {
      lastModified: long
      name: "string"
      size: long
      type: "string"
      webkitRelativePath: "string"
    }
  */

  // Create a download link for the Blob
  const downloadUrl = URL.createObjectURL(attachmentBlob);
  const downloadLink = document.createElement('a');
  downloadLink.href = downloadUrl;
  downloadLink.download = attachmentItem.AttachmentName;
  downloadLink.style.display = 'none';

  document.body.appendChild(downloadLink);
  downloadLink.click();

  setTimeout(() => {
    document.body.removeChild(downloadLink);
    URL.revokeObjectURL(downloadUrl);
  }, 100);
}).catch(error => {
  console.error('Error downloading attachment:', error);
});

Wraps the GetAttachment API. The arguments are based on the API request body with the following differences:

The response data is the same as the API response body. chatSession.downloadAttachment() invokes the GetAttachment using the AttachmentId as a request parameter and fetches the Attachment from the S3 bucket using the pre-signed URL received in the GetAttachment API response.

chatSession.getAttachmentURL()
const s3Url = await chatSession.getAttachmentURL({
  attachmentId: "string"
});

Wraps the GetAttachment API. The arguments are based on the API request body with the following differences:

  • Fields are in camelCase. The response is a url string. chatSession.getAttachmentURL() invokes the GetAttachment using the AttachmentId as a request parameter and directly returns pre-signed URL received in the GetAttachment API response.
chatSession.sendMessageReceipt()
const awsSdkResponse = await chatSession.sendMessageReceipt({
  event: "delivered", // REQUIRED: "delivered" or "read"
  messageId: "message-id-from-transcript" // REQUIRED
});

Sends a Read or Delivered receipt for a specific message. Unlike sendEvent(), this method bypasses the automatic receipt gate and throttle, allowing you to send receipts even when shouldSendMessageReceipts is set to false in the global config.

This is useful when you want manual control over when receipts are sent (e.g., sending a Read receipt only when the user scrolls a message into view).

The event field must be either "delivered" or "read". The messageId field is the ID of the message you want to acknowledge. You can also pass message with an object containing an Id field instead of messageId.

// Alternative: pass the message object directly
await chatSession.sendMessageReceipt({
  event: "read",
  message: transcriptItem // must have an `Id` property
});

chatSession.getChatDetails()

const chatDetails = await chatSession.getChatDetails();
const {
  contactId,
  initialContactId,
  participantId,
  participantToken,
} = chatDetails;

Gets the chat session details.

chatSession.getAuthenticationUrl()

const awsSdkResponse = await chatSession.getAuthenticationUrl({
  redirectUri: 'www.example.com',
  sessionId: 'exampleId' // This comes from the `authentication.initiated` event
  metadata: { foo: "bar" }, // optional
});
const authenticationUrl = getAuthenticationUrlResponse?.data?.AuthenticationUrl;

Wraps the GetAuthenticationUrl API.

The arguments are based on the API request body

The response data is the same as the API response body.

Important note: The session id is only available from the authentication.initiated event which is only emitted when the authenticate customer contact flow block is used. The session id is a 1 time use code for this api. It can be re used in the cancelParticipantAuthentication api below

chatSession.describeView()

const awsSDKResponse = await chatSession.describeView({
  viewToken: "asdf...asdf", //REQUIRED
  metadata: { foo: "bar" }, // optional
});

const { View } = awsSDKResponse.data;

Wraps the DescribeView API.

The arguments are based on the API model with the following differences:

  • All fields are in camelCase.

ChatJS automatically supplies the connectionToken via the session's internal data. This api will only function after chatSession.connect() succeeds.

chatSession.cancelParticipantAuthentication()

const awsSdkResponse = await chatSession.cancelParticipantAuthentication({
  sessionId: 'exampleId' // This comes from the authentication.initiated event
  metadata: { foo: "bar" }, // optional
});

Wraps the CancelParticipantAuthentication API.

The arguments are based on the API request body

The response data is the same as the API response body.

Important note: The session id is only available from the authentication.initiated event which is only emitted when the authenticate customer contact flow block is used. The session id is a 1 time use code.

customerChatSession.suspendWebSocketConnection() / resumeWebSocketConnection()

await customerChatSession.suspendWebSocketConnection();   // socket closed, contact still live
// ...later
await customerChatSession.resumeWebSocketConnection();    // reconnects on a fresh WebSocket
const { data } = await customerChatSession.getTranscript({ /* from your last message */ });

Closes the WebSocket without ending the contact, and keeps event handlers, the transcript and session state. resumeWebSocketConnection() reconnects with the arguments of the last connect(). Matches the iOS and Android SDKs.

  • suspendWebSocketConnection() resolves once the close has been initiated; no further messages are delivered after that. It never rejects.
  • It closes the WebSocket for every session on the same contact, since they share it.
  • While suspended, calls that need the connection (such as sendMessage()) reject. Messages sent meanwhile are not replayed, so call getTranscript() after resuming.
  • The contact keeps running while suspended: chat idle timeouts and the chat duration still apply.
  • Every session on the contact gets onConnectionSuspended(); only resumeWebSocketConnection() reconnects, ChatJS doesn't.
  • If the chat ended while suspended, resume rejects with chatEnded: true, the session moves to ended, and onEnded() fires. A customChatClient must reject with the service's statusCode (403) for this to work.

chatSession.reset()

await chatSession.reset();
const next = connect.ChatSession.create({ /* new chatDetails */ });

Tears the session down without ending the contact: closes the WebSocket and releases its event handlers, transcript, credentials and client reference. Afterwards service operations on that session reject with code: "CHAT_SESSION_RESET"; read-only details remain available for diagnostics. Create a new ChatSession to continue. Use disconnectParticipant() to end the contact instead.

  • Returns a promise that resolves once the close has been initiated. It never rejects, and calling it again is a no-op.
  • To end the old chat as well, call disconnectParticipant() before reset().
  • With a customChatClient, also end the session on your backend so it drops the stored tokens; ChatJS can't do that for you.
  • A customChatClient registered with setGlobalConfig() is not cleared, because other sessions may use it. A new session without its own customChatClient