자체 SIP 트렁크 사용: 이미 쓰는 통신사에서 AI 음성 에이전트 운영
이미 보유한 SIP 트렁크에서 AI 음성 에이전트를 운영합니다. 번호와 통신사 요금은 그대로 유지되며 마진이 붙지 않습니다.
최종 업데이트:
게시일 . 통신사 이름은 각 소유자의 상표입니다. Wixzel Voice는 표준 SIP로 이들과 연동하며, 어느 곳과도 제휴 관계가 없고 보증을 받지 않았습니다.
통신사 가이드
Twilio
Elastic SIP Trunking. Termination IP ACL에 플랫폼 IP를 허용하고, 수신 통화용 Origination SIP URI를 설정합니다.
Telnyx
IP 인증 SIP Connection. 플랫폼 IP를 승인된 주소로 추가하고, 수신 리전을 고르고, 전송 방식을 맞춥니다.
Plivo
Zentrunk. IP ACL에 플랫폼 IP를 넣은 발신 트렁크와, Primary URI가 플랫폼을 가리키는 별도의 수신 트렁크가 필요합니다.
Vonage
Programmable SIP. SIP Dashboard에서 트렁크의 ACL에 플랫폼 IP를 추가하고, 수신 통화를 origination URI로 보냅니다.
Bandwidth
SIP REGISTER를 지원하지 않으므로 고정 IP가 필요합니다. 로케이션에 플랫폼 IP를 추가하고 Termination과 Origination을 따로 설정하거나, 네트워크 브리지 자격 증명을 사용합니다.
Exotel
인도 번호 체계용 Virtual SIP Trunking(vSIP), TCP 사용. 플랫폼 IP를 ACL로 트렁크에 매핑하고, 수신용 Destination URI는 플랫폼의 TCP 포트를 가리키게 합니다.
Vobiz
트렁크별 SIP 도메인을 호스트로 쓰고, 트렁크의 IP ACL에 플랫폼 IP를 넣습니다. "origination URI"는 Twilio와 반대 의미입니다.
Mobily
Saudi Arabia, ordered through Mobily Business sales and delivered over a private link. No one-step connect: your own SBC on the link relays calls, with G.711 A-law and a one-hour call cap.
모든 SIP 제공업체
방법은 어디서나 같습니다. 플랫폼 IP를 허용 목록에 추가하고, 수신 목적지를 origination URI로 설정하고, 번호 형식과 전송 방식을 맞춥니다.
왜 자체 SIP 트렁크를 쓰나요?
- 번호는 그대로 내 소유
- Wixzel Voice는 번호를 판매하거나 이전하지 않습니다. 떠날 때는 통신사에서 설정 하나만 바꾸면 됩니다.
- 요금도 그대로
- 회선 요금은 통신사가 청구합니다. Wixzel Voice는 음성 엔진만 초 단위로 청구합니다.
- 규정 준수도 그대로
- 발신자 번호 표시, KYC, 각종 등록은 이미 신뢰하는 통신사에 그대로 남습니다.
- 모든 SIP 제공업체
- 8개 통신사에 가이드가 있습니다. SIP 트렁크가 있다면 어디든 작동합니다.
자체 SIP 트렁크는 어떻게 연결되나요?
Wixzel Voice 트렁크는 두 부분으로 이루어지며, 각각 통신사 콘솔의 다른 곳에서 설정합니다. 두 주소는 모든 트렁크에 반환되므로, 페이지가 최신 상태라고 믿기보다 API에서 읽으세요.
통신사의 IP 허용 목록에 187.126.120.231를 추가합니다. 거의 모든 통신사가 출발지 IP로 발신 통화를 승인하므로, 다른 모든 면에서 올바른 트렁크도 이것이 없으면 실패합니다.
통신사의 수신 목적지를 sip:187.126.120.231:5090 주소로 설정합니다. 이를 빠뜨리면 번호가 그냥 울리지 않습니다. 통신사가 통화를 전달할 곳이 없으므로 어떤 로그에도 아무것도 나타나지 않습니다.
curl https://api.voice.wixzel.com/v1/sip-trunks \
-H "Authorization: Bearer $WIXZEL_API_KEY" \
| jq '.data[0] | {platform_ip, origination_uri}'어느 통신사에 설정 가이드가 있나요?
아래 각 통신사에는 무엇을 구매하고, 무엇을 허용 목록에 넣고, 수신 통화를 어디로 보내는지, 그 통신사에 맞는 트렁크 요청과 그 통신사만의 주의 사항을 담은 전용 페이지가 있으며, 문서의 전체 콘솔 단계로 가는 링크도 있습니다. 통신사마다 두 설정의 이름은 다르지만 설정 자체는 같습니다.
| 통신사 | 제품 | 허용 목록 명칭 | 수신 목적지 명칭 | 전송 방식 |
|---|---|---|---|---|
| Twilio | Elastic SIP Trunking | IP Access Control List | Origination SIP URI | udp |
| Telnyx | SIP Connections | authorised addresses on an IP-authenticated SIP Connection | 가이드에 아직 명시되지 않음 | udp |
| Plivo | Zentrunk | IP Access Control List | Primary URI | udp |
| Vonage | Programmable SIP | ACL (Access Control List) | 가이드에 아직 명시되지 않음 | udp |
| Bandwidth | - | Voice IP addresses / DNS hosts on a location | Origination | udp |
| Exotel | Virtual SIP Trunking (vSIP) | ACL mapped to the trunk | Destination URI | tcp |
| Vobiz | - | IP ACL | 가이드에 아직 명시되지 않음 | udp |
| Mobily | SIP Trunk | trusted peers on the SBC that holds your Mobily link | SBC route for inbound Mobily calls | udp |
| 모든 SIP 제공업체 | - | IP ACL, 허용 목록 또는 승인된 주소 | Origination URI 또는 통신사가 부르는 이름 | udp |
통신사는 두 설정을 무엇이라고 부르나요?
| 역할 | 통신사별 명칭 |
|---|---|
| Wixzel Voice에서 오는 통화 승인 | IP ACL, IP Access Control List, Access Control List, allowlist, authorised address, network bridge |
| Wixzel Voice로 통화 전달 | Origination URI, Primary URI, Destination URI, termination point, destination SIP URI, host |
올바르게 보이는 트렁크가 실제로 작동하는지는 두 가지 설정이 더 결정합니다. 번호 형식: Twilio, Telnyx, Vobiz는 번호 앞에 +가 붙기를 기대합니다. 많은 도매 통신사는 이를 해석하지 못해 408로 시간 초과되는데, send_plus: false로 해결됩니다. 전송 방식: 거의 모든 곳에서 UDP가 기본값이지만 Exotel은 UDP를 받지 않으므로 Exotel 트렁크는 TCP로 실행됩니다. 전송 방식이 맞지 않으면 통신사가 응답하지 않는 것처럼 보입니다.
통화가 연결되지 않으면 어떻게 되나요?
API가 수락한 뒤 통신사가 거부한 통화는 GET /v1/calls/{id}에서 status: "failed"(원인 17이면 busy, 원인 19이면 no-answer)로 표시되며, failure_code(통신사가 보낸 Q.850 원인 코드로, 분기 처리에 쓸 수 있는 안정적인 값)와 failure_reason(무엇을 해야 하는지 쉬운 말로 설명)이 함께 나옵니다. cost_micros는 null입니다. 연결되지 않은 통화는 비용이 없으며, 이를 위해 보류했던 크레딧은 해제됩니다.
먼저 통신사 자체의 통화 로그를 확인하세요. 통화가 목록에 없다면 통신사에 도달하지 못한 것으로, 허용 목록, 트렁크 호스트 또는 방화벽이 잘못된 것입니다. 응답 0건, 비용 0으로 목록에 있다면 통신사가 INVITE를 수락한 뒤 끊은 것이며, 이는 설정 문제보다 통신사 권한 문제인 경우가 훨씬 많습니다. 표시하는 발신자 번호가 계정에서 승인되어 있어야 하고, 해당 시장에서 요구한다면 KYC와 목적지 등록이 완료되어 있어야 하며, 목적지 번호 대역은 잔액만 있는 것이 아니라 활성화되어 있어야 합니다. API가 설명하는 원인은 다음과 같습니다.
모든 실패 코드, 거부 사유, 트렁크 디버깅 방법
| failure_code | 통신사 응답 | 의미 | 조치 |
|---|---|---|---|
| 1 | 404 | 통신사가 번호를 인식하지 못합니다. | 번호 형식을 확인하세요. 통신사가 기술 다이얼 접두사를 요구한다면 트렁크에 dial_prefix를 설정하세요. |
| 3 | - | 통신사에 이 착신지로 가는 경로가 없습니다. | 통신사 계정에서 착신지가 활성화되지 않았을 가능성이 큽니다. 통신사에 경로를 열어 달라고 요청하세요. |
| 16 | - | 정상 종료: 상대방이 의도적으로 통화를 끝냈습니다. | 응답되지 않은 통화에서 이 코드가 나오면, 완료된 통화가 아니라 상위 단계의 무언가가 통화를 끝낸 것으로 보세요. |
| 17 | 486 | 통화 중입니다. | - |
| 18 | 480 | 착신지가 응답하지 않았습니다. | 전화기가 꺼져 있거나 연결할 수 없는 상태일 수 있습니다. |
| 19 | - | 벨이 울렸지만 아무도 받지 않았습니다. | 고칠 것이 없습니다. 트렁크와 번호 모두 정상입니다. |
| 20 | - | 가입자가 부재 중이거나 연결할 수 없습니다. | - |
| 21 | 403 / 407 | 통신사가 번호로 연결을 시도하기 전에 통화를 바로 거부했습니다. | 가능성이 높은 순서대로: 통신사 계정이 정지, 해지되었거나 잔액이 없음, 트렁크 사용자 이름이나 비밀번호가 틀림, platform_ip가 허용 목록에 없음, 발신자 번호가 계정에서 승인되지 않음. 먼저 통신사 대시보드를 확인하세요. |
| 22 | - | 번호가 변경되어 더 이상 사용되지 않습니다. | - |
| 27 | - | 착신지가 고장 상태입니다. | - |
| 28 | 484 | 통신사가 번호 형식을 거부했습니다. | 통신사가 기술 다이얼 접두사를 요구한다면 트렁크에 dial_prefix를 설정하세요. |
| 34 | - | 통신사에 사용 가능한 회선이 없습니다(혼잡). | 잠시 후 다시 시도하세요. |
| 38 | 500 / 501 / 502 | 통신사가 서버 오류를 반환했습니다. | - |
| 41 | 503 | 통신사에 연결은 되지만 통화를 거부하고 있습니다. | 보통 용량, 잔액, 또는 통신사 쪽 경로 장애 때문입니다. |
| 42 | - | 통신사 교환기가 혼잡합니다. | 잠시 후 다시 시도하세요. |
| 58 | 488 | 코덱 불일치: 통신사가 제시된 오디오 코덱을 거부했습니다. | 통신사 쪽에서 G.711(PCMU 또는 PCMA)을 제공하세요. G.729는 지원되지 않습니다. |
| 88 | 493 | 통신사가 호환되지 않는 통화로 거부했습니다. | - |
| 102 | 408 | 통신사가 제시간에 응답하지 않았습니다. | 트렁크의 host와 port, 그리고 통신사가 platform_ip에서 오는 SIP를 받는지 확인하세요. 통신사에 통화가 수신되었지만 응답하지 않은 것으로 표시된다면 send_plus를 false로 설정하세요. |
다음은 다이얼하기 전에 POST /v1/calls에서 거부되며 비용이 들지 않습니다.
| HTTP 상태 | code | 의미 |
|---|---|---|
| 400 | no_outbound_number | 발신자 번호가 없습니다. from_number_id를 전달하거나 에이전트에 outbound_phone_number_id를 설정하세요. |
| 400 | number_not_on_trunk | 발신 번호에 sip_trunk_id가 없어 통화를 보낼 곳이 없습니다. |
| 400 | missing_idempotency_key | 원시 HTTP 요청에 Idempotency-Key가 없습니다. SDK는 자동으로 보냅니다. |
| 402 | insufficient_credits | 잔액으로 처음 15초를 감당할 수 없습니다. 충전한 뒤 다시 시도하세요. |
| 429 | rate_limit_exceeded | 이 키로 초당 10개를 넘는 요청을 보냈습니다. Retry-After만큼 기다리세요. 429 응답은 과금되지 않습니다. |
| 503 | - | 음성 엔진을 사용할 수 없거나, 계정의 진행 중인 통화가 동시 통화 한도(기본값 5개)에 도달했거나, API 키가 지출 한도에 도달했습니다. 메시지에 어느 경우인지 나옵니다. |
GET /v1/sip-trunks/{id}/status는 지금 트렁크에 연결할 수 있는지 보여 주고 최근 통신사 거부 몇 건을 나열합니다. POST /v1/sip-trunks/{id}/test는 필요할 때 트렁크를 점검하고, GET /v1/sip-trunks/{id}/logs는 SIP 로그를 반환합니다.
curl https://api.voice.wixzel.com/v1/sip-trunks/$TRUNK_ID/status \
-H "Authorization: Bearer $WIXZEL_API_KEY"벨이 울리지 않는 수신 번호는 조회할 수 있는 실패가 아닙니다. 통신사에 목적지가 설정되어 있지 않으면 통화가 통신사를 떠나지 않으므로 살펴볼 실패한 통화가 없습니다. 수신 목적지, 통신사 쪽에서 번호가 트렁크에 연결되어 있는지, 번호에 inbound_agent_id가 있는지 확인하세요. 통화는 연결되는데 아무 소리도 들리지 않는다면 미디어가 통과하지 못하는 것입니다. 경로에 있는 방화벽이 시그널링 포트만이 아니라 RTP 범위도 허용해야 합니다.
자주 묻는 질문
Wixzel Voice에는 왜 자체 SIP 트렁크가 필요한가요?
Wixzel Voice와 함께 쓸 수 있는 통신사는 어디인가요?
트렁크에 필요한 두 가지 설정은 무엇인가요?
platform_ip(현재 187.126.120.231)를 추가하는 것으로, 통신사가 플랫폼에서 오는 통화를 수락하게 합니다. 수신 쪽은 통신사의 수신 통화 목적지를 origination_uri(현재 sip:187.126.120.231:5090)로 설정하는 것으로, 내 번호로 오는 통화가 플랫폼에 도달하게 합니다. 호스트와 포트만 받거나 UDP를 보내지 않는 통신사는 다른 형식이 필요하며, 해당 가이드에 나와 있습니다. 두 값 모두 GET /v1/sip-trunks가 모든 트렁크에 대해 반환하므로, 페이지에서 복사하지 말고 거기서 읽으세요.기존 전화번호를 계속 쓸 수 있나요?
POST /v1/phone-numbers로 번호를 등록하고 inbound_agent_id를 지정하세요. Wixzel Voice는 번호를 이전하지 않으므로 번호는 통신사에 그대로 남습니다.통신사 비밀번호는 어떻게 저장되나요?
웹이나 모바일 앱에도 SIP 트렁크가 필요한가요?
POST /v1/realtime/sessions로 실시간 세션을 만들고, 앱은 WebSocket으로 에이전트와 대화합니다. 트렁크도 번호도 필요 없습니다.트렁크를 변경하면 재시작해야 하나요?
전화번호는 Wixzel Voice에서 사나요, 통신사에서 사나요?
POST /v1/phone-numbers/purchase로 그 계정에서 번호를 구매할 수 있습니다. 요금은 통신사가 자체 가격으로 청구합니다. Exotel과 Bandwidth에서는 통신사에서 직접 번호를 구매하세요. 어느 통신사든 이미 가진 번호는 POST /v1/phone-numbers로 해당 번호가 속한 트렁크에 등록할 수 있습니다.번호로 전화해도 에이전트에게 벨이 울리지 않는 이유는 무엇인가요?
origination_uri(현재 sip:187.126.120.231:5090)로 통화를 전달해야 하고, 통신사 쪽에서 번호가 그 트렁크에 연결되어 있어야 하며, Wixzel Voice에서 번호에 inbound_agent_id가 지정되어 있어야 합니다. 첫 번째가 빠지면 통화가 통신사를 떠나지 않아 어떤 로그에도 나타나지 않습니다.
