AI 電話通話 API:用 AI 代理撥打和接聽真實電話
Wixzel Voice 是一個語音 AI API,用於打造 AI 代理,透過您自己的 SIP 中繼撥打和接聽真實的電話,或在您的網頁和行動應用程式中與人對話。一把 API 金鑰和一份預付餘額即可使用所有語音引擎,依實際用量按秒計費。
最後更新於
什麼是 Wixzel Voice 的 AI 電話通話 API?
使用 Wixzel Voice API,由您定義的 AI 代理會透過您自己的 SIP 中繼撥打和接聽真實電話:以號碼和代理 id 呼叫 POST /v1/calls,依實際用量逐秒計費。
簡單來說,Wixzel Voice 是用於打造 AI 電話代理的語音 AI API:一個由您定義代理、由 Wixzel Voice 執行通話的 AI 撥號 API。外撥時,POST /v1/calls 撥打號碼並接上您的代理。來電時,設定了 inbound_agent_id 的電話號碼會接聽每一通打進來的電話。同一個代理也可以透過即時 API,在網頁或應用程式中與人對話,不需要電話線路;或透過 MCP 伺服器由 AI 助理操作。
Wixzel Voice 的做法是一把 API 金鑰、一份餘額、所有語音引擎:語音轉文字、語言和語音供應商的帳號都屬於平台,因此不需要自備 Deepgram、ElevenLabs 或 OpenRouter 金鑰。唯一需要您自備的是電話線路:自帶 SIP 中繼,可來自 Twilio、Telnyx、Plivo 或任何 SIP 供應商。
如何用 Wixzel Voice 撥打 AI 電話?
在您有了 API 金鑰和一些點數之後,只需四個請求。每個回應都帶有下一個請求需要的 id;範例程式碼從 shell 變數讀取這些 id。
- 01
連接您的 SIP 中繼
您電信業者的主機和憑證。密碼會加密儲存,之後不會再傳回。回應中包含
platform_ip(目前為187.126.120.231),您的電信業者必須將其加入允許清單;以及origination_uri(目前為sip:187.126.120.231:5090),您的電信業者會把來電送到這裡。cURLcurl https://api.voice.wixzel.com/v1/sip-trunks \ -H "Authorization: Bearer $WIXZEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "My carrier", "host": "sip.carrier.example", "username": "acct123", "password": "..." }' - 02
在中繼上登錄電話號碼
您在該電信業者已擁有的號碼,使用 E.164 格式。Wixzel Voice 不販售號碼,也不辦理號碼移轉。如果中繼連接的是您的 Twilio、Telnyx、Plivo、Vobiz 或 Vonage 帳號,也可以改用
POST /v1/phone-numbers/purchase在該帳號上購買新號碼,由您的電信業者依其價格計費。cURLcurl https://api.voice.wixzel.com/v1/phone-numbers \ -H "Authorization: Bearer $WIXZEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+14155550100", "sip_trunk_id": "'"$TRUNK_ID"'" }' - 03
建立代理
一段簡短、口語風格的提示詞、開場第一句話,以及語音:三個模型,或一個即時模型。
opening_message為必填,因為沒有開場白的代理接起電話後會一片沉默。outbound_phone_number_id會讓步驟 2 的號碼成為它的來電顯示號碼。cURLcurl https://api.voice.wixzel.com/v1/agents \ -H "Authorization: Bearer $WIXZEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Support", "system_prompt": "You are a concise support agent.", "opening_message": "Hi, how can I help?", "voice": { "stt": { "model": "deepgram/nova-3" }, "llm": { "model": "openrouter/gpt-4o-mini" }, "tts": { "model": "elevenlabs/eleven_flash_v2_5" } }, "outbound_phone_number_id": "'"$NUMBER_ID"'" }' - 04
撥打電話
一個目的地號碼和一個代理。
Idempotency-Key為必填,因為網路逾時並不能告訴您通話是否已撥出:用同一個金鑰重試,會傳回原本的通話,而不會重複撥號。回應為201,內容是該通話,status: "queued"。cURLcurl https://api.voice.wixzel.com/v1/calls \ -H "Authorization: Bearer $WIXZEL_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "to": "+14155551234", "agent_id": "'"$AGENT_ID"'" }'
在第一通電話接通之前,您的電信業者必須將 platform_ip 加入允許清單。電信業者指南說明了這項設定在 Twilio, Telnyx, Plivo, Vonage, Bandwidth, Exotel, Vobiz, Mobily 中的位置。
如何用 TypeScript 或 Dart 撥打 AI 電話?
官方 SDK 是 npm 上的 wixzel-voice,適用於 Node、瀏覽器和邊緣執行環境上的 TypeScript 與 JavaScript;以及 pub.dev 上的 wixzel_voice,適用於 Dart 與 Flutter。兩者都涵蓋所有端點、會在遇到速率限制時重試,並在會花費金額的路徑上自動產生 Idempotency-Key。其他語言請使用一般的 HTTP API 和 OpenAPI 文件。
import { WixzelVoice } from 'wixzel-voice';
const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY! });
// 1. Connect your SIP trunk.
const trunk = await client.sipTrunks.create({
name: 'My carrier',
host: 'sip.carrier.example',
username: 'acct123',
password: process.env.CARRIER_PASSWORD!,
});
console.log('Allowlist', trunk.platform_ip, 'and send inbound calls to', trunk.origination_uri);
// 2. Register a number you own on it.
const number = await client.phoneNumbers.create({
phone_number: '+14155550100',
sip_trunk_id: trunk.id,
});
// 3. Create the agent, with that number as its caller ID.
const agent = await client.agents.create({
name: 'Support',
system_prompt: 'You are a concise support agent.',
opening_message: 'Hi, how can I help?',
voice: {
stt: { model: 'deepgram/nova-3' },
llm: { model: 'openrouter/gpt-4o-mini' },
tts: { model: 'elevenlabs/eleven_flash_v2_5' },
},
outbound_phone_number_id: number.id,
});
// 4. Place the call. The SDK sends the Idempotency-Key for you.
const call = await client.calls.create({ to: '+14155551234', agent_id: agent.id });
// Inbound: calls to the number are answered by the same agent.
await client.phoneNumbers.update(number.id, { inbound_agent_id: agent.id });
// Later: what happened, what it cost, what was said.
const detail = await client.calls.retrieve(call.id);
console.log(detail.status, detail.cost_micros, detail.failure_code, detail.failure_reason);
for (const line of detail.transcript) console.log(line.role, line.content);import 'dart:io';
import 'package:wixzel_voice/wixzel_voice.dart';
Future<void> main() async {
final client = WixzelVoice(apiKey: Platform.environment['WIXZEL_API_KEY']!);
// 1. Connect your SIP trunk.
final trunk = await client.sipTrunks.create(CreateSipTrunk(
name: 'My carrier',
host: 'sip.carrier.example',
username: 'acct123',
password: Platform.environment['CARRIER_PASSWORD']!,
));
print('Allowlist ${trunk.platformIp}; send inbound calls to ${trunk.originationUri}');
// 2. Register a number you own on it.
final number = await client.phoneNumbers.create(CreatePhoneNumber(
phoneNumber: '+14155550100',
sipTrunkId: trunk.id,
));
// 3. Create the agent, with that number as its caller ID.
final agent = await client.agents.create(CreateAgent(
name: 'Support',
systemPrompt: 'You are a concise support agent.',
openingMessage: 'Hi, how can I help?',
voice: VoiceConfig.composed(
stt: const SttConfig(model: 'deepgram/nova-3'),
llm: const LlmConfig(model: 'openrouter/gpt-4o-mini'),
tts: const TtsConfig(model: 'elevenlabs/eleven_flash_v2_5'),
),
outboundPhoneNumberId: number.id,
));
// 4. Place the call. The SDK sends the Idempotency-Key for you.
final call = await client.calls.create(CreateCall(
to: '+14155551234',
agentId: agent.id,
));
// Inbound: calls to the number are answered by the same agent.
await client.phoneNumbers.update(
number.id, UpdatePhoneNumber(inboundAgentId: agent.id));
// Later: what happened, what it cost, what was said.
final detail = await client.calls.retrieve(call.id);
print('${detail.status} ${detail.costMicros} ${detail.failureCode}');
for (final line in detail.transcript) {
print('${line.role}: ${line.content}');
}
client.close();
}AI 代理如何在 Wixzel Voice 上接聽來電?
為電話號碼設定 inbound_agent_id,打到這個號碼的每通電話都會由該代理接聽。沒有設定時,打到這個號碼的來電會被拒絕。
curl -X PATCH https://api.voice.wixzel.com/v1/phone-numbers/$NUMBER_ID \
-H "Authorization: Bearer $WIXZEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "inbound_agent_id": "'"$AGENT_ID"'" }'另一半設定在您的電信業者端:來電必須送到中繼的 origination_uri(目前為 sip:187.126.120.231:5090)。這是與允許清單分開的設定,位於電信業者主控台的不同位置;如果少了這項設定,號碼就永遠不會響:電信業者無處可送這通電話,所以任何記錄中都不會出現。每通來電都會記錄 direction: "inbound" 和雙方號碼,並觸發 inboundCall webhook。
Wixzel Voice 的通話紀錄會傳回什麼?
POST /v1/calls 會立即傳回該通話,status: "queued"。GET /v1/calls/{id} 在通話進行中和結束後都會傳回完整記錄;通話結束時,會有一個以 X-Wixzel-Signature 簽署的 callCompleted webhook 通知您的伺服器,因此您不必輪詢。
| 欄位 | 內容 |
|---|---|
| status | queued、ringing、in-progress、completed、failed、busy、no-answer 或 canceled。 |
| direction / channel | outbound 或 inbound;透過您的中繼進行的通話為 phone,從瀏覽器或應用程式發起的即時工作階段為 web。 |
| duration_seconds | 通話結束後的通話時長。 |
| engine | 代理所使用的語音引擎。 |
| cost_micros | 通話費用,以微美元計(1,000,000 = $1.00),於通話結算時寫入。從未接通的通話為 null,不收任何費用。 |
| transcript | 每一輪對話,包含 role(user、assistant 或 system)、content 和 UTC 時間戳記。也可以從 GET /v1/calls/{id}/transcript 取得。 |
| summary / recording_url | 錄音,僅限有錄音的通話。透過 API 撥打的通話,summary 為空;請閱讀逐字稿。 |
| failure_code / failure_reason | 未接通的通話:電信業者提供的 Q.850 原因碼(適合用來做程式分支的穩定依據),以及以白話說明的處理方式。 |
| transfers | 每次嘗試把來電者轉給真人都有一筆記錄,包含狀態、響鈴時間和 SIP 原因碼。 |
| metadata | 您附加在 POST /v1/calls 上的扁平字串對應表,原樣傳回。永遠不會傳送給模型。 |
cost_micros 上的每一微美元,都能在 GET /v1/usage/events 的用量記錄中找到對應:辨識的語音秒數、模型的輸入與輸出 token、合成的字元數,以及每分鐘的協調費。
AI 電話未接通時會怎樣?
被電信業者拒絕的通話會有 status: "failed"(或 busy、no-answer)、failure_code 和 failure_reason,以及 cost_micros: null:不收任何費用,為它預留的點數也會釋放。failure_code 是電信業者提供的 Q.850 原因碼,是做程式分支的穩定依據;failure_reason 以白話說明該如何處理。
有些請求在撥號之前就會被拒絕,且不收費:餘額不足以支付前 15 秒時為 402 insufficient_credits,未帶 Idempotency-Key 的直接請求為 400 missing_idempotency_key,超過同時通話上限的通話則以 503 拒絕。 每個失敗代碼和每種拒絕情況,以及各自的處理方式,都列在電信業者頁面上。
在 Wixzel Voice 上,一通 AI 電話的費用是多少?
以一般語速計算的單通通話引擎費用,由計費系統實際依據的價目表算出。每個價格都已含每分鐘 $0.012 的協調費。通話依實際用量逐秒計費,因此 90 秒的通話費用約為三分鐘通話的一半。電信使用您自己的中繼,以您電信業者的費率計費,不包含在內。
| 引擎 | 管線 | 1 分鐘通話 | 3 分鐘通話 | 5 分鐘通話 |
|---|---|---|---|---|
| classic | Deepgram + GPT-4o-mini + ElevenLabs | $0.0867 | $0.2601 | $0.4335 |
| sarvam | Sarvam,全程處理印度語言 | $0.0617 | $0.1851 | $0.3085 |
| gemini-live | Gemini Live,原生音訊 | $0.0491 | $0.1473 | $0.2455 |
| deepgram-agent | Deepgram Voice Agent | $0.1851 | $0.5553 | $0.9255 |
預付制:從 $5 起儲值點數,沒有訂閱,也沒有免費方案。目前最便宜的引擎是 gemini-live,每分鐘 $0.0491。估算您自己的組合。
Wixzel Voice 的 AI 電話通話 API 有哪些限制?
- Wixzel Voice 已上線,正在處理真實通話。行為變更會透過標註日期的
Wixzel-Version標頭發布,現有的金鑰會保留建立時的行為。 - 預設每個帳號可同時進行 5 通通話,可依申請提高。網頁與應用程式工作階段計入同一個上限。
- 轉接真人僅支援盲轉:來電者會直接轉到您列出的號碼。尚未支援指定轉接(先與對方通話再轉),測試通話以及網頁或應用程式工作階段也無法轉接。
- Wixzel Voice 不販售號碼,也不辦理號碼移轉,電話通話需要您自己的 SIP 中繼。它可以在您自己的 Twilio、Telnyx、Plivo、Vobiz 或 Vonage 帳號上為您購買號碼,由您的電信業者計費。
- 網頁與應用程式工作階段傳輸 8 kHz 的 G.711 µ-law 音訊,屬於電話音質,而不是寬頻音質。
- 每把金鑰每秒 10 次 API 請求,突發上限 20 次。遭速率限制的請求一律不收費。
- API 和儲存的資料位於印度孟買。位於美國和印度的語音與語言供應商會在通話期間處理音訊和文字;sarvam 引擎在印度處理語音。
- 沒有免費方案,也沒有試用點數。最低儲值金額為 $5。唯一的免費使用,是每個帳號 5 分鐘從主控台與您的代理對話。
常見問題
什麼是 AI 電話通話 API?
POST /v1/calls 透過您自己的 SIP 中繼撥打電話,而設定了 inbound_agent_id 的電話號碼也以同樣方式接聽來電。Wixzel Voice 是 AI 撥號 API,還是現成的通話代理?
一通 AI 電話的費用是多少?
AI 代理除了外撥,也能接聽來電嗎?
PATCH /v1/phone-numbers/{id} 為電話號碼設定 inbound_agent_id,打到該號碼的電話就會由該代理接聽。您的電信業者必須把來電送到中繼傳回的 origination_uri。沒有設定 inbound_agent_id 時,打到該號碼的來電會被拒絕。AI 代理可以把來電者轉給真人嗎?
human_transfer 中列出的其中一個目的地,透過您的 SIP 中繼撥出。代理先與對方通話再轉接的指定轉接尚未支援,測試通話以及網頁或應用程式工作階段也無法轉接。可以同時進行多少通 AI 通話?
有免費試用嗎?
402 insufficient_credits 拒絕。
