ThunderPhone 2.0 is live.Self-serve, from 2¢/min.Read the announcement

Developer cookbook

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

  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 web.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

Static agent
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"]
  }'
Dynamic via webhook
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:

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.


Next steps