SDK API Reference
The Messaging Web SDK exposes an adaEmbed interface with corresponding settings and actions. Get the interface from loadAdaMessaging in the npm package, from createAdaEmbedInterface in the module script, or from the window.adaEmbed global that the Chat SDK script tag continues to provide.
All three paths return the same interface. The window.adaEmbed global remains fully supported for existing installs, but is deprecated for new installations, which should hold the interface in a private scope instead. See Security best practices. The examples on this page call window.adaEmbed for brevity; substitute your own scoped reference.
Frame layout
Module scripts, npm, and embed2.js use the same DOM IDs and default frame geometry.
Messaging creates #ada-entry with direct frame children. Existing page elements with matching IDs remain unchanged.
The container mounts inside parentElement when you set it. Otherwise, it mounts on the page body.
The mask follows the launcher. A rule for #ada-entry div:first-child does not hide or transform the frames.
The launcher clips the transparent strip above the badge, so it does not intercept bubble clicks.
Page CSS can override frame offsets and dimensions. For example, #ada-chat-frame { max-width:500px !important; } widens the desktop drawer.
On mobile, top and height determine the drawer box. The SDK leaves bottom unset.
The viewport height updates when the keyboard changes the visible area.
Explicit custom-app frame dimensions, limits, and insets keep their frame style API behavior.
Settings
Configure the SDK by passing a settings object to start or to loadAdaMessaging:
Pages that load the SDK through the legacy script tag can keep defining a window.adaSettings object before the script loads. Both forms accept the same settings, and window.adaSettings remains fully supported for existing installs. For new installations it is deprecated: pass settings to start() or loadAdaMessaging instead. See Security best practices.
Settings merge in priority order: values passed to start(settings) override window.adaSettings. A few newer settings are read only from start(settings) and not from window.adaSettings; each one is marked below.
For legacy callback compatibility, window.adaSettings.analyticsCallback receives ada:analytics events as { event: string; data: object }.
For console diagnostics, see Debug a blocked widget.
The following are all of the available settings for the Messaging Web SDK.
adaReadyCallback
adaReadyCallback?(params: { isRolledOut: boolean }): void;
Specifies a callback function that the SDK calls when it has finished setting up. isRolledOut is false when the browser session falls outside the configured rollout percentage; in that case the widget does not render.
The equivalent event is ada:start, which delivers the same { isRolledOut } payload to subscribers.
align
align?: "right" | "left" | "auto";
Sets the side of the page that the launcher button and the chat drawer anchor to. Defaults to "right". With "auto", the SDK anchors left when the configured language is Arabic (ar) or Hebrew (he), and right otherwise.
allowMetaFieldsInReset
allowMetaFieldsInReset?: boolean;
Controls whether a full reset({ metaFields }) applies caller-supplied meta fields to the new session. Defaults to true, so reset meta fields apply unless you opt out. Set it to false to restore the meta fields you passed to start() instead.
Calling adaEmbed.stop() and then adaEmbed.start() creates a new client that can use different settings. Scripts with a client reference can still call start(), setMetaFields(), and setSensitiveMetaFields(). This setting does not authenticate the script that calls these methods.
History-preserving resets (resetChatHistory: false) apply reset meta fields regardless of this setting, because the current end user session survives the reset.
appUrl
appUrl?: string;
URL of a customer-hosted conversation app that the SDK mounts in place of Ada’s default conversation UI.
Your handle’s Allowed websites list controls custom apps. In your dashboard, go to Channels > Messaging. Before your transition, use Channels > Chat. Add your app’s origin. A URL on an origin that the list does not allow is dropped with a console warning, and the default app mounts instead. An empty list disables custom apps for the handle. For local development, a loopback appUrl is allowed implicitly when the page that embeds the widget also runs on a loopback host, so pure local development needs no entry. A deployed page gets no implicit loopback allowance: expose your development server through an https: tunnel and add the tunnel origin to Allowed websites, because the dashboard accepts only https:// entries. Chromium 142 and later, and Firefox 149 and later, also gate the loopback navigation behind a Local Network Access permission prompt. The SDK delegates that permission down its frame chain for a loopback appUrl, and never for other values. Set appUrl in the settings that the page starts with. Click Allow when the browser asks. A missing or denied permission surfaces as a handshake_timeout fallback. The https: tunnel path needs no permission and works in every browser. See Local development.
The value must be an absolute https: URL without embedded credentials, on an origin you control. For local development, http: is accepted on loopback hosts such as localhost and 127.0.0.1. Any other value (non-loopback http:, javascript:, data:, relative, credentialed, or on an Ada-hosted origin such as *.ada.support) is dropped with a console warning, and the default app mounts instead. The SDK validates the URL again inside its core frame, so the check cannot be bypassed from the page. The core-frame check also rejects a URL on the Messaging frame’s own origin, and enforces the Allowed websites check after the handle’s configuration loads.
The custom app frame:
- Runs in a sandboxed iframe with
allow-same-origin, so the document keeps its own origin. Cookies and storage work inside the frame, partitioned by the embedding site. See Sandbox, origin, and storage. - Receives all conversation state through
@ada-cx/messaging-bridge. The SDK never appends query parameters or tokens to a custom app URL. - Must complete the bridge
app.initializehandshake within 15 seconds after core mounts the frame. The budget includes loading your document. The handshake requiresdocument.referrer: the SDK mounts the frame withreferrerpolicy="origin", so your app document always receives the Messaging frame’s origin, and never its full URL. This includes apps served overhttp:on a loopback host during local development. A browser extension or proxy that strips theRefererheader entirely breaks the handshake, and the SDK falls back to the default app. - Stays pinned to its first document. A navigation or reload, even to the same origin, disconnects the bridge permanently.
When the custom frame fails to load or complete its handshake, or when its origin is not allowed by your handle’s Allowed websites list, the SDK publishes the ada.customApp.fallback event with { appUrl, reason, code, retryable } and logs a console warning with the reason. It destroys the failed frame and mounts the default app in its place. After one of these fallbacks, the SDK stays on the default app for the rest of the page’s lifetime. Set appUrlFallback to false to fail closed instead.
One fallback reason is transient: the handle’s configuration did not load in time to verify the Allowed websites list. That fallback applies only to the one mount attempt. The next mount after a reset() checks the loaded list again.
appUrl and appUrlFallback are locked on the first configuration. A runtime re-configuration or reset() cannot redirect the app frame to a different URL.
This setting is read only from start(settings) or the loadAdaMessaging settings object. It is not read from window.adaSettings.
appUrlFallback
appUrlFallback?: boolean;
Controls what happens when a custom appUrl frame fails to load, fails its bridge handshake, or fails the Allowed websites check. It also applies when your handle’s configuration does not load in time to verify the Allowed websites list. Defaults to true, which mounts Ada’s default app in place of the failed custom frame.
When set to false, the SDK does not fall back. The activation fails through the normal activation error path, and later activation attempts retry the custom URL until three consecutive default-app failures latch the activation. The ada.activation.error event’s data then carries a code field with the same values as the ada.customApp.fallback event. In fail-closed mode, the next activation retries every cause, including origin_not_allowlisted. The retryable flag exists only on the fallback event.
Only meaningful together with appUrl. Like appUrl, this setting is read only from start(settings), not from window.adaSettings, and is locked on the first configuration.
branding
branding?: AdaMessagingBranding;
Overrides the appearance settings from your Ada dashboard for the page that sets it. Use it when one AI Agent serves several brands, and each brand’s site needs its own name, colors, and launcher. Every field is optional. A field that you do not set keeps its dashboard value.
The SDK checks each field and ignores a field that fails, with a console notice that names the field and the rule. The other fields still apply. The notice never includes the value that you set. The rules are:
- Colors are 3- or 6-digit hex values, for example
#1a73e8. - URLs are absolute
https:URLs. launcher.sizeis an integer from 32 to 120.- Text fields are objects that map a language code to a string. Each map must include the Agent’s default language. A text field without an entry for that language is ignored.
headerTextColorneeds a header background color, fromheaderColoror from a dashboard that has header coloring turned on. Without one, it is ignored.
A key that is not part of branding is ignored with a console notice.
Text fields show the end user’s current language, or the Agent’s default language when the map has no entry for it. aiAgentName and aiAgentDescription update when the language changes, for example after setLanguage. The launcher text also updates when the language changes. The dashboard’s launcher text behaves the same way.
When launcher includes both iconUrl and text, the launcher shows the text. launcher.backgroundColor changes the launcher color. tintColor does not.
branding stays in effect after reset and deleteHistory. A custom app receives the resulting values in the same state keys that carry the dashboard values, so it needs no changes to show them.
chatterTokenCallback
chatterTokenCallback?(chatterToken: string): void;
Specifies a callback for when the end user token has been set. The equivalent event is ada:chatter_token.
cluster
cluster?: string | null;
Specifies the regional cluster your AI Agent runs on. Accepts either a regional segment (for example, "eu") that the SDK combines with domain, or a full base domain (for example, "eu.ada.support") used as-is.
Set this only if your Agent is hosted on a non-default cluster. If the Agent is on the default cluster, leave this unset.
conversationEndCallback
conversationEndCallback?(event?: Record<string, unknown>): void;
Specifies a callback function that the SDK calls when the end user ends the conversation. The callback receives the same payload as the ada:end_conversation event.
crossWindowPersistence
crossWindowPersistence?: boolean;
Persists the chat drawer open state across page refreshes and tabs while a live agent conversation is active, using the Window.sessionStorage API. When the browser is closed, the state is forgotten. Has no effect in headless or parentElement mode.
Defaults to true. Set to false to disable.
window.adaSettings, new AdaMessagingClient(config), and adaEmbed.start(settings) also accept the legacy object form { enabled: boolean }.
Set enabled: false to disable persistence.
For invalid values, the SDK logs a console warning once per page load.
If a later start() call passes an invalid value, the SDK keeps the earlier setting or window.adaSettings fallback.
Invalid constructor values preserve the window.adaSettings fallback.
Without a valid setting, persistence defaults to on.
On the legacy Chat SDK this behavior was opt-in. On the Messaging SDK it is on by default.
The legacy Chat SDK enables persistence for { enabled: false }. The Messaging SDK disables it.
domain
domain?: string;
Overrides the Ada base-domain segment (for example, "ada"). The SDK combines it with handle and any regional cluster into the API host https://<handle>.[<cluster>.]<domain>.support. For a full URL override, use endpoint instead.
Unless directed by an Ada team member, you do not need to change this value.
enableProgrammaticControl
enableProgrammaticControl?: boolean;
Opt-in to the transcript-bearing programmatic surface. When set to true, your page can:
- Call
getConversation,getMessages,selectQuickReply,sendMessage,setComposerText,setDelegate, andtriggerPlaybook. - Receive the
ada:message:sentandada:message:receivedevents on host-page subscribers.
While this setting is false (the default), those methods reject with ProgrammaticControlNotEnabled and the events are not delivered to host subscribers. The value is locked on the first configuration and cannot be changed at runtime.
Every script that lives in your host page (analytics tags, GTM, ad pixels, session replay tools, and any third-party SaaS pixel) inherits your page’s trust and can subscribe to these events or call these methods. They will see full message bodies, including any PII your end users type. Have your product and security teams accept that exposure risk explicitly before turning this on.
endpoint
endpoint?: string;
Full base URL for the Ada API. Overrides all default host derivation from handle, cluster, and domain.
eventCallbacks
eventCallbacks?: Record<string, AdaSdkEventCallback>;
A map of event key to callback, registered eagerly before the first startup event fires. Two kinds of keys are supported:
- Public
ada:*event keys, registered exactly likesubscribeEventsubscriptions. - Custom JavaScript event names configured in your Ada dashboard, keyed by the event’s
event_name. The key"*"receives every custom JavaScript event.
greeting
greeting?: string;
Customizes the greeting that new end users see. The value is the response id of the Answer to trigger, which you can find in the URL of the corresponding Answer in the dashboard. This is useful for setting page-specific greetings across your app.
handle
handle?: string;
Your AI Agent’s handle. Required: pass it in start(settings), in the loadAdaMessaging settings, or in window.adaSettings. Pages migrating from the Chat SDK script tag can keep the data-handle attribute on that script.
headless
headless?: boolean;
When set to true, the SDK connects to the AI Agent in the background without rendering the default launcher button, intro popup, or chat drawer. Use this when your page renders its own chat UI and drives the conversation through getConversation, getMessages, selectQuickReply, sendMessage, and subscribeEvent.
Headless sessions are typically paired with enableProgrammaticControl: true. Without it, the methods needed to drive a custom UI reject at runtime.
Methods that act on the built-in UI are not available in headless mode:
setComposerTextrejects withHeadlessModeError. There is no built-in composer to write to.toggle,open, andcloseare no-ops. There is no drawer to open or close.isOpenalways resolvesfalse.
In headless mode, call start to activate the session, or let the first sendMessage activate it for you.
Headless sessions run with no visual indicator. The end user token is created and persisted to local storage the same way as a visible session. If your page is compromised, an attacker can run conversation activity under the visiting user’s token without any user-facing signal. Host pages should treat enabling headless as a meaningful trust decision.
hideMask
hideMask?: boolean;
Controls the page mask behind the open drawer on desktop. By default, no mask appears, and users can interact with your page while the chat window is open.
Set hideMask to false to show the mask. The mask dims your page, and a click on it minimizes the drawer instead of reaching the page.
Leave hideMask unset, or set it to true, when users need to navigate the page while the chat window is open.
identityToken
identityToken?: string;
A short-lived, single-use identity token that your backend mints through Ada’s Platform API for a known end user. Pass it here to start an identified session instead of an anonymous one. See the identity guide for the full flow.
Your server can supply optional verified_email and name values when it mints the token.
Ada links only when the mint request includes verified_email.
Without either field, mint, exchange, and handoff keep their existing behavior.
Ada stores the values encrypted on the session’s end user.
Ada uses them only in the first 7 days after the exchange.
Ada deletes them after the first Zendesk Messaging handoff uses them and Sunshine initialization succeeds.
If no handoff uses them, Ada deletes them at the next handoff or token exchange after the 7 days end.
How the exchange works:
- The SDK exchanges the token once with the AI Agent backend, before it restores any persisted session state. The exchange request carries the token in the JSON body as
identity_token. The token never appears in a URL. - The token is one-shot. After a successful exchange, the SDK clears its cached copy and the server will not accept the same token again. A later
reset()without a new token starts an anonymous session. - To identify a new user (for example, after a login change), pass a fresh token to
reset({ identityToken }). A reset that carries an identity token is always a full reset.
On exchange failure, the SDK clears identity-sensitive storage and continues with an anonymous session. It publishes ada:identity_token:error with a reason from the following list. An expired token additionally publishes ada:identity_token:expired.
language
language?: string;
Sets the initial display language. Takes a language code in ISO 639-1 format, for example "fr".
To use the same language for AI Agent replies, first turn languages on in your dashboard, under Customization > Languages. See Support multiple languages in the same AI Agent.
On each page load, a configured language takes precedence over a saved language choice. A language picker or setLanguage change during that visit is still saved when session persistence is enabled. The configured language takes precedence again on the next load. Omit this setting to allow a saved choice to restore.
Pages on the same site share the saved session for an AI Agent. If some pages configure language and others omit it, a configured page can change the saved language used by the other pages.
When a configured page activates and restores that session, it synchronizes the configured language if the Agent supports it. If the reply language changes, other open tabs using that session apply the update live, even during a conversation. An embedded widget can activate automatically on page load; a floating widget’s initial load alone does not send this update.
Later language updates from the Agent or another tab sharing the session can change the display language. With session persistence enabled, the widget saves its current display language.
If the Agent does not support the display language, or the language update fails, the display language can differ from the Agent’s reply language. An unsupported configured value can still replace a supported saved choice when session persistence is enabled.
Alternatively, you can use the setLanguage action, which changes the language without clearing the chat history.
lazy
lazy?: boolean;
Defers loading until your page calls start().
- On the Chat SDK script tag, add the
data-lazyattribute to the<script id="__ada">element. - Without that element, set
lazy: trueinwindow.adaSettings.
Passing lazy to start() or loadAdaMessaging has no effect. Those calls start the SDK.
Call start() before open() or triggerProactive() on the adaEmbed interface.
metaFields
metaFields?: Record<string, MetaFieldValue>;
Use metaFields to pass information about an end user to Ada. This can be useful for tracking information about your users, as well as personalizing their experience. For example, you may wish to track the phone_number and name for conversation attribution. (See Variables for more information.)
Values must be a string, number, boolean, or null. The SDK has no metadata count limit. It accepts keys up to 256 characters and string values up to 100,000 characters. It drops longer keys and truncates longer values with a console notice.
The SDK sets initialURL, introShown, and test_user itself. It ignores these keys when your page passes them. getMetaFields can return them. To mark a test user, use testMode.
To change these values after setup, use the setMetaFields action.
Meta field keys should not include whitespace, emojis, special characters, or periods.
onAdaEmbedLoaded
onAdaEmbedLoaded?(): void;
Called when the embed interface is ready to be used, before startup events fire. This is useful for subscribing to events. Subscribing here ensures that subscriptions are in place before events are triggered.
The equivalent event is ada:embed_loaded.
parentElement
parentElement?: string | HTMLElement;
Specifies where to mount the conversation frame if the default side drawer is not desired. Accepts the HTMLElement or element id of the desired parent element.
In parentElement mode, toggle throws, and open and close do not show or hide a drawer. The WindowInfo field isDrawerOpen is always false.
Chat renders immediately inside the parentElement provided. This means that the conversation also gets initialized. Avoid initializing the SDK with the parentElement setting automatically on every page, since it could lead to low engagement rates.
privateMode
privateMode?: boolean;
Puts the SDK into private mode when set to true. In private mode, the SDK stores nothing in the browser. It forgets the conversation on every refresh or tab close, even during a live agent handoff. This is not the same as the customer persistence setting Forget After Reload.
That setting also forgets the conversation on refresh, except during a live agent handoff. A same-tab refresh during a handoff keeps the same agent conversation. It forgets the conversation when the tab closes.
rolloutOverride
rolloutOverride?: number;
Overrides the rollout value set in the dashboard for this session. Useful if you need page-specific rollout values, or together with testMode to always show the widget. For testing and QA purposes only.
Accepts a fraction between 0 and 1. For backward compatibility, a window.adaSettings value above 1 is treated as a legacy percentage (for example, 50 becomes 0.5).
sensitiveMetaFields
sensitiveMetaFields?: Record<string, MetaFieldValue>;
Like metaFields, you can use sensitiveMetaFields to pass information about an end user to Ada. With sensitiveMetaFields, however, values are:
- encrypted immediately upon entering the Ada system
- temporarily stored in a cache on the Ada side, that is cleared after 24 hours
- not stored in the database
- redacted on the dashboard
Sensitive values are delivered over the SDK’s secure storage transport and are never readable back through getMetaFields.
To change these values after setup, use the setSensitiveMetaFields action.
Meta field keys should not include whitespace, emojis, special characters, or periods.
showFallbackOnTimeout
showFallbackOnTimeout?: boolean;
When true (the default), the SDK shows a self-contained fallback document in the chat frame if chat activation exceeds the timeout budget and no exact ada:chat_frame_timeout subscriber has taken over handling. A subscribeAll() listener does not count: it receives the event and still gets the fallback. Set to false to suppress the built-in fallback and handle timeouts yourself. The fallback is a data: document, so a frame-src that allows only the Ada asset host blocks it.
styles
styles?: Record<string, string>;
styles is deprecated and has no effect. To change the accent color, set branding.tintColor.
The SDK ignores styles in every form, and the legacy embedStyles key in window.adaSettings. It shows a console notice for each one that it reads.
testMode
testMode?: boolean;
Marks the end user as a test user. The session keeps the real transport and backend; the SDK stamps the test_user: 1 meta variable on the session so analytics can exclude it. Rollout percentage still applies; set rolloutOverride to 1 to always show the widget.
theme
theme?: "light" | "dark" | "auto";
Color scheme for the chat widget. When set to "auto" (the default), the widget follows the user’s OS preference via prefers-color-scheme. This overrides the server-configured theme. Change it at runtime with setTheme.
This setting is read only from start(settings) or the loadAdaMessaging settings object. It is not read from window.adaSettings.
toggleCallback
toggleCallback?(isDrawerOpen: boolean): void;
Use this setting to trigger side effects when the chat drawer is opened or closed. The equivalent event is ada:toggle.
zdChatterAuthCallback
zdChatterAuthCallback?(callback: (token: string) => void): void;
Use zdChatterAuthCallback for Zendesk Chat or Zendesk Messaging end user authentication. Request a JWT from your server and pass it to the callback.
For Zendesk Messaging, return your Zendesk Messaging authentication JWT. Sign it with a Zendesk Messaging signing key using HS256.
Include a kid header and the scope: "user", external_id, and exp claims.
The external_id must be a non-empty string of at most 255 characters.
It must not contain /, ?, #, %, whitespace, or control characters.
Send the required external_id claim and the optional name, email, and email_verified claims.
Verified email linking requires the Messaging SDK.
Ada links to or creates a Zendesk user from the email. A wrong email links the conversation to another person’s Zendesk user.
Ada uses name and email for display and linking only when the JWT has an email with boolean email_verified: true.
Without a verified email, Ada uses only external_id.
With a verified email, Ada writes META jwt_name and jwt_email, as it does for Zendesk Chat.
Ada updates name only when it is empty or still equals the previous JWT’s name.
Ada never writes META email from these claims.
This preserves the email that your page or a Capture block sets.
With a verified email, Ada first uses a Zendesk end user with the same external_id as the JWT.
With email_verified: true, Ada next matches exactly one Zendesk end user by primary email.
Ada trims whitespace and converts the email to lowercase before matching.
Ada uses the matched user’s external ID or sets it to the JWT’s external_id if missing.
When Ada sets a missing external ID on the Zendesk user, Zendesk keeps that link for later conversations.
If a verified email has no match, Ada creates a Zendesk end user with the JWT’s name and email. If the JWT has no name, Ada uses the email as the name.
If Ada cannot select or create a Zendesk end user, Ada uses the JWT’s external_id.
Ada uses the JWT’s email to match or create a Zendesk user only when email_verified is true.
Ada never links agents or admins, or a match that is not exact.
See Authenticate end users for the full matching rules.
The SDK requests the token at startup.
After successful verification, the server stores the identity and its validity window on the end user record. Each successful startup check renews the window for 24 hours. Browser metadata cannot supply or change these values.
If authentication fails and no other identity mapping applies, the Handoff proceeds with an anonymous Sunshine user.
When a user signs out, call reset() so the next user starts a new conversation and a new Zendesk user.
Actions
You can call the following actions on the adaEmbed interface. Every action except setDelegate returns a Promise.
These actions work before start():
createProactivedestroyevaluateCampaignConditionssetDelegatestartsubscribeAllsubscribeEventtriggerCampaignunsubscribeEvent
Other actions reject until start() runs, with this message:
The Messaging SDK supports generative AI Agents only. The scripted-campaign actions createProactive, evaluateCampaignConditions, and triggerCampaign are deprecated. Calls resolve without effect. The SDK logs a console warning when SDK diagnostics are turned on. See Debug a blocked widget. To start a proactive conversation, use triggerProactive.
close
close(): Promise<void>;
Closes the chat drawer and restores the launcher button. A no-op when the chat is already closed, in headless mode, and in parentElement mode.
This action emits neither ada:minimize_chat nor ada:close_chat. It still emits ada:toggle(false) and calls toggleCallback(false).
closeCampaign
closeCampaign(): Promise<void>;
Closes the currently displayed proactive message bubble. Does nothing if no proactive bubble is currently displayed.
createProactive
createProactive(body: string, duration?: number, responseId?: string): Promise<void>;
This action is deprecated on the Messaging SDK. Calls resolve without effect. The SDK logs a console warning when SDK diagnostics are turned on. See Debug a blocked widget. Use triggerProactive instead.
deleteHistory
deleteHistory(): Promise<void>;
Permanently deletes the end user’s conversation history and persisted state, and resets the session. When the end user opens a new chat window, a new end user token is generated. The promise resolves once the SDK confirms the persisted clear is durable.
destroy
destroy(): Promise<void>;
Tears down all SDK frames, channels, and listeners, and clears every event subscription and the delegate. Use stop instead when you plan to start again and want subscriptions to survive.
evaluateCampaignConditions
evaluateCampaignConditions(options?: Record<string, unknown>): Promise<void>;
This action is deprecated on the Messaging SDK. Calls resolve without effect. The SDK logs a console warning when SDK diagnostics are turned on. See Debug a blocked widget. Use triggerProactive instead.
getConversation
getConversation(): Promise<ConversationInfo>;
Returns information about the active conversation: its id (or null if the end user has not sent or received any messages yet) and the live agent handoff state. See ConversationInfo for the full shape.
Requires enableProgrammaticControl: true. Otherwise rejects with ProgrammaticControlNotEnabled. Rejects with a timeout error when the chat frame does not respond in time.
getInfo
getInfo(): Promise<WindowInfo>;
Returns a WindowInfo object containing information about the current client state.
getMessages
getMessages(): Promise<PublicMessage[]>;
Returns the messages currently held in the chat session, in the order they were sent. See PublicMessage for the field shape.
Requires enableProgrammaticControl: true. Otherwise rejects with ProgrammaticControlNotEnabled.
Important behaviors:
- In-memory only. This is the transcript the SDK holds for the current end user. There is no server-side history endpoint or pagination. Refreshing the page resets the list to whatever the SDK rehydrates from the persisted session.
- Filtered to conversational messages. Presence notifications (typing, conversation-ended), system events, and other non-conversational entries are excluded. Every returned message has one of the
rolevalues documented in PublicMessage.
getMetaFields
getMetaFields(): Promise<Record<string, MetaFieldValue>>;
Returns the non-sensitive meta fields currently set on the active session: the values passed in settings plus any subsequent setMetaFields updates. Sensitive meta fields are never returned.
handleNotification
handleNotification(): Promise<void>;
Opens the chat drawer in response to a notification the host page handled itself, for example a push notification tap. A no-op in headless mode.
On the legacy Chat SDK, this action toggled the drawer only when the chat was closed. On the Messaging SDK it calls open unconditionally, which is a no-op when the drawer is already open. The end state is the same.
isOpen
isOpen(): Promise<boolean>;
Resolves to true when the chat is currently visible to the end user, and false otherwise. Always resolves false in headless mode.
open
open(): Promise<void>;
Opens the chat drawer. A no-op when the chat is already open and in headless mode.
requestNotifications
requestNotifications(): Promise<NotificationPermission | null>;
Requests browser web-notification permission. Call it from a user gesture, such as a button click, per browser policy. Resolves the resulting permission ("granted", "denied", or "default"), or null when the browser does not support the Notification API.
Once permission is granted, the widget shows notifications while the page is hidden or the chat is closed. Notifications cover new live agent messages and live agent joins or departures. Ending chat yourself does not produce a leave notification. Clicking the notification focuses the window, opens the chat, and publishes the ada:web_notification:click event.
reset
reset(resetParams?: ResetParams): Promise<void>;
Resets the session. By default this clears the history and creates a new end user; pass resetChatHistory: false to update configuration while keeping the history and the current end user. See ResetParams for all options.
Behaviors to know:
- Caller-supplied
metaFieldsapply on a full reset by default. SetallowMetaFieldsInResettofalseto block them and restore thestart()baseline instead. History-preserving resets always apply them. - Caller-supplied
sensitiveMetaFieldsapply on a full reset by default, the same asmetaFields. SetallowMetaFieldsInResettofalseto drop them instead. A full reset does not restore droppedsensitiveMetaFieldsfrom astart()baseline. The device binding registered throughsetDeviceTokensurvives either way. - Passing
identityTokenstarts a new identified session and always forces a full reset. See identityToken. - The promise resolves on the SDK’s confirmation. Full resets wait for the persisted conversation clear to be durable.
selectQuickReply
selectQuickReply(messageId: string, index: number): Promise<void>;
Selects a quick reply through the same send path as a tap in the built-in UI.
Requires enableProgrammaticControl: true.
The runtime reads the reply fields from its own transcript. The host supplies only the message ID and index.
For suggestion and switch replies, the runtime sends a trigger with the stored target.
For accepted_value replies, the runtime sends the stored label as text. If the label is empty, the runtime sends the stored value.
The method starts engagement and activates the chat, like sendMessage.
If the SDK is not initialized, it starts headless mode or opens the chat.
In visible mode, it opens a closed chat and reloads a chat that shows the timeout fallback.
The runtime waits for a pending history-preserving reset, then activates the chat before it validates the stored row.
Selection uses the normal activation greeting rules.
A restored conversation with messages or an already sent greeting prevents a duplicate greeting.
A rejected selection on a fresh session still allows the normal greeting.
The promise resolves when the runtime accepts the send, at the same point as sendMessage.
The selected user message carries origin: "programmatic" in getMessages() and ada:message:sent.
Built-in UI taps and custom-app bridge selections omit this field.
Selection does not use the beforeSend text hook.
The promise rejects when programmatic control is off, with ProgrammaticControlNotEnabled.
It also rejects empty or non-string message IDs and indices that are not non-negative integers.
The runtime rejection messages include these codes:
After SEND_FAILED, the host can call selectQuickReply again for the same message once the rate limit permits it.
The runtime withdraws that answer and releases the block in the app display state and host selection checks.
The message must still belong to the current conversation and pass the other selection checks.
After SEND_UNCONFIRMED, the block stays answered because the selection may already have taken effect.
Another selection of that message rejects with ALREADY_ANSWERED.
If the conversation or session changes during the request, the promise resolves as accepted, as sendMessage does.
The runtime does not apply the send result to the replacement state or publish ada:message:sent for that request.
Cancellation before the send, activation errors, frame closure, and timeouts also reject the promise.
This example adds a button for each received reply. Each button selects its reply by index.
sendMessage
sendMessage(text: string): Promise<SendMessageResult>;
Sends a message to the AI Agent on behalf of the end user. Resolves with the new message’s id, which matches the id on the same message in getMessages and in the ada:message:sent event payload.
Requires enableProgrammaticControl: true. Otherwise rejects with ProgrammaticControlNotEnabled.
Sending opens the chat drawer if it is not already visible. In headless mode, sending activates the session in the background instead. If the conversation has not started, the auto-greeting is skipped and the message starts the conversation.
Possible rejections:
sendMessage requires non-empty text:textis empty, whitespace-only, or not a string.DelegateRejected: a registeredbeforeSendhook returnedfalse.DelegateTimeout: thebeforeSendhook did not resolve within 5 seconds.sendMessage rejected by chat: <CODE>: chat-side validation rejected the message. Codes includeTOO_LONG(exceeds the 500-character message cap),RATE_LIMITED(a previous send was less than 200 ms ago),EMPTY_TEXT, andDISPATCH_FAILED. During a Zendesk Chat handoff, a message that exceeds the limit rejects withMESSAGE_TOO_LONG.sendMessage cancelled: the session changed before it could be sent: areset()or identity change superseded the send.- A timeout error when the chat frame does not respond in time.
To attach metadata to the conversation, use setMetaFields before calling sendMessage.
setComposerText
setComposerText(text: string): Promise<void>;
Pre-fills the chat composer with text without sending it. The end user can still edit or clear the text before sending.
Requires enableProgrammaticControl: true. Otherwise rejects with ProgrammaticControlNotEnabled. Not available in headless mode (rejects with HeadlessModeError). Rejects with setComposerText rejected by chat: TOO_LONG if text exceeds the composer’s 500-character cap.
setDelegate
setDelegate(delegate: Delegate | null | undefined): void;
Registers a beforeSend hook that runs on outgoing messages sent via sendMessage. Use it to transform, cancel, or pass the message through.
Requires enableProgrammaticControl: true. Called after start(), it throws synchronously with ProgrammaticControlNotEnabled when the gate is off. Before start(), the SDK queues the delegate. If programmatic control is disabled at startup, the SDK ignores the delegate. It logs a console warning when SDK diagnostics are turned on. See Debug a blocked widget.
The hook fires only for programmatic sendMessage() calls. Messages typed into the chat composer are sent through a separate path and do not flow through beforeSend. Do not rely on this hook as a moderation or PII-redaction gate for composer input.
The hook receives { text: string } (not a full PublicMessage) and returns one of:
- A modified
{ text: string }to change what is sent. false(or a Promise resolving tofalse) to cancel.sendMessagerejects withDelegateRejected.- The input unchanged to pass through.
The hook can be synchronous or asynchronous. It is bounded by a 5-second timeout; a slow or never-resolving delegate causes sendMessage to reject with DelegateTimeout. The transformed text is re-validated: returning { text: "" } or { text: " " } causes sendMessage to reject, and the message is not sent.
Pass null or undefined to clear the delegate.
See Delegate for the type shape.
setDeviceToken
setDeviceToken(token: string): Promise<void>;
Stores the APNs or FCM device token with the end user’s sensitive metadata. To send push notifications, use webhooks and your push provider. See Push notifications.
The SDK ignores an empty device token or one that contains only whitespace. The mobile SDK wrappers use this action.
setLanguage
setLanguage(language: string): Promise<void>;
Changes the conversation language programmatically. Use this action, rather than the language setting, to change the language without clearing the chat history. Language codes use ISO 639-1 format, for example en, fr, ar.
You must first turn languages on in your Ada dashboard, under Customization > Languages. See Support multiple languages in the same AI Agent.
On the legacy Chat SDK, setLanguage threw when the chat frame was not ready yet. On the Messaging SDK, the call is queued and applied when the frame is ready; it does not throw. A host that relied on catching the “not ready” error should stop doing so.
setMetaFields
setMetaFields(fields: Record<string, MetaFieldValue>): Promise<void>;
Updates metaFields after setup. In most situations, the metaFields setting is enough for user attribution. However, in cases where the chat remains open while page changes occur (like in single-page applications), this method may be useful.
The same value rules and limits as the metaFields setting apply.
Meta field keys should not include whitespace, emojis, special characters, or periods.
setSensitiveMetaFields
setSensitiveMetaFields(fields: Record<string, MetaFieldValue>): Promise<void>;
Updates sensitiveMetaFields after setup. The values are not stored in the database and are deleted after 24 hours.
Meta field keys should not include whitespace, emojis, special characters, or periods.
setTestModeBanner
setTestModeBanner(label: string | null): Promise<void>;
Shows a test-mode banner with the given label, or removes it with null. This action exists for the Ada dashboard’s test surface; host pages do not normally call it.
setTheme
setTheme(theme: "light" | "dark" | "auto"): Promise<void>;
Changes the chat widget’s color scheme at runtime. Takes effect immediately, without a reset or reload. "auto" follows the user’s OS preference.
start
start(settings?: AdaMessagingStartOptions): Promise<void>;
Initializes the SDK on your page with the merged settings: window.adaSettings first, then any settings passed to createAdaEmbedInterface or loadAdaMessaging, then this call’s settings on top. handle is required unless it was already provided.
AdaMessagingStartOptions accepts everything listed in the Settings section.
If the assigned AI Agent’s configuration explicitly turns web chat off, start() logs a warning, mounts no widget, and resolves. This applies to the standard widget and parentElement mode. Headless mode skips this check.
After this start() resolves, calls behave as they do before the widget starts. For example, getInfo(), toggle(), and metadata setters reject with the not-instantiated error. Calls already waiting on this start reject with start_interrupted.
Turn on web chat in the Agent’s settings. Then call start() again. You do not need to call stop() first.
For both primary and alternative Agents, failed configuration reads, timeouts, or missing chat availability data keep the existing startup behavior. The SDK starts the assigned Agent without checking chat availability.
Rejections:
AdaEmbedErrorwith codestart_already_activewhen the SDK has already been started. Callstopfirst to restart.AdaEmbedErrorwith codestart_interruptedwhenstop()ordestroy()interrupts the start.AdaEmbedErrorwith codestart_owner_conflictwhen a differentadaEmbedinterface already runs on the page. Only one interface can own a page. Stop the other interface first.loadAdaMessagingreuses its saved interface, including after a start with web chat off. Repeated loader calls do not start it again. Callstart()on the returned interface to retry. See One interface per page.- An error asking for a
handlewhen none was provided anywhere.
If start() fails for another reason, queued calls reject with the same error that start() returns.
When a client starts in headless or parentElement mode, start() also activates the conversation session. These modes have no launcher gesture.
stop
stop(): Promise<void>;
Removes the SDK from your page and tears down its frames. A later start can run again. Event subscriptions made through subscribeEvent and subscribeAll survive a stop and replay onto the next started client; a delegate set with setDelegate does not.
If start() resolved with web chat off, no client exists to stop. In that state, stop() rejects with the not-instantiated error.
subscribeAll
subscribeAll(callback: (eventKey: string, data: unknown) => void): Promise<number>;
Subscribes to every broadcast event with a single callback. The callback receives the event key and the event data. Resolves a subscription id for unsubscribeEvent.
This action is designed for bridge adapters, such as native wrappers, that forward SDK events wholesale.
The transcript-bearing events ada:message:sent and ada:message:received are never delivered to subscribeAll subscribers. They require exact subscribeEvent subscriptions, so transcript data is not exposed to generic host-page listeners.
subscribeEvent
subscribeEvent(eventKey: string, callback: (data: unknown, context: { eventKey: string }) => void): Promise<number>;
Certain things in Ada trigger events. Each event consists of an event key and a data payload. Using subscribeEvent, you can define callbacks that are called when a specific event is triggered.
Callbacks are triggered whenever an event starts with the eventKey provided to subscribeEvent. This means you can subscribe to all events of a certain category. For example, the callback in a subscription to ada:campaigns is called on ada:campaigns:shown, ada:campaigns:engaged, and any other event beginning with ada:campaigns.
Transcript-bearing events are the exception: ada:message:sent and ada:message:received require exact subscriptions to those event keys. They are not delivered through prefix subscriptions such as ada:message or broad listeners such as subscribeAll, so transcript data is not exposed to generic host-page subscribers.
Two arguments are provided to each callback when it is called: data and context.
datais specific to each event.contextis an object with a single property, theeventKeyof the event that triggered the callback.
subscribeEvent resolves a numeric subscriptionId that you can use to unsubscribe later (see unsubscribeEvent). Subscriptions made before start() are queued and replay onto each started client.
It is strongly recommended that you place initial subscriptions in the onAdaEmbedLoaded setting. This ensures that subscriptions are in place before any events are triggered, so that no events are missed.
The following are the events that you can currently subscribe to:
toggle
toggle(): Promise<void>;
Opens the chat drawer if it is closed, and closes it if it is open. A no-op in headless mode. Rejects when the parentElement setting is in use.
trackEvent
trackEvent(eventKey: string, value?: number, meta?: Record<string, unknown>): Promise<void>;
Tracks a business Event for conversation analytics. The arguments of this function are:
eventKey: string: the key of the Event to track (required).value?: number: an optional value to assign to the Event. Defaults to0.meta?: Record<string, unknown>: an optional object containing metadata corresponding to the Event, such as currency, product group, or customer segment. The SDK always stamps the current page URL onto the metadata.
Tracked events are also re-published to subscribers as ada:analytics events.
On the legacy Chat SDK, value was required. On the Messaging SDK, both value and meta are optional.
triggerAnswer
triggerAnswer(answerId: string): Promise<void>;
Triggers a specific Answer in the conversation. Include the Answer’s response id, which you can find in the URL of the corresponding Answer in the dashboard.
triggerCampaign
triggerCampaign(campaignKey: string, options?: Record<string, unknown>): Promise<void>;
This action is deprecated on the Messaging SDK. Calls resolve without effect. The SDK logs a console warning when SDK diagnostics are turned on. See Debug a blocked widget. Use triggerProactive instead.
triggerGreeting
triggerGreeting(handle?: string): Promise<void>;
Triggers the AI Agent’s configured greeting in the active conversation. handle optionally overrides the configured handle for the greeting.
triggerPlaybook
triggerPlaybook(playbookId: string, options?: TriggerPlaybookOptions): Promise<void>;
Starts a specific Playbook from your host page. Opens the chat drawer if it is closed. Headless clients activate the session without a drawer.
This method is in Early Access.
It requires enableProgrammaticControl: true and an active v2 Playbook marked as startable from the SDK.
Set startable_from_sdk: true through the dashboard API, or ask the Ada team to mark the Playbook.
This Playbook setting defaults to false.
Pass the Playbook ID as a 24-character hexadecimal string.
The SDK sends metaFields and sensitiveMetaFields with the trigger.
For a valid Playbook ID within the rate limit, the API stores metadata before it checks Playbook eligibility.
It also applies a supported language.
It also binds the push device token when push notifications are enabled.
These updates persist even when a later check refuses the trigger. A rate-limited request stores nothing.
Both options use the same value rules as setMetaFields and setSensitiveMetaFields.
The Playbook must allow standalone use and pass its availability rules for the end user.
The API refuses the request during a live handoff or when another Playbook is running.
If another trigger for the same end user is in progress, the API returns HTTP 409 with failure_reason: "trigger_in_progress".
If the AI Agent is still answering an earlier message in the conversation, the API returns HTTP 409 with failure_reason: "turn_in_progress".
If metaFields.language requests an unsupported language, the API returns HTTP 409 with failure_reason: "language_not_supported".
For this language refusal, the API keeps the current conversation language and skips push device binding and Playbook activation.
Other metadata and email fields remain stored under the same rules as the metadata setters.
If either metadata field has a non-null value that is not an object, the API returns HTTP 409 with failure_reason: "invalid_metadata".
The API stores no metadata and does not activate the Playbook for this refusal.
Each end user can make three valid-ID attempts with valid metadata objects per minute per AI Agent.
The promise resolves when the API accepts the trigger. It rejects on refusal, invalid input, metadata write failure, or timeout.
The failure includes the reason, such as triggerPlaybook rejected: playbook_running.
HTTP 503 with activation_indeterminate means the API cannot confirm whether the Playbook started.
The rejection does not mean the Playbook did not start.
Timeouts and network errors can also leave the result unknown. Do not retry automatically.
triggerProactive
triggerProactive(messageKeyOrOptions: string | { messageKey: string; params?: Record<string, string> }, params?: Record<string, string>): Promise<void>;
Triggers a proactive conversation using a specified key. This displays a predefined static or template message, where template messages can include dynamic parameters.
Parameters:
The Messaging SDK accepts both the object form and a plain string key. The legacy Chat SDK accepted only the object form, so existing calls keep working.
The trigger is ignored while the chat drawer is open.
Examples
- Triggering a static proactive conversation:
- Triggering a template proactive conversation, for example “Hello {{name}}, how can I help you today?”:
unsubscribeEvent
unsubscribeEvent(subscriptionId: number): Promise<void>;
Removes a subscription created with subscribeEvent or subscribeAll. It takes a single parameter, subscriptionId, which is the id of the subscription to be removed.
Type signatures
Messaging SDK actions commonly use the following type signatures. When you use the @ada-cx/messaging-sdk npm package, import them by these names.
AdaMessagingBranding
The object accepted by the branding setting.
AdaMessagingBrandingLauncher
The launcher overrides inside AdaMessagingBranding. backgroundColor is a 3- or 6-digit hex color. iconUrl is an absolute https: URL, ignored when text is set. size is an integer from 32 to 120, in pixels. text is the launcher label, at most 40 characters per language.
AdaMessagingLocalizedText
Text keyed by language code, for example { en: "Aurora Concierge", fr: "Concierge Aurora" }. The map must include the AI Agent’s default language, which the widget uses when the end user’s language has no entry.
AdaMessagingStartOptions
The object accepted by start and loadAdaMessaging. It extends the settings object with handle, which is required unless it was already provided elsewhere.
AdaReadyCallbackParams
The payload for adaReadyCallback.
AdaSdkEventCallback
The callback shape for subscribeEvent subscriptions and eventCallbacks entries.
AdaSdkEventKey
A string type for subscribeEvent keys. It suggests known event keys and also accepts custom strings.
BeforeSend
The hook type for Delegate.
ConversationInfo
The shape returned by getConversation. id is the id of the active conversation, or null if the end user has not sent or received any messages yet. handoff.agent is populated only during an active live agent handoff.
Delegate
The object accepted by setDelegate. beforeSend is called for messages sent via sendMessage only (not composer-typed messages). Return { text } to change the message, false to cancel it (causing sendMessage to reject with DelegateRejected), or pass the input through unchanged. Bounded by a 5-second timeout.
LoadMessagingSdkOptions
The loader options for loadAdaMessaging and loadMessagingSdk. See Pin the CDN build.
MessagingSdkLoadErrorCode
The failure codes on MessagingSdkLoadError.
MetaFieldValue
The value type accepted by metaFields, sensitiveMetaFields, setMetaFields, and setSensitiveMetaFields.
PublicAgentInfo
Basic live agent identity, carried on ConversationInfo and on agent messages in PublicMessage.
PublicMessage
The message shape returned by getMessages and carried in the ada:message:sent and ada:message:received event payloads.
ResetParams
The options accepted by reset. greeting and greetingResponseId both name an Answer response id to trigger after the reset; greeting matches the legacy Chat SDK field. identityToken starts a new identified session and forces a full reset. resetChatHistory: false keeps the conversation history and the current end user.
SendMessageResult
The result resolved by sendMessage once Messaging accepts the end user message.
TriggerPlaybookOptions
Context to apply before a Playbook starts.
WindowInfo
The shape returned by getInfo. isChatOpen reports whether the chat is visible to the end user. isDrawerOpen reports the floating drawer specifically and is always false in parentElement mode. hasActiveChatter reports whether an end user session exists. hasClosedChat reports whether the end user has previously closed a chat.
Before activation, hasActiveChatter reads persisted session presence from local storage in normal mode or session storage in session mode. It applies the configured “Forget after X time” retention window to the confirmed storage snapshot. Confirmed active handoffs and Zendesk Messaging continuity remain present after that window expires. This read does not change storage. It reports false in private mode, with a supplied identityToken, or while a persistence clear is pending. If storage cannot confirm the read, core retries once and reports false if the retry remains unconfirmed.
For this read, private mode includes the dashboard’s Forget After Reload setting, even during a live agent handoff, as in legacy chat.
A stored end user session reports true whether or not the earlier visit was identified, subject to retention. Malformed session records and conflicting stored tokens report false.
During a background resume, persisted session presence remains available while session announcements wait for validation and the App handshake. The provisional conversation, handoff, and messages remain hidden until the resume completes. In parentElement mode, hasActiveChatter uses only the current session and does not read persistence.
Calls from onAdaEmbedLoaded or adaReadyCallback read persisted session presence without opening the drawer or creating a session. Readiness and adaReadyCallback do not wait for storage.
isOpen() resolves immediately from local visibility state without a core request.
With floating widget chrome, getInfo() queues for up to 35 seconds from the host call. In mobile webview, parentElement, and headless modes, it queues for up to five seconds. Requests still queued at the applicable deadline resolve with local state.
Before activation, floating and headless reads wait up to 15 seconds after delivery for core’s storage read. In these modes, delivery sets the response deadline to the later of the current deadline and delivery plus 15 seconds. Total wait is at most 50 seconds for floating requests and 20 seconds for headless requests.
In parentElement and mobile webview modes, delivery starts a fresh five-second response timeout. These calls settle within 10 seconds, below the 30-second bridge timeout and the 35-second native timeouts. If core does not answer by the response deadline, the call resolves with local state.
The 10-second core frame load timeout leaves info requests pending. A later core.ready can deliver requests before the queue deadline. Terminal core errors, current public config failures, and the SDK timeout fallback resolve pending and later calls immediately with local fallback values. A failed activation attempt or the configured outage UI keeps info reads available through core.
A superseded startup failure sends no failure signal and leaves replacement requests pending. Successful activation lets later info reads query core again. destroy() and stop() resolve pending calls immediately with local defaults.