Gemini Live on a real phone call with the Wixzel Voice API
Four HTTP requests take you from an empty account to a phone ringing with Google's Gemini Live model on the line: connect your SIP trunk, register a number, create a realtime agent, place the call. A fifth reads back the record, with the transcript and what the call cost. With your carrier already set up it takes about 10 minutes. The Gemini Live engine is $0.0491 per connected minute, the lowest in the price book, so a three-minute call is about $0.15, billed per second from a prepaid balance, plus your carrier's rate.
By Aqeel Shamsudheen · Published · Updated
- Takes
- About 10 minutes with your carrier set up
- Engine
- gemini-live
- Engine time
- $0.0491 per connected minute
What do you need before you start?
- A Wixzel Voice API key with credit. The minimum top-up is $5.
- A SIP trunk at your carrier and a number on it that the carrier lets you present as caller ID.
- curl, jq and uuidgen.
How do you build this on Wixzel Voice, step by step?
01Connect your SIP trunk
Set your key and the API base once, then create the trunk.
teekeeps the full response, because you need two values from it besides the id:shellexport WIXZEL_API_KEY="wv_live_..." API=https://api.voice.wixzel.com/v1 TRUNK_ID=$(curl -s $API/sip-trunks \ -H "Authorization: Bearer $WIXZEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "My carrier", "host": "sip.your-carrier.example", "username": "your-sip-username", "password": "your-sip-password" }' | tee trunk.json | jq -r .id) jq -r '.platform_ip, .origination_uri' trunk.jsonLeave out
usernameandpasswordif your carrier authorises by IP. Either way, allowlistplatform_ipat the carrier so it accepts calls from the platform;origination_uriis where the carrier should send inbound calls, which this guide does not need.02Register the number you will call from
Use your own number, in E.164 form:
shellNUMBER_ID=$(jq -n --arg trunk "$TRUNK_ID" \ '{phone_number: "+14155550100", sip_trunk_id: $trunk}' | curl -s $API/phone-numbers \ -H "Authorization: Bearer $WIXZEL_API_KEY" \ -H "Content-Type: application/json" \ -d @- | jq -r .id)03Create the Gemini Live agent
The voice is one realtime model rather than three stages:
shellAGENT_ID=$(jq -n --arg number "$NUMBER_ID" '{ name: "Gemini Live", system_prompt: "You are a friendly assistant on a phone call. Keep answers to one or two sentences.", opening_message: "Hi, this is an automated assistant. Do you have a minute?", outbound_phone_number_id: $number, voice: { realtime: { model: "google/gemini-live", voice: "Charon" } } }' | curl -s $API/agents \ -H "Authorization: Bearer $WIXZEL_API_KEY" \ -H "Content-Type: application/json" \ -d @- | jq -r .id)voice.realtimehands the whole turn, listening, reasoning and speaking, to Gemini Live, so there is nostt,llmorttsblock; the API refuses a voice that names both shapes.Charonis one of Gemini's prebuilt voices, andGET /v1/engines/gemini_live/voiceslists them all with Google's one-word descriptions.outbound_phone_number_idgives the agent a caller ID, which is what lets the next request leave outfrom_number_id.04Place the call
Replace the
tonumber with the phone you want to ring:shellCALL_ID=$(jq -n --arg agent "$AGENT_ID" '{to: "+14155551234", agent_id: $agent}' | curl -s $API/calls \ -H "Authorization: Bearer $WIXZEL_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d @- | jq -r .id)The API answers
201withstatus: "queued"at once, and the phone rings a moment later.Idempotency-Keyis required here: a network timeout tells you nothing about whether the call was placed, and a retry with the same key returns the original call instead of dialling twice, so keep the key if you script retries. A call that cannot fund its first 15 seconds is refused with402before anything is dialled.05Read what happened
The fifth request reads the call back:
shellcurl -s $API/calls/$CALL_ID \ -H "Authorization: Bearer $WIXZEL_API_KEY" | jqExample response, shortened{ "id": "6a96a3ead6e886d42462dd3e", "object": "call", "session_id": "sip-5b0c7c0e-9d1f-4c52-8a9e-2f0d3a4b6c7d", "status": "completed", "direction": "outbound", "channel": "phone", "engine": "gemini_live", "to": "+14155551234", "duration_seconds": 94, "cost_micros": 76923, "failure_code": null, "failure_reason": null, "transcript": [ { "role": "assistant", "content": "Hi, this is an automated assistant. Do you have a minute?" }, { "role": "user", "content": "Sure, go ahead." } ] }statusmoves fromqueuedthroughringingandin-progresstocompleted, or ends asfailed,busyorno-answer.cost_microsis written when the call settles (1,000,000 is $1.00) and staysnullon a call that never connected, because such a call is not charged. When a call fails,failure_codeis the carrier's Q.850 cause (17 busy, 19 no answer, 21 rejected by the carrier) andfailure_reasonsays what to do about it.GET /v1/usage/events?session_id=…itemises every charge.
What does this build cost on Wixzel Voice?
Engine time for 3-minute calls on the gemini-live engine at $0.0491 per connected minute: about $0.15 per call. Telephony is your own trunk at your carrier’s rate and is not included.
| Calls per month | Connected minutes | Engine cost per month |
|---|---|---|
| 300 | 900 | $44.19 |
| 1,500 | 4,500 | $221 |
| 6,000 | 18,000 | $884 |
The per-minute figure is at typical speech rates, including the orchestration fee. Gemini Live is metered in audio tokens while the call is live, so a quiet call costs less than the estimate and a talkative one more. The example response above prices a 94-second call at the per-minute rate. Your carrier bills the line separately, with no markup.
Prepaid, with no subscription and no free tier: add credit from $5 and usage spends it. Estimate your own mix.
Which Wixzel Voice limits apply to this build?
- Phone calls need your own SIP trunk. Wixzel Voice does not sell, port or hold numbers. It can buy one for you on a Twilio, Telnyx, Plivo, Vobiz, Vonage or Exotel account you connect from the console, billed by your carrier.
- A test call from
POST /v1/agents/{id}/test-callspeaks its one phrase through the classic voice pipeline, because Gemini Live has no single-phrase mode. To hear the Gemini voice itself, place an ordinary call. - Five calls can be live at once per account by default, raised on request.
- No latency figure is published: a realtime engine answers as fast as the model itself does. Behavioural changes to Wixzel Voice ship behind a dated
Wixzel-Versionheader.
Frequently asked questions
Can Gemini Live make phone calls?
{"realtime": {"model": "google/gemini-live"}}, and POST /v1/calls dials a real number over your own SIP trunk with Gemini Live on the line.Do I need a Google Cloud or Gemini API key?
wv_live_ API key and a prepaid balance cover Gemini Live and every other engine.Which voices can Gemini Live use on a call?
Charon, Kore and Puck. GET /v1/engines/gemini_live/voices lists them all. A voice from another engine's roster is refused when the agent is created.What does a Gemini Live phone call cost?
Can the Gemini Live agent answer inbound calls too?
inbound_agent_id to the agent with PATCH /v1/phone-numbers/{id}, and point your carrier's inbound route at the trunk's origination_uri.Where to read more
- Quickstartdocs
The same four requests, also in the TypeScript and Dart SDKs.
- Voice enginesdocs
The realtime voice shape, rosters and languages.
- SIP trunksdocs
Allowlisting, inbound routing and what each failure code means.
- Idempotencydocs
Why POST /v1/calls needs a key and how replays work.
About Wixzel Voice
Wixzel Voice is the unified API for voice agents: the latest voice engines and the models they run, any SIP carrier, and the apps an agent uses on a call, behind one API key and one prepaid balance, billed per second of actual usage. Build agents that place and answer real phone calls, or talk to people in your web and mobile apps, and switch engines or carriers anytime.
More guides
Claude, in Claude Code or claude.ai, placing a real call over your SIP trunk and reading back the transcript, with a confirmation before anything dials.
Your existing Twilio number answered by an AI receptionist that books appointments into the API, built in Node.js.
Two phone agents, one speaking Hindi and one Malayalam, on Sarvam's Indian-language models, answering or placing calls over your SIP trunk.
A Flutter app where users talk to your voice agent over a WebSocket, with the API key kept on your server and no phone number involved.
A list of leads called by your agent over your SIP trunk, in batches sized to your concurrency limit, with every call's status and transcript read back.
A talking mascot in the corner of your website that visitors call from the browser, limited to your domains and your daily caps, with every caller listed.
A Flutter screen with your agent's mascot that moves its mouth with the agent's voice during a realtime call, with your API key kept on your server.
Build your first voice agent

