Skip to navigation

Interactive Avatar: Widget page API

Control the widget from your own code, and react when a call starts, ends or fails.

The script snippet gives your page a small JavaScript API, window.SynthesiaInteractiveAvatar. You can use it to open and close the widget from your own buttons, to react when a call starts, ends or fails, and to link each call to your own records. For example, you can send those events to your analytics, or show a fallback contact form when the avatar can’t take a call.

You can also control the <synthesia-interactive-avatar> element directly. It has its own open(), close() and init() methods, and it fires each event as a DOM event. The iframe snippet has no page API, so you need the script snippet for anything on this page.

Methods

All methods live on window.SynthesiaInteractiveAvatar. Most of them take an optional deployment ID. Pass one to address a single widget, or leave it out to address every widget on the page.

MethodWhat it does
open(deploymentId?)Expands the bubble.
close(deploymentId?)Minimizes the bubble.
init(deploymentId?)Loads a widget that is waiting for consent. See Consent deferral.
on(name, handler)Calls handler each time the event fires. It returns a function that you call to remove the handler again.

The element has its own open(), close() and init() methods, which act on that element’s widget only.

open() and close() only work once the widget is ready. If you want the bubble to open as soon as possible, call open() from a ready handler. This example uses the function form of the API, so it also works before the script has loaded:

SynthesiaInteractiveAvatar("on", "ready", function (detail) {
SynthesiaInteractiveAvatar.open(detail.deploymentId);
});

Events

Events tell your page what the widget and the visitor are doing. Listen to them with on(), or with addEventListener on the element, where each event has a name that starts with synthesia-ia:.

Every handler receives an object with the widget’s deploymentId and its current state. When the state is error, the object also has an error field. The two call events also carry a sessionId. On the element, you find the same object in the event’s detail.

EventDOM event on the elementFires when
readysynthesia-ia:readyThe widget appears on the page for the first time.
openedsynthesia-ia:openedThe bubble expands. This includes a bubble that starts expanded.
closedsynthesia-ia:closedThe bubble minimizes.
session_startedsynthesia-ia:session-startedThe visitor’s call has started. It fires once per call.
session_endedsynthesia-ia:session-endedA call that started is over, because it ended, dropped or failed. It fires once for each call that started.
errorsynthesia-ia:errorThe widget enters the error state.

state tells you where the call is. It’s idle before a call or when the visitor is back at the start, connecting while a call starts, and in_call while it runs. It’s ending while a call the visitor ended is closing, ended once the call is over, and error when something went wrong. The changes to connecting, to ending and back to idle have no event of their own. You see them in state on the next event.

Errors

When something goes wrong, for example the widget can’t load or a call can’t start or go on, the widget enters the error state and fires an error event. The event’s error field holds a code and a message. Branch on code, which stays stable. Use message only for your logs: it’s English text for developers, and we may reword it.

CodeWhat happened
handshake_invalidSynthesia refused the widget’s security check. A retry usually works.
captcha_failedThe bot check failed.
origin_not_allowedYour page’s origin isn’t in the deployment’s allowed origins.
not_foundThe deployment doesn’t exist, or it isn’t published.
configuration_invalidThe published configuration can’t run a session.
rate_limitedYour workspace sent too many session requests in a short time.
no_creditYour workspace has no credit left.
concurrency_limit_reachedYour workspace has reached its limit on calls at the same time, or the visitor waited too long for a free place.
daily_limit_reachedA daily call limit has been reached.
spend_limit_reachedYour workspace has reached its spend limit.
session_unavailableThe service couldn’t start a call.
internalSomething went wrong in the visitor’s browser or on your page, or something unexpected failed. See below.

The internal code

internal covers problems on the visitor’s side and on your page, plus anything unexpected. Its message, meant for your logs, says which of these happened:

  • The visitor denied the microphone, your page blocked it, or the browser found none.
  • The connection check before the call failed.
  • Your page sent no referrer, so the widget couldn’t check your origin.
  • The widget frame didn’t load. In that case your page gets a single error event about 15 seconds after the page loads, or after you call init() if you use consent deferral. The message is “The widget frame did not become ready.”
  • Something else failed unexpectedly.

A blocked origin or an unpublished deployment usually stops the frame from loading at all. That’s why you usually see internal for these two cases, and not origin_not_allowed or not_found.

We may add new codes over time. Treat any code you don’t recognize as a generic failure.

Calling the API before the script loads

Because the script loads with async, it doesn’t hold up your page, but SynthesiaInteractiveAvatar may not exist yet when your own code runs. To call the API early, add this stub above the script tag. The stub queues your calls, and the script runs them once it has loaded:

<script>
window.SynthesiaInteractiveAvatar =
window.SynthesiaInteractiveAvatar ||
function () {
(SynthesiaInteractiveAvatar.q = SynthesiaInteractiveAvatar.q || []).push(
arguments
);
};
SynthesiaInteractiveAvatar("on", "session_started", function (detail) {});
</script>

Until the script has loaded, call the API as a function and pass the method name first, for example SynthesiaInteractiveAvatar("open"). In this form, on doesn’t return a function that removes the handler.

If your site has a Content Security Policy, the stub needs your nonce or its hash, like any other inline script. See Use a nonce.

session_started and session_ended also carry a sessionId. It’s the call’s public ID, in the form ses_…, and it’s the same on both events for one call. Store it next to your own records, such as an order or a support ticket, so you can tell later which conversation belongs to which customer:

SynthesiaInteractiveAvatar.on("session_started", function (detail) {
saveSessionId(detail.sessionId);
});

sessionId can be missing if the widget didn’t report one, so treat it as optional.