본문으로 건너뛰기
에이전트형 전화 통신을 위한 API

AI 전화 통화 API: AI 에이전트로 실제 전화를 걸고 받기

Wixzel Voice는 자체 SIP 트렁크로 실제 전화를 걸고 받거나 웹·모바일 앱에서 사람들과 대화하는 AI 에이전트를 만들기 위한 음성 AI API입니다. API 키 하나와 선불 잔액 하나로 모든 음성 엔진을 사용하며, 실제 사용량에 따라 초 단위로 과금됩니다.

최종 업데이트:

AI 전화 통화를 위한 Wixzel Voice 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가 들어 있으며, 아래 코드는 그 값을 셸 변수에서 읽습니다.

  1. 01

    SIP 트렁크 연결

    통신사의 호스트와 자격 증명입니다. 비밀번호는 암호화되어 저장되며 다시 반환되지 않습니다. 응답에는 통신사가 허용 목록에 추가해야 하는 platform_ip(현재 187.126.120.231)와 통신사가 수신 전화를 보내는 곳인 origination_uri(현재 sip:187.126.120.231:5090)가 들어 있습니다.

    cURL
    curl 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": "..."
      }'
  2. 02

    트렁크에 전화번호 등록

    그 통신사에서 이미 가지고 있는 번호를 E.164 형식으로 등록합니다. Wixzel Voice는 번호를 판매하거나 이동하지 않습니다. 트렁크가 Twilio, Telnyx, Plivo, Vobiz, Vonage 계정에 연결되어 있다면 대신 POST /v1/phone-numbers/purchase로 그 계정에서 새 번호를 구매할 수 있습니다. 요금은 통신사가 자체 가격으로 청구합니다.

    cURL
    curl 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"'"
      }'
  3. 03

    에이전트 만들기

    말하듯 쓴 짧은 프롬프트, 처음 하는 말, 그리고 음성(모델 세 개 또는 실시간 모델 하나)입니다. opening_message는 필수입니다. 없으면 에이전트가 전화를 받고도 아무 말도 하지 않기 때문입니다. outbound_phone_number_id는 2단계의 번호를 발신자 번호로 지정합니다.

    cURL
    curl 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"'"
      }'
  4. 04

    전화 걸기

    수신 번호와 에이전트를 지정합니다. 네트워크 시간 초과만으로는 통화가 걸렸는지 알 수 없으므로 Idempotency-Key가 필수입니다. 같은 키로 다시 시도하면 두 번 전화를 거는 대신 원래 통화를 반환합니다. 응답은 201과 status: "queued" 상태의 통화입니다.

    cURL
    curl 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는 Node, 브라우저, 엣지 런타임에서 TypeScript와 JavaScript용인 npm의 wixzel-voice, 그리고 Dart와 Flutter용인 pub.dev의 wixzel_voice입니다. 두 SDK 모두 모든 엔드포인트를 지원하고, 속도 제한에 걸리면 다시 시도하며, 비용이 드는 경로에서는 Idempotency-Key를 생성합니다. 다른 언어는 일반 HTTP API와 OpenAPI 문서를 사용합니다.

TypeScript
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);
Dart
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();
}

Wixzel Voice에서 AI 에이전트는 수신 전화를 어떻게 받나요?

전화번호에 inbound_agent_id를 지정하면 그 번호로 오는 모든 전화를 해당 에이전트가 받습니다. 지정하지 않으면 그 번호로 오는 수신 전화는 거부됩니다.

cURL
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 웹훅을 보냅니다.

Wixzel Voice 통화 기록은 무엇을 반환하나요?

POST /v1/calls는 status: "queued" 상태의 통화를 바로 반환합니다. GET /v1/calls/{id}는 통화 중과 통화가 끝난 뒤 전체 기록을 반환하며, X-Wixzel-Signature로 서명된 callCompleted 웹훅이 통화가 끝났음을 서버에 알려 주므로 폴링할 필요가 없습니다.

필드담긴 내용
statusqueued, ringing, in-progress, completed, failed, busy, no-answer 또는 canceled.
direction / channeloutbound 또는 inbound. 트렁크를 통한 통화는 phone, 브라우저나 앱의 실시간 세션은 web입니다.
duration_seconds통화가 끝난 뒤의 통화 시간.
engine에이전트가 사용한 음성 엔진.
cost_micros통화 비용을 마이크로 USD(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 원인과 함께 기록됩니다.
metadataPOST /v1/calls에 첨부한 평면 문자열 맵을 그대로 반환합니다. 모델에는 절대 보내지 않습니다.

cost_micros의 모든 마이크로 달러는 GET /v1/usage/events의 사용량 행으로 설명됩니다. 인식한 음성의 초, 모델의 입력·출력 토큰, 합성한 문자 수, 분당 오케스트레이션 수수료입니다.

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초 통화는 3분 통화의 약 절반입니다. 전화 통신은 자체 트렁크를 통신사 요금으로 사용하며 포함되지 않습니다.

엔진파이프라인1분 통화3분 통화5분 통화
classicDeepgram + GPT-4o-mini + ElevenLabs$0.0867$0.2601$0.4335
sarvamSarvam, 처음부터 끝까지 인도 언어$0.0617$0.1851$0.3085
gemini-liveGemini Live, 네이티브 오디오$0.0491$0.1473$0.2455
deepgram-agentDeepgram Voice Agent$0.1851$0.5553$0.9255

선불입니다. $5부터 크레딧을 충전하며, 구독도 무료 요금제도 없습니다. 현재 가장 저렴한 엔진은 분당 $0.0491인 gemini-live입니다. 내 사용량으로 견적 내기.

AI 전화 통화를 위한 Wixzel Voice API의 한계는 무엇인가요?

  • Wixzel Voice는 배포되어 실제 통화를 처리하고 있습니다. 동작 변경은 날짜가 붙은 Wixzel-Version 헤더로 구분해 배포하며, 기존 키는 만들어질 때의 동작을 유지합니다.
  • 기본적으로 계정당 동시 통화 5건이며, 요청하면 상향됩니다. 웹·앱 세션도 같은 한도에 포함됩니다.
  • 사람에게 연결하는 기능은 블라인드 방식만 지원합니다. 발신자는 등록된 번호로 바로 연결됩니다. 상담 후 연결(attended transfer)은 구현되지 않았고, 테스트 통화와 웹·앱 세션에서는 연결 기능을 쓸 수 없습니다.
  • Wixzel Voice는 전화번호를 판매하거나 이동하지 않으며, 전화 통화에는 자체 SIP 트렁크가 필요합니다. 자체 Twilio, Telnyx, Plivo, Vobiz, Vonage 계정에서 번호를 대신 구매할 수 있으며, 요금은 통신사가 청구합니다.
  • 웹·앱 세션은 G.711 µ-law 8 kHz 오디오를 사용합니다. 광대역이 아니라 전화 음질입니다.
  • 키당 초당 API 요청 10건, 버스트 20건입니다. 속도 제한에 걸린 요청은 청구되지 않습니다.
  • API와 저장 데이터는 인도 뭄바이에 있습니다. 미국과 인도의 음성·언어 제공업체가 통화 중에 오디오와 텍스트를 처리하며, sarvam 엔진은 음성을 인도에서 처리합니다.
  • 무료 요금제와 체험 크레딧이 없습니다. 최소 충전 금액은 $5입니다. 유일한 무료 사용은 계정당 5분간 콘솔에서 자기 에이전트와 대화하는 것입니다.

자주 묻는 질문

AI 전화 통화 API란 무엇인가요?

AI 에이전트를 실제 전화 통화에 연결하는 API입니다. 코드에서 번호와 에이전트를 지정하면 API가 전화를 걸고, 음성 인식, 언어 모델, 음성 합성으로 대화를 진행한 뒤 통화 상태, 대화 기록, 비용을 반환합니다. Wixzel Voice가 그런 API입니다. POST /v1/calls가 자체 SIP 트렁크로 전화를 걸고, inbound_agent_id가 설정된 전화번호는 같은 방식으로 전화를 받습니다.

Wixzel Voice는 AI 통화 API인가요, 완성된 통화 에이전트인가요?

API입니다. 에이전트는 직접 만듭니다. 프롬프트, 첫인사, 음성 엔진, 그리고 결과를 시스템에서 어떻게 처리할지까지 정합니다. Wixzel Voice는 API, SDK, MCP 서버를 판매하며 완성된 에이전트는 판매하지 않습니다.

AI 전화 통화 비용은 얼마인가요?

음성 엔진 비용은 classic에서 연결된 1분당 $0.0867, sarvam에서 연결된 1분당 $0.0617, gemini-live에서 연결된 1분당 $0.0491, deepgram-agent에서 연결된 1분당 $0.1851이며, 각각 $0.012의 오케스트레이션 수수료가 포함되어 있고 실제 사용량만큼 초 단위로 과금됩니다. classic에서 3분 통화는 약 $0.2601입니다. 전화 회선 요금은 통신사가 기존 요금으로 마진 없이 따로 청구합니다.

AI 에이전트가 발신뿐 아니라 수신 전화도 받을 수 있나요?

네. PATCH /v1/phone-numbers/{id}로 전화번호에 inbound_agent_id를 설정하면 그 번호로 오는 전화를 해당 에이전트가 받습니다. 통신사는 수신 전화를 트렁크가 반환한 origination_uri로 보내야 합니다. inbound_agent_id가 없으면 그 번호로 오는 수신 전화는 거부됩니다.

AI 에이전트가 발신자를 사람에게 연결할 수 있나요?

네, 블라인드 방식으로 연결합니다. 발신자가 사람을 찾으면 에이전트는 진행 중인 통화를 에이전트의 human_transfer에 등록한 연결 대상 중 하나로 넘기며, 전화는 자체 SIP 트렁크로 걸립니다. 에이전트가 먼저 상대와 통화하는 상담 후 연결은 구현되지 않았고, 테스트 통화와 웹·앱 세션에서는 연결 기능을 쓸 수 없습니다.

AI 통화는 한 번에 몇 건까지 할 수 있나요?

기본적으로 계정당 동시 통화 5건이며, 요청하면 상향됩니다. 한도를 넘는 통화는 전화를 걸기 전에 거부되며 비용이 들지 않습니다. 웹·앱 세션도 같은 한도에 포함됩니다.

무료 체험이 있나요?

무료 요금제와 체험 크레딧은 없습니다. API는 선불이며 최소 충전 금액은 $5이고 구독은 없습니다. 새 계정마다 콘솔에서 자기 에이전트와 대화할 수 있는 무료 5분이 주어지며, 전화 통화에는 항상 크레딧이 쓰입니다. 처음 15초를 감당할 수 없는 통화는 무엇도 할당되기 전에 402 insufficient_credits로 거부됩니다.

다음으로 볼 곳

첫 음성 에이전트를 만드세요