Skip to main content
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

1

Create an agent

The agent whose prompt and voice will run the widget session. Set widget_enabled: true (the default).
2

Decide the routing mode

  • mode="agent" — one static agent per key. Simplest.
  • mode="webhook" — your server picks the agent per visitor via a call.incoming webhook. Use this for logged-in users, A/B tests, or per-page routing.
3

List the allowed domains

Publishable keys are origin-locked. You must name every hostname that will embed the widget. localhost / 127.0.0.1 are 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"]
  }'
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.
allowed_domains must contain at least one entry. *.example.com matches subdomains (e.g. api.example.com) but not the bare domain. Bare wildcards like * or *.* are rejected.

Drop the widget on your site

Three integration options are covered in the widget SDK docs:

React component

<ThunderPhoneWidget publishableKey="pk_live_..." />.

Headless hook

useThunderPhone() for custom UIs.

CDN script tag

ThunderPhone.mount({...}) for non-bundler sites.
All three accept the same publishableKey and render the mic button plus the in-call audio element.

Widget-mode webhooks

When mode="webhook", ThunderPhone calls your webhook_url on every session start with a call.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":   "en-US-James1",
  "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.

Next steps

Widget SDK reference

React / hook / CDN integration details.

Dynamic per-call config

Implement the mode="webhook" flow end-to-end.

Publishable keys reference

Every field on the key resource.

Mic sessions API

Skip the widget; drive LiveKit directly for custom UIs.