Skip to main content
Headless Mode lets you hide the floating widget completely and start AI voice calls or chat from your own buttons - your website keeps its design while the widget does the work invisibly in the background. Embed the widget with the hide-launcher attribute, drive it with imperative methods (startCall(), sendChatMessage(), …) and react to namespaced DOM events (voice.*, chat.*, widget.*). The widget renders nothing - your page owns 100% of the UI.
Pro feature: Headless Mode is available on our Pro tiers only. To use hide-launcher and the JavaScript API, upgrade your plan from the dashboard.

Why Headless Mode?

You embed our widget on your website, but you may want the call or chat trigger to be your own branded button - a navbar link, a hero CTA, an image - not our floating launcher. Headless Mode removes our UI from the page entirely (even during an active call) and exposes a small, stable JavaScript API so any element on the page can become the trigger, and any part of the page can display the call or chat state.

What you can rely on

Truly invisible

With hide-launcher, the widget renders nothing - ever, even in the middle of an active call.

One API for every provider

The API is identical across Vapi, Retell, and ElevenLabs - same methods, same events, same payloads, same ordering. You never branch on the provider.

Never lose a click

Calls and chat messages triggered before the widget finishes loading are buffered, never lost.

Guaranteed terminal events

Every started flow reaches a guaranteed terminal event - your state machine cannot get stuck.

How it works

  • No SDK, no npm package. One script tag plus one custom element. The API is plain DOM methods and events, so it works in React, Vue, Svelte, vanilla JS, and Webflow custom code alike.
  • Per-embed, not per-campaign. hide-launcher is an attribute on the embed snippet. The same widget can be embedded normally on one page and headless on another.
  • Voice and chat are independent. One invisible widget can power a call button and a custom chat panel at the same time.

Next steps

Quick start

A 5-minute integration: one attribute, five methods, copy-paste examples.

Methods

startCall(), stopCall(), sendChatMessage(), endChatSession(), acceptConsent().

Events

The full widget.*, voice.*, and chat.* event reference with ordering guarantees.

Consent in Headless Mode

How to show your own consent UI when “Require consent” is enabled.

Examples

Complete, copy-paste HTML examples for voice, chat, and both together.

Troubleshooting & FAQ

Requirements, gotchas, and answers to common questions.