Oracle Digital Assistant Native Client SDK for Web

Release 25.08

Enhance your website or web app with live, production-grade chat using the Oracle Digital Assistant (ODA) Web SDK. This SDK offers a flexible, customizable chat widget, a headless API for building fully custom UIs, advanced messaging features, and robust support for attachments, voice, forms, internationalization, and accessibility.

Introduction

The ODA Web SDK enables you to:

Integrate conversational experiences, bot flows, or live agent capabilities into any website or single-page application.

Installation

Quick Start (Script Tag)

  1. Host SDK: Serve web-sdk.js yourself or use Oracle's CDN.
  2. Initialization: Create a settings.js file to configure and connect the widget:
    // settings.js
    const chatSettings = {
        URI: '<Server URI>',
        channelId: '<Channel ID>',
        userId: '<User ID>' // optional; random ID will be generated if omitted
    };
    
    function initSDK(name) {
        // Wait until the SDK global is available
        if (!document || !window.WebSDK) {
            setTimeout(() => initSDK(name), 2000);
            return;
        }
    
        const ns = name || 'Bots';
        const Bots = new WebSDK(chatSettings);
    
        let firstOpen = true;
        Bots.on(WebSDK.EVENT.WIDGET_OPENED, async () => {
            if (firstOpen) {
                try {
                    await Bots.connect();
                    console.log('Connection Successful');
                } catch (error) {
                    console.error('Connection failed', error);
                }
                firstOpen = false;
            }
        });
    
        window[ns] = Bots;
    }
    
  3. Include scripts in your page:
    <head>
        <script src="settings.js" defer></script>
        <script src="<WebSDK URL>" onload="initSDK('Bots')" defer></script>
    </head>
    

    Note:

    Client‑auth enabled channels require a JWT token generator function (see Security).

    Using the Oracle CDN

    You can also load the Web SDK from Oracle's Content Delivery Network (CDN). Using a CDN can offer benefits such as faster load times due to geographically distributed servers and a reduced hosting burden, as you won't need to host the web-sdk.js file yourself.

    <head>
        <script src="settings.js" defer></script>
        <!-- Pin a specific version in production -->
        <script src="https://static.oracle.com/cdn/oda/25.8.0/web-sdk.js" onload="initSDK('Bots')" defer></script>
        <!-- or track latest stable (use with caution in production) -->
        <!-- <script src="https://static.oracle.com/cdn/oda/latest/web-sdk.js" onload="initSDK('Bots')" defer></script> -->
    </head>
    

Official CDN URLs:

Tip:

To control updates, pin a specific version for production.

Dynamic Import (Utility)

You can dynamically inject the SDK from JavaScript if needed using the following utility function, which is based on the MDN example:

function fetchSDK(src, onloadFunction, name) {
    const script = document.createElement('script');
    script.type = 'application/javascript';
    script.defer = true;
    script.onload = () => onloadFunction(name);
    document.head.appendChild(script);
    script.src = src;
}

fetchSDK('<path-to-web-sdk.js>', initSDK, 'Bots');

AMD Modules

Load the SDK with RequireJS or SystemJS:

requirejs.config({
    paths: {
        WebSDK: '<path-to-web-sdk>' // without the .js extension
    }
});

define(['WebSDK'], (WebSDK) => {
    const settings = {
        URI: '<Server URI>',
        channelId: '<Channel ID>',
        userId: '<User ID>'
    };
    const Bots = new WebSDK(settings);
    Bots.connect();
});

Browser Support

Desktop (macOS, Windows, Linux):

Mobile:

Security

The SDK connects to an ODA Web Channel either with client auth disabled or enabled. Use client auth enabled whenever you can provision secure server‑side token generation.

Channel with Client Auth Disabled

When client authentication is disabled, only connections made from allowed domains (unblocked lists) are accepted. This use case is recommended when the client application can't generate a signed JWT Token but requires ODA integration.

Channel with Client Auth Enabled

When client auth is enabled, the authentication enforces a signed JWT in addition to allowed domains. Tokens must be generated and signed by your backend that safely stores the channel keyId and keySecret.

To enable this mode, these two fields are required during SDK initialization:

JWT Token Requirements

The JWT token generation and signing are the responsibility of the client application. Some token payload fields are mandatory and are validated by the ODA server.

The tokens must be signed with HS256 using the Web Channel's secret. Required claims are:

Header:

{ "typ": "JWT", "alg": "HS256" }

Payload:

{
    "iat": 1576747205,
    "exp": 1576748406,
    "channelId": "4920595c-ec79-4617-af9f-5950d603f8bb",
    "userId": "John"
}

If claims are missing or malformed, the SDK throws an error and does not attempt a connection.

Configuration

Configure the widget by passing settings to the WebSDK constructor.

Network

Property Optional Default Description
URI No Hostname of the ODA instance. Pass with or without protocol.
channelId No Web Channel ID.
userId Yes random Unique user identifier. Generated if omitted.
clientAuthEnabled Yes false Enable when connecting with JWT client authentication.

Feature Flags

Property Default Description
delegate Delegate callbacks for interception and custom rendering. See Delegation
embedded false Render widget inside targetElement. See Embedded mode.
targetElement Element ID for embedded mode (required when embedded is true).
enableAttachment true Enable file and location sharing.
enableAttachmentSecurity false Client‑auth enabled only. Adds auth headers to attachment requests.
enableHeaderActionCollapse true Collapse header actions into a menu if > 2 buttons.
shareMenuItems ['audio','file','location','visual'] Configure attachment categories and custom items. See Restrict attachment types.
enableAutocomplete false Suggest queries as the user types. See Autocomplete.
enableAutocompleteClientCache false Client‑side caching for autocomplete.
enableBotAudioResponse false Speak responses via TTS. See Text‑to‑Speech.
enableDefaultClientResponse false Show client‑side default messages when responses are delayed. See Default Client Responses.
enableOldLinkAdvisory false Advisory tooltip for older conversation links.
enableVoiceOnlyMode false Auto‑start voice recognition after responses, enabling the voice-only mode.
initBotAudioMuted true Start TTS muted (when TTS enabled).
disableInlineCSS false Prevent SDK from injecting inline CSS (you must provide CSS).
ttsVoice Preferred voices array for TTS.
ttsService 'oracle' TTS provider. See Speech Synthesis Service Injection.
enableHeadless false Headless mode (no UI). See Headless SDK.
enableLongPolling false HTTP long‑poll fallback when WebSocket not available. See Long Polling.
enableSpeech false Enable voice recognition. See Voice Recognition.
enableSpeechAutoSend true Auto‑send recognized text to the ODA.
speechLocale 'en-us' Recognition locale. See WebSDK.SPEECH_LOCALE.
enableTabsSync true Sync conversation across tabs. See Cross‑Tab Conversation Synchronization.
timestampMode 'relative' Show timestamp with messages. Set 'absolute' for full timestamp with each message, 'relative' for relative timestamp next to latest response, 'none' to disable.
timestampFormat Intl.DateTimeFormat options or pattern. See Format message timestamps. string.
timestampHeaderMode 'absolute' Header timestamp above first message of the day. Use 'absolute' for full timestamp, 'relative' for relative format, 'none' to hide it.
timestampHeaderFormat Formatting for header timestamps. Accepts values in the DateTimeFormat options object or a pattern string compatible with timestampFormat.
multiLangChat Enable language selection and/or detection. See Multi-Lingual Chat.
webViewConfig { referrerPolicy: 'no-referrer-when-downgrade', closeButtonType: 'icon', size: 'tall' } Configure in‑widget Webview. See In-Widget Webview.

Functionality

Property Default Description
alwaysShowSendButton false Always show send button.
customHeaderElementId Inject a custom element into header.
disablePastActions 'all' 'all', 'none', 'postback' to disable actions of past messages.
defaultGreetingTimeout 5 Seconds before greeting message appears when response is delayed.
defaultWaitMessageInterval 5 Interval in seconds between wait messages.
displayActionsAsPills false Display local actions with global actions outside bubble.
embeddedVideo true Inline supported platforms' videos in messages.
embedBottomScrollId Element to render below conversation (scrollable).
embedBottomStickyId Element to pin at bottom.
embedTopScrollId Element to render above conversation (scrollable).
embedTopStickyId Element to pin at top.
enableAgentSneakPreview false Send current user text to live agent (requires OSvC Sneak Preview).
enableClearMessage false Show clear conversation button.
enableDraggableButton false Make launch button draggable. See Draggable Launch Button and widget.
enableDraggableWidget false Make expanded widget draggable. See Draggable Launch Button and widget.
enableEndConversation true Enable ending the current session.
enableLocalConversationHistory false Load previous conversations for provided userId.
enableResizableWidget false Resize edges/corners of expanded widget.
enableSendTypingStatus false Send typing status to live agent.
focusOnNewMessage 'input' 'input' or 'action' to focus first action button. See Focus First Action of Response Message.
hotkeys {} Define ALT+key shortcuts for elements. See Keyboard Shortcuts - Hotkeys.
i18n {'en': {...}} Per‑locale strings for UI and a11y text. See Text (i18n).
icons {} Custom icons (URL or inline SVG).
initUserHiddenMessage Send a hidden user message on connect/open.
initUserProfile Initialize user profile before conversation starts.
initMessageOptions { sendAt: 'expand' } 'expand' or 'init' timing for init messages/profile.
isDebugMode false Log debug statements to console.
linkHandler { onclick, target } Override link handling (see Webview/Open Links). See Open Links.
locale 'en' UI locale. Fallback logic described below.
messageCacheSizeLimit 2000 Max messages stored in web storage.
name 'oda-chat' Namespace for CSS classes and element IDs.
noSpeechTimeout 0 (ODA) / 30 (OCI) Seconds to stop recognition if no voice detected.
ociSpeechConfig Configuration for OCI speech service based recognition
openChatOnLoad false Expand chat on initialization.
openLinksInNewWindow false Force window open instead of following browser prefs. See See Open Links.
reconnectInterval 5 Seconds between reconnect attempts.
reconnectMaxAttempts 5 Max reconnect attempts.
showConnectionStatus false Show connection state in header subtitle.
showPrevConvStatus true Show "end of previous conversation" marker.
showTypingIndicator true Show typing indicator while waiting for response.
typingIndicatorTimeout 30 Auto hide typing indicator after N seconds.
typingStatusInterval 3 Throttle user typing status to agent (seconds).
storageType 'localStorage' 'localStorage' or 'sessionStorage'.
theme 'default' 'default', 'redwood-dark', 'classic'.

Layout

Property Default Description
actionsLayout 'vertical' Local action layout orientation.
badgePosition { top: '0', right: '0' } Notification badge position relative to launch button.
cardActionsLayout 'vertical' Card actions orientation.
formActionsLayout 'vertical' Form actions orientation.
colors {branding:'#1B8FD2',text:'#212121',textLight:'#737373'} Color config (see Colors).
conversationBeginPosition 'bottom' Start conversation at top or bottom.
font 16px "Oracle Sans", ... Font shorthand for wrapper.
fontFamily "Oracle Sans", ... Font family for all text (overrides font).
fontSize '16px' Base font size (overrides font).
globalActionsLayout 'vertical' Global action orientation.
height '620px' Widget height.
messagePadding '6px 16px' Bubble padding.
position { bottom:'20px', right:'20px' } Fixed position for floating widget.
width '375px' Widget width.

Colors

You can modify the following colors to customize the look of the widget. Provide either:

Most UI elements have dedicated variables/keys. Example (CSS variables):

.oda-chat-wrapper {
    --color-branding: #e00;
    --color-text: #545454;
}

Equivalent config:

colors: {
    branding: '#e00',
    text: '#545454'
}

See the full colors reference table for the full list of supported variables/keys.

Icons

The icons used in the widget can be customized in two ways - image URLs or inline SVG strings. Inline SVGs allow theming and animation.

Example:

const settings = {
    icons: {
        rating: '<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><path d="M15.994 3.006a5.7 5.7 0 00-3.795 1.707L12 4.916l-.199-.202a5.676 5.676 0 00-8.128 0c-2.231 2.275-2.231 5.953 0 8.228L12 21.428l8.326-8.486A5.873 5.873 0 0022 8.828a5.873 5.873 0 00-1.675-4.115A5.693 5.693 0 0016.262 3z"/></svg>'
    }
};

The complete list of icon property mappings are available at Full Icons Reference.

You can also control the typing indicator icon size via:

Text (i18n)

Provide per‑locale strings under i18n. Keys include UI labels, a11y strings, and fallbacks:

i18n: {
    fr: { chatTitle: 'Soutien' },
    en: { chatTitle: 'Support' },
    es: { chatTitle: 'Apoyo' },
    'zh-cn': { chatTitle: '支持' }
}

Keyboard Shortcuts (Hotkeys)

Use ALT + key (a‑z, 0‑9) to focus/activate UI elements:

const settings = {
    hotkeys: {
        launch: 'l',   // ALT+L to launch
        collapse: 'c', // ALT+C to collapse
        input: 'i',
        send: 's'
    }
};

Supported keys map to elements like launch, close, send, mic, keyboard, shareMenu, etc. See the Full Hotkeys Element Map for details.

CSS Class Hooks

Override styles by targeting these classes:

Class Component
oda-chat-wrapper Root wrapper
oda-chat-button Launch button
oda-chat-widget Expanded widget
oda-chat-header Header
oda-chat-title Header title
oda-chat-footer Footer
oda-chat-message Message wrapper
oda-chat-left / oda-chat-right Bot/User bubble wrappers
See Full CSS Class Hooks all hooks

Usage Examples

Initialize and Connect

<script>
    const chatSettings = {
        URI: '<Chat server URI>',
        channelId: '<Channel ID>',
        userId: '<User ID>',
        fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif',
        locale: 'en',
        enableClearMessage: true,
        icons: {
            launch: 'style/Robot.png',
            avatarBot: 'style/Robot.png',
            avatarUser: 'style/userIcon.png'
        }
    };

    function initSDK(name) {
        if (!document || !window.WebSDK) {
            setTimeout(() => initSDK(name), 2000);
            return;
        }

        const ns = name || 'Bots';
        setTimeout(() => {
            const Bots = new WebSDK(chatSettings);

            // Register events BEFORE connect
            Bots.on(WebSDK.EVENT.READY, () => {
                console.log('Widget ready');
            });

            Bots.connect();
            window[ns] = Bots;
        }, 0);
    }
</script>
<script src="<WebSDK URL>" onload="initSDK('Bots')" defer></script>

Handle Events

Bots.on(WebSDK.EVENT.MESSAGE_SENT, (msg) => {
    console.log('User sent:', msg);
});

Bots.on(WebSDK.EVENT.MESSAGE_RECEIVED, (msg) => {
    console.log('Bot sent:', msg);
});

Bots.on(WebSDK.EVENT.NETWORK, (status) => {
    // WebSocket.CONNECTING=0, OPEN=1, CLOSING=2, CLOSED=3
    console.log('Network status:', status);
});

Send Messages and Attachments

// Simple text
await Bots.sendMessage('Show my payslip');

// Structured text
await Bots.sendMessage({ type: 'text', text: 'Show menu' });

// Postback
await Bots.sendMessage({
    type: 'postback',
    text: 'Order Pizza',
    postback: {
        'system.botId': '5409672A-AB06-4109-8303-318F5EDE91AA',
        'system.state': 'ShowMenu',
        action: 'pizza',
        variables: {}
    }
});

// Attachment (file input change)
const file = document.querySelector('#file').files[0];
await Bots.sendAttachment(file);

// Hidden user message (not shown in UI)
await Bots.sendMessage('What is the menu today?', { hidden: true });

Headless Usage

const Bots = new WebSDK({ /* settings */, enableHeadless: true });
await Bots.connect();

Bots.on(WebSDK.EVENT.MESSAGE_RECEIVED, (message) => {
    // Render your own UI
});

await Bots.sendMessage('Hello from headless UI!');

Open all links inside the widget:

const Bots = new WebSDK({
    // ...
    linkHandler: { target: 'oda-chat-webview' },
    webViewConfig: {
        accessibilityTitle: 'In‑widget Webview',
        size: 'tall',
        sandbox: ['allow-scripts', 'allow-downloads']
    }
});

Open only specific links via delegate:

const Bots = new WebSDK({
    // ...
    delegate: {
        beforeDisplay(message) {
            // Convert URL actions to open in webview
            const mp = message?.messagePayload;
            if (mp?.actions?.length) {
                mp.actions.forEach(a => {
                    if (a.type === 'url') a.type = 'webview';
                });
            }
            return message;
        }
    }
});

Multi‑Lingual Chat (Quick Setup)

const Bots = new WebSDK({
    // ...
    multiLangChat: {
        supportedLangs: [
            { lang: 'en' },
            { lang: 'es', label: 'Español' },
            { lang: 'fr', label: 'Français' },
            { lang: 'hi', label: 'हिंदी' }
        ],
        primary: 'en'
    }
});

// Dynamically switch
Bots.setPrimaryChatLanguage('fr'); // or 'und' to auto‑detect

API Reference

This section documents runtime enums, methods, and events.

Enums

WebSDK.EVENT

Subscribe with Bots.on(WebSDK.EVENT.<NAME>, handler):

For details about each event, see Events.

WebSDK.SPEECH_LOCALE

This enum provides the locales that are supported by the voice recognition service. The ODA Supported locales for voice recognition are:

With OCI Speech integration, more languages can be added for recognition.

The enum values can be passed in the speechLocale setting or setSpeechLocale(locale) API.

WebSDK.THEME

This enum provides the themes that can be applied to the chat widget. The values are:

WebSDK.TTS

This enum provides the text-to-speech (TTS) services that are exposed . The values are:

You can set the service in settings with ttsService or via setTTSService().

Methods

The SDK namespace is the name you pass to initSDK. For example, with initSDK('Bots'), call methods as Bots.<method>().

Core connection and lifecycle:

connect()

Connects to the current chat server.

Bots.connect()

The API returns a Promise which can be used to execute code after the connection is complete or closed.

try {
    await Bots.connect();
    // Successful connection
} catch (error) {
    // Something went wrong during connection
}

connect(config)

Connects to current chat server with passed parameters. All fields are optional, if a field is not passed and is already set from initial settings or an earlier invocation, the existing value is reused. If userId is not passed and is not set so far, a random userId is generated and used.

Bots.connect({
    URI: '<URI>',
    channelId: '<channelId>',
    userId: '<userId>'
})

The API returns a Promise which can be used to execute code after the connection is complete or closed.

try {
    await Bots.connect({
        URI: '<URI>'
        channelId: '<channelId>',
        userId: '<userId>'});
    // Successful connection
} catch (error) {
    // Something went wrong during connection
}

The call to connect() API can result in a new connection or continuing existing connection depending on a few factors:

disconnect()

Closes the currently active connection to the chat server. This includes closing the connection to the chat server, any active voice recognition, ongoing attachment uploads, and running speech synthesis.

Bots.disconnect()

The API returns a Promise which is resolved when the connection is closed.

await Bots.disconnect();
console.log('The connection is now closed');

isConnected()

Returns whether the connection to the chat server is currently active.

Bots.isConnected()

endChat()

Ends the current conversation session. The SDK sends an event message to the digital assistant to mark the conversation as complete. It then closes the connection, collapses the chat widget, erases the user's conversation history, and triggers the 'chatend' event for subscribers.

Bots.endChat()

destroy()

Destroys the SDK instance by closing any active connection, voice recognition, speech synthesis, file uploads, and by removing the widget from the UI. Once called, none of the current instance methods can be called afterward.

Bots.destroy();

Widget visibility and state:

openChat()

Opens the chat widget popup.

Bots.openChat();

closeChat()

Collapses the chat widget and displays the chat icon.

Bots.closeChat();

isChatOpened()

Returns true if the widget is open. Otherwise, it returns false.

Bots.isChatOpened();

showWidget()

Displays the chat widget in its collapsed or expanded state if it is hidden from the page. The method invocation is ignored in the embedded or headless modes.

Bots.showWidget();

hideWidget()

Hides the chat widget in its collapsed or expanded state if it is visible on the page. The method invocation is ignored in the embedded or headless modes.

Bots.hideWidget();

Messaging:

sendMessage(message, options)

Sends a message on the user's behalf. Returns a Promise that is resolved with the user message on success, or gets rejected with an error message for an unsuccessful delivery or an invalid message payload. The user message is not displayed if the Promise is rejected.

Bots.sendMessage({
    type: 'text',
    text: 'hello'
});
// OR
Bots.sendMessage('hello');

The messages can be sent in these formats:

Note:

To keep the message from being displayed in the widget, pass the hidden boolean flag in the options object:
Bots.sendMessage('What is the menu today?', { hidden: true });
This call sends the message to the server without displaying it in the widget.

sendAttachment(file)

Uploads file to the server. Returns a Promise that is resolved with the server response for successful uploads, or gets rejected with an error message for unsuccessful uploads.

try {
    const result = await Bots.sendAttachment(file);
    console.log('File uploaded successfully.');
} catch (error) {
    console.log(reason);
}

sendUserTypingStatus(status, userText)

Sends the user's typing status to the agent. The status can be either RESPONDING or LISTENING, where RESPONDING represents the user typing activity. Use this API to send the user typing status when running in headless mode.

Bots.sendUserTypingStatus('RESPONDING', 'Hello!'); // Send typing status for the user with the user text `Hello!`

Bots.sendUserTypingStatus('LISTENING'); // Send listening status for the user

getConversationHistory()

Returns information about the current conversation for the user. The response is an object containing user ID, messages, and unread message count.

Bots.getConversationHistory()

{
    messages: [
        {
            date: '2020-01-22T17:06:24.085Z',
            isRead: true,
            messagePayload: {
                text: 'show menu',
                type: 'text'
            },
            userId: 'user74882436'
        }
    ],
    messageCount: 1,
    unread: 0,
    userId: 'user74882436'
}

clearConversationHistory(userId, shouldClearWidget)

This API clears the conversation history for a known user from the browser's localStorage. The userId must be a string. On passing an empty or no userId, the current user's history is removed.

If the passed userId is the same as the current user's userId, then you can also pass an optional boolean argument, shouldClearWidget, to configure whether the current chat widget UI should also be cleared on calling this API. By default, the value is true.

Bots.clearConversationHistory('Jonathan');
      // Removes conversation history of Jonathan

Bots.clearConversationHistory('Adriana');
       // Removes conversation history of Adriana and clears the widget UI if Adriana is current user

Bots.clearConversationHistory('', false);
       // Removes conversation history of current user without clearing the widget UI

Note:

This API does not interact with sessionStorage for users other than the current user. The sessionStorage is automatically cleared on closing the tab.

clearAllConversationsHistory(shouldClearWidget)

This API clears the conversation history for all users from the browser's localStorage. You can also pass an optional boolean argument, shouldClearWidget, to configure whether the current chat widget UI should also be cleared on calling this API.

Bots.clearAllConversationsHistory()

Caution:

The actions taken by calling this API cannot be undone. Once the messages are deleted, they cannot be recovered. Call this method sparingly and only when absolutely needed.

Like clearConversationHistory, this method can also help in recovering significant portions of localStorage from the user's browser. By default, the value is true.

Note:

This API does not interact with sessionStorage for users other than the current user. The sessionStorage is automatically cleared on closing the tab.

getUnreadMessagesCount()

Returns the count of the unread messages.

Bots.getUnreadMessagesCount();

setAllMessagesAsRead()

Marks all messages as have been read/seen by the user.

Bots.getUnreadMessagesCount(); // 2
Bots.setAllMessagesAsRead();
Bots.getUnreadMessagesCount(); // 0

setUserInputMessage(text)

Populates the user input field with the passed message.

Bots.setUserInputMessage('Show my agenda for today please.');

setUserInputPlaceholder(text)

Updates user input's placeholder text. It can be used to change the placeholder text according to the input expected from the user.

Bots.setUserInputPlaceholder('Add your pizza topping');

showTypingIndicator()

Displays the typing indicator in the conversation. If the typing indicator is already visible, then the timer to hide it gets reset. The typing indicator is automatically removed if the server sends a response, or the timer period set by typingIndicatorTimeout (in seconds) has expired.

The method only works if the showTypingIndicator setting is set to true, the SDK is not in headless mode, and the widget is connected to the server.

Bots.showTypingIndicator();

User/Agent Data:

updateUser(userDetails)

Updates the user information.

Bots.updateUser({
    messagePayload: {
        text: 'give me a pizza',
        type: 'text'
    },
    profile: {
        firstName: 'Jane',
        lastName: 'Smith',
        email: 'updated@email.com',
        properties: {
            justGotUpdated: true
        }
    }
});

Note:

You can also use the initUserProfile property to set profile values. If you use the initUserHiddenMessage property, and the response from the server is expected to have user profile values, then you must use the initUserProfile property instead of setting the values in updateUser(). For later updates to the user profile, use updateUser().

setUserAvatar(userAvatar)

Sets the user avatar. The value passed must be the URL of the image source, or the source string of the SVG image that should be displayed alongside the user messages.

Bots.setUserAvatar('../assets/images/avatar-user.jpg');

setAgentDetails(agentDetails)

Sets the current agent details that should be displayed for agent messages. If there is an agent handover, the latest agent details will replace the details set by this API. All fields are optional, so if a field is not passed and is already set from the initial settings or an earlier invocation, the existing value is reused. The value passed for avatarImage must be the URL of the image source, or the source string of the SVG image that should be displayed alongside the agent messages. The values passed for nameTextColor, avatarTextColor, and avatarBackgroundColor must be in standard color format.

Bots.setAgentDetails({
    name: 'Ana Lee',
    avatarImage: '../assets/images/avatar-agent.jpg',
    nameTextColor: 'rgba(22, 21, 19, 0.65)',
    avatarTextColor: 'green',
    avatarBackgroundColor: '#A890B6'
});

Note:

This API does not change the previous agent details. These passed values will have the lifetime of the current agent session only

getAgentDetails()

Returns the current agent details.

Bots.getAgentDetails();

Autocomplete:

getSuggestions(query)

If the autocomplete feature is enabled (enableAutocomplete: true), this API returns a Promise that resolves to the suggestions for the given query string. If it takes too long (~10s) to fetch the suggestion, the Promise is rejected.

try {
    const suggestions = await Bots.getSuggestions('pizza');
    const suggestionString = suggestions.toString();
    console.log('The suggestions are: ', suggestionString);
} catch (error) {
    console.log('Suggestion request failed', error);
}

The API expects a single query string parameter and returns a Promise. On a successful request for suggestions, the Promise is resolved to a string array. On failure, the Promise is rejected with an error message.

If the API is called when the feature is disabled, it returns a rejected Promise.

Voice & TTS:

startVoiceRecording(onSpeechRecognition, onSpeechNetworkChange, options)

Starts the voice recording if the speech recognition feature is enabled. The API returns a Promise that is resolved when the speech service starts recording. In case of an error, the Promise is rejected with an Error object. The API expects two callbacks to be passed as its parameters: onSpeechRecognition function is called on the speech server response. The JSON response is passed as a parameter. onSpeechNetworkChange function is called on a change in the speech connection. A single parameter, the WebSocket status, is passed.

Bots.startVoiceRecording(function(data) {
    let recognizedText = '';
    if (data && (data.event === 'finalResult' || data.event === 'partialResult')) {
        if (data.nbest && data.nbest.length > 0) {
            recognizedText = data.nbest[0].utterance;
        }
    }
}, function(status) {
    if (status === WebSocket.OPEN) {
        // Connection established
    } else if (status === WebSocket.CLOSED) {
        // Connection closed
    }
})

The function also accepts an optional options object that can have fields for two callback functions for the analyser - onAnalyserReady, and onAnalyserFrequencies. Either one, or both, fields can be passed. These callbacks can be used to get regular frequency values for visualization.

onAnalyserReady is a one-time callback that is called when the analyser node is initialized. The callback method is passed as a single argument, an AnalyserNode, which is configured with a fftSize of 256, and connected to the voice input source.

onAnalyserFrequencies is a callback method that is called every time a new set of voice input frequencies are provided by the analyser node. The callback method is passed a single argument, an Uint8Array of size 128, depicting the frequency data composed of integers on a scale from 0 to 255. Each item in the array represents the decibel value for a specific frequency. The frequencies are spread linearly from 0 to 1/2 of the sample rate. For example, for the 48000 sample rate, the last item of the array will represent the decibel value for 24000 Hz.

Bots.startVoiceRecording(function(data) {
    let recognizedText = '';
    if (data && (data.event === 'finalResult' || data.event === 'partialResult')) {
        if (data.nbest && data.nbest.length > 0) {
            recognizedText = data.nbest[0].utterance;
        }
    }
}, function(status) {
    if (status === WebSocket.OPEN) {
        // Connection established
    } else if (status === WebSocket.CLOSED) {
        // Connection closed
    }
}, {
    onAnalyserReady: function(analyserNode) { console.log('The analyser node is', analyserNode); },
    onAnalyserFrequencies: function(frequencies) { console.log('New input frequencies are', frequencies); }
})

stopVoiceRecording()

Stops any running voice recording. Throws an error if speech recognition is not enabled.

Bots.stopVoiceRecording()

setSpeechLocale(locale)

Sets the locale used for speech connection. The user is expected to speak with the same locale that is set here to the SDK. The list of currently supported locales is available at WebSDK.SPEECH_LOCALE. If an unsupported locale is passed, the API returns false while maintaining the passed locale. In such a case, any voice recognition attempt is failed. The function returns a boolean indicating whether the passed locale is supported or not.

Bots.setSpeechLocale('fr-fr');

Note:

When both voice recognition and audio response are enabled but the audio response locale is not set, then the locale for the audio response voice gets set to the same locale as the voice recognition locale.

In this example, the locale for audio response voice is set to 'es-es' automatically.

const Bots = new WebSDK({
    // ...,
    enableSpeech: true,
    enableBotAudioResponse: true
});

// ...

Bots.setSpeechLocale('es-es');

setPrimaryChatLanguage(languageTag)

Updates the language selected for the conversation between the user and the skill in the selection dropdown. This function can only be called when the multi-lingual chat feature is configured.

Bots.setPrimaryChatLanguage('fr')

If the passed language tag does not match any of the passed supported languages, Detect Language is set and skill determines which language is being used for conversation.

setTTSService(service)

Injects a TTS service that is used by the SDK for the utterance of incoming skill messages. The passed service object needs to implement the SpeechSynthesisService interface to have the functions that the SDK requires to utilize it. If an invalid or empty service object is passed, the synthesis service is disabled. See Speech Synthesis Service Injection for more details.

const myOwnTTSService = {
    /**
     * Adds a phrase to the utterance queue to be spoken
     *
     * @param {string} phrase
     */
    speak: function(phrase) {},

    /**
     * Cancels any ongoing speech synthesis utterance
     */
    cancel: function() {},

    /**
     * Returns a Promise that resolves into a list of SpeechSynthesisServiceVoice objects representing
     * the available voices
     *
     * @return {*}  {Promise<SpeechSynthesisServiceVoice[]>}
     */
    getVoices: function() {},

    /**
     * Sets the voice to be used for speaking the utterances. It accepts an array of candidate voices
     * sorted in their preference order, and sets one of them according to its matching criteria.
     * It returns a Promise that gets resolved when the voice is set.
     *
     * @param {SpeechSynthesisServiceVoice[]} voice
     * @return {*}  {Promise<void>}
     */
    setVoice: function(voices) {},

    /**
     * Returns the voice that is currently used for speaking utterances
     *
     * @return {*}  {SpeechSynthesisServiceVoice}
     */
    getVoice: function() {}
};

Bots.setTTSService(myOwnTTSService);

You can also pass the WebSDK.TTS values to the setTTSService method to set them as the TTS service used by the SDK.

Bots.setTTSService(WebSDK.TTS.oracle);      // Sets the OCI TTS service
Bots.setTTSService(WebSDK.TTS.platform);    // Sets the platform based TTS service

getTTSVoices()

Returns a Promise that resolves into a list of SpeechSynthesisServiceVoice objects representing the available voices for speech synthesis. When using SDK's native speech synthesis service, this list is populated with the voices provided by the platform/OS. When using a third-party synthesis service, the list is populated by the voices that are provided by that service.

await Bots.getTTSVoices();
console.log(voices);

/**
 * [
 * {
 *      default: false,
 *      lang: "en-US",
 *      localService: true,
 *      name: "Alex",
 *      voiceURI: "urn:moz-tts:osx:com.apple.speech.synthesis.voice.Alex"
 * },
 * {
 *      default: false,
 *      lang: "it-IT",
 *      localService: true,
 *      name: "Alice",
 *      voiceURI: "urn:moz-tts:osx:com.apple.speech.synthesis.voice.alice"
 * },
 * {
 *      default: false,
 *      lang: "sv-SE",
 *      localService: true,
 *      name: "Alva",
 *      voiceURI: "urn:moz-tts:osx:com.apple.speech.synthesis.voice.alva"
 * }...
 * ]
 * /

setTTSVoice(voices)

Sets the voice that's used for speaking the skill's utterances. It accepts an array of candidate voices that's sorted by preference. From this array, it either sets the first voice that's provided by the synthesis service as the skill's voice, or it sets a voice that closely matches one of the voices available in the synthesis service. It returns a Promise that gets resolved when the voice is set.

Note: This function is similar to the deprecated setSkillVoices(voices) method. Use setTTSVoice instead.

await Bots.setTTSVoice([{
    lang: 'es-mx',
    name: 'Juan'
}, {
    lang: 'es-es',
    name: 'Monica'
}, {
    lang: 'es-ar',
    name: 'Diego'
}, {
    lang: 'es-es'
}]);
Bots.speak('Hello');

getTTSVoice()

Returns the voice that is currently used by the synthesis service for speaking utterances. It returns a SpeechSynthesisServiceVoice object representing the selected voice.

const currentVoice = Bots.getTTSVoice();
console.log(currentVoice);
/**
 * {
 *      default: false,
 *      lang: "en-US",
 *      localService: true,
 *      name: "Alex",
 *      voiceURI: "urn:moz-tts:osx:com.apple.speech.synthesis.voice.Alex"
 * }
 * /

speakTTS(phrase)

Calls the speech synthesis service to speak the passed phrase. The passed phrase can either be a plain string, or a skill message object received from the server.

Bots.speakTTS('Hello World');

const skillMessage = {
    messagePayload: {
        type: 'text',
        text: 'What is your order number?'
    }
};

Bots.speakTTS(skillMessage);    // Will utter 'What is your order number?'

cancelTTS()

Cancels any ongoing utterance from the speech synthesis service.

Bots.cancelTTS();

Delegation & rendering:

setDelegate(delegate)

The setDelegate method can be used to change or remove delegate callbacks after a conversation has been initialized. If no value is passed, the existing delegates are removed.

await Bots.connect();
Bots.setDelegate({
    beforeDisplay(message) {
        return message;
    },
    beforeSend(message) {
        return message;
    },
    beforePostbackSend(postback) {
        return postback;
    },
    beforeEndConversation(message) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(message);
            }, 2000);
        });
    },
    render(message) {
        if (message.messagePayload.type === 'card') {
            // Perform custom rendering for card using msgId
            return true;
        }
        return false;
    }
});

Layout & appearance:

setWebViewConfig(webViewConfig)

Sets and updates the Webview configuration, customizing the Webview component. Check out the In-Widget Webview section under customization for more details.

Bots.setWebViewConfig({
    accessibilityTitle: 'Webview container for Wikipedia',
    sandbox: ['allow-scripts', 'allow-downloads'],
    size: 'tall',
    title: 'Wikipedia'
});

setChatBubbleIconHeight(height)

Sets the height of the loading chat bubble icon. The height must be provided as a string value in one of the standard length units.

Bots.setChatBubbleIconHeight('18px');

setChatBubbleIconWidth(width)

Sets the width of the loading chat bubble icon. The width must be provided as a string value in one of the standard length units.

Bots.setChatBubbleIconWidth('24px');

setChatBubbleIconSize(width, height)

Sets the size of the loading chat bubble icon. The width and height must be provided as string values in one of the standard length units.

Bots.setChatBubbleIconSize('24px', '18px');

setFontFamily(fontFamily)

Set font family used for all text content in the chat widget. The fontFamily argument must be a string and follow the standard pattern.

Bots.setFontFamily('"Gill Sans", sans-serif');

setFontSize(fontSize)

Sets the font size for the text in the chat widget. The syntax of fontSize must follow the standard permissible values.

Bots.setFontSize('16px');

setHeight(height)

Sets the height of the chat widget. The value passed must be in one of the length units.

Bots.setHeight('786px')

setWidth(width)

Sets the width of the chat widget. The value passed must be in one of the length units.

Bots.setWidth('320px')

setSize(width, height)

Sets the size of the chat widget. The values passed must be in one of the length units.

Bots.setSize('320px' ,'786px',)

setMessagePadding(padding)

Sets the padding around the message in the chat widget. The syntax of padding must follow standard permissible values.

// Apply padding to all four sides
Bots.setMessagePadding('15px');
// vertical | horizontal
Bots.setMessagePadding('5% 10%');
// top | horizontal | bottom
Bots.setMessagePadding('15em 20em 20em');
// top | right | bottom | left
Bots.setMessagePadding('15px 20px 20px 15px');

setTextColor(color)

Sets the primary text color of messages in the chat widget. It does not modify the colors in actions. The value passed must be in standard color format.

Bots.setTextColor('#33ee00')

setTextColorLight(color)

Sets the color of the secondary messages in the chat widget, like descriptions. The value passed must be in standard color format.

Bots.setTextColorLight('rgb(13, 155, 200)')

Events

Register with Bots.on(event, handler), remove with Bots.off() in one of following ways:

We recommend adding event handlers before calling the connect() method so that they can be registered and triggered appropriately.

ready

This event is triggered when connect completes successfully. Be sure to bind before calling connect.

Bots.on('ready', function(){
    console.log('the init has completed!');
});

Listeners to the ready event must be added before calling the connect() method. Otherwise, the listeners will not be registered in time to be triggered.

destroy

This event is triggered when the widget is destroyed.

Bots.on('destroy', function(){
    console.log('the widget is destroyed!');
});
Bots.destroy();

message:received

This event is triggered when the user receives a message. If beforeDisplay delegate is set, the callback would receive the message to be displayed after executing the delegate.

Bots.on('message:received', function(message) {
    console.log('the user received a message', message);
});

message:sent

This event is triggered when the user sends a message. If beforeSend delegate is set, the callback would receive the message sent to the server after executing the delegate.

Bots.on('message:sent', function(message) {
    console.log('the user sent a message', message);
});

message

This event is triggered when a message is added to the conversation.

Bots.on('message', function(message) {
    console.log('a message was added to the conversation', message);
});

networkstatuschange

This event is triggered whenever the network status of the connection to the server changes. The callback receives a status number parameter, which corresponds to WebSocket network status constants.

Bots.on('networkstatuschange', function(status) {
    switch (status) {
        case 0:
            status = 'Connecting';
            break;
        case 1:
            status = 'Open';
            break;
        case 2:
            status = 'Closing';
            break;
        case 3:
            status = 'Closed';
            break;
    }
    console.log(status);
});

typing

This event is triggered whenever the user starts or stops typing in the user input field. The listener receives a boolean parameter, which is set true when the user starts typing and set false when typingStatusInterval has elapsed after the user stops typing.

Bots.on('typing', function(isTyping) {
    console.log('User currently typing: ', isTyping);
});

unreadCount

This event is triggered when the number of unread messages changes.

Bots.on('unreadCount', function(unreadCount) {
    console.log('the number of unread messages was updated', unreadCount);
});

widget:opened

This event is triggered when the widget is opened.

Bots.on('widget:opened', function() {
    console.log('Widget is opened!');
});

widget:closed

This event is triggered when the widget is closed.

Bots.on('widget:closed', function() {
    console.log('Widget is closed!');
});

widget:show

This event is triggered when the widget is toggled to be shown with showWidget() method.

Bots.on(WebSDK.EVENT.WIDGET_SHOW , function() {
    console.log('Widget is visible.');
});

widget:hide

This event is triggered when the widget is toggled to be hidden with hideWidget() method.

Bots.on(WebSDK.EVENT.WIDGET_HIDE, function() {
    console.log('Widget is hidden.');
});

click:audiotoggle

This event is triggered when the audio utterance of response is toggled. The subscribers receive the boolean status - true if the audio response is turned on, false if it is turned off.

Bots.on('click:audiotoggle', function(status) {
    if (status === true) {
        console.log('Audio response is turned on.');
    } else {
        console.log('Audio response is turned off.');
    }
})

click:erase

This event is triggered when the erase conversation history button is clicked. No parameters are passed to the subscribers.

Bots.on('click:erase', function() {
    console.log('Conversation history is erased.');
})

click:voicetoggle

This event is triggered when the voice activation button is toggled. The subscribers receive the boolean status - true if the voice is activated, false if it is deactivated.

Bots.on('click:voicetoggle', function(status) {
    if (status === true) {
        console.log('Voice recording is started.');
    } else {
        console.log('Voice recording is stopped.');
    }
})

chatlanguagechange

This event is triggered when the chat language in language selection dropdown is selected or changed. This dropdown is exposed on enabling the Multi-Lingual Chat feature. Its subscribers receive the selected language's language tag. If auto-detect is selected, null is passed as the argument.

Bots.on('chatlanguagechange', function(language) {
    console.log('The selected chat language is', language);
});

chatend

This event is triggered when the conversation is ended.

Bots.on('chatend', function() {
    console.log('The conversation is ended.');
});

TTSStart

This event is triggered when the TTS is started.

Bots.on(WebSDK.EVENT.TTSStart, function() {
    console.log('The TTS is started.');
});

TTSStop

This event is triggered when the TTS is stopped or ended.

Bots.on(WebSDK.EVENT.TTSStop, function() {
    console.log('The TTS is ended.');
});

Examples in the Usage section show typical subscriptions.

Message Model

The SDK uses a consistent, typed message model for all traffic. Understanding the envelope and payload types is important for headless integrations, delegates, custom rendering, and testing.

Overview and Envelope

All conversation items are "messages" with a standard envelope:

{
  "messagePayload": { /* see types below */ },
  "userId": "guest"
}

Base Types

These are building blocks that are reused across payloads:

User Messages

User message payloads (types extend MessagePayload):

Response Messages

Response payloads from the skill/agent include:

See Conversation Message Model Reference for complete message model.

Advanced Features

Autocomplete

Autocomplete provides suggestions to end users to better form the utterance and select the specific entity value. To enable autocomplete, you must add autocomplete suggestions to the skill's intents. Then, whenever the user types a character in the input field, the intents' autocomplete suggestions display in a popup to suggest the best format, helping to minimize user errors. An intent's autocomplete suggestions should not be a full word dictionary. Their purpose is to minimize the scope and allow better guidance to the end user.

The feature can also be used in headless mode using getSuggestions(query) API.

Auto‑Submit in Edit‑Form

Replace Previous Edit‑Form

Delegation

The delegation feature enables you set a delegate to receive callbacks before certain events in the conversation. To set a delegate, pass it in the delegate property or use the setDelegate method. The delegate object may optionally contain beforeDisplay, beforeSend, beforePostbackSend, beforeEndConversation and render delegate functions.

const delegate = {
    beforeDisplay: function(message) {
        return message;
    },
    beforeSend: function(message) {
        return message;
    },
    beforePostbackSend: function(postback) {
        return postback;
    },
    beforeEndConversation: function(message) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(message);
            }, 2000);
        });
    },
    render: function(message) {
        if (message.messagePayload.type === 'card') {
            // Create a placeholder with id = message.msgId and render custom UI
            return true;
        }
        return false;
    }
}

Bots.setDelegate(delegate);

beforeDisplay

The beforeDisplay delegate allows a skill message to be modified before it is displayed in the conversation. The message returned by the delegate displays instead of the original message. The returned message is not displayed if the delegate returns a falsy value like null, undefined, or false. If the delegate errors out, then the original message will be displayed instead.

beforeSend

The beforeSend delegate allows a user message to be modified before it is sent. The message returned by the delegate is sent to the skill instead of the original message. The message returned by the delegate is not sent if the delegate returns a falsy value like null, undefined, or false. If the delegate errors out, the original message will be sent instead.

beforePostbackSend

The beforePostbackSend delegate is similar to beforeSend but is instead applied to postback messages from the user. The postback returned by the delegate is sent to the skill. The postback returned by the delegate is not sent if the delegate returns a falsy value like null, undefined, or false. If the delegate errors out, the original postback will be sent instead.

beforeEndConversation

The beforeEndConversation delegate allows an interception the end conversation flow if some pre-exit activity must be performed. The function receives the exit message as its input parameter. It must return a Promise. If this Promise resolves with the exit message, then the CloseSession exit message is sent to the chat server. Otherwise, the exit message is prevented from being sent.

render

The render delegate allows to override the default message rendering. If the render delegate function returns true for a particular message type, then the WebSDK creates a placeholder slot instead of default message rendering. To identify the placeholder, the WebSDK adds the msgId of the message as the id of the element. In the render delegate function, you can use this identifier to get the reference for the placeholder and render your custom message template. See Custom Message Rendering for more details.

Embedded Mode

The chat widget appears as a fixed position element on the bottom right of the page, which does not respond to gestures on the page. But it can also be embedded into the host and become part of the page. To activate the embedded mode, you need to pass embedded: true, and provide a target container with targetElement: <targetDivId>. This accepts a DOM element that will be used as the container where the widget will be rendered.

The embedded widget occupies the full width and height of the container. A height and width must be specified for the target element. Otherwise, the widget will collapse.

Headless SDK

Similar to headless browsers, the SDK can also be used without a UI. The SDK maintains the connection to the server, and provides APIs to send messages, receive messages, and get updates of the network status. Developers can use the APIs to interact with the SDK, and update UI appropriately.

The communication can be implemented as follows:

In‑Widget Webview

The Web SDK contains an in-widget Webview component that can be used to view the message links within the chat widget. This feature allows users to interact with links in the conversation without taking them away from the widget to a new tab or window. The in-widget Webview can be applied globally to open all links in the messages inside it, or can be selectively configured for specific links.

To open all links in the conversation in the Webview, you just need to pass linkHandler: { target: 'oda-chat-webview' } in the settings. This sets the target of all links to oda-chat-webview, which is the name of the Webview iframe.

In more general scenarios, you'll probably need to open only certain links in the Webview, while ensuring other links open normally in other tabs/windows. The beforeDisplay delegate can be used to make that work. To open a specific message URL action in the Webview, replace action.type field's value from url to webview. Once the action type is changed to webview in beforeDisplay, clicking that action button will open the link in the Webview. Opening specific links embedded in the text in Webview is a bit more challenging. The embedded link needs to be converted into an anchor element (<a href="https://www.oracle.com"\>), and the target="oda-chat-webview" attribute should be added in that anchor element.

The webViewConfig setting allows customizing the Webview component. It accepts an object that can have the following optional fields:

{
    accessibilityTitle: string,                             // Name of Webview frame element for Web Accessibility
    closeButtonIcon: string,                                // Image URL/SVG string that is used to display the close button icon
    closeButtonLabel: string,                               // Text label/tooltip title for the close button
    closeButtonType: 'icon' | 'label' | 'iconWithLabel',    // Sets how the close button is displayed in the Webview
    errorInfoBar: boolean,                                  // Sets to display or hide fallback view with original URL
    errorInfoDismissLabel: string,                          // Label for error-view bar dismiss button
    errorInfoText: string,                                  // Informational text displayed in an error-view bar inside Webview as a fallback for the user in case the URL fails to load in the Webview
    referrerPolicy: ReferrerPolicy                          // Indicates which referrer to send when fetching the frame's resource
    sandbox: string[],                                      // Array of extra restrictions to the content in the Webview frame
    size: 'tall' | 'full',                                  // Height of the Webview compared to chat widget. When set 'tall', it is set as 80%, 100% for 'full'.
    title: string                                           // Webview title shown on the header of the Webview container
}

The referrerPolicy policy value passed should be a valid directive. The default policy applied is 'no-referrer-when-downgrade'.

The sandbox field accepts an array of valid restriction strings that allows for the exclusion of certain actions inside the frame. The restrictions that can be passed to the field can be found under the sandbox attribute manual at MDN.

The configuration can also be updated dynamically by passing a webViewConfig object in the method setWebViewConfig(). Every property in the object is optional.

The Webview optionally presents a fallback view that contains the original URL link as a fallback in case the page fails to load inside the Webview. Clicking the link in this view opens the page in a new tab. The informational text can be customized with the webViewErrorInfoText i18n translation string and must contain a placeholder text for the link label. For example:

settings = {
    URI: 'instance',
    //...,
    i18n: {
        en: {
            webViewErrorInfoText: 'This link can\'t be opened here. You can open it in a new page by clicking {0}here{/0}.'
        }
    }
}

This error view can be disabled by passing errorInfoBar: false in the webViewConfig setting.

Limitations

  1. Pages that provide response header X-frame-options: deny or X-frame-options: sameorigin may not open in the Webview due to server-side restrictions preventing the page to be opened inside iframes. The Webview presents a dismissible popup with a link back to the user in the Webview. Users can open it in a new window or tab by clicking it.
  2. Due to the above restrictions, authorization pages like IDCS, Google Login, FB Login, etc. can not be opened inside the WebViews, as authorization pages always return X-frame-options: deny to prevent clickjacking.
  3. Only links inside the conversation messages can be opened inside the Webview. Any external links must not be targeted to be opened in the Webview, clicking on such links won't open the Webview correctly.

Long Polling

The SDK uses WebSockets to connect to the server and converse with skills. If for some reason the WebSocket is disabled over the network, traditional HTTP calls can be used to chat with the skill. This feature is known as long polling, as the SDK has to continuously call or poll the server to fetch the latest messages from the skill.

Long polling provides fallback support for conversations on browsers that don't have WebSockets enabled or blocked.

Multi‑Lingual Chat

The Web SDK's native language support enables the chat widget to detect a user's language or allow users to select the conversation language.

Enable the Language Menu

You can enable a menu that allows users to select a preferred language from a dropdown menu by defining the multiLangChat property with an object containing the supportedLangs array, which is comprised of language tags (lang) and optional display labels (label) to override the default translation strings. Outside of this array, you can optionally set the default language with the primary key (primary: 'en' in the following snippet). If the primary key matches one of the supported languages, then that language is selected. When no match can be found, Detect Language is activated.

multiLangChat: {
    supportedLangs: [{
        lang: 'en'
    }, {
        lang: 'es',
        label: 'Español'
    }, {
        lang: 'fr',
        label: 'Français'
    }, {
        lang: 'hi',
        label: 'हिंदी'
    }],
    primary: 'en'
}

The chat widget displays the passed-in supported languages in a dropdown menu that's located in the header. In addition to the available languages, the menu also includes a Detect Language option. When a user selects a language from this menu, the current conversation is reset, and a new conversation is started with the selected language. The language selected by the user persists across sessions in the same browser, so the user's previous language is automatically selected when the user revisits the skill through the page containing the chat widget.

You can add an event listener for the chatlanguagechange event, which is triggered when a chat language has been selected from the dropdown menu or has been changed.

Bots.on('chatlanguagechange', function(language) { console.log('The selected chat language is', language); });

Disable Language Menu

You can also configure and update the chat language without also having to configure the language selection dropdown menu by passing multiLangChat.primary in the initial configuration without also passing a multiLangChat.supportedLangs array. The value passed in the primary variable is set as the chat language for the conversation.

Language Detection

In addition to the passed in languages, the chat widget displays a Detect Language option in the dropdown. Selecting this option tells the skill to automatically detect the conversation language from the user's message and, when possible, to respond in the same language.

If you omit the primary key or if the primary key is invalid, the widget automatically detects the language in the user profile and activates the Detect Language option in the menu. You can dynamically update the selected language by calling the setPrimaryChatLanguage(lang) API. If the passed lang matches one of the supported languages, then that language is selected. When no match can be found, Detect Language is activated. You can also activate the Detected Language option by calling setPrimaryChatLanguage('und') API, where 'und' indicates undetermined or by passing either multiLangChat: {primary: null} or multiLangChat: {primary: 'und'}. You can update the chat language dynamically using the setPrimaryChatLanguage(lang) API even when the dropdown menu has not configured. For example:

Bots.setPrimaryChatLanguage('fr')

You can dynamically update the language irrespective of whether the chat language is initially configured or not.

Response narration and voice recognition, when configured, are available when users select a supported language. They are not available when the Detect Language option is set. Selecting a language that is not supported by voice recognition disables the recognition functionality until a supported language has been selected.

Multi-Lingual Chat Quick Reference

To do this... ...Do this
Display the language selection dropdown to end users. Pass multiLangChat.supportedLangs.
Set the chat language without displaying the select language selection dropdown menu to end users. Pass multiLangChat.primary.
Set a default language. Pass multiLangChat.primary with multiLangChat.supportedLangs. The primary value must be one of the supported languages included the array.
Enable language detection. Pass primary: null or primary: 'und' with multiLangChat.
Dynamically update the chat language. Call the setPrimaryChatLanguage(lang) API.

Text‑to‑Speech

You can enrich the conversational experience by enabling text-to-speech (TTS) to speak the responses as they reach the SDK. The SDK provides two types of TTS service out of the box: WebSDK.TTS.platform and WebSDK.TTS.oracle. By default, the SDK uses the Oracle Cloud Infrastructure (OCI) Speech service, to have the responses spoken in a more naturalistic tone. This service has several voices that you can select from to provide a more branded experience. However, you can instead use the platform-dependent TTS service, WebSDK.TTS.platform that's based on the Web Speech API. It uses the speech synthesis APIs on the user's device to speak the responses.

You use the ttsVoice array to configure the voice for the TTS. Each item in the array must be an object that has at least a lang field or a name field. The SDK looks up the availability of each voice in the order that they are passed in the setting. The first complete match is set as the voice. If no exact match is found, then the SDK uses the first match based on the lang value alone. If there's still no match, then the SDK uses the default voice.

const settings = {
    ...,
    enableBotAudioResponse: true,
    ttsVoice: [{
        lang: 'en-US',
        name: 'Samantha'
    }, {
        lang: 'en-US',
        name: 'Alex'
    }, {
        lang: 'en-UK'
    }]
}

To tailor the way the utterances are spoken, the ttsVoice array allows passing optional pitch, rate, and volume properties in each item. These properties correspond to the same fields in SpeechSynthesisUtterance interface.

const settings = {
    // ....,
    ttsVoice: [{
        lang: 'en-us',
        name: 'Alex',
        pitch: 1.5,
        rate: 2,
        volume: 0.8
    }, {
        lang: 'en-us',
        name: 'Victoria',
        pitch: 1.2,
        rate: 1.7,
    }, {
        lang: 'en',
        name: 'Fiona',
        pitch: 2,
    }, {
        lang: 'en'
    }]
}

Speech Synthesis Service Injection

Implement the SpeechSynthesisService interface and inject via settings or setTTSService(service):

const myTTS = {
  speak(phrase) {},
  cancel() {},
  getVoices() { return Promise.resolve([]) },
  setVoice(voices) { return Promise.resolve() },
  getVoice() { return null },
  on(event, listener) {},
  off(event, listener) {}
};

Bots.setTTSService(myTTS);

Voice Recognition

OCI Speech Integration

interface OCIAuthCredentials {
  compartmentId: string;
  region: string;
  token: string;
}
interface OCISpeechConfig {
  getOCIAuthCredentials(): Promise<OCIAuthCredentials>;
  useOCISpeech?: 'auto' | 'always' | 'never';
}

Example:

async function getOCIAuthCredentials() {
  const res = await fetch('<OCIAuthCredentialsEndpoint>');
  if (!res.ok) throw new Error(String(res.status));
  return res.json();
}

const ociSpeechConfig = {
  getOCIAuthCredentials,
  useOCISpeech: 'auto'
};

Timestamps

You can enable absolute or relative timestamps for chat messages. Absolute timestamps display the exact time for each message. Relative timestamps display only on the latest message and express the time in terms of the moments, minutes, hours, days, months, or years ago relative to the previous message.

The precision afforded by absolute timestamps makes them ideal for archival tasks, but within the limited context of a chat session, this precision detracts from the user experience because users must compare timestamps to find out the passage of time between messages. Relative timestamps allow users to track the conversation easily through terms like Just Now and A few moments ago that can be immediately understood. Relative timestamps improve the user experience in another way while also simplifying your development tasks: because relative timestamps mark the messages in terms of seconds, minutes, hours, days, months, or years ago, you don't need to convert them for time zones.

Cross‑Tab Conversation Synchronization

You may need to open the website in multiple tabs for various reasons. With enableTabsSync: true, you can synchronize and continue your conversation from any tab, as long as the connections parameters (i.e., URI, channelId, and userId) are the same across all tabs. This feature ensures that you can see messages from the skill on any tab and respond from the same tab or any other one.

Additionally, if you clear the conversation history in one tab, it is deleted from other tabs as well. If you update the chat language on one tab, it also gets synchronized on other tabs.

Limitations

End Conversation Session

This feature adds a close button to the chat header that allows user to end the current conversation session. Clicking the close button opens a confirmation prompt. On confirming the action, the SDK sends an event message to the skill to mark the current conversation session as ended. The instance then disconnects from the skill, collapses the chat widget, and erases the conversation history of the current user. It also raises a 'chatend' event that you can register for. Opening the chat widget afterward starts a new conversation session.

Default Client Responses

Use this flag to provide default client-side responses along with a typing indicator when the skill response has been delayed, or when there's no skill response at all. If the user sends out the first message/query, but the skill does not respond within the number of seconds set by defaultGreetingTimeout, the skill can display a greeting message that's configured using the defaultGreetingMessage translation string. Next, the client checks again for the skill response. The client displays the skill response if it has been received, but if it hasn't, then the client displays a wait message (configured with the defaultWaitMessage translation string) at intervals set by defaultWaitMessageInterval. When the wait for the skill response exceeds the threshold set by typingIndicatorTimeout, the client displays a sorry response to the user and stops the typing indicator. You can configure the sorry response using the defaultSorryMessage translation string.

Custom Message Rendering

This feature lets you override the default message rendering with your custom message template. To use this feature, you need to implement the render delegate function which takes the message model as the input and returns a boolean flag as the output. It must return true to replace the default rendering with your custom rendering for a particular message type. If false is returned, the default message is rendered instead.

Note: For custom rendering, all of the action click handling, and the disabling or enabling of action must be handled explicitly.

You can use any external framework component for your message rendering. Refer to the integration samples to check how you can use this feature with such frameworks like React, Angular and Oracle JavaScript Extension Toolkit (JET).

Live Agent Typing Indicator

This feature allows agents to ascertain if users are still engaged in the conversation by sending the user status to the live agent. When this flag is enabled, the SDK sends a RESPONDING status message with the text that is currently being typed by the user to Oracle Service Cloud. This, in turn, displays a typing indicator on the agent console. When the user has finished typing, the SDK sends a LISTENING status message to Oracle Service Cloud to hide the typing indicator on the agent console.

The typingStatusInterval configuration, which has a minimum value of three seconds, throttles the typing status update.

To send the agent both the text as it's being typed by the user and the typing status, enableAgentSneakPreview (which by default is false) must be set to true and Sneak Preview must be configured in Oracle Service Cloud. For more details refer to Sneak Preview documentation

Note: You do not have to configure live typing status on the user side. The user can see the live typing status of the agent by default. When the agent is typing, the SDK receives a RESPONDING status message which results in the display of a typing indicator in the user's view. Similarly, when the agent is idle, the SDK receives a LISTENING status message which hides the typing indicator.

Customization

Customizability is one of the biggest strengths of the Web SDK. In this section, we'll cover some of the various customization that can be performed on the SDK.

Add Avatar Icons to Messages

The messages in the chat are not accompanied by any avatars by default. You can, however, display icons with user and skill messages with the following parameters:

All of the above settings can only be passed in the initialization settings. They cannot be modified dynamically.

Card Cardinal Utterance for Card Messages

To identify the place of each card in a CRC cards message during a TTS utterance, the card translation string is used with its cardinal number before the content of each card. If the cards message contains a single card though, this identifier is skipped.

The default string used for the card translation key is 'Card {0}', where the placeholder {0} is replaced with its cardinal position. You can overwrite this translation with your own custom string. If you do not include the placeholder {0} in your custom string, it is added to the end of the string by default. You can localize the string by placing {0} before or after the word.

If you don't want this card identifier to be uttered, you can do so by passing an empty string to the card key.

i18n: {
    en: {
        card: '',           // Will prevent uttering 'Card 1', 'Card 2' before the card message content
    }
}

Change Header Buttons Icons

There are three buttons on the chat header that be displayed in the chat widget. These buttons can be configured and customized as follows:

These header button icons can be customized in two ways: through passing the source URL of the image, or through a raw SVG string. If a raw SVG string is passed, the fill color of the SVG can be customized by CSS classes, as well as by passing a color value in the colors.headerButtonFill property in the initial settings. The color customization may not work for all SVGs, as they can be multi-colored or have their own stroke and fill colors.

Draggable Launch Button and widget

Feature flag: enableDraggableButton: true (default: false)

Feature flag: enableDraggableWidget: true (default: false)

In some scenarios, the chat widget or the launch button can block the background content and there may not be an easy way to view it. This can be especially apparent in mobile screens where there is less space available for the web page. However, by setting enableDraggableButton or enableDraggableWidget to true, the chat widget or launch button can be made draggable, so the users can drag it around the screen as needed.

Feedback Message's Rating Gauge

The new feedback component enables users to rate their interactions with your skill. When users complete a conversation flow, the feedback message presents users with a star rating system, a row of stars (typically there are five stars, depending on the configuration of the System.Feedback component in the dialog flow). The stars are highlighted as users hover over them, which indicates that they have selected a rating.

You can change the icon for the component's rating selecting buttons by passing the icon of your choice in using the rating icon setting. For the best user experience, use a solid SVG string without a fill color, as it allows for a recognizable highlighting on hover.

new WebSDK({
    URI: '<Server URI>',
    //...,
    icons: {
        rating: '<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.994 3.006a5.7 5.7 0 00-3.795 1.707L12 4.916l-.199-.202a5.676 5.676 0 00-8.128 0c-2.231 2.275-2.231 5.953 0 8.228L12 21.428l8.326-8.486A5.873 5.873 0 0022 8.828a5.873 5.873 0 00-1.675-4.115A5.693 5.693 0 0016.262 3z"/></svg>'    // A heart icon
    }
})

The color of the icon in the two states, unselected and hovered/selected, can be configured with the ratingStar and ratingStarFill color fields in colors setting respectively.

new WebSDK({
    URI: '<Server URI>',
    //...,
    icons: {
        rating: '<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.994 3.006a5.7 5.7 0 00-3.795 1.707L12 4.916l-.199-.202a5.676 5.676 0 00-8.128 0c-2.231 2.275-2.231 5.953 0 8.228L12 21.428l8.326-8.486A5.873 5.873 0 0022 8.828a5.873 5.873 0 00-1.675-4.115A5.693 5.693 0 0016.262 3z"/></svg>'    // A heart icon
    },
    colors: {
        ratingStar: '#ffebee',
        ratingStarFill: '#d32f2f'
    }
})

Focus First Action of Response Message

Feature flag: focusOnNewMessage: 'action' (default: 'input')

With each new message, the chat widget normally sets the focus back to the user input field. This works well when the dialog flow expects a lot of textual input from the user. However, if the dialog flow contains a number of messages with actions, then the user needs to either use their mouse or reverse tab navigation to select one of the actions. For such use cases and for power users who prefer keyboard-based navigation, a better choice can be focusing the first action button in the skill message as it is received. By setting focusOnNewMessage: 'action', when a new skill message containing actions is received, the focus is set to the first action button. If the message does not contain any actions, the focus is set to the user input field.

Format Message Timestamps

Feature flag: timestampMode: 'relative' | 'absolute' (default: 'relative')

Functionality configuration: timestampFormat

Timestamps are shown with messages indicating the time they were sent or received. By default, they are displayed in the locale time in day of week, month date, year, time am/pm format (Thursday, August 13, 2020, 9:52:22 AM, for example). This timestamp can be configured by passing formatting options in the timestampFormat setting.

The formatting can be performed in two ways - by passing a pattern string consisting of formatting tokens, or by passing an object containing Intl.DateTimeFormat options.

Component Token Output
Day of Month D 1 2 ... 30 31
Do 1st 2nd ... 30th 31st
DD 01 02 ... 30 31
Day of Week d 0 1 ... 5 6
ddd Sun Mon ... Fri Sat
dddd Sunday Monday ... Friday Saturday
Month M 1 2 ... 11 12
MM 01 02 ... 11 12
MMM Jan Feb ... Nov Dec
MMMM January February ... November December
Year YY 70 71 ... 29 30
YYYY 1970 1971 ... 2029 2030
Hour H 0 1 ... 22 23
HH 00 01 ... 22 23
h 1 2 ... 11 12
hh 01 02 ... 11 12
Minute m 0 1 ... 58 59
mm 00 01 ... 58 59
Second s 0 1 ... 58 59
ss 00 01 ... 58 59
Fractional Second S 0 1 ... 8 9
SS 0 1 ... 98 99
SSS 0 1 ... 998 999
AM/PM A AM PM
a am pm
Timezone Z -07:00 -06:00 ... +06:00 +07:00
ZZ -0700 -0600 ... +0600 +0700

So, passing timestampFormat: 'hh:mm:ss a' would set timestamp as '09:30:14 pm'.

Note:

The tokens in the pattern string are case-sensitive: e.g., passing yyyy instead of YYYY would not display a year in the date.

The timestamp can also be formatted using the options defined for Intl.DateTimeFormat object. The object can be passed with some or all of the following properties:

Property Acceptable Values
dateStyle 'full', 'long', 'medium', 'short'
timeStyle 'full', 'long', 'medium', 'short'
weekday 'long' (e.g., Thursday), 'short' (e.g., Thu), 'narrow' (e.g., T)
day 'numeric' (e.g., 1), '2-digit' (e.g., 01)
month 'numeric' (e.g., 2), '2-digit' (e.g., 02), 'long' (e.g., March), 'short' (e.g., Mar), 'narrow' (e.g., M)
year 'numeric' (e.g., 2012), '2-digit' (e.g., 12)
era 'long' (e.g., Anno Domini), 'short' (e.g., AD), 'narrow' (e.g., A)
hour 'numeric', '2-digit'
minute 'numeric', '2-digit'
second 'numeric', '2-digit'
timeZoneName 'long' (e.g., British Summer Time), 'short' (e.g., GMT+1)
timeZone The time zone to use. The only value implementations must recognize is "UTC"; the default is the runtime's default time zone. Implementations may also recognize the time zone names of the IANA time zone database, such as "Asia/Shanghai", "Asia/Kolkata", "America/New_York".
hour12 Whether to use 12-hour time (as opposed to 24-hour time). Possible values are true and false

Custom handling: linkHandler: { onclick: <function>, target: '<string>' }

In the In-widget Webview : linkHandler: { target: 'oda-chat-webview' }

In new window: openLinksInNewWindow: true

The Web SDK provides various ways for you to control the target location of the URL links within the conversations. By default, clicking any link in the conversation opens the linked URL in the new tab. You can configure the widget to open it in a specific target using linkHandler setting.

The linkHandler setting expects an object that can take two optional fields - target and onclick. The target field accepts a string that identifies the location where the linked URL is to be displayed (a tab, window, or <iframe>). The following keywords have special meanings for where to load the URL:

settings = {
    ...,
    linkHandler: { target: '_blank'}
};

const Bots = new WebSDK(settings);

To open the links inside an iframe, you can pass its name attribute in the target property.

<iframe name="container" width="400" height="300"></iframe>

<script>
  settings = {
      ...
      linkHandler: { target: 'container'}
  }

  const Bots = new WebSDK(settings);
</script>

The onclick property of linkHandler allows you to add an event listener on all anchor links in the conversation. The listener is fired before the link is opened, and can be used to perform actions based on the link. The listener is passed an event object as parameter that is generated by the click action. You can prevent the link from being opened by returning false from the listener. The listener is also bound to the anchor element that is clicked, and the this context refers to the HTMLAnchorElement inside the listener.

linkHandler: {
    onclick: function(event) {
        console.log('The element clicked is', this);
        console.log('The event fired from the click is', event);
        console.log('The clicked link is', event.target.href);
        console.log('Preventing the link from being opened');
        return false;
    }
}

You can set either one or both properties of the linkHandler setting, but passing one of the fields is required.

In some scenarios, you may want to open links explicitly in a new window, overriding browser preferences. This can be achieved by passing openLinksInNewWindow: true in the settings.

Finally, the chat widget also provides an in-widget Webview that can be used to display linked URLs inside the widget. This helps in preventing the user from navigating away from the page to a new tab or window. See In-Widget Webview for more details on this feature.

Relative Timestamps

Feature flag: timestampMode: 'relative'

Timestamp color: colors.timestamp: 'color string'

The appearance of the message timestamps can be modified with the timestampMode setting. When set as 'relative', the timestamp is only shown before the first message of the day as a header, and for the new messages as an updating timestamp indicating the time passed since the message was added in the conversation. This relative timestamp is refreshed in the following intervals if no new message is added:

As soon as a new message is added to the conversation, the relative timestamp from the last message is removed and added to the new message. The timestamp is also updated to start afresh for the new message.

For older messages in the conversation, a timestamp header is shown indicating the date before the first message of the day, for all days a conversation is performed. The timestamp header format can be customized using the timestampFormat setting.

Restrict Attachment Types

Feature flag: enableAttachment: true (default: true)

Functionality configuration: shareMenuItems

Users can share various kinds of files and their location to the skills using the share menu from the chat widget. By default, the share attachment popup menu shows 4 items - sharing visual media files (i.e., images and videos, audio files, general files like documents, PDF, excel sheets, etc., and location). This menu can be customized to show fewer options using the shareMenuItems setting. This setting accepts an array of strings where each item maps to a menu item – 'visual' for Share Image/Video, 'audio' for Share Audio, 'file' for Share File, and 'location' for Share Location. The share menu only shows the items for passed values, so by passing fewer items, the share menu can be modified. For example, passing shareMenuItems: ['audio', 'location'] in the settings will only show the Share Audio and Share Location menu items in the share popup menu. However, passing an empty array, or invalid values will show all menu items. To show no items, the feature can be disabled by passing enableAttachment: false.

Custom Share Menu Items

You can configure the share menu items to set specific file types that users are allowed to upload. The custom menu item can be passed as an object to the shareMenuItems array. It can be passed along with the string categories, or can also be passed without them. A custom share menu item may look as follows:

{
    type: string,       // Space separated list of file formats, pass '*' to allow all supported file types

    label: string,      // OPTIONAL, label for the share menu item, should preferably be configured through i18n strings

    icon?: string,      // OPTIONAL, Icon image source path or SVG source string, the file icon is displayed as fallback

    maxSize?: number    // OPTIONAL, Maximum file size allowed for upload in KiloBytes, the maximum and fallback value is 25 MB (25600 KB)
}

The following code snippet shows passing custom menu items in settings and defining their labels using the i18n field.

const settings = {
    shareMenuItems: [ {
        type: 'odf',
        label: 'Upload ODF',
    }, {
        type: 'pdf'
    }, {
        type: 'jpg png jpeg',
        icon: 'https://image-source-site/imageicon'
    }, {
        type: 'doc docx xls',
        maxSize: 4096
    }],
    i18n: {
        en: {
            share_pdf: 'Upload PDF',
            share_jpg_png_jpeg: 'Upload Image',
            share_doc_docx_xls: 'Upload document'
        }
    }
}

As illustrated by the above snippet, the i18n labels for the custom menu items can be set by passing them with share_\<type joined by '_'\> keys. For the wildcard '*', the label can be set using the 'share_all' i18n key. Using i18n is recommended over the label as it allows supporting the menu item labels in multiple languages.

Using attachment functionality often requires updating the network security policy of the host site. The attachments are uploaded to ODA object storage using HTTP calls and may get blocked by the site's CORS policies. With the site blocking the uploads, an error can be seen in the browser console indicating that the client has blocked the request due to CORS policy. To fix such issues, the network security policy of the host site should be updated to whitelist the ODA domain, allowing the upload requests to go through. Since the CORS policy does not apply to WebSockets, the conversations between the SDK and ODA skills are not impacted by such restrictions.

When connecting to a client auth enabled channel on the ODA platform, you can optionally make attachments more secure by passing enableAttachmentSecurity: true. When set to true, extra headers are passed to the attachment upload requests to ensure that they can't be downloaded without passing a valid signed JWT token as the value of the token query parameter in the attachment fetch request URL.

Troubleshooting

Limitations

References

Full Colors Reference

You can modify the following colors to customize the look of the widget. The provided color must be a hexadecimal color. If you don't provide a color, then a default color is used instead. The colors can be configured using the CSS variables defined on the chat wrapper (.oda-chat-wrapper) or by passing the colors configuration. We recommend using CSS variables.

CSS Variable Color Config Key Description
--color-branding branding The primary color for branding the widget
--color-launch-icon-background launchIconBackground The background color of the launch icon
--color-text text The text color of the messages in the chat widget
--color-text-light textLight The text color of the secondary text in messages, like card descriptions
--color-header-background headerBackground The background color of the chat widget's header
--color-header-button-fill headerButtonFill The SVG fill color of buttons in the chat header
--color-header-text headerText The color of title in the chat header
--color-header-button-background-hover headerButtonBackgroundHover The background color of the header buttons on hover
--color-header-button-fill-hover headerButtonFillHover The fill color of the header buttons on hover
--color-conversation-background conversationBackground The background of the chat widget's conversation pane
--color-bot-message-background botMessageBackground The skill message background color
--color-bot-text botText The skill text color. Overrides the text color, if passed.
--color-user-message-background userMessageBackground The user message background color
--color-user-text userText The user text color. Overrides the text color, if passed.
--color-actions-background actionsBackground The action button background color
--color-actions-background-focus actionsBackgroundFocus The action button background color on focus
--color-actions-background-hover actionsBackgroundHover The action button background color on hover
--color-actions-border actionsBorder The action button border color
--color-actions-text actionsText The action button text color
--color-actions-text-focus actionsTextFocus The action button text color on focus
--color-actions-text-hover actionsTextHover The action button text color on hover
--color-global-actions-background globalActionsBackground The global action button background color
--color-global-actions-background-focus globalActionsBackgroundFocus The global action button background color on focus
--color-global-actions-background-hover globalActionsBackgroundHover The global action button background color on hover
--color-global-actions-border globalActionsBorder The global action button border color
--color-global-actions-text globalActionsText The global action button text color
--color-global-actions-text-focus globalActionsTextFocus The global action button text color on focus
--color-global-actions-text-hover globalActionsTextHover The global action button text color on hover
--color-primary-actions-background primaryActionsBackground The primary action button background color
--color-primary-actions-background-focus primaryActionsBackgroundFocus The primary action button background color on focus
--color-primary-actions-background-hover primaryActionsBackgroundHover The primary action button background color on hover
--color-primary-actions-border primaryActionsBorder The primary action button border color
--color-primary-actions-text primaryActionsText The primary action button text color
--color-primary-actions-text-focus primaryActionsTextFocus The primary action button text color on focus
--color-primary-actions-text-hover primaryActionsTextHover The primary action button text color on hover
--color-danger-actions-background dangerActionsBackground The danger action button background color
--color-danger-actions-background-focus dangerActionsBackgroundFocus The danger action button background color on focus
--color-danger-actions-background-hover dangerActionsBackgroundHover The danger action button background color on hover
--color-danger-actions-border dangerActionsBorder The danger action button border color
--color-danger-actions-text dangerActionsText The danger action button text color
--color-danger-actions-text-focus dangerActionsTextFocus The danger action button text color on focus
--color-danger-actions-text-hover dangerActionsTextHover The danger action button text color on hover
--color-card-background cardBackground The card message's background color
--color-card-nav-button cardNavButton The card navigation button background color
--color-card-nav-button-focus cardNavButtonFocus The card navigation button background color on focus
--color-card-nav-button-hover cardNavButtonHover The card navigation button background color on hover
--color-rating-star ratingStar The color applied to unselected rating stars of the feedback message
--color-rating-star-fill ratingStarFill The color applied to hovered or selected rating stars of feedback message
--color-links links The color of the links that are embedded in skill messages
--color-user-links userLinks The color of the links that are embedded in user messages
--color-horizontal-rule-background horizontalRuleBackground The color of the separator displayed at the end of the previous conversation
--color-timestamp timestamp The color of the timestamp header and the relative timestamp in messages
--color-agent-initials agentInitials The color of the agent initials that is displayed alongside the agent messages
--color-agent-avatar-background agentAvatarBackground The background color of the agent initials avatar that is displayed alongside the agent messages
--color-agent-name agentName The color of the agent name that is displayed above the agent messages
--color-typing-indicator typingIndicator The background fill color of the typing indicator
--color-footer-background footerBackground The background color of the chat widget's footer
--color-footer-button-fill footerButtonFill The SVG fill color of the buttons in chat footer
--color-footer-button-background-hover footerButtonBackgroundHover The background color of the footer buttons on hover
--color-footer-button-fill-hover footerButtonFillHover The SVG fill color of the footer buttons on hover
--color-input-background inputBackground The background color of the message input field
--color-input-border inputBorder The border color of the input field
--color-input-text inputText The text color in the message input field. Overrides text, if passed.
--color-recognition-view-text recognitionViewText The text color in the recognition text view that is displayed in voice mode. If it's absent, text color is used.
-- recognitionViewButtonFill The SVG fill color of the mode toggle color in voice mode
--color-visualizer-container-background visualizerContainerBackground The background color of the visualizer container displayed in voice mode. If absent, the user message background color is used.
--color-visualizer visualizer The color used in the bars of the visualizer graph. If it's absent, the branding color is used instead.
--color-notification-badge-background notificationBadgeBackground The background color of the message notification badge
--color-notification-badge-text notificationBadgeText The text color of message count in notification badge
--color-popup-background popupBackground The background color of prompts and popups
--color-popup-text popupText The text and icon color of prompts and popups
--color-popup-button-background popupButtonBackground The background color of popup buttons
--color-popup-button-text popupButtonText The text color of popup buttons
--color-popup-horizontal-rule popupHorizontalRule The horizontal rule color for separator for multi-lang chat menu action
--color-popup-item-background-hover popupItemBackgroundHover The background color on hover of popup list items
--color-table-header-background tableHeaderBackground The background color of table headers
--color-table-header-text tableHeaderText The text color of table headers
--color-table-background tableBackground The background color of tables
--color-table-text tableText The text color of tables
--color-table-separator tableSeparator The separator color of table rows
--color-table-row-background-hover tableRowBackgroundHover The background color of table rows on hover in table-form messages
--color-table-actions-background tableActionsBackground The background color of table actions
--color-table-actions-background-focus tableActionsBackgroundFocus The background color of table actions on focus
--color-table-actions-background-hover tableActionsBackgroundHover The background color of table actions on hover
--color-table-actions-border tableActionsBorder The border color of table actions
--color-table-actions-text tableActionsText The text color of table actions
--color-table-actions-text-focus tableActionsTextFocus The text color of table actions on focus
--color-table-actions-text-hover tableActionsTextHover The text color of table actions on hover
--color-form-header-background formHeaderBackground The background color of form titles
--color-form-header-text formHeaderText The text color of form titles
--color-form-background formBackground The background color of forms
--color-form-text formText The text color of forms
--color-form-input-background formInputBackground The background color of the input fields in Edit-Form messages
--color-form-input-border formInputBorder The border color of the input fields in Edit-Form messages
--color-form-input-border-focus formInputBorderFocus The border color of the input fields on focus in Edit-Form messages
--color-form-input-text formInputText The text color of the input fields in Edit-Form messages
--color-form-label formLabel The color of the form labels
--color-form-error formError The SVG fill color of the error message icon in Edit-Form messages
--color-form-error-text formErrorText The text color of field-level error message that is displayed in Edit-Form messages
--color-form-actions-background formActionsBackground The background color of form actions
--color-form-actions-background-focus formActionsBackgroundFocus The background color of form actions on focus
--color-form-actions-background-hover formActionsBackgroundHover The background color of form actions on hover
--color-form-actions-border formActionsBorder The border color of form actions
--color-form-actions-text formActionsText The text color of form actions
--color-form-actions-text-focus formActionsTextFocus The text color of form actions on focus
--color-form-actions-text-hover formActionsTextHover The text color of form actions on hover
--color-primary-form-actions-background primaryFormActionsBackground The background color of primary actions in Table, Form, Table-Form and Edit-Form messages
--color-primary-form-actions-background-focus primaryFormActionsBackgroundFocus The background color of primary actions on focus in Table, Form, Table-Form and Edit-Form messages
--color-primary-form-actions-background-hover primaryFormActionsBackgroundHover The background color of primary actions on hover in Table, Form, Table-Form and Edit-Form messages
--color-primary-form-actions-border primaryFormActionsBorder The border color of primary actions in Table, Form, Table-Form and Edit-Form messages
--color-primary-form-actions-text primaryFormActionsText The text color of primary actions in Table, Form, Table-Form and Edit-Form messages
--color-primary-form-actions-text-focus primaryFormActionsTextFocus The background color of primary actions on focus in Table, Form, Table-Form and Edit-Form messages
--color-primary-form-actions-text-hover primaryFormActionsTextHover The background color of primary actions on hover in Table, Form, Table-Form and Edit-Form messages
--color-danger-form-actions-background dangerFormActionsBackground The background color of danger actions in Table, Form, Table-Form and Edit-Form messages
--color-danger-form-actions-background-focus dangerFormActionsBackgroundFocus The background color of danger actions on focus in Table, Form, Table-Form and Edit-Form messages
--color-danger-form-actions-background-hover dangerFormActionsBackgroundHover The background color of danger actions on hover in Table, Form, Table-Form and Edit-Form messages
--color-danger-form-actions-border dangerFormActionsBorder The border color of danger actions in Table, Form, Table-Form and Edit-Form messages
--color-danger-form-actions-text dangerFormActionsText The text color of danger actions in Table, Form, Table-Form and Edit-Form messages
--color-danger-form-actions-text-focus dangerFormActionsTextFocus The text color of danger actions on focus in Table, Form, Table-Form and Edit-Form messages
--color-danger-form-actions-text-hover dangerFormActionsTextHover The text color of danger actions on hover in Table, Form, Table-Form and Edit-Form messages
--color-error-message-background errorMessageBackground The background color of form-level error message
--color-error-border errorBorder The border color of form-level error message
--color-error-title errorTitle The title color of a form-level error message
--color-error-text errorText The description color of an error message content.

Full Icons Reference

Property Name Description
avatarAgent The avatar icon displayed alongside responses from a live agent.
avatarBot The avatar icon displayed alongside responses.
avatarUser The avatar icon displayed alongside user messages.
fileAudio The icon in audio attachment messages for unreachable URL.
fileImage The icon in image attachment messages for unreachable URL.
fileGeneric The icon in file attachment messages.
fileVideo The icon in video attachment messages for unreachable URL.
clearHistory The icon for the chat header button to clear local conversation history.
close The icon for the close button in error message banners, expanded image previews, and the in-widget Webview.
collapse The icon for the chat header button to collapse the widget to launch button.
download The icon for the download file button in image attachment messages.
error The icon displayed alongside error messages like upload failure
expandImage The icon for the button to expand the image in attachment messages to full-screen
externalLink The icon to indicate external link.
keyboard The icon for chat footer button to switch to text input mode and stop voice recognition.
logo The logo icon displayed in the chat header.
launch The icon for the launch button displayed when the widget is collapsed.
mic The icon for the chat footer button to switch to voice input mode and initiate voice recognition.
rating The icon for the feedback rating actions. Preferable to pass a filled SVG string.
send The icon for the chat footer button to send messages.
shareMenu The icon for the share menu button in chat footer.
shareMenuAudio The icon for the audio menu item in the share menu popup.
shareMenuFile The icon for the file menu item in the share menu popup.
shareMenuLocation The icon for the location menu item in the share menu popup.
shareMenuVisual The icon for the image or video menu item in the share menu popup.
ttsOff The icon for the chat header button to toggle message audio response when on mute.
ttsOn The icon for the chat header button to toggle message audio response when audible.
typingIndicator The animated icon in conversation pane indicating response being generated.

Full Text (i18n) Keys Reference

Key Default Value Description
agent 'Agent' The text used for the Agent.
agentMessage '{0} says' The skill message indicator for screen readers. It is spoken by the screen readers before the skill responses. The text ({0}) is replaced by the agent name.
attachment_audio 'Audio attachment' The text used for the TTS utterance of an audio attachment.
attachment_file 'File attachment' The text used for the TTS utterance of a file attachment.
attachment_image 'Image attachment' The text used for the TTS utterance of an image attachment.
attachment_video 'Video attachment' The text used for the TTS utterance of a video attachment.
attachmentAudioFallback 'Your browser does not support embedded audio. However you can {0}download it{/0}.' The fallback message that is displayed in place of an audio attachment if the audio can not be rendered by the client. The text between {0} and {/0} is set to a link to download the file.
attachmentVideoFallback 'Your browser does not support embedded video. However you can {0}download it{/0}.' The fallback message that's displayed in place of a video attachment if the video can not be rendered by the client. The text between {0} and {/0} is set to a link to download the file.
audioResponseOff 'Turn audio response on' The tooltip that appears when hovering over the audio utterance on the button in the header.
audioResponseOn 'Turn audio response off' The tooltip that appears when hovering over the audio utterance off the button in the header.
avatarAgent 'Agent icon' The alternative text used for the agent icon that's displayed alongside the agent messages.
avatarBot 'Bot icon' The alternative text used for the skill icon that's displayed alongside the skill messages.
avatarUser 'User icon' The alternative text used for the user icon that's displayed alongside the user messages.
card 'Card {0}' The card identifier. The text ({0}) is replaced by the card index.
cardImagePlaceholder 'Card image' The text placeholder that's displayed while the card image is fetched and loaded.
cardNavNext 'Next card' The card navigation button label that displays the next card in horizontal layout.
cardNavPrevious 'Previous card' The card navigation button label that displays the previous card in horizontal layout.
chatButtonTitle The title of the chat widget launch button. The chatTitle string is used if this is not passed.
chatTitle 'Chat' Title of the chat widget that is displayed on the header.
chatSubtitle The subtitle of the chat widget that's displayed on the header below the title. If showConnectionStatus is set to true, and the subtitle is set as well, then the subtitle displays in place of the connection status.
clear 'Clear conversation' The tooltip that appears when hovering over the clear messages button in the header.
close 'Close widget' The tooltip that appears when hovering over the close widget button in the header.
closing 'Closing' The status text when the connection between the chat widget and the server is closing.
connected 'Connected' The status text when the connection between the chat widget and the server is established.
connecting 'Connecting' The status text when the connection between the chat widget and the server is connecting.
connectionFailureMessage 'Sorry, the assistant is unavailable right now. If the issue persists, contact your help desk.' The failure message that displays when the widget can't connect to skill.
connectionRetryLabel 'Try Again' The label of the retry connection button.
defaultGreetingMessage 'Hey, Nice to meet you! Allow me a moment to get back to you.' The default client greeting response that's displayed when the skill response has not been received within the number of seconds set by defaultGreetingTimeout.
defaultWaitMessage 'I\'m still working on your request. Thank you for your patience!' The default response that displays at the interval when an actual skill response has not been received. This interval is set, in seconds, by defaultWaitMessageInterval.
defaultSorryMessage: 'I\'m sorry. I can\'t get you the right content. Please try again.' The default client response when the skill response has not received within the number of seconds set by typingIndicatorTimeout.
disconnected 'Disconnected' The status text when the connection between the chat widget and the server is closed.
download 'Download' The tooltip that appears when hovering over the download button in attachments.
editFieldErrorMessage 'Field input is invalid' The field-level error message that is displayed in the Edit-Form messages when the value entered by the user is invalid for that field. SDK defaults to this message in-case clientErrorMessage is not supplied by the skill or browser validation errors are not present for input field.
editFormErrorMessage 'Some of the fields need your attention' The form-level error message that is displayed below the form submit action in Edit-Form messages on client-side validation. This is shown when at least one of the fields is not valid and there are more than one field. SDK defaults to this message in-case errorMessage is not supplied by the skill in the message payload.
endConversation 'End Conversation' The tooltip that appears when hovering over the end conversation header button.
endConversationConfirmMessage 'Are you sure you want to end the conversation?' The confirmation message that displays when a user clicks the end conversation button.
endConversationDescription 'This will also clear your conversation history.' The description message that displays along with the confirm message in the end conversation prompt.
errorSpeechInvalidUrl 'ODA URL for connection is not set. Please pass \'URI\' parameter during SDK initialization.' The error message that is displayed when the voice server URL is invalid or not set.
errorSpeechMultipleConnection 'Another voice recognition is ongoing. Can\'t start a new one.' The error message that's displayed when the user attempts a new voice message while another recognition is ongoing. This usually happens when multiple voice connections are attempted in a short interval by repeatedly toggling between keyboard and voice mode.
errorSpeechNoResponse 'Speech recognition is taking too long. Please try again.' The message displayed when speech recognition times out (after 10 seconds).
errorSpeechStartRecognition 'Unable to start recognition. Please try again.' The message displayed when recognition start fails because of either a network or backend failure.
errorSpeechTooMuchTimeout 'The voice message is too long to recognize and generate text.' The error message that's displayed when the user provides a voice message that can't be recognized because it's too long.
errorSpeechUnavailable 'To allow voice messaging, update your browser settings to enable access to your microphone.' The error message that's displayed when the browser does not provide any API to access the microphone.
errorSpeechUnsupportedLocale 'The locale set for voice recognition is not supported. Please use a valid locale in \'speechLocale\' setting.' The error message that's displayed when an unsupported speech locale is configured for voice recognition and a recording is attempted.
inputPlaceholder 'Type a message' The placeholder text that appears in the user input field in keyboard mode.
imageViewerClose 'Close image viewer' Accessibility text for the button that closes the expanded image.
imageViewerOpen 'Open image viewer' Accessibility text for the button that expands the image.
itemIterator 'Item {0}' Item identifier in a list of items in a message like Table, Form, or Table-Form message. The placeholder {0} is replaced by the item index.
noResultText 'No more results' The status text that's displayed when there are no matches while doing a search in multi select dropdown list.
noSpeechTimeout 'The voice could not be detected to perform recognition.' The status text that's displayed when the server is unable to recognize the voice.
languageSelectDropdown 'Select chat language' The tooltip that appears when users hover over the language selection button in the header.
language_detect 'Detect Language' The label for auto-detect option in language selection dropdown.
language_<languageTag> Language Label The label for the language represented by the languageTag. For example, 'English' for 'en' in the language selection dropdown available when Multi-Lingual Chat is configured.
linkField 'Click on the highlighted text to open Link for {0}' The replacement utterance text for a link Field. The placeholder {0} is replaced with the linkLabel of the field.
noText 'No' The label for the No confirmation button.
oldLinkAdvisory 'Please note that the content of this link may have been updated since it was originally shared.' The label for advisory tooltip for links in messages from older conversations.
openMap 'Open Map' The label of the action button to open a location map.
previousChats 'End of previous conversation' The status text that's displayed at the end of older messages.
ratingStar 'Rate {0} star' The tooltip text that's displayed for each rating star in a feedback message. The placeholder {0} is replaced by the number of stars that the user has selected.
recognitionTextPlaceholder 'Speak your message' Placeholder text that appears in the recognition text field in voice mode.
requestLocation 'Requesting location' Text that is displayed while user location is requested on the browser.
requestLocationDeniedPermission 'To allow sharing your location, update your browser settings to enable access to your location. You can also type in the location instead.' The error message that's displayed when permission to access the location is denied.
requestLocationDeniedTimeout 'It is taking too long to get your location. Please try sharing it again, or else type it in.' The error message that's displayed when the location request is not resolved due to a timeout.
requestLocationDeniedUnavailable 'Your current location is unavailable. Please try sharing it again, or else type it in.' The error message that is displayed when the location request is denied due to the unavailability of the current location in the client's device.
retryMessage 'Try again' Text that is displayed when a user message is not sent to the server.
send 'Send message' Tooltip that appears when hovering over send button in the footer.
shareAudio 'Share Audio' The menu item text for sharing an audio file in the share popup.
shareFile 'Share File' The menu item text for sharing a generic file in the share popup.
shareLocation 'Share Location' The menu item text for sharing a location in the share popup.
shareVisual 'Share Image/Video' The menu item text for sharing an image or video file in the share popup.
shareFailureMessage 'Sorry, sharing is not available on this device.' The error message that's shown when a user clicks on a share action button and the share API is not supported by the device.
skillMessage 'Skill says' The skill message indicator for screen readers. It is spoken by the screen readers before the skill responses.
showOptions 'Show Options' The tooltip that appears when users hover over the menu button in the header when the header actions are collapsed.
speak 'Say your request' The tooltip that appears when hovering over speak button in the footer.
relTimeNow 'Now' The relative timestamp that's shown right after a new message
relTimeMoment 'A few seconds ago' The relative timestamp that displays ten seconds after the message has been received and before 60 seconds has elapsed since the last message was received.
relTimeMin '{0}min ago' The relative timestamp that's shown for every minute since the last message. The placeholder {0} is replaced by the number of minutes passed.
relTimeHr '{0}hr ago' The relative timestamp shown for each hour since the last message. The placeholder {0} is replaced by the number of hours passed.
relTimeDay '{0}d ago' The relative timestamp that's shown each day since the last message. The placeholder {0} is replaced by the number of days passed.
relTimeMon '{0}mth ago' The relative timestamp shown for each month since the last message. The placeholder {0} is replaced by the number of months passed.
relTimeYr '{0}yr ago' The relative timestamp shown for every year since the last message. The placeholder {0} is replaced by the number of years passed.
typingIndicator 'Waiting for response' The accessibility text for the typing indicator. It is spoken by the screen readers.
upload 'Share popup' The tooltip that appears when hovering over the upload share popup button in the footer.
uploadFailed 'Upload Failed.' The error text for an upload failure.
uploadFileNetworkFailure 'Upload not completed due to network failure.' The error text that's displayed when the upload file does not complete due to network failure.
uploadFileSizeLimitExceeded 'File size should not be more than {0}MB.' The error text that's displayed when the upload file size is too large. The placeholder {0} is replaced by the SDK to the maximum allowed file size, which defaults to 25MB.
uploadFileSizeZeroByte 'Files of size zero bytes can\'t be uploaded.' The error text that's displayed when the upload file size is 0 bytes.
uploadUnauthorized 'Upload request is unauthorized.' The error text that's displayed when the upload request is unauthorized.
uploadUnsupportedFileType 'Unsupported file type.' The error text that's displayed when an unsupported file type upload is attempted.
userMessage 'I say' The user message indicator for screen readers. It is spoken by the screen readers before the user messages.
utteranceGeneric 'Message from skill.' The fallback description of a response message for an utterance that was not parsed by the SDK.
webViewAccessibilityTitle 'In-widget Webview to display links' The default accessibility title for the Webview that is read out by screen readers
webViewClose 'Done' The default label/tooltip title for Webview close button
webViewErrorInfoDismiss 'Dismiss' The tooltip for the dismiss button that's used to close the fallback link inside the webview.
webViewErrorInfoText 'Don't see the page? {0}Click here{/0} to open it in a browser.' The informational text displayed in the webview when the clicked link can't be opened within it. The text between {0} and {/0} is set to the original link that opens in a new tab or window.
yesText 'Yes' The label for the Yes confirmation button.

Full Hotkeys Element Map

The following table lists the keys and the corresponding elements against which you can pass the hotkey attribute. The attribute value is not case-sensitive.

Key Element
clearHistory The button that clears the conversation history.
close The button that closes the chat widget and ends conversation.
collapse The button that collapses the expanded chat widget.
input The text input field on the chat footer.
keyboard The button that switches the input mode from voice to text.
language The select menu that shows the language selection list.
launch The chat widget launch button.
mic The button that switches the input mode from text to voice.
send The button that sends the input text to the skill.
shareMenu The share menu button in the chat footer.
shareMenuAudio The menu item in the share menu popup that selects an audio file for sharing.
shareMenuFile The menu item in the share menu popup that selects a generic file for sharing.
shareMenuLocation The menu item in the share menu popup that selects user location for sharing.
shareMenuVisual The menu item in the share menu popup that selects an image or video file for sharing.

Full CSS Class Hooks

Class Component
oda-chat-wrapper The wrapper for entire chat widget
oda-chat-button The chat widget launcher button
oda-chat-notification-badge An message notification badge yet unseen
oda-chat-widget The expanded chat widget; wraps the widget header, conversation, and footer
oda-chat-header The chat widget header
oda-chat-logo The logo on the widget header
oda-chat-title The title on the widget header
oda-chat-connection-status The connection status. Each connection value has its own class as well - oda-chat-connected, oda-chat-disconnected, etc.
oda-chat-connected Applied as a sibling to connection-status when the widget is connected to server
oda-chat-connecting Applied as a sibling to connection-status when the widget is connecting to server
oda-chat-disconnected Applied as a sibling to connection-status when the widget is disconnected from server
oda-chat-closing Applied as a sibling to connection-status when the widget is disconnecting from server
oda-chat-header-button A common class for all header buttons
oda-chat-button-clear The clear messages button
oda-chat-button-narration The skill audio response toggle button
oda-chat-button-close The close widget button
oda-chat-conversation The container for the conversation
oda-chat-message A common wrapper class for all chat messages
oda-chat-left The skill message wrapper
oda-chat-right The user message wrapper
oda-chat-icon-wrapper The skill/person icon wrapper displayed alongside message
oda-chat-message-icon The skill/person icon image displayed alongside message
oda-chat-message-bubble The message bubble
oda-chat-message-actions The action buttons wrapper
oda-chat-message-global-actions The global action buttons wrapper
oda-chat-rating-star The rating star button in a feedback message
oda-chat-rating-star-icon The SVG icon for the rating star button
oda-chat-action-postback The postback action button
oda-chat-action-location The location request action button
oda-chat-card The card message
oda-chat-footer The chat widget footer
oda-chat-footer-button The common class for all footer buttons
oda-chat-button-upload The upload file button
oda-chat-button-send The send message button
oda-chat-user-input the user input text area

Conversation Message Model Reference

To use features like headless mode and delegate, a clear understanding of skill and user messages is essential. Everything received from and sent to the chat server are represented as messages. This includes:

The following section describes each of the message types in more detail.

Base Types

These are the base types that are used by user-to-skill messages and skill-to-user messages. They are the building blocks for the messages.

Action

An action represents something that the user can select. Every action includes the following properties:

Name Description Type Required?
type The action type 'call', 'client', 'location', 'popup', 'postback', 'share', 'submitForm', 'url' Yes
label The descriptive label text for the action. string At least a single label or imageUrl property must be present
imageUrl Image to display for the action string At least a single label or imageUrl property must be present.
style The rendering style of the button "primary", "danger", "default" No
displayType The rendering for the type of action element (button, link, or icon). "button", "link", "icon" No
voice Content to be used for voice description of the action Voice No
tooltip The tooltip displayed when hovering over the action button string No
channelExtensions The channel-specific extension properties associated with the action JSONObject No
CallAction

This action will request the client to call a specified phone number on the user's behalf. It adds the following properties to the Action properties:

Name Description Type Required?
type The action type "call" Yes
phoneNumber The phone number to call string Yes

Example JSON

{
    "type": "call",
    "label": "Call Support",
    "imageUrl": "http://ahoraescuando.bluefm.com.ar/files/2016/05/cuidado.jpg",
    "phoneNumber": "18002231711"
}
ClientAction

This action performs an action on the client app when activated by the user. It adds the following properties to the Action properties:

Name Description Type Required?
type The action type "client" Yes
actionType The type of client action 'custom', 'copyMessageText', 'navigate', 'query', 'updateFields' Yes
context The application context string No
customAction Set when actionType is 'custom' string No
properties Key-value pairs that can be used as arguments when executing the action JSONObject No
LocationAction

This action will request the client to ask the user for a location. It adds the following properties to the Action properties:

Name Description Type Required?
type The action type "location" Yes
PopupAction

This action will request the client to ask the user for a location. It adds the following properties to the Action properties:

Name Description Type Required?
type The action type "popup" Yes
popupContent The CMM message type that should be displayed inside the dialog window MessagePayload Yes
{
    "type": "popup",
    "label": "Give Feedback",
    "popupContent": {
        "formRows": [
            {
                "columns": [
                    {
                        "width": "stretch",
                        "fields": [
                            {
                                "displayType": "text",
                                "label": "What was the issue with this response?"
                            },
                            {
                                "displayType": "multiSelect",
                                "options": [
                                    {
                                        "label": "Inaccurate",
                                        "value": "inaccurate"
                                    },
                                    {
                                        "label": "Inappropriate",
                                        "value": "inappropriate"
                                    }
                                ],
                                "id": "system_feedback_reasons",
                                "required": true
                            },
                            {
                                "displayType": "textInput",
                                "id": "system_feedback_comments",
                                "placeholder": "Additional feedback"
                            }
                        ]
                    }
                ]
            },
            {
                "columns": [
                    {
                        "fields": [
                            {
                                "displayType": "action",
                                "action": {
                                    "postback": {
                                        "rating": "negative",
                                        "action": "cancel",
                                    },
                                    "label": "Cancel",
                                    "type": "postback"
                                },
                            }
                        ]
                    },
                    {
                        "fields": [
                            {
                                "displayType": "action",
                                "action": {
                                    "postback": {
                                        "rating": "negative",
                                        "system.state": "invokeLLM"
                                    },
                                    "label": "Submit Feedback",
                                    "type": "submitForm"
                                },
                            }
                        ]
                    }
                ]
            }
        ],
        "type": "editForm",
        "title": "Give your feedback",
        "formColumns": 1,
    }
}
PostbackAction

This action will send a predefined postback back to the skill if the user selects the action. It adds the following properties to the Action properties:

Name Description Type Required?
type The action type "postback" Yes
postback The postback to be sent back if the action is selected string or JSONObject Yes

Example JSON

{
    "type": "postback",
    "label": "Large Pizza",
    "imageUrl": "https://amicis.com/images/gallery/locations/11.jpg",
    "postback": {
        "state": "askSize",
        "action": "getCrust"
    }
}
ShareAction

This action will request the client to open a sharing dialog for the user. It adds the following properties to the Action properties:

Name Description Type Required?
type The action type "share" Yes
SubmitFormAction

This action is used to submit an Editable Form to the skill in case the form passes the client side validation. It adds the following properties to the Action properties:

Name Description Type Required?
type The action type "submitForm" Yes
postback The postback payload, which might include an action property to trigger navigation. The value of this property should be set in the FormSubmissionMessagePayload JSONObject No

Example JSON

{
    "type": "submitForm",
    "label": "Submit",
    "postback": {
        "system.botId": "6803DE12-DAA9-4182-BD54-3B4D431554F4",
        "system.flow": "ExpenseFlow",
        "system.state": "editFormMapVar"
    }
}
UrlAction

This action will request the client to open a website in a new tab or in an in-app browser. It adds the following properties to the Action properties:

Name Description Type Required?
type The action type "url" Yes
url The URL of the website to display string Yes

Example JSON

{
    "type": "location",
    "label": "Share location",
    "imageUrl": "http://images.clipartpanda.com/location-clipart-location-pin-clipart-1.jpg"
}

Attachment

This represents an attachment that's sent from the user to the skill or from the skill to the user.

Name Description Type Required?
type The type of attachment "audio", "file", "image", "video" Yes
url The URL to download the attachment string Yes
title A title for the attachment string No

Example JSON

{
    "title": "Oracle Open World Promotion",
    "type": "image",
    "URL": "https://www.oracle.com/us/assets/hp07-oow17-promo-02-3737849.jpg"
}

Card

A card represents a single card in the message payload. It contains the following properties:

Name Description Type Required?
title The title of the card, displayed as the first line on the card. string Yes
description The description of the card string No
imageUrl URL of the image that is displayed string No
URL URL of a website that is opened when taping on the card string No
actions An array of actions related to the text Array<Action> No
voice Content to be used for voice description of the card Voice No
channelExtensions The channel-specific extension properties associated with the card JSONObject No

Location

This represents a Location object.

Name Description Type Required?
latitude The GPS coordinate's longitude value double Yes
longitude The GPS coordinate's longitude value double Yes
title A title for the location string No
url A URL for displaying a map of the location string No

Example JSON

{
    "title": "Oracle Headquarters",
    "url": "https://www.google.com.au/maps/place/37°31'47.3%22N+122°15'57.6%22W",
    "longitude": -122.265987,
    "latitude": 37.529818
}

Voice

This represents a voice information in a message.

Name Description Type Required?
text Summary text for TTS string At least one of the properties must be passed
longText Detailed text for TTS string At least one of the properties must be passed
soundUrl URL of a sound file to play string At least one of the properties must be passed

Field

This represents the atomic information of a table cell or a form field in Table, Form, Table-Form, Edit Form object, provided as key-value pair. The fields can be of two types: ReadOnlyField and EditableField.

Name Description Type Required?
displayType The field type "link", "text", "datePicker", "multiSelect", "numberInput", "singleSelect", "textInput", "timePicker", "toggle", "action", "media" Yes
label Key of the field string No
marginTop The amount of vertical space between this field and the previous field in the same column "none", "medium", "large" No
labelFontSize The font size used for the field label 'extraSmall', "small", "medium", "large" No
labelFontWeight The font weight used for the field label "light", "medium", 'semiBold', "bold" No
channelExtensions The channel-specific extension properties associated with the field JSONObject No

Read Only Field

This represents a read only field. All read only fields inherit the generic field properties and have the following additional properties:

Name Description Type Required?
alignment The positioning of the label within its cell. "center", "left", "right" No
value The field value unknown No
width The suggested percentage of the total available width that the field should occupy in a table layout. number No
Action Field

The media field inherits all read only field properties and has following additional properties:

Name Description Type Required?
displayType The field type "action" Yes
action The action that should be performed when the user clicks the action button. Action Yes

The link field inherits all read only field properties and has following additional properties:

Name Description Type Required?
displayType The field type "link" Yes
linkLabel The label used for the hyperlink string No
imageUrl The URL of the image that opens a link when clicked. string No
Media Field

The media field inherits all read only field properties and has following additional properties:

Name Description Type Required?
displayType The field type "media" Yes
mediaType The field media type. "audio", "image", "video" Yes
Text Field

The text field inherits all read only field properties and has following additional properties:

Name Description Type Required?
displayType The field type "text" Yes
fontSize The font size used for the field value "small", "medium", "large" No
fontWeight The font weight used for the field value "medium", "bold", "light" No
truncateAt The position at which lengthy text gets truncated and an ellipsis mark (which indicates the value has been truncated) displays. number No

Note: If both linkLabel and imageUrl are present, image will be displayed that opens a link when clicked.

Editable Field

This represents an editable field. All editable fields inherit the generic field properties and have the following additional properties:

Name Description Type Required?
id The ID of the field string Yes
autoSubmit When set to true, the form is partially submitted when the user has entered a value for the field. See Auto-Submit for more details. boolean No
clientErrorMessage The field level error message that's displayed below the field when a client-side validation error occurs. If not provided, SDK defaults to editFieldErrorMessage string No
defaultValue The default value for the corresponding field unknown No
placeholder A description of the input that's expected from the user. This text displays when the user has not yet made a selection or entered a value. string No
required Whether this input is required boolean No
serverErrorMessage The field level error message that's displayed below the field when a server-side validation error occurs. This error message must be included in the payload sent by the skill. string No
DatePicker

The date picker field inherits all editable field properties and has the following additional properties:

Name Description Type Required?
displayType The field type "datePicker" Yes
defaultValue The initial value for this field, format must be YYYY-MM-DD string No
minDate The minimum, or earliest, date allowed. The format must be YYYY-MM-DD. string No
maxDate The maximum, or latest, date allowed. The format must be YYYY-MM-DD. string No
MultiSelect

The multi select field inherits all editable field properties and has the following additional properties:

Name Description Type Required?
displayType The field type "multiSelect" Yes
options An array of options presented to the user. Array<SelectFieldOption> Yes
defaultValue The default selection Array<object> primitive data types (could be a string, number, boolean, etc.) No
layoutDirection The layout direction to use for the radio buttons when layoutStyle is set to radioGroup. The default direction is "vertical". "horizontal", "vertical" No
layoutStyle The layout style used to render the multi select options. The default layout is list. "list", "checkboxes" No
NumberInput

The number input field inherits all editable field properties and has the following additional properties:

Name Description Type Required?
displayType The field type "numberInput" Yes
defaultValue The initial value for this field number No
minValue A smallest allowable number number No
maxValue A largest allowable number number No
SingleSelect

The single select field inherits all editable field properties and has the following additional properties:

Name Description Type Required?
displayType The field type "singleSelect" Yes
options An array of options presented to the user. Array<SelectFieldOption> Yes
defaultValue The default selection Primitive data types (string, number, boolean, etc.) No
layoutDirection The layout direction to use for the radio buttons when layoutStyle is set to radioGroup. The default direction is "vertical". "horizontal", "vertical" No
layoutStyle The layout style used to render the single select options. The default layout is list. "list", "radioGroup" No
TextInput

The text input field inherits all editable field properties and has the following additional properties:

Name Description Type Required?
displayType The field type "textInput" Yes
defaultValue The initial value for this field string No
inputStyle The input style that should be rendered. Falls back to text when not specified. Allowable values are: "text", "tel", "url", "email" and "password" string No
maxLength The maximum number of characters allowed in the text input field number No
minLength The minimum length of input that the user must provide number No
multiline The flag that determines whether to render multiple lines of input boolean No
validationRegularExpression A regular expression indicating the required format for this text input. string No
TimePicker

The time picker field inherits all editable field properties and has the following additional properties:

Name Description Type Required?
displayType The field type "timePicker" Yes
defaultValue The initial value for this field, format must be HH:mm in 24H format string No
minTime The minimum, or earliest, time allowed, entered as HH:mm in 24-hour format. For example, 00:00. string No
maxTime The maximum, or latest, time allowed, entered as HH:mm in 24-hour format. For example, 00:00. string No
Toggle

The toggle field inherits all editable field properties and has the following additional properties:

Name Description Type Required?
displayType The field type "toggle" Yes
valueOff The value when toggle is off string Yes
valueOn The value when toggle is on string Yes
defaultValue The initial selected value. If you want the toggle to be initially on, set this to the value of valueOn's value. string No
labelOff The label that is displayed when the toggle field is hovered in the off state string No
labelOn The label that is displayed when the toggle field is hovered in the on state string No

SelectFieldOption

The SingleSelect and MultiSelect fields use a list of select options with following properties:

Name Description Type Required?
label The display text string Yes
value The raw value for the choice Primitive data types (string, number, boolean, etc.) Yes
channelExtensions The channel-specific extension properties associated with the field option JSONObject No

TableHeading

This represents a heading for tables in a Table or Table-Form object.

Name Description Type Required?
label The label for the heading string Yes
alignment Positioning of the label within its cell "center", "left", "right" Yes
width Suggested percentage of table width that should be provided to the heading string No
channelExtensions The channel-specific extension properties associated with the heading JSONObject No

TableRow

This represents an array of fields.

Name Description Type Required?
fields Array of read-only fields Array<Field> Yes
selectAction The action that is executed when the row is selected. The label of the action is shown as a tooltip when users hover over the row. Action No
channelExtensions The channel-specific extension properties associated with the row JSONObject No

Form

This represents an array of fields or form rows along with a title. Used in Table-Form messages for nested forms of a table row.

Name Description Type Required?
fields Array of fields Array<Field> Yes
id The ID of the form string No
title A representative title for the form in the table row string No
formRows A list of rows displayed in the form. You can define either the list of fields using the fields property, or a list of rows using this property. The fields and formRows properties are mutually exclusive. Array<FormRow> No
selectAction The action that is executed when the form is selected. The label of the action is shown as a tooltip when users hover over the form. Action No
actions A list of actions displayed at the bottom of the form Array<Action> No
separator Whether to display a separator for the form or not. If this value is not passed, then a separator displays for the form. boolean No
channelExtensions The channel-specific extension properties associated with the form JSONObject No

FormRow

A form row contains a list of columns that are laid out side-by-side. Multiple form rows are laid out vertically with each form row starting on a new line below the previous form row.

Name Description Type Required?
columns A list of columns displayed in the form row. Array<FormColumn> Yes
type Indicates when the form row is a header or a data row. 'header', 'dataRow' No
id The ID of the form row string No
selectAction The action that is executed when the form row is selected. The label of the action is shown as a tooltip when users hover over the form row. Action No
separator When set to true, a separator line is added above the form row content. boolean No
channelExtensions The channel-specific extension properties associated with the form row JSONObject No

FormColumn

A column contains a list of fields. These fields are laid out vertically.

Name Description Type Required?
fields A list of fields displayed vertically in the column. The fields must be read only fields when the column is used in a FormRow within a Form message Payload. The fields can include both editable and read only fields when the FormRow is used within an EditFormMessagePayload. Array<Field> Yes
id The ID of the column string No
verticalAlignment The vertical alignment of the column with respect to other columns in the same form row "bottom", "center", "top" No
width Determines how the width of the column is determined within the form row. "auto", "stretch", 'fixed' No
widthPct Passed when width is set to fixed. Sets the width property on the column element to the passed in percentage value. number No
channelExtensions The channel-specific extension properties associated with the column JSONObject No

PaginationInfo

This represents the paging information of results in a Table, Form, and Table-Form object.

Name Description Type Required?
totalCount Total count of results number Yes
rangeSize Range size of results per page number Yes
status Paging status message string Yes
currentRangeSize Size of current range of results number Yes
rangeStart Starting offset of the current range of results number Yes
nextRangeSize Size of the next range of results number Yes
hasPrevious Indicates whether there is a previous set of results boolean Yes
hasNext Indicates whether there is next set of results boolean Yes

EventContextProperties

The Event Context Properties represent the CloudEvent context properties.

Name Description Type Required? Example
dataschema Identifies the schema that the data adheres to. URI No "/dw/approval_payload.json"
datacontenttype The content type of the data contained in the data attribute. string No "application/json"
source The resource that produced the event. URI No "objectstorage"
time The time of the event expressed in RFC 3339 timestamp format. Timestamp No "2021-01-10T21:19:24Z"
specversion The version of the CloudEvents specification string No "1.0"
id The ID of the CloudEvents specification string No "123e4567-e89b-12d3-a456-426614174000"
subject The event's subject in the context of the event producer and/or event type. string No "mynewfile.jpg"
requesttype Determines how the runtime executes the event handler flows. Defaults to 'interrupt' if the value is missing. "interrupt", "join", "notification", "reset", "sync" No "interrupt"

Conversation Messages

All messages that are part of the conversation are structured as follows:

Name Description Type Required?
messagePayload Message payload Message Payload Yes
userId User ID string Yes

Example conversation message

{
    "messagePayload": {
        "text": "show menu",
        "type": "text"
    },
    "userId": "guest"
}

Message Payload

Message is the abstract base type for all other messages. All messages extend it to provide more information.

Name Description Type Required?
type The message type string Yes

User Message Payload

This represents a Message sent from a user to a skill.

User Text Message Payload

This is a simple text message sent to the server. It applies the following properties to the Message Payload:

Name Description Type Required?
type The message type "text" Yes
text Text message string Yes
{
    "messagePayload": {
        "text": "Order Pizza",
        "type": "text"
    },
    "userId": "guest"
}

User Attachment Message Payload

This is the attachment response message sent to the server. It applies the following properties to the Message Payload:

Name Description Type Required?
type The message type "attachment" Yes
attachment Attachment metadata Attachment Yes
{
    "messagePayload": {
        "attachment": {
            "type": "image",
            "URL": "http://oda-instance.com/attachment/v1/attachments/d43fd051-02cf-4c62-a422-313979eb9d55"
        },
        "type": "attachment"
    },
    "userId": "guest"
}

User Location Message Payload

This is the location response message sent to the server. It applies the following properties to the Message Payload:

Name Description Type Required?
type The message type "location" Yes
location User location information Location Yes
{
    "messagePayload": {
        "location": {
            "latitude": 45.9285271,
            "longitude": 132.6101925
        },
        "type": "location"
    },
    "userId": "guest"
}

User Postback Message Payload

This is the postback response message sent to the server. It applies the following properties to the Message Payload:

Name Description Type Required?
type The message type "postback" Yes
postback The postback of the selected action string or JSONObject Yes
text Text for postback string No
{
    "messagePayload": {
        "postback": {
            "variables": {
                "pizza": "Small"
            },
            "system.botId": "69F2D6BB-35BF-4BCA-99A0-A88D44A51B35",
            "system.state": "orderPizza"
        },
        "text": "Small",
        "type": "postback"
    },
    "userId": "guest"
}

User InboundEvent Message Payload

This represents the inbound event messages that can be sent to the server. It applies the following properties to the Message Payload

Name Description Type Required?
type The message type "inboundEvent" Yes
eventData The business data JSONObject Yes
eventType The event type (defined in the event catalog) string Yes
eventVersion The event type version (defined in the event catalog) string Yes
contextProperties The event context properties EventContextProperties No

Here's an example:

{
    "messagePayload": {
        "eventData": {
            "size": "Medium",
            "type": "Cheese"
        },
        "eventVersion": "1.0",
        "eventType": "com.pizzastore.pizza.orderserved",
        "type": "inboundEvent",
        "contextProperties": {
            "id": "6ce23f09-bff7-4369-8467-0c510e971aaf",
            "source": "pizza/service",
        }
    },
    "userId": "guest"
}

User Form Submission Message Payload

This represents the form submission message that's sent after the user has submitted a form by clicking SubmitFormAction. It has the following properties:

Name Description Type Required?
type The message type "formSubmission" Yes
submittedFields Key-value pairs of the submitted field values. The key is the name (ID) of the field. JSONObject Yes
partialSubmitField The ID of the field that triggers a partial form submission. Fields with the autoSubmit property set to true can trigger a partial form submission. See Auto-Submit for more details. string No
postback The postback payload, which might include an action property to trigger navigation. The value of this property should be taken from the SubmitFormAction JSONObject No

Here's an example:

{
    "messagePayload": {
        "submittedFields": {
            "Attendees": [
                "Toff van Alphen"
            ],
            "Type": "Public transport",
            "Description": "expense",
            "Subject": "Expense",
            "Date": "2023-06-07",
            "Time": "18:58",
            "Amount": 6,
            "TipIncluded": "true"
        },
        "partialSubmitField": "Attendees",
        "type": "formSubmission"
    },
    "userId": "guest"
}

Response Message Payload

This represents a Message Payload sent from a skill or an agent to the user. It applies the following properties to the MessagePayload:

Name Description Type Required?
type The message type string Yes
headerText The header text displayed above the message text string No
footerText The footer text displayed below the message text and actions, but before the global actions string No
actions A list of actions related to the message Array<Action> No
footerForm A form layout that displays below the footer text of the message and above its global actions. Form No
globalActions A list of global actions related to the text Array<Action> No
embeddedActions List of actions that can be triggered by a special HTML <span> tag in the message text Array<Client Action> No
llmGenerated Indicates whether the content is LLM-generated boolean No
voice Description of the message that can be used for audio-based description Voice No
channelExtensions The channel-specific extension properties associated with the message JSONObject No

Response Attachment Message

This represents an attachment message. It applies the following properties to the Response Message:

Name Description Type Required?
type The message type "attachment" Yes
attachment The attachment sent Attachment Yes

Response Card Message

This represents a set of choices displayed to the user, either horizontally like a carousal or vertically like a list. It applies the following properties to the Response Message:

Name Description Type Required?
type The message type "card" Yes
cards Array of cards to be rendered Array<Card> Yes
layout Whether to display the cards horizontally or vertically 'horizontal', 'vertical' Yes

Response Command Message Payload

This represents a command message payload.

Name Description Type Required?
type The message type "command" Yes
command Command that needs to be performed string Yes
properties Map of key-value pairs JSONObject Yes

Response Error Message Payload

This represents an error message payload that provides feedback to clients on errors in the backend.

Name Description Type Required?
type The message type "error" Yes
errorMessage The error message string Yes
error java.lang.Error object string No

Response ExecuteApplicationContextCommand Message Payload

This represents an execute application action command message payload.

Name Description Type Required?
type The message type "executeApplicationActionCommand" Yes
actionType Type of action "custom", "navigate", "query", "updateFields" Yes
command Execute application action command "executeApplicationAction" Yes
context Name of the application context string Yes
customAction Must be set when actionType is 'custom' string No
properties Key-value pairs that can be used as arguments when executing the action JSONObject No

Response Feedback Message

This represents a feedback rating component that takes user's feedback using a rating gauge. Typically, this gauge is represented as a star rating system. Its payload is similar to a normal text message, but it has an additional channelExtensions object field that is set as { "displayType": "stars" }. It applies the following properties to the Response Message:

Name Description Type Required?
type The message type "text" Yes
text Text of the message string Yes
channelExtensions An object depicting specific extension to the payload { "displayType": "stars" } Yes

Example JSON

{
    "messagePayload":{
        "text":"How would you like to rate us?",
        "type":"text",
        "actions":[
            {
                "postback":{
                    "variables":{
                        "rating":"1"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"1",
                    "system.state":"giveFeedback"
                },
                "label":"1",
                "type":"postback"
            },
            {
                "postback":{
                    "variables":{
                        "rating":"2"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"2",
                    "system.state":"giveFeedback"
                },
                "label":"2",
                "type":"postback"
            },
            {
                "postback":{
                    "variables":{
                        "rating":"3"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"3",
                    "system.state":"giveFeedback"
                },
                "label":"3",
                "type":"postback"
            },
            {
                "postback":{
                    "variables":{
                        "rating":"4"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"4",
                    "system.state":"giveFeedback"
                },
                "label":"4",
                "type":"postback"
            },
            {
                "postback":{
                    "variables":{
                        "rating":"5"
                    },
                    "system.botId":"61C8D800-23AF-4DDD-B5AF-D79AB3F3BE67",
                    "action":"5",
                    "system.state":"giveFeedback"
                },
                "label":"5",
                "type":"postback"
            }
        ],
        "channelExtensions":{
            "displayType":"stars"
        }
    },
    "source":"BOT",
    "userId":"<userID>"
}

Response Location Message

This represents a location message. It applies the following properties to the Response Message:

Name Description Type Required?
type The message type "location" Yes
location The location Location Yes

Example JSON

{
    "messagePayload": {
        "type": "card",
        "layout": "horizontal",
        "cards": [
            {
                "title": "Hawaiian Pizza",
                "description": "Ham and pineapple on thin crust",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Order Small",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "hawaiian",
                                "pizzaCrust": "thin",
                                "pizzaSize": "small"
                            }
                        }
                    },
                    {
                        "type": "postback",
                        "label": "Order Large",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "hawaiian",
                                "pizzaCrust": "thin",
                                "pizzaSize": "large"
                            }
                        }
                    }
                ]
            },
            {
                "title": "Cheese Pizza",
                "description": "Cheese pizza (i.e. pizza with NO toppings) on thick crust",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Order Small",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "cheese",
                                "pizzaCrust": "thick",
                                "pizzaSize": "small"
                            }
                        }
                    },
                    {
                        "type": "postback",
                        "label": "Order Large",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "cheese",
                                "pizzaCrust": "thick",
                                "pizzaSize": "large"
                            }
                        }
                    }
                ]
            }
        ],
        "globalActions": [
            {
                "type": "call",
                "label": "Call for Help",
                "phoneNumber": "123456789"
            }
        ]
    },
    "userId": "guest"
}

Response OutboundEvent Message

This represents the outbound event messages that can be sent by the server. It applies the following properties to the Message Payload

Name Description Type Required?
type The message type "outboundEvent" Yes
eventType The event type (defined in the event catalog) string Yes
eventVersion The event type version (defined in the event catalog) string Yes
eventData The business data JSONObject Yes
contextProperties The event context properties EventContextProperties No

Here's an example:

{
    "messagePayload": {
        "eventData": {
            "size": "Medium",
            "type": "Cheese"
        },
        "eventVersion": "1.0",
        "eventType": "com.pizzastore.pizza.ordercreated",
        "type": "outboundEvent",
        "contextProperties": {
            "tenancy": "odaserviceinstance00",
            "specversion": "1.0",
            "id": "7a923f09-bff7-4369-8467-0c510e971aaf",
            "source": "hello/app",
            "time": 1659357000,
            "type": "com.pizzastore.pizza.ordercreated",
            "channelname": "System_Global_Test",
            "version": "1.0",
            "userid": "3910088",
            "contenttype": "application/json"
        }
    }
}

Response Raw Message Payload

This is used when a component creates the channel-specific payload itself. It applies the following properties to the Message Payload:

Name Description Type Required?
type The message type "raw" Yes
payload The channel-specific payload JSONObject Yes

Response Session Closed Message Payload

This represents a session closed message payload. It provides acknowledgement of session closure at the backend.

Name Description Type Required?
type The message type "sessionClosed" Yes

Response Text Message Payload

This represents a text message. It applies the following properties to the Response Message:

Name Description Type Required?
type The message type "text" Yes
text Text of the message string Yes

Example

{
    "messagePayload": {
        "type": "text",
        "text": "What do you want to do?",
        "actions": [
            {
                "type": "postback",
                "label": "Order Pizza",
                "postback": {
                    "state": "askAction",
                    "action": "orderPizza"
                }
            },
            {
                "type": "postback",
                "label": "Cancel A Previous Order",
                "postback": {
                    "state": "askAction",
                    "action": "cancelOrder"
                }
            }
        ]
    },
    "userId": "guest"
}

Response Text Stream Message Payload

This represents a streaming text response that is delivered in chunks It applies the following properties to the Response Message Payload:

Name Description Type Required?
type The message type "texStream" Yes
aggregateText Aggregated text delivered in the stream till the current chunk string Yes
streamId ID for the stream. Chunks of the same stream have same streamId string Yes
streamState Stream state of the current stream chunk "start", "running", "end" Yes
text Partial text delivered in the current chunk string Yes

Response Form Message Payload

Represents a message that returns the results of a query in a form that's read only. The message consists of an array of form results. Each form result contains a fields array with key-value pairs that represent a field. It applies the following properties to the Response Message:

Name Description Type Required?
type The message type "form" Yes
forms An array of form results. Each result contains a fields array that represents the form fields. Array<Form> Yes
formColumns A number suggesting the number of columns in which the fields of the form should be grouped. 1, 2 Yes
paginationInfo The paging information for the results in the form PaginationInfo No

Example JSON

{
    "type":"form",
    "headerText":"A-Team",
    "forms":[
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Aaron"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Adams"
                },
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Demo Builder"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/aaron-adams-4862752"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Bob"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Brown"
                },
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Multi-lingual Expert"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Bobbrown"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Bob is a member of the cloud architects team which is specialized in enterprise mobility and cloud development. Bob has been directly involved with Oracle middleware since 2005 during which he held different roles in managing highly specialized teams."
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Charlie"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Chase"
                },
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Flow Builder"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Charlie-chase-97a418"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Charlie is a member of the enterprise mobility team. Charlie has 20+ years experience with custom development. Charlie is an expert on mobile cloud services and development tools. He is the creator of productivity tools. His latest passion is building chatbots with a minimum amount of custom code."
                }
            ]
        }
    ],
    "formColumns":2,
    "paginationInfo":{
        "currentRangeSize":3,
        "rangeStart":0,
        "nextRangeSize":2,
        "hasPrevious":false,
        "hasNext":true,
        "totalCount":5,
        "rangeSize":3,
        "status":"Showing 1-3 of 5 items"
    },
    "globalActions":[
        {
            "postback":{
                "variables":{},
                "action":"system.showMore"
            },
            "label":"Show More",
            "type":"postback"
        }
    ]
}

Response Table Message Payload

Represents a message that returns the results of a query in table form The message consists of an array of headings and an array of rows. The rows themselves contain a fields array that represents individual cells. It applies the following properties to the Response Message:

Name Description Type Required?
type The message type "table" Yes
headings An array of table headings Array<TableHeading> Yes
rows An array of table rows. Each row contains a fields array that represents the table cells. Array<TableRow> Yes
tableTitle The table title string No
paginationInfo The paging information for the results in the table PaginationInfo No

Example JSON

{
    "type":"table",
    "headerText":"A-Team",
    "tableTitle": "Document",
    "headings":[
        {
            "width":20,
            "label":"First Name",
            "alignment":"left"
        },
        {
            "width":20,
            "label":"Last Name",
            "alignment":"left"
        },
        {
            "width":35,
            "label":"Title",
            "alignment":"left"
        },
        {
            "width":25,
            "label":"Phone",
            "alignment":"right"
        }
    ],
    "rows":[
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Aaron"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Adams"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Demo Builder"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Bob"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Brown"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Multi-lingual Expert"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Charlie"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Chase"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Flow Builder"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"David"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Davidson"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Machine Learning Expert"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Eric"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Eastman Junior"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Docker Expert"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        }
    ],
    "paginationInfo":{
        "currentRangeSize":5,
        "rangeStart":0,
        "nextRangeSize":-3,
        "hasPrevious":false,
        "hasNext":false,
        "totalCount":5,
        "rangeSize":8,
        "status":"Showing 1-5 of 5 items"
    }
}

Response Table-Form Message

This message combines the Table and Form message types. It represents a message that returns the results of a query in the form of a table. Each each row of the table has a read-only form in addition to the row information. It applies the following properties to the Response Message:

Name Description Type Required?
type The message type "tableForm" Yes
headings An array of table headings Array<TableHeading> Yes
rows An array of table rows each themselves containing an array of fields representing the table cells Array<TableRow> Yes
forms An array of form results that correspond to each table row. Each form contains a fields array that represents the form fields. Array<Form> Yes
paginationInfo The paging information for the results in the table form PaginationInfo Yes
formColumns The number suggesting the number of columns in which the fields of the form should be grouped. 1, 2 No
showFormButtonLabel Label of the button used to show the form layout for a specific row. string No
tableTitle The table title string No

Example JSON

{
    "type":"tableForm",
    "headerText":"A-Team",
    "tableTitle":"Document",
    "headings":[
        {
            "width":47,
            "label":"First Name",
            "alignment":"left"
        },
        {
            "width":47,
            "label":"Last Name",
            "alignment":"left"
        }
    ],
    "rows":[
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Aaron"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Adams"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Bob"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Brown"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Charlie"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Chase"
                }
            ]
        }
    ],
    "forms":[
        {
            "title":"View details Aaron Adams",
            "fields":[
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Demo Builder"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Aaron-adams-4862572"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left"
                }
            ]
        },
        {
            "title":"View details Bob Brown",
            "fields":[
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Multi-lingual Expert"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Bobbrown"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Bob is a member of the cloud architects team which is specialized in enterprise mobility and cloud development. Bob has been directly involved with Oracle middleware since 2005 during which he held different roles in managing highly specialized teams."
                }
            ]
        },
        {
            "title":"View details Charlie Chase",
            "fields":[
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Flow Builder Fanatic"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Charlie-chase-97a418"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Charlie is a member of the enterprise mobility team. Charlie has 20+ years experience with custom development. Charlie is an expert on mobile cloud services and development tools. He is the creator of productivity tools. His latest passion is building chatbots with a minimum amount of custom code."
                }
            ]
        }
    ],
    "formColumns":2,
    "paginationInfo":{
        "currentRangeSize":3,
        "rangeStart":0,
        "nextRangeSize":2,
        "hasPrevious":false,
        "hasNext":true,
        "totalCount":5,
        "rangeSize":3,
        "status":"Showing 1-3 of 5 items"
    },
    "actions":[
        {
            "postback":{
                "variables":{

                },
                "action":"system.showMore"
            },
            "label":"Show More",
            "type":"postback"
        }
    ],
    "footerText":"Tap on a row to see personal details"
}

Response Edit-Form Message Payload

Represents an Editable Form message. The message consists of an array of fields.

Name Description Type Required?
type The message type "editForm" Yes
fields A list of fields, this can be both read-only and editable fields. One of fields and formRows is required, they are mutually exclusive Array<Field> Yes
formRows A list of rows displayed in the form. One of fields and formRows is required, they are mutually exclusive Array<FormRow> Yes
errorMessage A form-level error message string No
formColumns Number of columns used in form layout, defaults to 1 number No
title A representative title for the edit form string No
actions An array of actions related to the edit form. This array should include a SubmitFormAction Array<Action> No
channelExtensions A set of channel-specific extension properties JSONObject No

The channelExtensions object can include a replaceMessage property that's used to replace the previous Edit-Form message. See Replace Previous Edit‑Form for more details on this feature.

Here's an example:

Example JSON

{
    "messagePayload": {
        "headerText": "Create Expense",
        "type": "editForm",
        "title": "Fill in the below form",
        "fields": [
            {
                "displayType": "textInput",
                "serverErrorMessage": "Invalid Text Input",
                "defaultValue": "Expense",
                "minLength": 5,
                "id": "Subject",
                "label": "Subject",
                "placeholder": "Enter subject of the expense",
                "clientErrorMessage": "Subject is required and must be between 5 and 15 characters",
                "maxLength": 15,
                "required": true
            },
            {
                "displayType": "textInput",
                "defaultValue": "expense",
                "multiLine": true,
                "id": "Description",
                "label": "Description",
                "placeholder": "What is expense justification",
                "clientErrorMessage": "Description is required",
                "required": true
            },
            {
                "displayType": "datePicker",
                "defaultValue": "2023-06-07",
                "maxDate": "2023-06-22",
                "id": "Date",
                "label": "Expense Date",
                "placeholder": "Pick a date in the past",
                "clientErrorMessage": "Expense date is required and must be in the past.",
                "required": true
            },
            {
                "displayType": "timePicker",
                "defaultValue": "18:58",
                "id": "Time",
                "label": "Expense Time",
                "placeholder": "What time was the expense",
                "clientErrorMessage": "Time is required. Please fill a value",
                "required": true
            },
            {
                "displayType": "numberInput",
                "minValue": 5,
                "defaultValue": 6,
                "maxValue": 500,
                "id": "Amount",
                "label": "Amount",
                "placeholder": "Enter expense amount",
                "clientErrorMessage": "Amount is required and must be between 5 and 500.",
                "required": true
            },
            {
                "autoSubmit": true,
                "displayType": "toggle",
                "defaultValue": "true",
                "labelOn": "Yes",
                "id": "TipIncluded",
                "label": "Tip Included?",
                "valueOff": "false",
                "labelOff": "No",
                "valueOn": "true"
            },
            {
                "displayType": "singleSelect",
                "serverErrorMessage": "Invalid Selection",
                "defaultValue": "Public transport",
                "options": [
                    {
                        "label": "Public transport",
                        "value": "Public transport"
                    },
                    {
                        "label": "Flight",
                        "value": "Flight"
                    }
                ],
                "layoutStyle": "list",
                "id": "Type",
                "label": "Expense Type",
                "placeholder": "Select expense type",
                "clientErrorMessage": "Expense type is required",
                "required": true
            },
            {
                "displayType": "multiSelect",
                "defaultValue": [
                    "Toff van Alphen"
                ],
                "options": [
                    {
                        "label": "Toff van Alphen",
                        "value": "Toff van Alphen"
                    },
                    {
                        "label": "Roger Federer",
                        "value": "Roger Federer"
                    }
                ],
                "layoutStyle": "checkboxes",
                "id": "Attendees",
                "label": "Attendees",
                "placeholder": "Select attendees",
                "clientErrorMessage": "Please select at least one attendee",
                "required": true
            }
        ],
        "formColumns": 1,
        "actions": [
            {
                "postback": {
                    "system.botId": "6803DE12-DAA9-4182-BD54-3B4D431554F4",
                    "system.flow": "ExpenseFlow",
                    "system.state": "editFormMapVar"
                },
                "label": "Submit",
                "type": "submitForm"
            }
        ],
        "channelExtensions": {
            "replaceMessage": "True"
        }
    },
    "source": "BOT",
    "userId": "guest"
}