amazon-connect-chatjs
v5.4.1
Published
Provides chat support to AmazonConnect customers
Readme
Amazon Connect ChatJS
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

Table of Contents
- Announcements
- Examples
- Getting Started
- Usage
- API Reference
- Feature Documentation
- Local Development 💻
- Known Issues and Debugging 🐛
- Troubleshooting and Support
📢 Announcements
- 2026-10-07: v5.3.0 - Added
useDualStackinsetGlobalConfig(), to call the dual-stack (IPv4 + IPv6) Participant Service endpointparticipant.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.NextTokenis now optional, so strict-mode consumers assigning it tostringmust widen tostring | 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.0by 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.1or higher)
Examples
- HTML Examples
- React Examples
- Mobile Examples
Getting Started
Prerequisites
- AWS Account
- Amazon Connect instance
- Contact Flow ready to receive chat contacts (recommended: "Sample inbound flow")
- Deploy a startChatContactAPI CloudFormation stack
Installation
npm install amazon-connect-chatjs
# or
yarn add amazon-connect-chatjs
# or
pnpm add amazon-connect-chatjsImporting 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.tsImporting 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();
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:PORTfor 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
endAPI
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 settinguseDualStack: true; otherwise API calls can succeed while the WebSocket fails to connect, and incoming messages are not delivered in real time.
Note on
features: thefeaturesblock (includingmessageReceipts) is only re-evaluated when you pass it explicitly. If a subsequentsetGlobalConfigcall omitsfeatures, the previously configured message-receipts settings (shouldSendMessageReceiptsandthrottleTime) are preserved. This keeps wrapping libraries that only update unrelated fields likeloggerConfigorregionfrom 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
ConnectionCredentialsfromcreateParticipantConnection, or omit it to run tokenless. ChatJS never readsConnectionToken. It only passes the value back as theconnectionTokenargument of every other method, so it can be any string your backend recognizes. Keep theConnectionTokenthatCreateParticipantConnectionreturned on your backend. - Set
ConnectionCredentials.Expiryto theExpiryyour backend received fromCreateParticipantConnection(e.g."2026-09-29T21:00:00.000Z"). ChatJS callscreateParticipantConnectionagain 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
Websocketunchanged fromCreateParticipantConnection. The browser opens this WebSocket itself.ConnectionTokenis the only field you may replace with your own value. - Return
IdfromsendMessage. 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
asyncmethods or return a rejected promise, so ChatJS can roll back its transcript state. - Map
getTranscriptargs to the service request. They arrive in camelCase (maxResults,nextToken,scanDirection,sortOrder,startPosition: { id, absoluteTime, mostRecent },contactId).startPositionmay be an empty object. sendAttachmentdoes 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
createParticipantConnectionmakesconnect()reject withconnectSuccess: false. - Calling any other missing method throws an
UnImplementedMethoderror synchronously, so.catch()on the call doesn't catch it. Useawaitinsidetry/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
- Call
StartChatContact. KeepParticipantTokenand return onlyContactIdandParticipantIdto the browser. - For
createParticipantConnection, callCreateParticipantConnectionwithType: ["WEBSOCKET", "CONNECTION_CREDENTIALS"]. Store the returnedConnectionTokenand return theWebsocketblock with your stand-inConnectionCredentials, or with noConnectionCredentialsin tokenless mode.- ChatJS calls this on
connect(), again 1 minute beforeExpiry, and whenever the WebSocket reconnects. Every call refreshes both the WebSocket and the token, so handle each call the same way. CallCreateParticipantConnectionagain, replace the storedConnectionToken, and return the newWebsocketobject together with your stand-inConnectionCredentials(carrying the newExpiry). - On refresh calls,
acknowledgeConnectionisnull. In that case, leaveConnectParticipantout of theCreateParticipantConnectionrequest.
- ChatJS calls this on
- For every other method, authenticate the request with your own credentials. Then look up the stored
ConnectionTokenand 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:
connectionTokenisnullon every otherChatClientmethod, andchatSession.getChatDetails().connectionDetails.connectionTokenisnull. Your backend attaches the real token.participantTokenis whatever you passed inchatDetails, so omit it there to keep it off the browser. It is thennullon everycreateParticipantConnectioncall, including websocket refreshes.- ChatJS does not poll to refresh the connection token. Your backend owns token refresh.
- ChatJS logs a
WARNonce, when the session goes tokenless. If you didn't intend it, check that your backend forwardsConnectionCredentials. - Tokenless mode lasts for the rest of the session. If a later
createParticipantConnectionresponse includesConnectionCredentials, ChatJS ignores it andconnectionTokenstaysnull. 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: foobarExposes 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
metadataargumentmetadatais not used byamazon-connect-chatjsinternally- The
metadatavalue is copied to the response object- Developers can use
metadatafor their own purposesExample:
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 succeededWraps 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. ClientTokencannot 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_ResponseSyntaxFetch the chat transcript (uses ConnectionToken). Wraps the GetTranscript API
Important note: In order to specify
scanDirectionasFORWARD, you need to explicitly include astartPosition. This is because the defaultstartPositionis at the most recent update to the transcript, so requesting a transcript in theFORWARDdirection from the defaultstartPositionis 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. ClientTokencannot be specified.ContentTypeallows 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:
eventmust be"delivered"or"read".- Provide either
messageId(string) ormessage(a transcript item with anIdfield). - This method bypasses the automatic receipt gate and throttle entirely — the receipt is sent immediately regardless of the
shouldSendMessageReceiptssetting. - Aligns with the
sendMessageReceiptAPI 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 callgetTranscript()after resuming. - The contact keeps running while suspended: chat idle timeouts and the chat duration still apply.
- Every session on the contact gets
onConnectionSuspended(); onlyresumeWebSocketConnection()reconnects, ChatJS doesn't. - If the chat ended while suspended, resume rejects with
chatEnded: true, the session moves to ended, andonEnded()fires. AcustomChatClientmust reject with the service'sstatusCode(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()beforereset(). - With a
customChatClient, also end the session on your backend so it drops the stored tokens; ChatJS can't do that for you. - A
customChatClientregistered withsetGlobalConfig()is not cleared, because other sessions may use it. A new session without its owncustomChatClient
