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.0466 per connected minute, the lowest in the price book, so a three-minute call is about $0.14, 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.0466 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": 73007, "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.0466 per connected minute: about $0.14 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 | $41.94 |
| 1,500 | 4,500 | $210 |
| 6,000 | 18,000 | $839 |
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.
- 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. Wixzel Voice is in alpha, and behavioural changes ship behind a dated
Wixzel-Versionheader.
Frequently asked questions
- Can Gemini Live make phone calls?
- Gemini Live is a model, not a phone service. Wixzel Voice connects the two: create an agent whose voice is
{"realtime": {"model": "google/gemini-live"}}, andPOST /v1/callsdials a real number over your own SIP trunk with Gemini Live on the line. - Do I need a Google Cloud or Gemini API key?
- No. On the hosted platform the provider accounts belong to Wixzel Voice. One
wv_live_API key and a prepaid balance cover Gemini Live and every other engine. - Which voices can Gemini Live use on a call?
- Its prebuilt voices, such as
Charon,KoreandPuck.GET /v1/engines/gemini_live/voiceslists them all. A voice from another engine's roster is refused when the agent is created. - What does a Gemini Live phone call cost?
- $0.0466 per connected minute at typical speech rates, about $0.14 for three minutes, billed per second from prepaid credit, plus your carrier's rate. A call that never connects costs nothing.
- Can the Gemini Live agent answer inbound calls too?
- Yes. Set the phone number's
inbound_agent_idto the agent withPATCH /v1/phone-numbers/{id}, and point your carrier's inbound route at the trunk'sorigination_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 a voice AI API for building AI agents that place and answer real phone calls over your own SIP trunk, or talk to people in your web and mobile apps. One API key and one prepaid balance cover every voice engine, billed per second of actual usage.
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.
