Organizations
Top-level tenant. Owns every other resource.
Agents
The configuration that drives each call — prompt, voice, tier.
Phone numbers
Inbound / outbound endpoints tied to an agent.
Calls
One real conversation. Has a transcript, recording, grade, and bill.
Web widget
Browser-mic version of a call, keyed to a publishable key.
Webhooks
Real-time events ThunderPhone sends to your server.
Organizations
An organization is the unit of tenancy. Every other resource — agents, phone numbers, calls, keys — belongs to exactly one org. Your account can belong to many orgs; each has its own balance, its own keys, and its own members list. Thesk_live_ API key you create from the dashboard is bound to one
organization. That binding is what makes the REST API so flat: you
never put an org id in URL paths, because your key already identifies
it.
You’ll use:
/v1/orgs— list, create, rename, or delete organizations./v1/membersand/v1/invites— team and role management./v1/developer/api-keys— create or rotate API keys.
Agents
An agent is the AI configuration that runs a call. It bundles:- A prompt that governs what the agent says and how it behaves.
- A voice for text-to-speech output.
- A product tier (
spark,bolt,storm-*) that trades latency for reasoning quality — see the product tier table. - Optional tool integrations — reusable HTTP calls the agent can make mid-conversation.
- Optional behavior knobs: speak order, acknowledgement-prompt mode, background track, hold timeout.
PATCH records a snapshot under
GET /v1/agents/{id}/versions.
You’ll use:
/v1/agents— CRUD + duplicate / transfer / version history.- Prompt helpers to detect or translate prompts.
Phone numbers
A phone number belongs to an org and has an inbound agent and/or an outbound agent assigned. Inbound calls to the number are routed to the inbound agent; outbound calls placed from the number use the outbound agent by default. Two sources exist:- Demo numbers — provisioned by ThunderPhone for inbound use only. Good for smoke tests and trials. Demo numbers can’t place outbound calls.
- VoIP numbers — brought from your own provider (Twilio, Telnyx, SignalWire, Vonage, or any SIP trunk) via a VoIP connection. Once imported and verified, they support inbound and outbound.
GET /v1/phone-numbers/{id}/versions.
You’ll use:
/v1/phone-numbers— list, provision, assign, transfer, release./v1/voip-connections— bring your own numbers./v1/phone-number-labels— label the external numbers your agents are talking to.
Calls
Every inbound call, outbound call, mic session, and widget session becomes a call log record. A call log carries:call_id— stable across every event for this call.direction—inbound,outbound,mic, orwidget.- The snapshotted agent config (
prompt,voice,product). - Full transcript (role-tagged), full structured turn history (including function calls and interruption markers), and a time- limited signed URL to the MP3 recording.
- Billing total in cents and billable minutes.
- Optional AI quality grade (
score,call_outcome,detected_issues). - Optional issue reports filed by humans or by grading.
in_progress → completed or failed. On
completion, ThunderPhone can optionally fire a
call.complete webhook.
You’ll use:
/v1/calls— list (paginated), fetch detail / transcript / history / audio / grade, file issues./v1/calls/export— bulk CSV / JSON dump./v1/issue-reports— org-wide feed./v1/test-calls— programmatic smoke tests.
Web widget
The web widget is an embeddable JavaScript / React component that gives your site visitors a mic-based conversation with an agent — no phone number needed. It authenticates to ThunderPhone with a publishable key (pk_live_...) that’s origin-locked via an
allowed-domain list, so it’s safe to ship in client-side code.
Publishable keys run in one of two modes:
mode="agent"— the key is statically bound to one agent. Easiest setup.mode="webhook"— the widget calls yourcall.incomingwebhook per visitor to dynamically choose an agent. Use this for customer-specific or session-aware routing.
direction="widget" or direction="mic" on
the call log.
You’ll use:
/v1/publishable-key— CRUD for widget keys./v1/mic-session— if you want to bypass the widget and drive LiveKit directly.- Widget SDK docs — React, headless hook, and CDN script-tag integrations.
Webhooks
ThunderPhone sends HTTP POST webhooks to your server when things happen during and after a call. There are two delivery models:- Webhook endpoints (recommended): manage many URLs at
/v1/developer/webhook-endpointswith per-endpoint secrets and per-endpoint event subscriptions. - Legacy single-URL webhook: one URL per org receives every event.
Managed at
/v1/webhook. Kept for backward compatibility.
- Blocking events expect your server to respond with configuration
that shapes the in-flight call. Only
call.incomingis blocking; you have ~2 seconds to respond. - Non-blocking events are fire-and-forget. We retry on non-2xx with exponential backoff for 24 hours.
X-ThunderPhone-Signature. See
Signature verification.
You’ll use:
/webhooks/overview— delivery semantics and verification./webhooks/events— the full event catalog./webhooks/endpoints— endpoint CRUD.
Tool integrations
A tool integration is a reusable HTTP endpoint an agent can call during a conversation. You give ThunderPhone:- An OpenAI-style function schema (
{type: "function", function: {...}}). - An endpoint URL + method + headers to call when the agent invokes it.
tools field
(for one-off use) or save reusable ones as
/v1/integrations and link them to
multiple agents via integration_ids.
You’ll use:
/v1/integrations— CRUD./v1/integrations/test-request— sandbox request against your tool endpoint.- Function Tools guide — the full JSON schema and signed-request contract.
Billing
ThunderPhone is prepaid. Each org carries a USD balance; every call debits the balance at the product tier’s per-minute rate. When balance reaches$0.00, inbound calls are rejected and outbound calls
return 402 Payment Required.
You can top up manually via POST /v1/billing/top-up or configure
automatic reloads at a balance threshold.
You’ll use:
/v1/billing— balance, auto-reload, transaction history.
Putting it together
Handle inbound calls
The canonical “answer a phone call with an AI” flow.
Place outbound calls
Programmatic outbound calling from your own code.
Embed the web widget
Drop an agent onto your marketing or support site.
Bring your own numbers (VoIP)
Connect Twilio / Telnyx / SignalWire / Vonage and import numbers.
Dynamic per-call config
Pick an agent or rewrite a prompt per incoming call via webhook.
Build a tool integration
Give your agent an HTTP superpower.
Test an agent end-to-end
Use the test-calls API to run batches of canned scenarios.
Verify webhook signatures
Get the HMAC check right once and reuse everywhere.