Skip to main content

Phone Calls

Give your voice agent a phone number so customers can call it — or have it call them. thinnestAI handles the entire call lifecycle: answering, speaking, listening, and hanging up.

Prerequisites

  • A thinnestAI account with voice enabled
  • A voice agent configured with TTS and STT settings
  • A phone number from Twilio, Vobiz, or Exotel (BYOK supported for all three)

Quick Start

1. Get a Phone Number

Option A: Twilio (recommended for most users)
  1. Sign up at twilio.com
  2. Purchase a phone number in the Twilio Console
  3. In thinnestAI dashboard, go to Settings > Phone Numbers > Add > Twilio
  4. Enter your Account SID and Auth Token
Option B: Vobiz (for Indian telephony)
  1. Get SIP credentials from your Vobiz account
  2. In thinnestAI, go to Settings > Phone Numbers > Add > Vobiz
  3. Enter your SIP trunk credentials
Option C: Exotel BYOK (for Indian telephony with an existing Exotel account)
  1. In thinnestAI, go to Settings > Phone Numbers > Add > Exotel BYOK
  2. Enter your Exotel API key, API token, and account SID
  3. Pick the ExoPhone you want to import → click Import
During import we:
  • create an Exotel vSIP trunk so outbound calls route through LiveKit, and
  • attempt to set the ExoPhone’s VoiceUrl to our inbound webhook so inbound calls reach your agent.
The inbound auto-configure step is best-effort — see Exotel inbound setup below for the exact webhook URL and a manual fallback if it doesn’t take. Option D: Plivo BYOK (for Indian or global telephony with an existing Plivo account)
  1. In thinnestAI, go to Settings > Phone Numbers > Add > Plivo BYOK
  2. Enter your Plivo main-account auth_id (starts with MA…) and auth_token
  3. Pick the number you want to import → click Import
During import we set up the full Plivo Zentrunk SIP path on your account in one shot:
  • a SIP credential for outbound auth
  • an Origination URI pointing at our LiveKit SIP endpoint
  • a Zentrunk outbound trunk so your agent can place calls from the number
  • a Zentrunk inbound trunk so incoming calls route directly to your agent
  • attaching the number to the inbound trunk
There’s no webhook in the loop. Calls go SIP-direct between Plivo and our LiveKit termination, which is lower latency and fewer moving parts than the webhook-based providers above.
Plivo Zentrunk is required. Plivo BYOK only works on Plivo plans that include the Zentrunk SIP-trunking product (Pay-As-You-Go with the Zentrunk add-on, or higher). If your account is on the free trial or your plan doesn’t include Zentrunk, the import is blocked with a clear error toast telling you to upgrade — we don’t fall back to a slower webhook-based path. Use BYO-SIP (Option E) with a different provider if you can’t upgrade Plivo.
Main-account credentials only. Use your Plivo main-account auth_id (starts with MA…), not a subaccount (SA…). Subaccount credentials can read your Zentrunk resources but typically can’t create new ones, which makes Plivo BYOK import fail at the first step.
Indian local numbers are one-way bound by Plivo’s carrier policy. Plivo permanently locks Indian local DIDs to whichever Zentrunk trunk they were first bound to. Once you import an Indian local number through thinnestAI, you cannot delete-and-re-import it later — Plivo’s API rejects the re-bind step with "INDIA - local numbers cannot be linked to Zentrunk."If you accidentally delete one of these numbers, the only recovery paths are:
  1. Release the number on your Plivo dashboard and re-purchase it. Plivo resets the binding on a fresh purchase.
  2. Open a Plivo support ticket asking them to clear the binding on the specific number.
thinnestAI catches this case before it costs you anything: a pre-flight check on the import endpoint refuses with HTTP 409 + a clear error message if the number is already locked, and the delete confirmation in the phone-numbers UI warns you before you click Delete on an Indian Plivo BYOK row.This restriction applies only to Indian local numbers. Toll-free / mobile / non-Indian Plivo numbers can be re-imported normally — last confirmed 2026-06-04 against +91 80 3144 8181.
Option E: Bring Your Own Number (other providers) If you already have a number with any other SIP provider:
  1. Go to Settings > Phone Numbers > Add > Existing
  2. Enter the number in E.164 format (e.g., +14155551234)
  3. Point your provider’s webhook to:
https://api.thinnest.ai/twilio/incoming/YOUR_PHONE_ID

2. Assign to Your Agent

  1. Open your voice agent
  2. Go to Deploy > Phone
  3. Select your phone number
  4. Configure the greeting message
  5. Click Enable

3. Test It

Call your number — your agent picks up immediately.

Test from the studio (browser or phone)

Every voice agent’s builder page has a Try Voice Call dropdown with two options:
  • Web Call — opens a browser-based playground; you speak through your mic, the agent replies through your speakers. Best for quick iteration while editing the prompt.
  • Phone Call — opens a modal, you enter your phone number, and the platform places a real outbound call to you. Best for verifying voice quality on the actual phone network and confirming the agent feels right end-to-end.

How it works

  1. Click Try Voice Call → Phone Call on the agent builder page.
  2. Type your number with country code (+91 or +1) and press Call my phone. Recently-used numbers are remembered for one-click retest.
  3. Your phone rings. Pick up and talk to the agent — same TTS, STT, prompt, and turn detection it would use in production.
  4. The modal walks through Setting up → Ringing → Connected (with a MM:SS / 02:00 counter)Ended. You can hang up your phone or click End Call in the modal at any time.

Limits

Phone test calls are free — the platform absorbs the per-minute telephony cost. Bounded by:
LimitValueWhat happens at the limit
Per user / day5 callsModal shows “You’ve used all 5 test calls for today. They reset at midnight UTC.”
Per destination / day (across all users)3 calls”That number has already received 3 test calls today. Try again tomorrow.” (anti-robodial)
Per call duration2 minutesModal counter shows 02:00; call ends server-side at the cap, you don’t have to do anything
Counters reset at midnight UTC.

Country support

DestinationTrial-pool number from
+91 (India)Vobiz IN
+1 (US)Plivo US
Anywhere elseNot supported — modal returns “Test calls currently support +91 (India) and +1 (US) destinations only.” Use a BYOK number (Twilio / Vobiz / Exotel) for other regions.

What you can rely on

  • Same code path as production. Pool dial reuses dispatch_outbound_call — the same flow campaigns and /voice/outbound/dial use. Whatever you hear is what your customers will hear.
  • Recorded and logged. Every test call is a normal voice session in your activity log, tagged call_type=studio_test so analytics dashboards filter it out of paying-call totals.
  • No race on pool members. When two studio test calls fire at the same instant, only one wins the trial number (Postgres FOR UPDATE SKIP LOCKED) — the other gets 503 pool_exhausted and the modal shows “All trial numbers are in use right now. Try again in a minute.”
  • No silent hang on failed dispatch. If the SIP dial never reaches your phone, the modal surfaces a dispatch_timeout error after 90 seconds instead of spinning forever.

Endpoints (for reference)

EndpointPurpose
POST /voice/studio/test-callPlace a test call. Body: { "agent_id": "...", "to_number": "+91XXXXXXXXXX" }
GET /voice/studio/test-call/{session_id}/statusPoll for call state (initiating / ringing / live / ended) and duration.
POST /voice/studio/test-call/{session_id}/endEnd an in-progress test call (the modal’s End Call button).
GET /voice/studio/quotaGet the user’s remaining-quota hint without placing a call.

Inbound Calls

When someone calls your number:
Caller dials your number

Twilio/Vobiz routes to thinnestAI via SIP

Voice engine picks up, plays greeting

Caller speaks → STT → Agent processes → TTS → Caller hears response

Loop continues until call ends

Configuring Inbound Behavior

SettingDescriptionExample
GreetingFirst thing the agent says”Hello, thanks for calling Acme Support.”
System promptAgent’s personality and rules”You are a friendly support agent…”
Max durationMaximum call length600 seconds (10 min)
RecordingRecord calls for reviewEnabled/disabled
TranscriptionSave full text transcriptsEnabled by default
After-hoursMessage when agent is off”We’re closed. Please call back…”

Example Agent Configuration

{
  "voice": {
    "greeting": "Hi, thanks for calling Acme. How can I help you today?",
    "tts": {
      "provider": "aero",
      "model": "aero-2",
      "voice": "maya"
    },
    "stt": {
      "provider": "deepgram",
      "model": "nova-2",
      "language": "en"
    },
    "max_duration": 600,
    "recording": true
  }
}

Outbound Calls

Have your agent call customers proactively.

Single Call via API

curl -X POST "https://api.thinnest.ai/voice/outbound/dial" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agent_xyz",
    "to_number": "+14155551234",
    "from_number": "+18005551234",
    "context": {
      "customer_name": "Jane Doe",
      "appointment_date": "March 10, 2026"
    }
  }'

Scheduled Calls

Schedule a call for a future time:
curl -X POST "https://api.thinnest.ai/voice/outbound/dial" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "agent_id": "agent_xyz",
    "to_number": "+14155551234",
    "from_number": "+18005551234",
    "scheduled_at": "2026-03-10T14:00:00Z"
  }'

Batch Calls (Campaigns)

For bulk outreach, use Campaigns:
  1. Create a campaign with your voice agent
  2. Upload a contact list (CSV or manual)
  3. Set schedule, concurrency, and retry rules
  4. Launch — the platform calls each contact automatically

Call Status Webhook

Track call progress by providing a webhook URL:
{
  "webhook_url": "https://your-app.com/call-status",
  "to_number": "+14155551234",
  ...
}
You’ll receive events: initiating, ringing, in_progress, completed, failed, no_answer.

Exotel inbound setup (BYOK)

After importing an Exotel BYOK number, inbound calls only reach your agent once an App on the Exotel side points at our webhook. We try to set this automatically during import via Exotel’s IncomingPhoneNumbers API — if that works, you’re done. If it doesn’t (your Exotel account uses the newer Flow Builder, or the SID couldn’t be resolved), do the manual setup below.

Find the webhook URL

Every imported number has a unique webhook URL of the form:
https://api.thinnest.ai/exotel/incoming/{phone_id}
Note: the inbound webhook lives at the root path (/exotel/incoming/...), not under /voice/. The dashboard always shows the exact URL for the row so you don’t have to remember. Open Settings > Phone Numbers, find the row for your Exotel number, and click the gear icon next to the BYOK pill. The modal shows the exact webhook URL for that number (with a copy button) plus a Retry auto-configure button that calls the Exotel API again.

Retry auto-configure

The fastest path. The modal’s Retry auto-configure button hits:
POST https://api.thinnest.ai/voice/exotel/byok/configure-inbound/{phone_id}
…which calls Exotel’s API to set the ExoPhone’s VoiceUrl to our webhook. Safe to retry. Returns either { "configured": true } (you’re done) or { "configured": false, "manual_steps": "…" } (use the manual setup below).

Manual setup in the Exotel dashboard

If auto-configure didn’t take:
  1. Open the Exotel dashboard.
  2. Go to AppsCreate new App.
  3. Drag a Passthru applet onto the flow. Do not use the Voicebot applet — it expects a different audio protocol that LiveKit doesn’t speak.
  4. Paste the webhook URL (from the gear-icon modal) into the Passthru applet’s URL field. Save the App.
  5. Go to ExoPhones, find your number, and assign the App you just created.
  6. Place a test call to confirm.

Why the Voicebot applet doesn’t work

The Voicebot applet streams raw audio to a custom WebSocket endpoint using Exotel’s proprietary protocol. thinnestAI routes calls through LiveKit SIP, so the inbound flow needs a Passthru applet that hits our HTTP webhook — we respond with ExoML <Dial><Sip> and Exotel forwards the call to LiveKit.

SIP Trunking

For enterprise setups, connect your existing PBX or contact center via SIP:
Your PBX / Contact Center
        ↓ (SIP)
Twilio Elastic SIP Trunk / Vobiz
        ↓ (SIP)
thinnestAI Voice Engine (LiveKit)

AI Agent handles the call

Benefits

  • Use existing phone numbers — no porting needed
  • Keep your current PBX infrastructure
  • Route some calls to AI, others to humans
  • Failover between providers
See the full SIP Integration guide for setup details.

Call Analytics

Every call generates:
  • Duration and timestamps
  • Full transcript (caller and agent)
  • Recording (if enabled)
  • Token usage and cost
  • Caller phone number (auto-captured as a lead)
View call history in Voice > Sessions in the dashboard.

Pricing

ProviderRateUnit
Twilio~$0.015/minPer-minute (inbound + outbound)
Vobiz~$0.005/minPer-minute (India)
thinnestAIPer-tokenLLM + TTS + STT usage
Exact rates depend on your Twilio/Vobiz plan and the TTS/STT providers you choose.

Troubleshooting

IssueSolution
No audio on callsCheck TTS provider is configured and has valid API key
Agent doesn’t pick upVerify webhook URL is correct in Twilio/Vobiz/Exotel
Exotel inbound caller hears “no voicebot flow attached”Open the gear-icon modal for your Exotel number → Retry auto-configure, or follow the Exotel inbound setup manual steps — make sure you use a Passthru applet, not Voicebot
Calls drop immediatelyCheck max_duration setting and provider account balance
Poor transcriptionTry a different STT model (nova-2 is recommended)
High latencySwitch to a faster TTS provider or a lower-latency STT
Echo on callsCheck duplex audio settings in voice configuration