Embed the web widget
Drop a voice agent onto your marketing or support site with a single script tag — visitors talk to it straight from the browser, no phone number required.
The web widget gives your site visitors a click-to-talk conversation with an AI agent, using the browser's microphone. It's a separate JavaScript / React SDK with its own SDK reference — this guide focuses on the ThunderPhone-side setup the widget needs.
Prerequisites
- Create an agent
The agent whose prompt and voice will run the widget session. Set
widget_enabled: true(the default). - Decide the routing mode
mode="agent"— one static agent per key. Simplest.mode="webhook"— your server picks the agent per visitor via aweb.incomingwebhook. Use this for logged-in users, A/B tests, or per-page routing.
- List the allowed domains
Publishable keys are origin-locked. You must name every hostname that will embed the widget.
localhost/127.0.0.1are always allowed during local dev.
Create a publishable key
curl -X POST https://api.thunderphone.com/v1/publishable-key \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Marketing site (prod)",
"mode": "agent",
"agent_id": 12,
"allowed_domains": ["example.com", "*.example.com"]
}'curl -X POST https://api.thunderphone.com/v1/publishable-key \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Support (dynamic)",
"mode": "webhook",
"webhook_url": "https://example.com/thunderphone/widget-hook",
"allowed_domains": ["support.example.com"]
}'The response includes a key starting with pk_live_.... Publishable
keys are public by design — safe to ship in your front-end bundle.
See Publishable keys reference for
all fields.
Drop the widget on your site
Three integration options are covered in the widget SDK docs:
<ThunderPhoneWidget publishableKey="pk_live_..." />.
useThunderPhone() for custom UIs.
ThunderPhone.mount({...}) for non-bundler sites.
All three accept the same publishableKey and render the mic button
plus the in-call audio element.
Widget context is truncated at 12,000 characters (roughly 3,400
tokens of typical English text) and counts toward the
prompt-size surcharge.
Widget-mode webhooks
When mode="webhook", ThunderPhone calls your webhook_url on every
session start with a web.incoming payload. Return the agent
configuration you want to run for that visitor — it follows the same
response schema as phone
calls:
{
"prompt": "You are a VIP concierge for Jane Doe.",
"voice": "john",
"product": "storm-base",
"tools": [ /* per-customer tools */ ]
}You can mix context from your own session (which customer is browsing, which page they're on) into the prompt, and swap agents per rollout.
Observe the sessions
Widget sessions show up in
GET /v1/calls with
direction="widget" — same transcript, recording, grading, and
billing as phone calls. Filter by direction to build a widget-only
dashboard.