{"id":38604713,"url":"https://github.com/amazon-connect/amazon-connect-chatjs","last_synced_at":"2026-01-23T04:59:49.727Z","repository":{"id":36325239,"uuid":"222556287","full_name":"amazon-connect/amazon-connect-chatjs","owner":"amazon-connect","description":"Amazon Connect ChatJS - a browser-based contact center integration API for Chat on the Agent and Customer side.","archived":false,"fork":false,"pushed_at":"2026-01-07T22:04:30.000Z","size":7288,"stargazers_count":113,"open_issues_count":20,"forks_count":67,"subscribers_count":26,"default_branch":"master","last_synced_at":"2026-01-17T18:00:45.822Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://docs.aws.amazon.com/connect/latest/adminguide/what-is-amazon-connect.html","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amazon-connect.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-11-18T22:23:16.000Z","updated_at":"2026-01-16T21:16:02.000Z","dependencies_parsed_at":"2023-11-14T23:28:20.835Z","dependency_job_id":"18a726db-5665-4b93-bf5b-007e94279b66","html_url":"https://github.com/amazon-connect/amazon-connect-chatjs","commit_stats":{"total_commits":113,"total_committers":25,"mean_commits":4.52,"dds":0.7345132743362832,"last_synced_commit":"460fb78ac5fad1ca6b2953ded24ff95408acb330"},"previous_names":[],"tags_count":44,"template":false,"template_full_name":"amazon-archives/__template_Apache-2.0","purl":"pkg:github/amazon-connect/amazon-connect-chatjs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-connect%2Famazon-connect-chatjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-connect%2Famazon-connect-chatjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-connect%2Famazon-connect-chatjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-connect%2Famazon-connect-chatjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amazon-connect","download_url":"https://codeload.github.com/amazon-connect/amazon-connect-chatjs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-connect%2Famazon-connect-chatjs/sbom","scorecard":{"id":188572,"data":{"date":"2025-08-11","repo":{"name":"github.com/amazon-connect/amazon-connect-chatjs","commit":"de59935f24ab899382c4e08e6242d1d626643f5a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":6.3,"checks":[{"name":"Code-Review","score":9,"reason":"Found 29/30 approved changesets -- score normalized to 9","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/node.js.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":10,"reason":"16 commit(s) and 6 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/amazon-connect/amazon-connect-chatjs/node.js.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/amazon-connect/amazon-connect-chatjs/node.js.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/amazon-connect/amazon-connect-chatjs/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/amazon-connect/amazon-connect-chatjs/publish.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/publish.yml:34","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   1 out of   2 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/publish.yml:20"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/amazon-connect/.github/SECURITY.md:1","Info: Found linked content: github.com/amazon-connect/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/amazon-connect/.github/SECURITY.md:1","Info: Found text in security policy: github.com/amazon-connect/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-4v9v-hfq4-rm2v","Warn: Project is vulnerable to: GHSA-9jgg-88mc-972h"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-16T20:13:40.516Z","repository_id":36325239,"created_at":"2025-08-16T20:13:40.516Z","updated_at":"2025-08-16T20:13:40.516Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28680623,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T04:33:33.518Z","status":"ssl_error","status_checked_at":"2026-01-23T04:33:30.433Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-17T08:36:55.961Z","updated_at":"2026-01-23T04:59:49.711Z","avatar_url":"https://github.com/amazon-connect.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Amazon Connect ChatJS\n\n[![npm](https://img.shields.io/npm/v/amazon-connect-chatjs.svg?color=orange)](https://www.npmjs.com/package/amazon-connect-chatjs) ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg) [![Apache License](https://img.shields.io/badge/License-Apache%202.0-yellow.svg)](https://opensource.org/licenses/Apache-2.0) ![package size](https://img.shields.io/bundlephobia/minzip/amazon-connect-chatjs)\n\nA browser-based JavaScript library to build custom chat interfaces for [Amazon Connect](https://docs.aws.amazon.com/connect/latest/adminguide/what-is-amazon-connect.html). 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.\n\nThis 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](https://github.com/aws/amazon-connect-streams) library.\n\n\u003e 📌 **New to Amazon Connect?**\n\u003e First, explore the [Amazon Connect User Guide](https://docs.aws.amazon.com/connect/latest/userguide/) to understand its features and capabilities. We recommend trying out the [pre-built Omnichannel Hosted Widget](https://docs.aws.amazon.com/connect/latest/adminguide/add-chat-to-website.html) (Voice, Chat, Video) before customizing with this library. For step-by-step guidance, check out our [\"Getting Started with Amazon Connect Chat Open Source\"](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/blob/master/.github/docs/AmazonConnectChatOpenSourceWalkthrough.md) guide\n\n![ChatJS README Diagram](./docs/chatjs-readme-diagram.png)\n\n## Table of Contents\n\n- [Announcements](#announcements)\n- [Examples](#examples)\n- [Getting Started](#getting-started)\n- [Usage](#usage)\n  - [Customer Session](#customer-session)\n  - [Agent Session](#agent-session)\n- [API Reference](#api)\n  - [Global Properties](#global-properties)\n  - [ChatSession Class](#chatsession-class)\n  - [`chatSession` Methods](#chatsession-methods)\n  - [`chatSession` Events](#chatsession-events)\n- [Feature Documentation](#features)\n- [Local Development 💻](#local-development)\n- [Known Issues and Debugging 🐛](#known-issues-and-debugging)\n- [Troubleshooting and Support](#troubleshooting-and-support)\n\n## 📢 Announcements\n\n- **2025-05-29**: Migrated baked-in dependency from AWS SDK v2 to AWS SDK v3: `src/client/aws-sdk-connectparticipant.js`\n- **2024-04-02**: Connection Acknowledgement (ConnAck) has migrated from [SendEvent](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendEvent.html) API to the [CreateParticipant](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_CreateParticipantConnection.html) API. Please upgrade to `amazon-connect-chatjs@^1.4.0` by **Dec 31, 2024**\n- **2023-03-30**: v1.5.0 - Added support for _React Native environments_\n- **2023-12-23**: v1.3.0 - Added Message Receipts feature, enabled by default\n- **2022-11-08**: v1.2.0 - Added Client Side Metrics (CSM) feature, enabled by default\n- **2020-12-13**: Added support for TypeScript (requires `typescript@^3.0.1` or higher)\n\n## Examples\n\n- **HTML Examples**\n  - [Customer Chat UI](./examples/chatjs-customer.html)\n  - [Agent Chat UI with StreamsJS](./examples/chatjs-streamsjs-agent.html)\n- **React Examples**\n  - [Customer Chat UI](https://github.com/amazon-connect/amazon-connect-chat-interface)\n- **Mobile Examples**\n  - [React Native Customer Chat UI](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/mobileChatExamples/connectReactNativeChat)\n  - [Android Native Customer Chat UI](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/mobileChatExamples/androidChatExample)\n  - [iOS Native Customer Chat UI](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/mobileChatExamples/iOSChatExample)\n\n## Getting Started\n\n### Prerequisites\n\n- AWS Account\n- [Amazon Connect instance](https://docs.aws.amazon.com/connect/latest/adminguide/amazon-connect-instances.html)\n- Contact Flow ready to receive chat contacts (recommended: [\"Sample inbound flow\"](https://docs.aws.amazon.com/connect/latest/adminguide/sample-inbound-flow.html))\n- Deploy a [startChatContactAPI](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/cloudformationTemplates/startChatContactAPI) CloudFormation stack\n\n### Installation\n\n```sh\nnpm install amazon-connect-chatjs\n# or\nyarn add amazon-connect-chatjs\n# or\npnpm add amazon-connect-chatjs\n```\n\n### Importing ChatJS\n\nThis library supports ESModule (ES6) imports. This will make the `window.connect` variable available in the current context.\n\n```js\nimport 'amazon-connect-chatjs';\n```\n\n### TypeScript Support\n\nThis package includes built-in TypeScript type definitions (requires `typescript@\u003e=3.0.1`). No additional `@types` packages needed.\n\n```typescript\nimport 'amazon-connect-chatjs'; // loads dist/index.d.ts\n```\n### Importing from CDN\n\n```html\n\u003c!-- Using unpkg with semver range --\u003e\n\u003cscript src=\"https://unpkg.com/amazon-connect-chatjs@^3.0.0\"\u003e\u003c/script\u003e\n\n\u003c!-- Using unpkg with latest version --\u003e\n\u003cscript src=\"https://unpkg.com/amazon-connect-chatjs@latest\"\u003e\u003c/script\u003e\n\n\u003c!-- Using jsDelivr with specific version --\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/amazon-connect-chatjs@3.0.6/dist/amazon-connect-chat.js\"\u003e\u003c/script\u003e\n\n\u003c!-- Using with CORS --\u003e\n\u003cscript crossorigin src=\"https://unpkg.com/amazon-connect-chatjs\"\u003e\u003c/script\u003e\n```\n\n### Using the AWS SDK and ChatJS\n\nIf 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](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/) (in `src/client/aws-sdk-connectparticipant.js`).\n\n```js\nimport 'amazon-connect-chatjs';\n// Baked-in ChatJS dependency (AWS SDK v3)\n// import { ConnectParticipantClient } from './client/aws-sdk-connectparticipant.js'; // v3.x.x\n\n// Custom AWS SDK import, must be second\nimport { ConnectParticipantClient, StartAttachmentUploadCommand } from '@aws-sdk/client-connectparticipant'; // v3.x.x\n// your code ...\n```\n\n\n### Configuration\n\nSet the global configuration to use. This method should be called before `connect.ChatSession.create()`.\nFor all supported options, see [connect.ChatSession.create()](#connectchatsessionsetglobalconfig).\n\n```js\nconnect.ChatSession.setGlobalConfig({\n  region: \"\u003cAWS-REGION\u003e\", // (optional), defaults to: \"us-west-2\"\n  loggerConfig: { // (optional)\n    advancedLogWriter: null,\n    customizedLogger: {\n      debug: (...msg) =\u003e console.log(...msg),\n      info: (...msg) =\u003e console.log(...msg),\n      warn: (...msg) =\u003e console.log(...msg),\n      error: (...msg) =\u003e console.log(...msg)\n    },\n    level: connect.ChatSession.LogLevel.INFO, // (optional), default 10 (DEBUG, INFO, WARN, ERROR, ADVANCED_LOG)\n  },\n  webSocketManagerConfig: { // (optional) for React Native environments\n    isNetworkOnline: () =\u003e bool, // default: `() =\u003e navigator.onLine` (will break in React Native)\n  },\n  features: { // (optional)\n    messageReceipts: {\n      shouldSendMessageReceipts: true, // enabled by default, set to false to disable Read/Delivered receipts\n      throttleTime: 5000 // default: 5000, customize time to wait before sending Read/Delivered receipts\n    }\n  },\n  // Pass in a user agent suffix used to configure the AWS SDK client in Amazon Connect ChatJS.\n  // This will be appended to the x-amz-user-agent custom header used in outgoing API requests\n  customUserAgentSuffix: \"\", // (optional)\n});\n```\n\n## Usage\n\n### Customer Session\n\nCreate and join a new customer chat session.\n\nTo initialize ChatJS, you'll need chat details (`{ ContactId, ParticipantId, ParticipantToken }`) returned from a [StartChatContact](https://docs.aws.amazon.com/connect/latest/APIReference/API_StartChatContact.html) API request.\n\nWe recommend deploying this [startChatContactAPI](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/cloudformationTemplates/startChatContactAPI) CloudFormation stack for your chat proxy backend.\n\n```typescript\nimport \"amazon-connect-chatjs\"; // imports the \"window.connect\"\n\nconnect.ChatSession.setGlobalConfig({ region: \"us-west-2\" });\n\n// Step 1: Get chat details from your backend\n// Boilerplate endpoint: https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/cloudformationTemplates/startChatContactAPI\nconst response = await fetch(\"\u003curl-to-personal-chat-backend\u003e\", { method: \"POST\" });\nconst chatDetails = await response.json();\n\n// Step 2: Connect to the chat session\nconst customerChatSession = connect.ChatSession.create({\n  chatDetails: {\n    contactId: chatDetails.ContactId,\n    participantId: chatDetails.ParticipantId,\n    participantToken: chatDetails.ParticipantToken,\n  },\n  options: { region: \"us-west-2\" }, // optional\n  type: \"CUSTOMER\",\n  disableCSM: true\n});\nawait customerChatSession.connect();\n\n// Step 3: Send messages and events\nawait customerChatSession.sendMessage({ contentType: \"text/plain\", message: \"Hello World!\" });\nawait customerChatSession.sendEvent({ contentType: \"application/vnd.amazonaws.connect.event.typing\" });\n\n// Step 4: Handle incoming websocket events\ncustomerChatSession.onMessage(event =\u003e { /* ... */ });\ncustomerChatSession.onConnectionBroken(event =\u003e { /* ... */ });\ncustomerChatSession.onEnded(event =\u003e { /* ... */ });\ncustomerChatSession.onTyping(event =\u003e { /* ... */ });\ncustomerChatSession.onConnectionEstablished(event =\u003e { /* ... */ });\n\n// Step 5: End chat gracefully\nawait customerChatSession.disconnectParticipant();\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e📌 View: ChatJS Customer Session Diagaram\u003c/summary\u003e\n\n  ![ChatJS Customer Chat Session diagram](./docs/chatjs-initialization-diagram.png)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e📌 View: Customer Chat Sequence Diagaram\u003c/summary\u003e\n\n```mermaid\nsequenceDiagram\n    participant Client as Customer Chat UI\u003cbr/\u003e[ChatJS Client]\n    participant Proxy as startChatContactAPI\u003cbr/\u003e[Lambda]\n    participant Connect as Amazon Connect\u003cbr/\u003eBackend\n    participant Instance as Connect Instance\n    participant Agent as Agent\n\n    Client-\u003e\u003eProxy: POST /start-chat\n    Note over Proxy: Returns:\u003cbr/\u003e- ContactId\u003cbr/\u003e- ParticipantId\u003cbr/\u003e- ParticipantToken\n    Proxy--\u003e\u003eClient: Return chat credentials\n\n    Client-\u003e\u003eConnect: customerChatSession.connect()\n    Connect-\u003e\u003eInstance: Initiate chat\n    Instance-\u003e\u003eAgent: Notify new chat\n    Connect--\u003e\u003eClient: Return connection details\n\n    Client-\u003e\u003eConnect: subscribe to WebSocket connection\n\n    rect rgb(240, 240, 240)\n        Note over Client,Agent: Bi-directional WebSocket Communication\n        Client-\u003e\u003eConnect: WebSocket events\n        Connect-\u003e\u003eInstance: Internal routing\n        Instance-\u003e\u003eAgent: Agent interface\n        Agent-\u003e\u003eInstance: Agent responses\n        Instance-\u003e\u003eConnect: Internal routing\n        Connect-\u003e\u003eClient: WebSocket events\n    end\n\n    Client-\u003e\u003eConnect: customerChatSession.disconnectParticipant()\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e📌 HTML Sample: ChatJS Customer Session\u003c/summary\u003e\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003cmeta charset=\"UTF-8\"\u003e\n  \u003c!--\n  Alternative import method:\n  \u003cscript src=\"https://unpkg.com/amazon-connect-chatjs@3.0.3\"\u003e\u003c/script\u003e\n  --\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cdiv id=\"chat-container\"\u003e\n    \u003c!-- Chat UI elements would go here --\u003e\n  \u003c/div\u003e\n\n  \u003cscript type=\"module\"\u003e\n    import \"https://unpkg.com/amazon-connect-chatjs@3.0.3\";\n    const REGION = \"us-west-2\";\n\n    window.onload = async function () {\n      // Configure ChatJS\n      connect.ChatSession.setGlobalConfig({ region: REGION });\n\n      // Step 1: Get chat details from your backend\n      const response = await fetch(\"\u003curl-to-personal-chat-backend\u003e\", { method: \"POST\" });\n      const chatDetails = await response.json();\n\n      // Step 2: Connect to the chat session\n      const customerChatSession = connect.ChatSession.create({\n        chatDetails: {\n          contactId: chatDetails.ContactId,\n          participantId: chatDetails.ParticipantId,\n          participantToken: chatDetails.ParticipantToken,\n        },\n        options: { region: REGION }, // optional\n        type: \"CUSTOMER\",\n        disableCSM: true\n      });\n      await customerChatSession.connect();\n\n      // Step 3: Send messages and events\n      // These would typically be triggered by user actions\n      // await customerChatSession.sendMessage({ contentType: \"text/plain\", message: \"Hello World!\" });\n      // await customerChatSession.sendEvent({ contentType: \"application/vnd.amazonaws.connect.event.typing\" });\n\n      // Step 4: Handle incoming websocket events\n      customerChatSession.onMessage(event =\u003e { /* ... */ });\n      customerChatSession.onConnectionBroken(event =\u003e { /* ... */ });\n      customerChatSession.onEnded(event =\u003e { /* ... */ });\n      customerChatSession.onTyping(event =\u003e { /* ... */ });\n      customerChatSession.onConnectionEstablished(event =\u003e { /* ... */ });\n\n      // Step 5: End chat gracefully\n      // This would typically be triggered by a user action\n      // await customerChatSession.disconnectParticipant();\n    };\n  \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\u003c/details\u003e\n\n### Agent Session\n\nFor agent chat sessions and **Custom Custom Contact Control Panel (CCP)**, please integrate **ChatJS** with the [Amazon Connect Streams](https://github.com/aws/amazon-connect-streams) library.\n\nStreamJS 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()`.\n\n\u003e **Note:** for **Custom CCP**, you must to allow-list your domain before using StreamsJS, including `http://localhost:PORT` for local testing. More [details here](https://github.com/amazon-connect/amazon-connect-streams?tab=readme-ov-file#allowlisting). Update your instance settings in the Amazon Connect AWS Console.\n\n```html\n\u003chtml\u003e\n\u003c!-- OPTIONAL: hide the pre-built CCP UI\n\u003cstyle\u003e#ccp-iframe-root iframe{display:none}\u003c/style\u003e\n--\u003e\n\u003cbody\u003e\n  \u003cdiv id=\"ccp-iframe-root\"\u003e\u003c/div\u003e\n  \u003cscript type=\"module\"\u003e\n    import 'https://unpkg.com/amazon-connect-streams@2.18.3';  // StreamJS must be imported first\n\n    // To allow-list your domain, see: https://github.com/amazon-connect/amazon-connect-streams#allowlisting\n    const INSTANCE_URL = \"https://\u003cINSTANCE_NAME\u003e.my.connect.aws/ccp-v2/\";\n    const REGION = '\u003cAWS-REGION\u003e'; // \"us-west-2\"\n\n    // Step 1: Initialize CCP\n    // \u003cdiv id=\"ccp-iframe-root\" /\u003e\n    var containerElement = document.getElementById(\"ccp-iframe-root\");\n    await connect.core.initCCP(containerElement, {\n      ccpUrl: INSTANCE_URL,\n      region: REGION,\n      loginPopup: true,\n    });\n\n    // Step 2: Handle incoming chat contacts\n    connect.contact((contact) =\u003e {\n      if (contact.getType() !== connect.ContactType.CHAT) return;\n      // Auto-accept the incoming chat contact\n      contact.accept();\n\n      contact.onAccepted(async () =\u003e {\n        const agentConnection = contact.getConnections().find(conn =\u003e conn.getType() === connect.ConnectionType.AGENT);\n\n        // Configure ChatJS (optional)\n        connect.ChatSession.setGlobalConfig({ /* ... */ });\n\n        // Step 3: Initialize ChatJS and subscribe to WebSocket connection\n        const agentChatSession = await agentConnection.getMediaController();\n\n        // Fetch the transcript\n        const awsSDKResponse = await agentChatSession.getTranscript({\n          sortOrder: \"ASCENDING\",\n          maxResults: 100, // default: 15\n          metadata: { foo: \"bar\" }, // optional\n          // scanDirection: \"BACKWARD\", (optional) default: BACKWARD\n          // nextToken?: nextToken - OPTIONAL, for pagination\n        });\n        const { InitialContactId, NextToken, Transcript } = awsSDKResponse.data;\n\n        // Set up event listeners\n        agentChatSession.onConnectionEstablished((event) =\u003e {\n          // Handle connection established\n        });\n\n        agentChatSession.onMessage((event) =\u003e {\n          const message = event.data?.Content;\n          // Handle incoming message\n        });\n\n        // Send messages\n        await agentChatSession.sendMessage({ contentType: \"text/plain\", message: \"Hello World!\" });\n\n        // NOTE: disconnectParticipant() is not available in agentChatSession\n        // To leave an agent chat session, run:\n        // contact.destroy()\n      });\n    });\n  \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e📌 HTML Sample: Agent Custom CCP w/ ChatJS and StreamsJS\u003c/summary\u003e\n\n```html\n\u003c!-- chatjs-streamsjs-example.html --\u003e\n\u003c!--\n# Amazon Connect Custom Agent Chat UI\n\n## Overview\nCustom Agent Chat UI integrating ChatJS and StreamsJS for Amazon Connect Chat\n\n- StreamsJS: https://github.com/amazon-connect/amazon-connect-streams\n- ChatJS: https://github.com/amazon-connect/amazon-connect-chatjs\n- AWS Documentation: https://docs.aws.amazon.com/connect/latest/adminguide/chat-with-connect-contacts.html\n\n## Prerequisites\n- Amazon Connect Instance\n- Access to Agent Contact Control Panel (CCP): https://\u003cinstance-alias\u003e.my.connect.aws/ccp-v2\n  - Requires: Security Profile = \"CCP: Access CCP\"\n\n## Configuration Steps\n1. Allowlisting\n   - Login to your AWS Account, then navigate to the Amazon Connect console.\n   - Click the instance name of the instance for which you would like to allowlist pages to load the settings page for your instance.\n   - Click the \"Application integration\" link on the left.\n   - Click \"Add Origin\", then enter a domain URL: http://localhost:8080\n\n2. Configuration Updates\n   - Update the following values in the script:\n     * `INSTANCE_URL`: Your Amazon Connect instance URL\n     * `REGION`: Your AWS region\n\n## Local Testing Instructions\n1. Host the HTML file in a local browser\n   ``\n   npx live-server --port=8080 chatjs-streamsjs-example.html\n   ``\n   - Access URL: http://localhost:8080\n\n2. Login Process\n   - Open Contact Control Panel (CCP)\n   - Login with your Agent username/password\n\n3. Chat Interaction\n   - Keep CCP tab open\n   - In a second browser tab, launch Amazon Connect Test Chat Page: https://\u003cinstance-alias\u003e.my.connect.aws/test-chat\n   - Open the Customer widget\n   - Back on CCP tab, wait for an incoming chat contact, click \"Accept\"\n--\u003e\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\n\u003chead\u003e\n  \u003cmeta charset=\"UTF-8\"\u003e\n  \u003ctitle\u003eAgent Chat UI [Amazon Connect]\u003c/title\u003e\n  \u003cstyle\u003e\n    body {\n      display: flex;\n    }\n\n    #prebuilt-agent-ui-iframe,\n    #chat-ui-container {\n      width: 400px;\n      height: 800px;\n    }\n\n    #chat-ui-container {\n      font-family: Arial, sans-serif;\n      border: 1px solid #ddd;\n      padding: 15px;\n      border-radius: 5px;\n      margin: 20px auto;\n    }\n\n    #custom-agent-chat-transcript {\n      height: 300px;\n      overflow-y: auto;\n      background-color: #f8f8f8;\n      padding: 10px;\n      margin-top: 20px;\n      width: 100%;\n      box-sizing: border-box;\n    }\n\n    #custom-agent-chat-transcript::after {\n      content: \"\";\n      display: table;\n      clear: both;\n    }\n\n    .message {\n      margin: 5px 0;\n      padding: 8px;\n      border-radius: 5px;\n      max-width: 80%;\n      word-wrap: break-word;\n      clear: both;\n    }\n\n    .incoming-message {\n      background-color: #f0f0f0;\n      border: 1px solid #ddd;\n      float: left;\n      text-align: left;\n    }\n\n    .outgoing-message {\n      background-color: #0084ff;\n      color: white;\n      border: 1px solid #0073e6;\n      float: right;\n      text-align: right;\n    }\n\n    #message-input-container {\n      display: flex;\n      margin-top: 15px;\n    }\n\n    #messageInput {\n      flex-grow: 1;\n      margin-right: 5px;\n      padding: 8px;\n      border: 1px solid #ccc;\n      border-radius: 4px;\n    }\n\n    button {\n      padding: 8px 15px;\n      border-radius: 4px;\n      cursor: pointer;\n      background-color: #0084ff;\n      color: white;\n      border: none;\n    }\n\n    button:disabled {\n      background-color: #ccc;\n    }\n  \u003c/style\u003e\n\u003c/head\u003e\n\n\u003cbody\u003e\n  \u003cdiv id=\"prebuilt-agent-ui-iframe\"\u003e\u003c/div\u003e\n  \u003cdiv id=\"chat-ui-container\"\u003e\n    \u003ch3\u003eCustom Agent Chat UI (ChatJS + StreamsJS)\u003c/h3\u003e\n    \u003cdiv id=\"custom-agent-chat-transcript\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"message-input-container\" style=\"display: none\"\u003e\n      \u003cinput type=\"text\" id=\"messageInput\" placeholder=\"Type your message...\" disabled\u003e\n      \u003cbutton id=\"sendMessageButton\" disabled\u003eSend\u003c/button\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\n  \u003cscript type=\"module\"\u003e\n    // Option 1: import ChatJS and StreamJS directly from npm (order is important)\n    import \"https://unpkg.com/amazon-connect-streams@2.18.1\"; // imports `window.connect.*`\n    import \"https://unpkg.com/amazon-connect-chatjs@3.0.5\"; // also imports `window.connect.*`\n\n    // Option 2: Import bundle files\n    // import \"amazon-connect-streams.js\";\n    // import \"amazon-connect-chat.js\";\n\n    const INSTANCE_URL = \"https://{INSTANCE-ALIAS}.my.connect.aws/ccp-v2?visual-refresh=true\";\n    const REGION = 'us-west-2';\n    const MAX_TRANSCRIPT_MESSAGES = 15;\n\n    window.onload = async function () {\n      // DOM element references\n      const elements = {\n        prebuiltAgentUI: document.getElementById(\"prebuilt-agent-ui-iframe\"),\n        transcript: document.getElementById(\"custom-agent-chat-transcript\"),\n        messageInput: document.getElementById(\"messageInput\"),\n        sendButton: document.getElementById(\"sendMessageButton\"),\n        inputContainer: document.getElementById(\"message-input-container\"),\n      };\n\n      // Initialize Connect CCP and set up handlers\n      await connect.core.initCCP(elements.prebuiltAgentUI, {\n        ccpUrl: INSTANCE_URL,\n        region: REGION,\n        loginPopup: true,\n      });\n\n      connect.ChatSession.setGlobalConfig({\n        loggerConfig: { useDefaultLogger: true },\n        region: REGION,\n      });\n\n      // Handle new contacts\n      connect.contact(contact =\u003e {\n        if (contact.getType() === connect.ContactType.CHAT) {\n          // Automatically accept chat\n          contact.accept();\n        }\n\n        contact.onAccepted(() =\u003e initializeChatContact(contact));\n      });\n\n      // Check for existing contacts\n      connect.agent(agent =\u003e {\n        agent.onRefresh(() =\u003e {\n          agent.getContacts().forEach(contact =\u003e {\n            const contactStatus = contact.getStatus().type;\n            const isActiveChat =\n              contact.getType() === connect.ContactType.CHAT \u0026\u0026\n              (contactStatus === connect.ContactStateType.CONNECTED ||\n                contactStatus === connect.ContactStateType.ACCEPTED);\n\n            if (isActiveChat) initializeChatContact(contact);\n          });\n        });\n      });\n\n      /**\n       * Initialize a chat contact and set up the UI\n       */\n      async function initializeChatContact(contact) {\n        if (contact.getType() !== connect.ContactType.CHAT) return;\n\n        const agentConnection = contact.getConnections().find(\n          conn =\u003e conn.getType() === connect.ConnectionType.AGENT\n        );\n\n        let chatSession;\n        try {\n          chatSession = await agentConnection.getMediaController();\n\n          if (!chatSession) {\n            chatSession = connect.ChatSession.create({\n              chatDetails: agentConnection.getMediaInfo(),\n              options: { region: REGION },\n              type: connect.ChatSession.SessionTypes.AGENT,\n              websocketManager: connect.core.getWebSocketManager()\n            });\n            await chatSession.connect();\n          }\n\n          // To end an Agent Chat Session, equiv to customerChatSession.disconnectParticipant()\n          // await contact.destroy({\n          //     success: () =\u003e console.log(\"Contact ended successfully\"),\n          //     failure: (err) =\u003e console.error(\"Failed to end contact:\", err)\n          // });\n\n          setupChat(chatSession, elements);\n        } catch (error) {\n          console.error('Error getting chat session:', error);\n        }\n      }\n\n      /**\n       * Set up the chat UI and handlers\n       */\n      function setupChat(chatSession, elements) {\n        if (!chatSession) return;\n\n        // Show and enable UI elements\n        elements.transcript.style.display = \"block\";\n        elements.transcript.style.visibility = \"visible\";\n        elements.inputContainer.style.display = \"flex\";\n        elements.messageInput.disabled = false;\n        elements.sendButton.disabled = false;\n\n        // Set up message sending\n        const sendMessage = async () =\u003e {\n          const message = elements.messageInput.value.trim();\n          if (message) {\n            try {\n              await chatSession.sendMessage({ contentType: \"text/plain\", message });\n              elements.messageInput.value = '';\n            } catch (error) {\n              console.error('Error sending message:', error);\n            }\n          }\n        };\n\n        elements.sendButton.addEventListener('click', sendMessage);\n        elements.messageInput.addEventListener('keypress', e =\u003e {\n          if (e.key === 'Enter') sendMessage();\n        });\n\n        // Set up chat session handlers\n        chatSession.onConnectionEstablished(() =\u003e {\n          // Load previous messages\n          chatSession.getTranscript({\n            scanDirection: \"BACKWARD\",\n            sortOrder: \"ASCENDING\",\n            maxResults: MAX_TRANSCRIPT_MESSAGES\n          }).then(response =\u003e {\n            if (response.data?.Transcript) {\n              response.data.Transcript.forEach(msg =\u003e renderMessage(msg, chatSession, elements));\n            }\n          }).catch(error =\u003e console.error(\"Error loading transcript:\", error));\n        });\n\n        /**\n         * 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.\n         * @param {\n            chatDetails: Object,\n            data: {\n              AbsoluteTime: string,\n              Content?: string,\n              ContentType: string,\n              DisplayName?: string,\n              Id: string,\n              ParticipantId?: string,\n              ParticipantRole?: \"AGENT\" | \"CUSTOMER\" | \"SYSTEM\",\n              Type: \"MESSAGE\" | \"EVENT\" | \"ATTACHMENT\" | \"CONNECTION_ACK\",\n              ContactId?: string,\n              InitialContactId?: string\n            }\n        } event\n        */\n        chatSession.onMessage(event =\u003e {\n          if (event.data) renderMessage(event.data, chatSession, elements);\n        });\n\n        /**\n         * Subscribes an event handler that triggers whenever a \"application/vnd.amazonaws.connect.event.typing\" event is created by any participant.\n         * @param {\n            AbsoluteTime?: string,\n            ContentType: \"application/vnd.amazonaws.connect.event.typing\",\n            Type?: string,\n            ParticipantId?: string,\n            DisplayName?: string,\n            ParticipantRole?: \"AGENT\" | \"CUSTOMER\" | \"SYSTEM\",\n            InitialContactId?: string\n        } event.data\n        */\n        chatSession.onTyping((event) =\u003e {\n          // Handle typing indicator\n          renderMessage({\n            \"AbsoluteTime\": \"2025-05-23T06:01:24.287Z\",\n            \"ContentType\": \"text/plain\",\n            \"Content\": \"...\",\n            \"Id\": \"e69634e9-2b31-4598-923e-5b2be62d436b\",\n            \"Type\": \"EVENT\",\n            \"ParticipantId\": \"5b370166-c0ee-4e23-ac1b-87ceffa611c4\",\n            \"DisplayName\": \"Customer\",\n            \"ParticipantRole\": \"CUSTOMER\",\n            \"InitialContactId\": \"3358be3e-368d-4cde-ae92-352f44c35440\"\n          }, chatSession, elements);\n        })\n\n        /**\n         * Subscribes an event handler that triggers when a read message event is received from the customer or agent.\n         * @param {\n            AbsoluteTime?: string,\n            ContentType: \"application/vnd.amazonaws.connect.event.message.read\",\n            Type?: string,\n            ParticipantId?: string,\n            DisplayName?: string,\n            ParticipantRole?: \"AGENT\" | \"CUSTOMER\" | \"SYSTEM\",\n            InitialContactId?: string\n         } event.data\n         */\n        chatSession.onReadReceipt((event) =\u003e {\n          // handle message receipt\n        })\n\n        /**\n         * Subscribes an event handler that triggers when a delivered message event is received from the customer or agent.\n         * @param {\n            AbsoluteTime?: string,\n            ContentType: \"application/vnd.amazonaws.connect.event.message.delivered\",\n            Type?: string,\n            ParticipantId?: string,\n            DisplayName?: string,\n            ParticipantRole?: \"AGENT\" | \"CUSTOMER\" | \"SYSTEM\",\n            InitialContactId?: string\n         } event.data\n         */\n        chatSession.onDeliveredReceipt((event) =\u003e {\n          // handle message receipt\n        })\n      }\n\n      /**\n       * Render a message in the chat UI\n       */\n      function renderMessage(message, chatSession, elements) {\n        if (message.ContentType === \"text/plain\" || message.ContentType === \"text/markdown\") {\n          const messageElement = document.createElement(\"div\");\n          messageElement.className = \"message\";\n\n          const isFromAgent = message.ParticipantId === chatSession.getChatDetails().participantId;\n          messageElement.classList.add(isFromAgent ? \"outgoing-message\" : \"incoming-message\");\n\n          const displayName = message.DisplayName || (isFromAgent ? 'Agent' : 'Customer');\n          const content = document.createElement(\"div\");\n          const messageContent = message.Content || message.content;\n          content.textContent = `${displayName}: ${messageContent}`;\n          messageElement.appendChild(content);\n\n          messageElement.id = `msg-${message.Id}`;\n          messageElement.title = new Date(message.AbsoluteTime).toLocaleTimeString();\n\n          elements.transcript.appendChild(messageElement);\n          elements.transcript.scrollTop = elements.transcript.scrollHeight;\n        }\n      }\n    };\n  \u003c/script\u003e\n\u003c/body\u003e\n\n\u003c/html\u003e\n```\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e📌 View: Agent Chat Sequence Diagaram\u003c/summary\u003e\n\n```mermaid\nsequenceDiagram\n  participant ChatJS\n  participant ConnectAPI\n  participant WebSocket\n  participant AgentUI\n  participant StreamsJS\n\n  rect rgb(200, 230, 200)\n    Note over AgentUI, WebSocket: 1. Initialize + Subscribe\n    AgentUI -\u003e\u003e core.initCCP: core.initCCP\n    StreamsJS -\u003e\u003e AgentUI: initConnection success\n    AgentUI -\u003e\u003e StreamsJS: agent.onRefresh(handleAgentData)\n    AgentUI -\u003e\u003e StreamsJS: contact.onIncoming(handleContact)\n  end\n\n  rect rgb(230, 200, 230)\n    Note over AgentUI, WebSocket: 2. Incoming Chat Contact\n    ConnectAPI -\u003e\u003e StreamsJS: New CHAT contact\n    StreamsJS -\u003e\u003e AgentUI: contact.onIncoming event\n    Note right of AgentUI: Check contact.getType() === \"chat\"\n  end\n\n  rect rgb(200, 200, 230)\n    Note over AgentUI, WebSocket: 3. Accept Chat\n    AgentUI -\u003e\u003e StreamsJS: contact.accept()\n    StreamsJS -\u003e\u003e ConnectAPI: AcceptContact API\n    ConnectAPI --\u003e\u003e StreamsJS: Contact accepted\n    StreamsJS -\u003e\u003e AgentUI: contact.onAccepted event\n    Note over AgentUI: Initialize ChatJS\n    AgentUI -\u003e\u003e ChatJS: new ChatSession(chatDetails);\n    ChatJS -\u003e\u003e WebSocket: Connect with participantToken\n    WebSocket --\u003e\u003e ChatJS: Connection established\n    ChatJS -\u003e\u003e AgentUI: onConnectionEstablished event\n  end\n\n  rect rgb(240, 240, 240)\n    Note over AgentUI, WebSocket: 4. Chat Operations\n    WebSocket -\u003e\u003e ChatJS: Incoming message\n    ChatJS -\u003e\u003e AgentUI: onMessage callback\n    AgentUI -\u003e\u003e ChatJS: sendMessage(\"Hello\")\n    ChatJS -\u003e\u003e WebSocket: Send via WebSocket\n    WebSocket --\u003e\u003e ChatJS: Message delivered\n    ChatJS --\u003e\u003e AgentUI: Success callback\n    AgentUI -\u003e\u003e ChatJS: getTranscript()\n    ChatJS -\u003e\u003e WebSocket: Request transcript\n    WebSocket --\u003e\u003e ChatJS: Return transcript\n    ChatJS --\u003e\u003e AgentUI: Transcript data\n  end\n\n  rect rgb(230, 230, 200)\n    Note over AgentUI, WebSocket: 5. End Chat\n    AgentUI -\u003e\u003e StreamsJS: contact.destroy()\n    StreamsJS -\u003e\u003e ConnectAPI: StopContact API\n    ConnectAPI --\u003e\u003e StreamsJS: Contact ended\n    StreamsJS -\u003e\u003e AgentUI: contact.onEnded event\n    WebSocket -\u003e\u003e ChatJS: Connection closed\n    ChatJS -\u003e\u003e AgentUI: onConnectionLost event\n  end\n```\n\u003c/details\u003e\n\n## API\n\n- [Global Properties](#global-properties)\n- [ChatSession Class](#chatsession-class)\n- [`chatSession` Methods](#chatsession-methods)\n- [`chatSession` Events](#chatsession-events)\n\n### Global Properties\n\n#### `window.connect.ChatSession`\n\n```js\nwindow.connect.ChatSession = {\n  create: ({ /* ... */ }) =\u003e {},\n  setGlobalConfig: (config) =\u003e {},\n  LogLevel: { /* ... */ },\n  Logger: { /* ... */ },\n  SessionTypes: { /* ... */ },\n};\n```\nThis is the main entry point to `amazon-connect-chatjs`.\nAll your interactions with the library start here.\n\n#### `window.connect.ChatSession.LogLevel`\n\n```js\nconnect.ChatSession.LogLevel = {\n  DEBUG,\n  INFO,\n  WARN,\n  ERROR,\n  ADVANCED_LOG,\n};\n```\nEnumerates the logging levels.\n\n\u003c!--\n#### `window.connect.csmService` [INTERNAL ONLY]\n\n```js\nconst csmService = window.connect.csmService;\n\n// Example usage\ncsmService.initializeCSM();\ncsmService.updateCsmConfig({ widgetType: \"CustomChatWidget\" })\ncsmService.addCountAndErrorMetric(metricName, \"UI\" || \"API\", error=false);\ncsmService.addCountMetric(method, \"UI\" || \"API\");\n// ...\n```\nUsed for publishing client-side-metrics (CSM) to track API metrics (count, latency, error count). Only applies to `CustomerChatSession`.\n\nUsed internally and safe to disable: `connect.ChatSession.create({ ..., disableCSM: true })`. ChatJS will functionally normally without CSM.\n--\u003e\n\n### ChatSession Class\n\n#### `connect.ChatSession.create()`\n\n```js\nconst chatSession = await connect.ChatSession.create({\n  chatDetails: {\n    contactId: \"...\", // REQUIRED\n    participantId: \"...\", // REQUIRED\n    participantToken: \"...\", // REQUIRED\n  },\n  options: {\n    region: \"us-east-1\", // (optional) defaults to `region` set in `.setGlobalConfig()`\n  },\n  type: window.connect.ChatSession.SessionTypes.CUSTOMER, // REQUIRED - options: `CUSTOMER`, `AGENT`\n  disableCSM: true\n});\n```\n\n`ContactId`, `ParticipantId`, and `ParticipantToken` must be generated on your backend and passed to the client. Make a request to [StartChatContact](https://docs.aws.amazon.com/connect/latest/APIReference/API_StartChatContact.html) API (see [#Usage](#usage-customer-chat)) for more details.\n\n#### `connect.ChatSession.setGlobalConfig()`\n\n```js\nconnect.ChatSession.setGlobalConfig({\n  // AWS Region (optional, defaults to \"us-west-2\")\n  region: \"\u003cAWS-REGION\u003e\",\n\n  // Logger Configuration (optional)\n  loggerConfig: {\n    advancedLogWriter: null,\n    customizedLogger: {\n      debug: (...msg) =\u003e console.log(...msg),\n      info: (...msg) =\u003e console.log(...msg),\n      warn: (...msg) =\u003e console.log(...msg),\n      error: (...msg) =\u003e console.log(...msg)\n    },\n    // Log levels: DEBUG, INFO, WARN, ERROR, ADVANCED_LOG\n    level: connect.ChatSession.LogLevel.INFO\n  },\n\n  // WebSocket Manager Config (optional, for React Native environments)\n  webSocketManagerConfig: {\n    // Default: `() =\u003e navigator.onLine` (will break in React Native)\n    isNetworkOnline: () =\u003e bool\n  },\n\n  // Features Configuration (optional)\n  features: {\n    messageReceipts: {\n      // Enable/disable Read/Delivered receipts (enabled by default)\n      shouldSendMessageReceipts: true,\n      // Time to wait before sending Read/Delivered receipts (default: 5000ms)\n      throttleTime: 5000\n    }\n  },\n\n  // User agent suffix for AWS SDK client (optional)\n  // Appended to x-amz-user-agent custom header in API requests\n  customUserAgentSuffix: \"\"\n});\n```\nSet 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()`.\n\n#### `connect.ChatSession.Logger`\n\n```js\nconnect.ChatSession.Logger = {\n    debug(data) {}\n    info(data) {}\n    warn(data) {}\n    error(data) {}\n    advancedLog(data) {}\n}\nconst logger = connect.ChatSession.Logger;\nlogger.info('foobar')\n// INFO [2025-04-08T03:29:35.423Z] ChatJS: foobar\n```\nExposes the internal ChatJS logger. Group your logs and use consistent format for easier debugging.\n\n#### `connect.ChatSession.SessionTypes`\n\n```js\nconnect.ChatSession.SessionTypes = {\n  AGENT,\n  CUSTOMER,\n};\n```\nEnumerates the session types.\n\n### `chatSession` Methods\n\nAmazon Connect [Participant Service API](https://docs.aws.amazon.com/connect/latest/APIReference/API_Operations_Amazon_Connect_Participant_Service.html) wrappers\n\n\u003e ##### Metadata Usage\n\u003e\n\u003e - Most functions accept an optional `metadata` argument\n\u003e - `metadata` is not used by `amazon-connect-chatjs` internally\n\u003e - The `metadata` value is copied to the response object\n\u003e - Developers can use `metadata` for their own purposes\n\u003e\n\u003e Example:\n\u003e ```js\n\u003e chatSession.getTranscript({ metadata: \"foo\" })\n\u003e   .then(({ data, metadata }) =\u003e {\n\u003e     console.log(metadata); // \"foo\"\n\u003e   })\n\u003e   .catch(({ error, metadata}) =\u003e {\n\u003e      console.error(metadata); // \"foo\"\n\u003e   })\n\u003e ```\n\n#### `chatSession.connect()`\n\n```js\nconst { connectCalled, connectSuccess } = await chatSession.connect();\n// connectCalled: indicates whether the Amazon Connect Participant Service was called\n// connectSuccess: indicates whether the operation succeeded\n```\nWraps the [CreateParticipantConnection](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_CreateParticipantConnection.html) API.\n\n**Note:** If the operation fails, the Promise will reject, but the error will have the same schema as a successful response.\n\n#### `chatSession.sendMessage()`\n\n```js\nconst awsSdkResponse = await chatSession.sendMessage({\n  contentType: \"text/plain\",\n  message: \"Hello World!\",\n  metadata: { foo: \"bar\" }, // optional\n});\nconst { AbsoluteTime, Id, MessageMetadata } = awsSdkResponse.data;\nconst metadata = awsSdkResponse.metadata;\n```\n\nWraps the [SendMessage](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendMessage.html) API.\n\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendMessage.html#API_SendMessage_RequestSyntax) with the following differences:\n\n- Fields are in `camelCase`.\n- `ClientToken` cannot be specified.\n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendMessage.html#API_SendMessage_ResponseSyntax).\n\n#### `chatSession.getTranscript()`\n\n```js\nconst awsSDKResponse = await chatSession.getTranscript({\n    sortOrder: \"ASCENDING\",\n    maxResults: 100, // default: 15\n    metadata: { foo: \"bar\" }, // optional\n    // scanDirection: \"BACKWARD\", (optional) default: BACKWARD\n    // nextToken?: nextToken - OPTIONAL, for pagination\n});\nconst { InitialContactId, NextToken, Transcript } = awsSDKResponse.data;\n// see: https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_GetTranscript.html#API_GetTranscript_ResponseSyntax\n```\nFetch the chat transcript (uses ConnectionToken). Wraps the [GetTranscript](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetTranscript.html) API\n\n\u003e **Important note:** In order to specify `scanDirection` as `FORWARD`, you need to explicitly include a `startPosition`.\nThis 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!).\n\n#### `chatSession.sendEvent()`\n\n```js\nconst awsSdkResponse = await chatSession.sendEvent({\n  contentType: \"application/vnd.amazonaws.connect.event.typing\",\n  metadata: { foo: \"bar\" }, // optional\n});\nconst { AbsoluteTime, Id } = awsSdkResponse.data;\n```\n\nWraps the [SendEvent](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendEvent.html) API.\n\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendEvent.html#API_SendEvent_RequestSyntax) with the following differences:\n\n\n- Fields are in `camelCase`.\n- `ClientToken` cannot be specified.\n- `ContentType` allows the following values:\n  - `\"application/vnd.amazonaws.connect.event.typing\"`\n  - `\"application/vnd.amazonaws.connect.event.connection.acknowledged\"`\n  - `\"application/vnd.amazonaws.connect.event.message.delivered\"`\n  - `\"application/vnd.amazonaws.connect.event.message.read\"`\n  - `\"application/vnd.amazonaws.connect.event.participant.invited\"`\n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendEvent.html#API_SendEvent_ResponseSyntax).\n\n#### `chatSession.sendAttachment()`\n\n\u003e Important: an administrator must [enable attachments](https://docs.aws.amazon.com/connect/latest/adminguide/enable-attachments.html) for your Connect instance\n\n```js\nawait chatSession.sendAttachment({\n  attachment: attachment // type: File [HTML file object, see https://developer.mozilla.org/en-US/docs/Web/API/File]\n  metadata: { foo: \"bar\" }, // optional\n});\n// supported files: .csv, .doc, .docx, .jpeg, .jpg, .pdf, .png, .ppt, .pptx, .txt, .wav, .xls, .xlsx\n// max size: 20MB\n// source: https://docs.aws.amazon.com/connect/latest/adminguide/feature-limits.html#feature-limits-chat\n\n// Example usage\nvar input = document.createElement('input');\ninput.type = 'file';\ninput.addEventListener('change', (e) =\u003e {\n  const file = e.target.files[0];\n  chatSession.sendAttachment({ attachment: file })\n});\n```\nWraps the [StartAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_StartAttachmentUpload.html) and [CompleteAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_CompleteAttachmentUpload.html) API.\nThe arguments are based on the [StartAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_StartAttachmentUpload.html#API_StartAttachmentUpload_RequestSyntax) and [CompleteAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_CompleteAttachmentUpload.html#API_CompleteAttachmentUpload_RequestSyntax) API request body with the following differences:\n\nThe response `data` is the same as the [StartAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_StartAttachmentUpload.html#API_StartAttachmentUpload_ResponseSyntax) and [CompleteAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_CompleteAttachmentUpload.html#API_CompleteAttachmentUpload_ResponseSyntax) API response body.\n`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.\n\n#### `chatSession.downloadAttachment()`\n\n```js\nchatSession.onMessage(event =\u003e {\n  // event.contentType === \"application/vnd.amazonaws.connect.message.attachment\"\n  if (event.data \u0026\u0026 event.data.Type === \"ATTACHMENT\") {\n    const attachmentItem = event.data.Attachments[0];\n\n    console.log(event.data);\n    //  {\n    //     \"AbsoluteTime\": \"2025-05-24T21:42:55.867Z\",\n    //     \"Attachments\": [\n    //         {\n    //             \"ContentType\": \"image/png\",\n    //             \"AttachmentId\": \"asdfasdfasdfsadf\",\n    //             \"AttachmentName\": \"Screenshot 2025-05-24 at 2.42.48 PM.png\",\n    //             \"Status\": \"APPROVED\"\n    //         }\n    //     ],\n    //     \"Id\": \"86a061a2-f99c-4691-a63e-47d145628a80\",\n    //     \"Type\": \"ATTACHMENT\",\n    //     \"ParticipantId\": \"4393212f-4481-4c7d-8184-5be9d811d7ce\",\n    //     \"DisplayName\": \"Spencer\",\n    //     \"ParticipantRole\": \"CUSTOMER\",\n    //     \"InitialContactId\": \"f50e4cc0-b825-4da7-849a-27fa75f993de\",\n    //     \"ContactId\": \"7d007f43-a0cc-4efb-abc9-628fc216e6d5\"\n    // }\n  }\n\n  // ...\n});\n\nchatSession.downloadAttachment({\n  attachmentId: attachmentItem.AttachmentId\n}).then((awsSDKResponse) =\u003e {\n  const attachmentBlob = awsSDKResponse;  // Blob\n  /*\n    Attachment Object - This is the actual file that will be downloaded by either agent or end-customer.\n    {\n      lastModified: long\n      name: \"string\"\n      size: long\n      type: \"string\"\n      webkitRelativePath: \"string\"\n    }\n  */\n\n  // Create a download link for the Blob\n  const downloadUrl = URL.createObjectURL(attachmentBlob);\n  const downloadLink = document.createElement('a');\n  downloadLink.href = downloadUrl;\n  downloadLink.download = attachmentItem.AttachmentName;\n  downloadLink.style.display = 'none';\n\n  document.body.appendChild(downloadLink);\n  downloadLink.click();\n\n  setTimeout(() =\u003e {\n    document.body.removeChild(downloadLink);\n    URL.revokeObjectURL(downloadUrl);\n  }, 100);\n}).catch(error =\u003e {\n  console.error('Error downloading attachment:', error);\n});\n```\n\nWraps the [GetAttachment](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html) API.\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html#API_GetAttachment_RequestSyntax) with the following differences:\n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html#API_GetAttachment_ResponseSyntax).\n`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.\n\n##### `chatSession.getAttachmentURL()`\n```js\nconst s3Url = await chatSession.getAttachmentURL({\n  attachmentId: \"string\"\n});\n```\nWraps the [GetAttachment](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html) API.\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html#API_GetAttachment_RequestSyntax) with the following differences:\n- Fields are in `camelCase`.\n  The response is a url string.\n  `chatSession.getAttachmentURL()` invokes the GetAttachment using the AttachmentId as a request parameter and directly returns pre-signed URL received in the GetAttachment API response.\n\n#### `chatSession.getChatDetails()`\n\n```js\nconst chatDetails = await chatSession.getChatDetails();\nconst {\n  contactId,\n  initialContactId,\n  participantId,\n  participantToken,\n} = chatDetails;\n```\nGets the chat session details.\n\n#### `chatSession.getAuthenticationUrl()`\n\n```js\nconst awsSdkResponse = await chatSession.getAuthenticationUrl({\n  redirectUri: 'www.example.com',\n  sessionId: 'exampleId' // This comes from the `authentication.initiated` event\n  metadata: { foo: \"bar\" }, // optional\n});\nconst authenticationUrl = getAuthenticationUrlResponse?.data?.AuthenticationUrl;\n```\n\nWraps the [GetAuthenticationUrl](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_GetAuthenticationUrl.html) API.\n\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_GetAuthenticationUrl.html#API_connect-participant_GetAuthenticationUrl_RequestSyntax)\n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_GetAuthenticationUrl.html#API_connect-participant_GetAuthenticationUrl_ResponseSyntax).\n\n**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\n\n#### `chatSession.describeView()`\n\n```js\nconst awsSDKResponse = await chatSession.describeView({\n  viewToken: \"asdf...asdf\", //REQUIRED\n  metadata: { foo: \"bar\" }, // optional\n});\n\nconst { View } = awsSDKResponse.data;\n```\nWraps the [DescribeView](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_DescribeView.html) API.\n\nThe arguments are based on the [API model](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_DescribeView.html) with the following differences:\n\n- All fields are in camelCase.\n\nChatJS automatically supplies the connectionToken via the session's internal data.\nThis api will only function after `chatSession.connect()` succeeds.\n\n#### `chatSession.cancelParticipantAuthentication()`\n\n```js\nconst awsSdkResponse = await chatSession.cancelParticipantAuthentication({\n  sessionId: 'exampleId' // This comes from the authentication.initiated event\n  metadata: { foo: \"bar\" }, // optional\n});\n```\n\nWraps the [CancelParticipantAuthentication](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_CancelParticipantAuthentication.html) API.\n\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_CancelParticipantAuthentication.html#API_connect-participant_CancelParticipantAuthentication_RequestSyntax)\n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_CancelParticipantAuthentication.html#API_connect-participant_CancelParticipantAuthentication_ResponseSyntax).\n\n**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.\n\n#### `customerChatSession.disconnectParticipant()`\n\n```js\nawait customerChatSession.disconnectParticipant();\n// Chat session has ended, `customerChatSession.connect()` will not work anymore\n```\n\nDisconnect and end the chat. Applies only to `CustomerChatSession`. Wraps the [DisconnectParticipant](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_DisconnectParticipant.html) API.\n\nOnce this method is called, the `CustomerChatSession` cannot be used anymore.\n\n#### `agentChatSession.cleanUpOnParticipantDisconnect()`\n\n```js\nawait agentChatSession.cleanUpOnParticipantDisconnect();\n```\n\nCleans up all event handlers when chat has been ended.\n\nApplies only to `AgentChatSession`. See connect.ChatSession.create() for more info.\n\n### `chatSession` Events\n\n#### `chatSession.onMessage()`\n\n \u003e **Warning** messages received over websocket are not guaranteed to be in order!\n\n```js\n/**\n * 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.\n * @param {\n    chatDetails: Object,\n    data: {\n      AbsoluteTime: string,\n      Content?: string,\n      ContentType: string,\n      DisplayName?: string,\n      Id: string,\n      ParticipantId?: string,\n      ParticipantRole?: \"AGENT\" | \"CUSTOMER\" | \"SYSTEM\",\n      Type: \"MESSAGE\" | \"EVENT\" | \"ATTACHMENT\" | \"CONNECTION_ACK\",\n      ContactId?: string,\n      InitialContactId?: string\n    }\n } event\n */\nchatSession.onMessage(event =\u003e {\n  const { chatDetails, data: newMessageItem } = event;\n  const {\n    ContentType, // string, see: https://github.com/amazon-connect/amazon-connect-chatjs/blob/c5206ff3d13a210ba6567d7e9e5511e6bd2e47ce/src/constants.js#L82\n    Content, // string\n  } = newMessageItem;\n  // Handle message event\n  const newTranscript = [...transcript, newMessageItem].sort((a, b) =\u003e a.transportDetails.sentTime - b.transportDetails.sentTime); // ascending\n});\n```\n\nThe `data` field has the same schema as the [`Item` data type](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_Item.html) from the Amazon Connect Participant Service with the addition of the following **optional** fields: `ContactId`, `InitialContactId`.\n\n#### `chatSession.onTyping()`\n\n```js\n/**\n * Subscribes an event handler that triggers whenever a \"application/vnd.amazonaws.connect.event.typing\" event is created by any participant.\n * @param {\n    AbsoluteTime?: string,\n    ContentType: \"application/vnd.amazonaws.connect.event.typing\",\n    Type?: string,\n    ParticipantId?: string,\n    DisplayName?: string,\n    ParticipantRole?: \"AGENT\" | \"CUSTOMER\" | \"SYSTEM\",\n    InitialContactId?: string\n } event.data\n */\nchatSession.onTyping(event =\u003e {\n  const { chatDetails, data } = event;\n  if (data.ParticipantRole === \"AGENT\") {\n    // Handle agent typing event\n  } else if (data.ParticipantRole === \"CUSTOMER\") {\n    // Handle customer typing event\n  }\n});\n```\n\n#### `chatSession.onReadReceipt()`\n\n```js\n/**\n * Subscribes an event handler that triggers when a read message event is received from the customer or agent.\n * @param {\n    AbsoluteTime?: string,\n    ContentType: \"application/vnd.amazonaws.connect.event.message.read\",\n    Type?: string,\n    ParticipantId?: string,\n    DisplayName?: string,\n    ParticipantRole?: \"AGENT\" | \"CUSTOMER\" | \"SYSTEM\",\n    InitialContactId?: string\n } event.data\n */\nchatSession.onReadReceipt(event =\u003e {\n  const { chatDetails, data } = event;\n  // Handle read receipt event\n});\n```\n\n#### `chatSession.onDeliveredReceipt()`\n\n```js\n/**\n * Subscribes an event handler that triggers when a delivered message event is received from the customer or agent.\n * @param {\n    AbsoluteTime?: string,\n    ContentType: \"application/vnd.amazonaws.connect.event.message.delivered\",\n    Type?: string,\n    ParticipantId?: string,\n    DisplayName?: string,\n    ParticipantRole?: \"AGENT\" | \"CUSTOMER\" | \"SYSTEM\",\n    InitialContactId?: string\n } event.data\n */\nchatSession.onDeliveredReceipt(event =\u003e {\n  const { chatDetails, data } = event;\n  // Handle delivery receipt event\n});\n```\n\n#### `chatSession.onConnectionEstablished()`\n\n```js\n/**\n * Subscribes an event handler that triggers when the WebSocket connection is established successfully or reconnected.\n * @param {\n    chatDetails: Object,\n    data: {\n      Type: \"CONNECTION_ESTABLISHED\",\n      ConnectionDetails: Object\n    }\n } event\n */\nchatSession.onConnectionEstablished(event =\u003e {\n  const { chatDetails, data } = event;\n  // Handle connection established event\n\n  // Recommended: re-fetch the transcript to load any messages that were sent while connection was offline\n  chatSession.getTranscript({\n    scanDirection: \"BACKWARD\",\n    sortOrder: \"ASCENDING\",\n    maxResults: 15,\n    // nextToken?: nextToken - OPTIONAL, for pagination\n  }).then((response) =\u003e {\n      const { InitialContactId, NextToken, Transcript: latestTranscript } = response.data;\n      // ...\n      setState('transcript', latestTranscript)\n    })\n    .catch(() =\u003e {})\n});\n```\n\n#### `chatSession.onConnectionLost()`\n\n```js\n/**\n * Subscribes an event handler that triggers when the WebSocket connection is lost due to network issues or server errors. This includes abnormal closures and unexpected server conditions that terminate the chat connection. The method monitors for connection failures, allowing applications to handle reconnection logic or notify users of connectivity issues.\n * @param {\n    chatDetails: Object,\n    data: {\n      Type: \"CONNECTION_LOST\",\n      Reason: string\n    }\n } event\n */\nchatSession.onConnectionLost(event =\u003e {\n  const { chatDetails, data } = event;\n  // Handle connect lost event\n});\n```\n\n#### `chatSession.onConnectionBroken()`\n\n```js\n/**\n * Subscribes an event handler that triggers when the WebSocket connection fails to initialize or encounters permanent failures such as invalid configuration or authorization errors. This is primarily used for internal ChatJS logic and indicates a terminal state where no further connection retries will be attempted.\n * @param {\n    chatDetails: Object,\n    data: {\n      Type: \"CONNECTION_BROKEN\",\n      Reason: string\n    }\n } event\n */\nchatSession.onConnectionBroken(event =\u003e {\n  const { chatDetails, data } = event;\n  // Handle connection broken event\n});\n```\n\n#### `chatSession.onEnded()`\n\n```js\n/**\n * Subscribes an event handler that triggers when the chat session is ended by either participant.\n * @param {\n    chatDetails: Object,\n    data: {\n      Type: \"CHAT_ENDED\",\n      AbsoluteTime?: string,\n      ParticipantRole?: string\n    }\n } event\n */\nchatSession.onEnded(event =\u003e {\n  const { chatDetails, data } = event;\n  // Handle session ended event\n});\n```\n\n#### `chatSession.onAutoDisconnection()`\n\n\u003e **Note**: Related to [set up chat timeouts for chat participants](https://docs.aws.amazon.com/connect/latest/adminguide/setup-chat-timeouts.html).\n\n\n```js\n/**\n * Subscribes an event handler that triggers whenever a \"application/vnd.amazonaws.connect.event.participant.autodisconnection\" event is created by any participant.\n * @param {\n    AbsoluteTime?: string,\n    ContentType?: string,\n    Type?: string,\n    ParticipantId?: string,\n    DisplayName?: string,\n    ParticipantRole?: string,\n    InitialContactId?: string\n } event.data\n */\nchatSession.onAutoDisconnection(event =\u003e {\n  const { chatDetails, data } = event;\n  if (data.ParticipantRole === \"AGENT\") {\n    // ...\n  }\n});\n```\n\n#### `chatSession.onParticipantIdle()`\n\n\u003e **Note**: Related to [set up chat timeouts for chat participants](https://docs.aws.amazon.com/connect/latest/adminguide/setup-chat-timeouts.html).\n\n```js\n/**\n * Subscribes an event handler that triggers whenever a \"application/vnd.amazonaws.connect.event.participant.idle\" event is created by any participant.\n * @param {\n    AbsoluteTime?: string,\n    ContentType?: string,\n    Type?: string,\n    ParticipantId?: string,\n    DisplayName?: string,\n    ParticipantRole?: string,\n    InitialContactId?: string\n } event.data\n */\nchatSession.onParticipantIdle(event =\u003e {\n  const { chatDetails, data } = event;\n  if (data.ParticipantRole === \"AGENT\") {\n    // ...\n  }\n});\n```\n\n#### `chatSession.onParticipantReturned()`\n\n\u003e **Note**: Related to [set up chat timeouts for chat participants](https://docs.aws.amazon.com/connect/latest/adminguide/setup-chat-timeouts.html).\n\n```js\n/**\n * Subscribes an event handler that triggers whenever a \"application/vnd.amazonaws.connect.event.participant.returned\" event is created by any participant.\n * @param {\n    AbsoluteTime?: string,\n    ContentType?: string,\n    Type?: string,\n    ParticipantId?: string,\n    DisplayName?: string,\n    ParticipantRole?: string,\n    InitialContactId?: string\n } event.data\n */\nchatSession.onParticipantReturned(event =\u003e {\n  const { chatDetails, data } = event;\n  if (data.ParticipantRole === \"AGENT\") {\n    // ...\n  }\n});\n```\n\n#### `chatSession.onParticipantInvited()`\n\n```js\n /**\n  * Subscribes an event handler that triggers whenever a \"application/vnd.amazonaws.connect.event.participant.invited\" event is created by any participant.\n  * @param {\n     AbsoluteTime?: string,\n     ContentType?: string,\n     Type?: string,\n     ParticipantId?: string,\n     DisplayName?: string,\n     ParticipantRole?: string,\n     InitialContactId?: string\n  } event.data\n  */\n chatSession.onParticipantInvited(event =\u003e {\n   const { chatDetails, data } = event;\n   if (data.ParticipantRole === \"AGENT\") {\n     // ...\n   }\n });\n ```\n\n#### `chatSession.onDeepHeartbeatSuccess()`\n\n```js\n/**\n * Subscribes an event handler that triggers when a websocket heartbeat is received successfully.\n * @param {\n    chatDetails: Object,\n    data: {\n      Type: \"HEARTBEAT_SUCCESS\",\n      AbsoluteTime?: string,\n      LastHeartbeatTime?: string\n    }\n } event\n */\nchatSession.onDeepHeartbeatSuccess(event =\u003e {\n  const { chatDetails, data } = event;\n  // Handle deep heartbeat success event\n});\n```\n\n#### `chatSession.onDeepHeartbeatFailure()`\n\n```js\n/**\n * Subscribes an event handler that triggers when a websocket heartbeat fails.\n * @param {\n    chatDetails: Object,\n    data: {\n      Type: \"HEARTBEAT_FAILURE\",\n      AbsoluteTime?: string,\n      LastHeartbeatTime?: string,\n      Error?: string\n    }\n } event\n */\nchatSession.onDeepHeartbeatFailure(event =\u003e {\n  const { chatDetails, data } = event;\n  // Handle deep heartbeat failure event\n});\n```\n\n#### `chatSession.onAuthenticationInitiated()`\n\n```js\n/**\n * Subscribes an event handler that triggers when the contact flow reaches the authenticate customer flow block.\n * @param {\n    chatDetails: Object,\n    data: {\n      Content: string, // Contains JSON with SessionId\n      ContentType: \"application/vnd.amazonaws.connect.event.authentication.initiated\",\n      Type: string,\n      AbsoluteTime?: string,\n      ParticipantId?: string,\n      DisplayName?: string,\n      ParticipantRole?: string\n    }\n } event\n */\nchatSession.onAuthenticationInitiated(event =\u003e {\n  const eventDetails = event?.data;\n  try {\n      content = JSON.parse(eventDetails?.Content);\n    } catch (error) {\n        console.error(\"Invalid JSON content\", error);\n  }\n  const sessionId = content.SessionId;\n  // use the session id to call getAuthenticationUrl\n});\n```\n\n#### `chatSession.onAuthenticationSuccessful()`\n\n```js\n/**\n * Subscribes an event handler that triggers when authenticate customer flow block takes the success branch.\n * @param {\n    chatDetails: Object,\n    data: {\n      ContentType: \"application/vnd.amazonaws.connect.event.authentication.success\",\n      Type: string,\n      AbsoluteTime?: string,\n      ParticipantId?: string,\n      DisplayName?: string,\n      ParticipantRole?: string\n    }\n } event\n */\nchatSession.onAuthenticationSuccessful(event =\u003e {\n  const { data } = event;\n  // Handle authentication success\n});\n```\n\n#### `chatSession.onAuthenticationFailed()`\n\n```js\n/**\n * Subscribes an event handler that triggers when the authenticate customer flow block takes the failed branch.\n * @param {\n    chatDetails: Object,\n    data: {\n      ContentType: \"application/vnd.amazonaws.connect.event.authentication.failed\",\n      Type: string,\n      AbsoluteTime?: string,\n      ParticipantId?: string,\n      DisplayName?: string,\n      ParticipantRole?: string\n    }\n } event\n */\nchatSession.onAuthenticationFailed(event =\u003e {\n  const { data } = event;\n  // Handle authentication failure\n});\n```\n\n#### `chatSession.onAuthenticationTimeout()`\n\n```js\n/**\n * Subscribes an event handler that triggers when the authenticate customer flow block has timed out.\n * @param {\n    chatDetails: Object,\n    data: {\n      ContentType: \"application/vnd.amazonaws.connect.event.authentication.timeout\",\n      Type: string,\n      AbsoluteTime?: string,\n      ParticipantId?: string,\n      DisplayName?: string,\n      ParticipantRole?: string\n    }\n } event\n */\nchatSession.onAuthenticationTimeout(event =\u003e {\n  const { chatDetails, data } = event;\n  // Handle authentication timeout event\n});\n```\n\n#### `chatSession.onAuthenticationExpired()`\n\n```js\n/**\n * Subscribes an event handler that triggers when the authenticate customer flow block has expired.\n * @param {\n    chatDetails: Object,\n    data: {\n      ContentType: \"application/vnd.amazonaws.connect.event.authentication.expired\",\n      Type: string,\n      AbsoluteTime?: string,\n      ParticipantId?: string,\n      DisplayName?: string,\n      ParticipantRole?: string\n    }\n } event\n */\nchatSession.onAuthenticationExpired(event =\u003e {\n  const { data } = event;\n  // Handle authentication expired event\n});\n```\n\n#### `chatSession.onParticipantDisplayNameUpdated()`\n\n```js\n/**\n * Subscribes an event handler that triggers when a participant's display name is updated during authentication success and there is a customer profile associated with the user.\n * @param {\n    AbsoluteTime?: string,\n    ContentType?: string,\n    Type?: string,\n    ParticipantId?: string,\n    DisplayName?: string,\n    ParticipantRole?: string,\n    InitialContactId?: string\n } event.data\n */\nchatSession.onParticipantDisplayNameUpdated(event =\u003e {\n  const authenticatedParticipantDisplayName = event.data?.DisplayName;\n  // Handle display name update\n});\n```\n\n#### `chatSession.onAuthenticationCanceled()`\n\n```js\n/**\n * Subscribes an event handler that triggers when the contact flow reaches the authenticate customer flow block and the CancelParticipantAuthentication API is called.\n * doc: https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_CancelParticipantAuthentication.html\n * @param {\n    AbsoluteTime?: string,\n    ContentType?: string,\n    Type?: string,\n    ParticipantId?: string,\n    DisplayName?: string,\n    ParticipantRole?: string,\n    InitialContactId?: string\n } event.data\n */\nchatSession.onAuthenticationCanceled(event =\u003e {\n  const { data } = event;\n  // Handle authentication canceled event\n});\n```\n\n#### `chatSession.onChatRehydrated()`\n\n\u003e **Note:** Only when persistent chat is enabled.\n\n```js\n/**\n * Subscribes an event handler that triggers whenever a \"application/vnd.amazonaws.connect.event.chat.rehydrated\" event is fired.\n * @param {\n    AbsoluteTime?: string,\n    ContentType?: string,\n    Type?: string,\n    ParticipantId?: string,\n    DisplayName?: string,\n    ParticipantRole?: string,\n    InitialContactId?: string\n } event.data\n */\nchatSession.onChatRehydrated(event =\u003e {\n  const { chatDetails, data } = event;\n  // Load previous transcript\n});\n```\n\n## Features\n\nAdditional features and documentation can be found in the [docs/](docs) directory:\n\n- [Handling File Attachments in Chat](docs/ChatAttachmentsFeature.md)\n- [React Native Support](docs/ReactNativeSupport.md)\n- [Enabling Persistent Chat](docs/persistent-chat-feature.md)\n- [Enabling Attachment Scanner](docs/attachment-scanner-feature.md)\n- [Interactive Messages](docs/interactive-messages-feature.md)\n- [Multi-Party Chat Feature](docs/Multi-Party-Chat-Feature.md) ([StreamsJS](https://github.com/amazon-connect/amazon-connect-streams))\n- [Web Calling Feature](docs/WebCallingFeature.md) ([aws-chime-sdk](https://github.com/aws/amazon-chime-sdk-js))\n\n## Local Development\n\n```sh\ngit clone https://github.com/amazon-connect/amazon-connect-chatjs.git\ncd amazon-connect-chatjs\nnpm install\n```\n\n```sh\n# Generate a bundle file\nnpm run release\n# output: dist/amazon-connect-chat.js\n\n# Run unit tests\nnpm test\n```\n\n## Known Issues and Debugging\n\n### Enable Debug Logging\n\n```js\nconnect.ChatSession.setGlobalConfig({\n  loggerConfig: {\n    level: connect.ChatSession.LogLevel.DEBUG // INFO, WARN, ERROR, ADVANCED_LOG\n  }\n});\n```\n\n### Disable Logging\n\n```js\nwindow.connect.ChatSession.setGlobalConfig({\n  loggerConfig: { useDefaultLogger: false }, // disable\n  // loggerConfig: { useDefaultLogger: true }, // default\n});\n```\n\n### Connection Management\n\n```js\nchatSession.onConnectionLost(async () =\u003e {\n  console.log('Websocket lost connection');\n});\n\nchatSession.onConnectionEstablished(() =\u003e {\n  console.log('WebSocket connection has been established/reestablished');\n});\n\nchatSession.onConnectionBroken(event =\u003e {\n  console.log('WebSocket connection is broken or terminated');\n  // Implement reconnection logic\n  await chatSession.connect();\n});\n```\n\n### Network Health Checks\n\n```js\nchatSession.onDeepHeartbeatSuccess(() =\u003e {\n  console.log('WebSocket connection healthy');\n});\n\nchatSession.onDeepHeartbeatFailure(() =\u003e {\n  console.log('WebSocket connection issues detected');\n});\n```\n\n### Handle Browser Refresh\n\nWhen a user refreshes their browser during an active chat, you'll want to reconnect them to their existing session instead of starting a new one.\n\nWhen initially creating a chat session, store the `chatDetails` (received from [StartChatContact](https://docs.aws.amazon.com/connect/latest/APIReference/API_StartChatContact.html) API) in `sessionStorage`\nOn page load, check if `chatDetails` exists in `sessionStorage`:\n\n```js\n/* Initial page load */\nconst startChatResponse = await fetch('url-to-my-chat-backend').then(response =\u003e response.data);\n// --- Sample Backend Code ---\n// import AWS from 'aws-sdk'; // v2.1692.0\n// const connect = new AWS.Connect({\n//   region: 'us-west-2',\n//   credentials: new AWS.Credentials({ accessKeyId, secretAccessKey, sessionToken })\n// });\n// const startChatRequest = { InstanceId, ContactFlowId, SupportedMessagingContentTypes };\n// chatDetails = await connect.startChatContact(startChatRequest).promise(); // StartChatContact API\n// return { data: chatDetails } // { ContactId, ParticipantId, ParticipantToken }\nconst chatDetails = startChatResponse; // { ContactId, ParticipantId, ParticipantToken }\nsessionStorage.setItem('chatjs-session-chat-details', JSON.stringify(chatDetails));\n\nconst chatSession = connect.ChatSession.create({ chatDetails: { contactId, participantId, participantToken }, /* ... */ });\nawait chatSession.connect(); // Establish the WebSocket connection\n```\n\n```js\n/* Second page load (browser refresh) */\nconst existingChatDetails = sessionStorage.getItem('chatjs-session-chat-details'); // { ContactId, ParticipantId, ParticipantToken }\nconst reloadedChatSession = connect.ChatSession.create({ chatDetails: existingChatDetails, /* ... */ });\nawait reloadedChatSession.connect(); // Reestablish the WebSocket connection\n\n// (Optional) Fetch any unreceived messages/events\nreloadedChatSession.getTranscript({\n    scanDirection: \"BACKWARD\",\n    sortOrder: \"ASCENDING\",\n    maxResults: 15\n}).then((response) =\u003e {\n  const { Transcript } = response.data; // [{message}, {message}, ...]\n  // render the updated transcript\n});\n```\n\n### Handling Out-of-Order WebSocket Messages\n\nChatJS delivers messages in the order they are received, which may not match their actual timestamp order. You'll need to manually sort messages using their timestamps and filter duplicates by ID.\n\n```js\nconst response = await chatSession.getTranscript({\n    scanDirection: \"BACKWARD\",\n    sortOrder: \"ASCENDING\",\n    maxResults: 15\n});\n\nconst { Transcript } = response.data;\nTranscript.forEach(message =\u003e {\n    const timestamp = new Date(message.AbsoluteTime).toLocaleTimeString();\n    const id = message.Id;\n    // Sort messages by timestamp and filter duplicates using message ID\n});\n```\n\n### Messages Not Received During Network Disconnection\n\nIf a chat participant loses network connection during a session, the client may fail to receive WebSocket messages.\n\nChatJS requires manually calling `chatSession.getTranscript()` to fetch missed messages after reconnecting.\n\n```js\n// Fetch any missed messages by retrieving the recent transcript\nchatSession.onConnectionEstablished(() =\u003e {\n    console.log('WebSocket connection has been established/reestablished');\n\n    // Get recent messages including any that were missed while offline\n    const response = await chatSession.getTranscript({\n        scanDirection: \"BACKWARD\",\n        sortOrder: \"ASCENDING\",\n        maxResults: 15\n    });\n\n    const { Transcript } = response.data;\n    // ... filter and render the updated transcript\n});\n```\n\n### CSM not initialized\n\nClient-side-metric (CSM) is an internal feature. This functionality is enabled by default but completely safe to disable.\n\n```log\nChatJS-csmService: Failed to addCountAndErrorMetric csm:  ReferenceError: Property 'csm' doesn't exist undefined\n\nChatJS-csmService: Failed to addLatencyMetric csm:  ReferenceError: Property 'csm' doesn't exist undefined\n\naddCSMCountMetric: CSM not initialized TypeError: Cannot read properties of null (reading 'Metric')\n```\n\n**Fix:**\n\n```js\nconnect.ChatSession.create({\n  // ...\n  disableCSM: true\n});\n```\n\n### React Native Support\n\n\u003e 📌 Important: ensure you are using `amazon-connect-chatjs \u003e= v1.5.0`\n\nChatJS is supported in React Native environments but requires additional configuration. You'll need to pass in a network status listener, since the browser-based `window.navigator.onLine` isn't available.\n\nTo configure ChatJS WebSocketManager for React Native environments, it's recommended to use the [react-native-netinfo](https://github.com/react-native-netinfo/react-native-netinfo) library.\n\nFor a boilerplate React Native demo application, check out the [Amazon Connect React Native ChatJS Example](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/mobileChatExamples/connectReactNativeChat).\n\n```sh\nnpm install amazon-connect-chatjs@latest\nnpm install @react-native-community/netinfo@latest\n```\n\n```diff\n// MyChatUI.jsx\n\nimport React, { createContext, useContext, useState, useCallback, useMemo, useEffect } from 'react';\nimport \"amazon-connect-chatjs\"; // \u003e= v1.5.0 - imports the \"window.connect\"\n+ import NetInfo, { useNetInfo } from '@react-native-community/netinfo';\n\nconst MyChatUI = () =\u003e {\n  useEffect(() =\u003e {\n+   window.connect.ChatSession.setGlobalConfig({\n+       webSocketManagerConfig: {\n+         isNetworkOnline: async () =\u003e {\n+           const state = await NetInfo.fetch();\n+           return state.isConnected;\n+         }\n+       }\n+     });\n\n      // Your proxy backend makes StartChatContact API request: https://docs.aws.amazon.com/connect/latest/APIReference/API_StartChatContact.html\n      // Boilerplate backend: https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/cloudformationTemplates/startChatContactAPI\n     const startChatResponse = await fetch('url-to-my-chat-backend').then(response =\u003e response.data);\n\n      // Initialize ChatJS session\n      const chatSession = window.connect.ChatSession.create({\n      chatDetails: {\n        contactId: startChatResponse.ContactId,\n        participantId: startChatResponse.ParticipantId,\n        participantToken: startChatResponse.ParticipantToken,\n      },\n      options: { region: '\u003cAWS-REGION\u003e' },\n      type: \"CUSTOMER\",\n      disableCSM: true // CSM is an internal feature, safe to disable\n    })\n\n    // Connect to chat session WebsSocket connection\n    await chatSession.connect();\n  }, [])\n}\n```\n\n## Troubleshooting and Support\n\nReview the resources given in the README and use our documentation for guidance on how to develop with ChatJS. Additionally, search our [issues database](https://github.com/amazon-connect/amazon-connect-chatjs/issues) and [FAQs](https://github.com/amazon-connect/amazon-connect-chatjs/discussions) to see if your issue is already addressed. If not please cut us an [issue](https://github.com/amazon-connect/amazon-connect-chatjs/issues/new/choose) using the provided templates.\n\nIf you have more questions, or require support for your business, you can reach out to [AWS Customer support](https://console.aws.amazon.com/support/home#) and Amazon Connect Chat Frontend team.\n\n## License\n\n[Apache 2.0](./LICENSE)\n\n\n\u003c!--\n# Amazon Connect ChatJS [![npm](https://img.shields.io/npm/v/amazon-connect-chatjs.svg?color=orange)](https://www.npmjs.com/package/amazon-connect-chatjs) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Node.js CI](https://github.com/amazon-connect/amazon-connect-chatjs/actions/workflows/node.js.yml/badge.svg?branch=master)](https://github.com/amazon-connect/amazon-connect-chatjs/actions/workflows/node.js.yml)\n\n\u003e **_Important note:_**  Amazon Connect has migrated the `Connection Acknowledgement(ConnAck)` from the [SendEvent](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendEvent.html) API\nto the [CreateParticipant](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_CreateParticipantConnection.html) API.\nPlease upgrade your ChatJS to [1.4.0](https://github.com/amazon-connect/amazon-connect-chatjs/releases/tag/1.4.0) or a newer version to complete the migration by 12/31/2024.\n\n## Table of contents\n\n- [About](#about)\n- [Getting Started](#getting-started)\n  - [A note about the AWS-SDK and ChatJS](#a-note-about-the-aws-sdk-and-chatjs)\n  - [Usage](#usage)\n  - [Building](#building)\n- [React Native Support](#react-native-support)\n- [API](#api)\n  - [`connect.ChatSession` API](#connectchatsession-api)\n  - [ChatSession API](#chatsession-api)\n    - [Amazon Connect Participant Service API wrappers](#amazon-connect-participant-service-api-wrappers)\n    - [Events](#events)\n    - [Client side metric](#client-side-metric)\n    - [Other](#other)\n\n## About\n\nThe Amazon Connect Chat javascript library (ChatJS) gives you the power to build your own chat widget to customize the chat experience. This can be used for both the agent user interface, in conjunction with [Amazon Connect Streams](https://github.com/aws/amazon-connect-streams), and for the customer chat interface.\n\nThere is a [Chat UI reference implementation](https://github.com/amazon-connect/amazon-connect-chat-ui-examples) here. This will help you deploy an API Gateway and Lambda function for initiating chat from your webpage. From there you can use the ChatJS library to build a custom widget.\n\n### Learn More\n\nTo learn more about Amazon Connect and its capabilities, please check out\nthe [Amazon Connect User Guide](https://docs.aws.amazon.com/connect/latest/userguide/).\n\n**New to Amazon Connect and looking to onboard with Chat/Messaging capabilities?** Refer to the [“Amazon Connect Chat Open Source Walkthrough”](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/blob/master/.github/docs/AmazonConnectChatOpenSourceWalkthrough.md) documentation, and [“Hosted Widget vs Custom Builder Solution”](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/blob/master/.github/docs/HostedWidgetVSCustomBuilderSolution.md) if building a customer-facing chat interface.\n\n## Getting Started\n\n### A note about the AWS-SDK and ChatJS\n\nThe AWS-SDK is, by default, included in ChatJS as a \"baked-in\" dependency. You can view it at `./client/aws-sdk-connectparticipant.js`. In `./client/client.js` we import `ConnectParticipant` from this file. This file and import can be removed while using the AWS SDK imported through a script in the page file of your application, assuming that version of the AWS SDK has the `ConnectParticipant` service included.\nIncidentally, Amazon Connect Streams also contains a \"baked-in\" AWS SDK. This SDK cannot be removed, as it contains unreleased APIs that will not be available in the SDK you include as a script in the page file.\nTherefore, there are several occasions where implementations can run into AWS SDK issues.\n\n#### **Scenario 1:** Streams and ChatJS are used. You are not importing the AWS SDK\n\nEnsure you import ChatJS after Streams.\n\n#### **Scenario 2:** Streams and ChatJS are used. You are importing the AWS SDK\n\nImport Streams, then ChatJS, then the SDK.\nEnsure that your AWS SDK includes the ConnectParticipant Service (it is relatively new, so make sure you have an up-to-date AWS SDK version [^2.597.0]).\n\n#### **Scenario 3:** ChatJS only, no AWS SDK import\n\nNo need to worry here, this will always work.\n\n#### **Scenario 4:** ChatJS only, with AWS SDK import\n\nImport ChatJS before the AWS SDK, and ensure the AWS SDK version you are using contains the ConnectParticipant Service.\n\n#### A note for Scenarios 2 and 4\n\nWhen using the SDK and ChatJS, you may remove the SDK from ChatJS to ensure lack of import conflicts. However, this should not be relevant if the order in which you are importing these libraries is the order reflected above.\n\n#### Using AWS SDK ConnectParticipant Client\n\nIf you have replaced `./client/aws-sdk-connectparticipant.js` and use `@aws-sdk/client-connectparticipant`, make sure to import the aws-sdk after ChatJS\n\n```\nimport 'amazon-connect-streams'; // \u003c-- (optional) MUST be before ChatJS\nimport 'amazon-connect-chatjs';\nimport '@aws-sdk/client-connect'; // or 'aws-sdk'\nimport '@aws-sdk/clients/connectparticipant'; // \u003c-- IMPORTANT - should be last\n```\n\n\n### Usage\n\n#### Using ChatJS from npm\n\n`npm install amazon-connect-chatjs`\n\n#### Using ChatJS from CDN Link\n\n`amazon-connect-chat.js` bundle file is also available over a CDN.\n\n```html\n\u003cscript src=\"https://unpkg.com/amazon-connect-chatjs@1.5.1\"\u003e\u003c/script\u003e\n\u003c!-- OR -\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/amazon-connect-chatjs@1.5.1/dist/amazon-connect-chat.js\"\u003e\u003c/script\u003e\n\n\u003c!-- Specify exact version -\u003e\n\u003cscript src=\"https://unpkg.com/amazon-connect-chatjs@1.5.1\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/amazon-connect-chatjs@1\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/amazon-connect-chatjs\"\u003e\u003c/script\u003e\n\n\u003c!-- Use crossorigin if needed -\u003e\n\u003cscript crossorigin src=\"https://unpkg.com/amazon-connect-chatjs\"\u003e\u003c/script\u003e\n```\n\n#### Importing using npm and ES6\n\n`import \"amazon-connect-chatjs\"`\nNote: this will apply the global `connect` variable to your current scope.\n\n#### TypeScript Support\n\n`amazon-connect-chatjs` is compatible with TypeScript. You'll need to use version `typescript@^3.0.1` or higher:\n\n```ts\nimport \"amazon-connect-streams\";\n\nconnect.ChatSession.create({ /* ... */ });\n```\n\n#### Using ChatJS from Github\n\n```sh\ngit clone https://github.com/amazon-connect/amazon-connect-chatjs\n```\n\n### Building\n\n1. Install latest LTS version of [NodeJS](https://nodejs.org)\n2. Checkout this package into workspace and navigate to root folder\n3. `npm install`\n4. To build (non-minified):\n    1. `npm run devo` for a non-minified build.\n    2. Find build artifacts in **dist** directory.\n5. To build (minified):\n    1. `npm run release` for a minified build.\n    2. Find build artifacts in **dist** directory.\n6. To run unit tests:\n    1. `npm run test`\n7. To clean node_modules:\n    1. `npm run clean`\n8. To make webpack watch all files:\n    1. `npm run watch`\n\nFind build artifacts in **dist** directory -  This will generate a file called `amazon-connect-chat.js` - this is the full Connect ChatJS API which you will want to include in your page.\n\n## React Native Support\n\nAdditional configuration is required to support ChatJS in React Native applications. Use `amazon-connect-chatjs@^1.5.0` and follow the documenation: [ReactNativeSupport.md](./.github/docs/ReactNativeSupport.md)\n\nA demo application implementing basic ChatJS functionality is also available in the ui-examples repository: [connectReactNativeChat](https://github.com/amazon-connect/amazon-connect-chat-ui-examples/tree/master/connectReactNativeChat)\n\n## API\n\n### `connect.ChatSession` API\n\nThis is the main entry point to `amazon-connect-chatjs`.\nAll your interactions with the library start here.\n\n#### `connect.ChatSession.setGlobalConfig()`\n\n```js\nconnect.ChatSession.setGlobalConfig({\n  loggerConfig: { // optional, the logging configuration. If omitted, no logging occurs\n    // You can provide your own logger here, otherwise this property is optional\n    customizedLogger: {\n      debug: (...msg) =\u003e console.debug(...msg), // REQUIRED, can be any function\n      info: (...msg) =\u003e console.info(...msg), // REQUIRED, can be any function\n      warn: (...msg) =\u003e console.warn(...msg), // REQUIRED, can be any function\n      error: (...msg) =\u003e console.error(...msg) // REQUIRED, can be any function\n    },\n    // There are five levels available - DEBUG, INFO, WARN, ERROR, ADVANCED_LOG. Default is INFO\n    level: connect.LogLevel.INFO,\n    // Choose if you want to use the default logger\n    useDefaultLogger: true\n  },\n  region: \"us-east-1\", // optional, defaults to: \"us-west-2\"\n  //Control switch for enabling/disabling message-receipts (Read/Delivered) for messages\n  //message receipts use sendEvent API for sending Read/Delivered events https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendEvent.html\n  features: {\n    messageReceipts: {\n      shouldSendMessageReceipts: true, // DEFAULT: true, set to false to disable Read/Delivered receipts\n      throttleTime: 5000 //default throttle time - time to wait before sending Read/Delivered receipt.\n    }\n  },\n  // Pass in a user agent suffix used to configure the AWS SDK client in Amazon Connect ChatJS.\n  // This will be appended to the x-amz-user-agent custom header used in outgoing API requests\n  customUserAgentSuffix: \"\",\n});\n```\n\nSet the global configuration to use. If this method is not called, the defaults of `loggerConfig` and `region` are used.\nThis method should be called before `connect.ChatSession.create()`.\n\nCustomizing `loggerConfig` for ChatJS:\n\n- If you don't want to use any logger, you can skip this field.\n- There are five log levels available - DEBUG, INFO, WARN, ERROR, ADVANCED_LOG.\n- If you want to use your own logger, you can add them into `customizedLogger`, and add `customizedLogger` object as the value of `loggerConfig.customizedLogger`, then set the lowest logger level. `globalConfig.loggerConfig.useDefaultLogger` is not required.\n- If you want to use the default logger provided by ChatJS, you can set the logger level, and set `useDefaultLogger` to true. `loggerConfig.customizedLogger` is not required.\n- If you not only provide your own logger, but also set `useDefaultLogger` to true, your own logger will be overwritten by the default logger.\n- `amazon-connect-chatjs/src/log.js` - has the logic to select LogLevel. Default value is INFO - which cause all logs with higher priority than INFO to be logged. eg: by default info, warn, error and advancedLog messages will be logged.\n- Priority of logs:\n  10: \"DEBUG\"\n  20: \"INFO\"\n  30: \"WARN\"\n  40: \"ERROR\"\n  50: \"ADVANCED_LOG\"\n\n#### `connect.ChatSession.create()`\n\n```js\nconst customerChatSession = connect.ChatSession.create({\n  chatDetails: { // REQUIRED\n    contactId: \"...\", // REQUIRED\n    participantId: \"...\", // REQUIRED\n    participantToken: \"...\", // REQUIRED\n  },\n  options: { // optional\n    region: \"us-east-1\", // optional, defaults to `region` set in `connect.ChatSession.setGlobalConfig()`\n  },\n  type: \"CUSTOMER\", // REQUIRED\n});\n```\n\nCreates an instance of `AgentChatSession` or `CustomerChatSession`, depending on the specified `type`.\n\nIf you're creating a `CustomerChatSession`, the `chatDetails` field should be populated with the response of the [StartChatContact](https://docs.aws.amazon.com/connect/latest/APIReference/API_StartChatContact.html) API.\n\nIf you're creating an `AgentChatSession`, you must also include [`amazon-connect-streams`](https://github.com/amazon-connect/amazon-connect-streams). For example:\n\n```js\n// order is important, alternatively use \u003cscript\u003e tags\nimport \"amazon-connect-streams\";\nimport \"amazon-connect-chatjs\";\n\nconnect.contact(contact =\u003e {\n  if (contact.getType() !== connect.ContactType.CHAT) {\n    // applies only to CHAT contacts\n    return;\n  }\n\n  // recommended: calls `connect.ChatSession.setGlobalConfig()` and `connect.ChatSession.create()` internally\n  contact.onAccepted(async () =\u003e {\n    const cnn = contact.getConnections().find(cnn =\u003e cnn.getType() === connect.ConnectionType.AGENT);\n\n    const agentChatSession = await cnn.getMediaController();\n  });\n\n  // alternative: if you want control over the args of `connect.ChatSession.setGlobalConfig()` and `connect.ChatSession.create()`\n  contact.onAccepted(() =\u003e {\n    const cnn = contact.getConnections().find(cnn =\u003e cnn.getType() === connect.ConnectionType.AGENT);\n\n    const agentChatSession = connect.ChatSession.create({\n      chatDetails: cnn.getMediaInfo(), // REQUIRED\n      options: { // REQUIRED\n        region: \"us-east-1\", // REQUIRED, must match the value provided to `connect.core.initCCP()`\n      },\n      type: connect.ChatSession.SessionTypes.AGENT, // REQUIRED\n      websocketManager: connect.core.getWebSocketManager() // REQUIRED\n    });\n  });\n});\n```\n\nSee the [`amazon-connect-streams` API documentation](https://github.com/amazon-connect/amazon-connect-streams/blob/master/Documentation.md) for more information on the methods not documented here.\n\n**Note:** `AgentChatSession` and `CustomerChatSession` are logical concepts.\nAs a result, the `instanceof` operator will not work how you expect:\n\n```js\nif (connect.ChatSession.create(/* ... */) instanceof connect.ChatSession) {\n  // this will never execute\n}\n```\n\n#### `connect.ChatSession.LogLevel`\n\n```js\nconnect.ChatSession.LogLevel = {\n  DEBUG: /* ... */,\n  INFO: /* ... */,\n  WARN: /* ... */,\n  ERROR: /* ... */\n};\n```\n\nEnumerates the logging levels.\n\n#### `connect.ChatSession.SessionTypes`\n\n```js\nconnect.ChatSession.SessionTypes = {\n  AGENT: /* ... */,\n  CUSTOMER: /* ... */\n};\n```\n\nEnumerates the session types.\n\n### ChatSession API\n\nThe `ChatSession` API divided into three sections: Amazon Connect Participant Service API wrappers, events, and other.\n\n#### Amazon Connect Participant Service API wrappers\n\nFunctions in this section:\n\n- Wrap the APIs of the [Amazon Connect Participant Service](https://docs.aws.amazon.com/connect-participant/latest/APIReference/Welcome.html).\n- Return a `Promise\u003cResponse\u003e` (except for `chatSession.connect()`), where:\n  - `Response` is an [`aws-sdk` Response object](https://github.com/aws/aws-sdk-js/blob/master/lib/response.d.ts).\n  - If the `Promise` rejects, the error will still be a `Response` object. However, the `data` field will not be populated while the `error` field will.\n- Can optionally specify a `metadata` arg field (except for `customerChatSession.disconnectParticipant()`). The `metadata` arg field is not used directly by `amazon-connect-chatjs`, rather it's merely copied to the response object for usage by developers.\n\nFor example:\n\n```js\nfunction handleResponse(response) {\n  // `response` is an aws-sdk `Response` object\n  // `data` contains the response data\n  // `metadata` === \"foo\"\n  const { data, metadata } = response;\n  // ...\n}\n\nfunction handleError(response) {\n  // `response` is an aws-sdk `Response` object\n  // `error` contains the response error\n  // `metadata` === \"foo\"\n  const { error, metadata } = response;\n  // ...\n}\n\nchatSession\n  .getTranscript({ metadata: \"foo\" })\n  .then(handleResponse, handleError);\n```\n\n##### `chatSession.connect()`\n\n```js\n// connectCalled: indicates whether the Amazon Connect Participant Service was called\n// connectSuccess: indicates whether the operation succeeded\nconst { connectCalled, connectSuccess } = await chatSession.connect();\n```\n\nWraps the [CreateParticipantConnection](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_CreateParticipantConnection.html) API.\n\nThe arguments and response do not overlap with the API request or response.\n\n**Note:** If the operation fails, the `Promise` will reject, but the error will have the same schema as a successful response.\n\n##### `chatSession.getTranscript()`\n\n```js\nconst awsSdkResponse = await chatSession.getTranscript({\n  maxResults: 100,\n  sortOrder: \"ASCENDING\"\n});\nconst { InitialContactId, NextToken, Transcript } = awsSdkResponse.data;\n```\n\nWraps the [GetTranscript](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetTranscript.html) API.\n\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetTranscript.html#API_GetTranscript_RequestSyntax) with the following differences:\n\n- Fields are in `camelCase`.\n- `MaxResults` defaults to `15`.\n- `ScanDirection` defaults to `BACKWARD` always.\n- `SortOrder` defaults to `ASCENDING`.\n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetTranscript.html#API_GetTranscript_ResponseSyntax).\n\n**Important note:** In order to specify `scanDirection` as `FORWARD`, you need to explicitly include a `startPosition`.\nThis 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!).\n\n##### `chatSession.getAuthenticationUrl()`\n\n```js\nconst awsSdkResponse = await chatSession.getAuthenticationUrl({\n  redirectUri: 'www.example.com',\n  sessionId: 'exampleId' //This comes from the authentication.initiated event\n});\nconst authenticationUrl = getAuthenticationUrlResponse?.data?.AuthenticationUrl\n```\n\nWraps the [GetAuthenticationUrl](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_GetAuthenticationUrl.html) API.\n\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_GetAuthenticationUrl.html#API_connect-participant_GetAuthenticationUrl_RequestSyntax) \n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_GetAuthenticationUrl.html#API_connect-participant_GetAuthenticationUrl_ResponseSyntax).\n\n**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 \n\n##### `chatSession.cancelParticipantAuthentication()`\n\n```js\nconst awsSdkResponse = await chatSession.cancelParticipantAuthentication({\n  sessionId: 'exampleId' //This comes from the authentication.initiated event\n});\n```\n\nWraps the [CancelParticipantAuthentication](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_CancelParticipantAuthentication.html) API.\n\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_CancelParticipantAuthentication.html#API_connect-participant_CancelParticipantAuthentication_RequestSyntax) \n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-participant_CancelParticipantAuthentication.html#API_connect-participant_CancelParticipantAuthentication_ResponseSyntax).\n\n**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.\n\n##### `chatSession.sendEvent()`\n\n```js\nconst awsSdkResponse = await chatSession.sendEvent({\n  contentType: \"application/vnd.amazonaws.connect.event.typing\"\n  clientToken: \"12345\", // (optional) idempotency key\n});\nconst { AbsoluteTime, Id } = awsSdkResponse.data;\n```\n\nWraps the [SendEvent](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendEvent.html) API.\n\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendEvent.html#API_SendEvent_RequestSyntax) with the following differences:\n\n- Fields are in `camelCase`.\n- `ClientToken`  is optional and can be used to ensure idempotency of the request.\n- `ContentType` allows the following values:\n  - `\"application/vnd.amazonaws.connect.event.typing\"`\n  - `\"application/vnd.amazonaws.connect.event.connection.acknowledged\"`\n  - `\"application/vnd.amazonaws.connect.event.message.delivered\"`\n  - `\"application/vnd.amazonaws.connect.event.message.read\"`\n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendEvent.html#API_SendEvent_ResponseSyntax).\n\n##### `chatSession.sendMessage()`\n\n```js\nconst awsSdkResponse = await chatSession.sendMessage({\n  contentType: \"text/plain\",\n  message: \"Hello World!\"\n  clientToken: \"12345\", // (optional) idempotency key\n});\nconst { AbsoluteTime, Id } = awsSdkResponse.data;\n```\n\nWraps the [SendMessage](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendMessage.html) API.\n\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendMessage.html#API_SendMessage_RequestSyntax) with the following differences:\n\n- Fields are in `camelCase`.\n- `ClientToken`  is optional and can be used to ensure idempotency of the request.\n\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_SendMessage.html#API_SendMessage_ResponseSyntax).\n\n##### `chatSession.sendAttachment()`\n\n```js\n/**\n * Attachment Object - the actual file to be sent between the agent and end-customer.\n * Documentation: https://developer.mozilla.org/en-US/docs/Web/API/File\n * @property {number} lastModified - The last modified timestamp of the file.\n * @property {string} name - The name of the file.\n * @property {number} size - The size of the file.\n * @property {string} type - The type of the file.\n * @property {string} webkitRelativePath - The relative path of the file specific to the WebKit engine.\n */\nconst awsSdkResponse = await chatSession.sendAttachment({\n  attachment: attachment\n});\n\n// Example usage\nvar input = document.createElement('input');\ninput.type = 'file';\ninput.addEventListener('change', (e) =\u003e {\n  const file = e.target.files[0];\n  chatSession.sendAttachment({ attachment: file })\n});\n```\n\nWraps the [StartAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_StartAttachmentUpload.html) and [CompleteAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_CompleteAttachmentUpload.html) API.\nThe arguments are based on the [StartAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_StartAttachmentUpload.html#API_StartAttachmentUpload_RequestSyntax) and [CompleteAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_CompleteAttachmentUpload.html#API_CompleteAttachmentUpload_RequestSyntax) API request body with the following differences:\n\n- Fields are in `camelCase`.\nThe response `data` is the same as the [StartAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_StartAttachmentUpload.html#API_StartAttachmentUpload_ResponseSyntax) and [CompleteAttachmentUpload](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_CompleteAttachmentUpload.html#API_CompleteAttachmentUpload_ResponseSyntax) API response body.\n`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.\n\n##### `chatSession.downloadAttachment()`\n\n```js\nconst awsSdkResponse = await chatSession.downloadAttachment({\n  attachmentId: \"string\"\n});\nconst { attachment } = awsSdkResponse.data;\n/* \nAttachment Object - This is the actual file that will be downloaded by either agent or end-customer.\nattachment =\u003e {\n  lastModified: long\n  name: \"string\"\n  size: long\n  type: \"string\"\n  webkitRelativePath: \"string\"\n}\n*/\n```\n\nWraps the [GetAttachment](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html) API.\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html#API_GetAttachment_RequestSyntax) with the following differences:\n\n- Fields are in `camelCase`.\nThe response `data` is the same as the [API response body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html#API_GetAttachment_ResponseSyntax).\n`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.\n\n##### `chatSession.getAttachmentURL()`\n\n```js\nconst s3Url = await chatSession.getAttachmentURL({\n  attachmentId: \"string\"\n});\n```\n\nWraps the [GetAttachment](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html) API.\nThe arguments are based on the [API request body](https://docs.aws.amazon.com/connect-participant/latest/APIReference/API_GetAttachment.html#API_GetAttachment_RequestSyntax) with the following differences:\n\n- Fields are in `camelCase`.\n  The response is a url string.\n  `chatSession.getAttachmentURL()` invokes the GetAttachment using the AttachmentId as a request parameter and directly returns pre-signed URL received in the GetAttachment API response.\n\n##### `customerChatSession.disconnectParticipant()`\n\n```js\nconst awsSdkResponse = await customerChatSession.disconnectParticipant();\n```\n\nWraps the [DisconnectParticipant](https://docs.aws.amazon.com/con","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famazon-connect%2Famazon-connect-chatjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famazon-connect%2Famazon-connect-chatjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famazon-connect%2Famazon-connect-chatjs/lists"}