통화 실패 사유 (Hangup Cause)
통화가 왜 끝났는지를 나타내는 hangupCause·hangupCauseQ850·sipResponseCode·hangupSource 전체 목록. 결번(없는 번호) 자동 정제, 재시도 판단, 실패 분석에 사용합니다.
통화 실패 사유 (Hangup Cause)
status 는 통화가 어떻게 끝났는지(completed / failed / busy / no-answer ...)만
알려줍니다. 왜 그렇게 끝났는지 — 결번인지, 상대가 안 받은 건지, 망 장애인지 — 는
hangupCause 로 구분합니다.
특히 failed 는 결번·망 오류·시스템 오류를 모두 포함하는 대분류입니다.
발신 리스트를 정제하거나 재시도 여부를 판단하려면 status 가 아니라 hangupCause 를 보세요.
어디서 받나요
| 경로 | 필드 |
|---|---|
| 통화 단건 조회 | hangupCause · hangupCauseQ850 · sipResponseCode · hangupSource |
| 통화 목록 조회 | 위와 동일 (통화마다) |
| Status Callback webhook | HangupCause · HangupCauseQ850 · SipResponseCode · HangupSource (종료 이벤트) |
{
"callId": "CAabcdef1234567890",
"status": "failed",
"to": "07080588491",
"duration": 0,
"hangupCause": "invalid_number",
"hangupCauseQ850": 1,
"sipResponseCode": 404,
"hangupSource": "carrier"
}네 값은 같은 사건을 서로 다른 해상도로 표현합니다. 보통은 hangupCause 하나면 충분하고,
hangupCauseQ850·sipResponseCode 는 통신망 원본 신호가 필요한 정밀 분석용입니다.
재시도 판단
가장 흔한 용도입니다. 이 표만 보고 분기하면 됩니다.
재시도해도 소용없음 — 번호를 목록에서 제외하세요
hangupCause | Q.850 | 뜻 |
|---|---|---|
invalid_number | 1 · 5 · 28 | 결번. 없는 번호이거나 형식이 잘못됐습니다 |
number_changed | 22 | 번호가 변경됐습니다 |
incompatible_destination | 88 | 해당 번호로는 음성 통화를 연결할 수 없습니다 |
recipient_blocked | 21 | 수신거부 명단에 등록된 번호라 걸지 않았습니다. 벨은 울리지 않았고 요금도 발생하지 않습니다 |
recipient_blocked 는 통신망이 아니라 여러분이 등록한 명단 때문에 걸리지 않은 통화입니다.
재시도하면 같은 결과이고, 무엇보다 연락하지 말라고 한 상대에게 다시 거는 일이 됩니다.
명단은 수신거부 목록 조회 또는 콘솔의 수신거부 화면에서 관리하고,
해제해야 다시 발신됩니다. 발신 API 호출 자체는 422 recipient_blocked 로 즉시 거절됩니다.
재시도 가치 있음 — 일시적인 사유입니다
hangupCause | Q.850 | 뜻 |
|---|---|---|
no_answer | 18 · 19 · 20 | 벨은 울렸으나 받지 않음 |
user_busy | 17 | 통화 중 |
recovery_on_timer_expire | 102 | 응답 대기 시간 초과 |
temporary_failure | 41 | 통신망 일시 장애 |
switching_congestion | 42 | 교환기 혼잡 |
no_circuit_available | 34 | 회선 부족 |
network_out_of_order | 38 | 망 장애 |
destination_out_of_order | 27 | 상대 단말/교환기 장애 |
resource_unavailable | 47 | 망 자원 부족 |
protocol_error | 111 | 통신망 프로토콜 오류 |
계정 한도·상태 — 번호가 아니라 계정을 확인하세요
수신 통화가 계정 설정 때문에 연결되지 못한 경우입니다. 상대 번호에는 문제가 없습니다.
hangupCause | Q.850 | 뜻 |
|---|---|---|
concurrency_limit_exceeded | 17 | 동시통화 한도를 넘어 받지 못했습니다. 잠시 후 재시도하거나 동시통화 채널을 올리세요 |
subscription_inactive | 21 | 구독이 없거나 만료되어 받지 못했습니다. 재시도해도 동일합니다 |
inbound_quota_exceeded | 21 | 월 수신 통화 한도를 다 썼습니다. 다음 청구 주기에 초기화됩니다 |
inbound_not_supported | 21 | 현재 플랜이 수신 통화를 지원하지 않습니다 |
sip_trunk_inactive | 21 | SIP 트렁크 부가서비스가 없거나 만료되어 BYOC·소프트폰 번호로 받지 못했습니다 |
1채널로 운영 중에 두 번째 전화가 들어오면 concurrency_limit_exceeded 로 통화 기록이 남고
Status Callback webhook 이 발송됩니다. 발신번호(From)를 받아
콜백 안내 문자를 보내는 구성에 쓰실 수 있습니다.
ClawOps 측 오류 — 재시도하세요
hangupCause | hangupSource | 뜻 |
|---|---|---|
app_error | app | 통화 처리 중 오류가 발생했습니다 (VoiceML 파싱 실패 등 포함) |
call_stuck | system | 통화가 비정상 상태로 남아 시스템이 정리했습니다 |
hangupSource 가 app 또는 system 이면 상대방·번호 문제가 아니라 ClawOps 측 문제입니다.
수신자 번호를 정제 대상으로 넣지 마시고 재시도해 주세요. 반복되면 통화 ID 와 함께 문의해 주시면
원인을 확인해 드립니다.
실패가 아닌 종료
hangupCause | Q.850 | 뜻 |
|---|---|---|
normal_clearing | 16 | 통화 후 정상 종료 (status: "completed") |
caller_canceled | 16 | 상대가 받기 전에 발신 측이 끊음 |
call_rejected | 21 · 50 · 57 | 수신자가 거절 (수신 차단 포함) |
unspecified | 31 · 127 | 통신망이 사유를 주지 않음 |
unknown | — | 위 어디에도 해당하지 않는 cause |
사유로 조회하기
통화 목록 조회 의 hangupCause 로 필터링합니다.
status 는 failed 하나에 결번·망 오류·시스템 오류가 다 섞여 있어, 사유별로 보려면 이쪽을 쓰세요.
GET /v1/accounts/{accountId}/calls?hangupCause=concurrency_limit_exceeded
GET /v1/accounts/{accountId}/calls?hangupCause=invalid_number&hangupCause=number_changed기간·통화시간과 함께 좁힐 수도 있습니다. since/until 은 시작 시각 기준이고 until 은 미포함,
minDuration/maxDuration 은 초 단위로 양끝을 포함합니다. 통화 시간이 아직 확정되지 않은
통화(진행 중 등)는 minDuration/maxDuration 을 주면 결과에서 빠집니다.
# 지난달 놓친 전화 중 0초로 끝난 것만
GET /v1/accounts/{accountId}/calls?since=2026-08-01T00:00:00Z&until=2026-09-01T00:00:00Z&minDuration=0&maxDuration=0hangupSource — 누구 때문에 끝났나
| 값 | 뜻 |
|---|---|
carrier | 통신망이 통화를 끊었습니다 (결번·망 장애 등) |
callee | 수신자 측입니다 (거절·통화중·무응답·통화 후 종료) |
caller | 발신 측입니다 (연결 전 취소) |
app | ClawOps 통화 처리 오류 |
system | ClawOps 시스템이 정리한 통화 |
sipResponseCode
통신망이 보낸 SIP 응답코드가 있을 때만 채워집니다. 없이 끝난 통화는 null 입니다.
| 코드 | 흔한 의미 |
|---|---|
404 | 없는 번호 |
403 | 발신이 거부됨 |
408 | 응답 없음 |
480 | 일시적으로 연결할 수 없음 |
486 | 통화 중 |
500 | 통신망 내부 오류 — 실제 사유는 hangupCause 를 보세요 |
국내 통신망은 실제 사유를 500 으로 감싸 보내는 경우가 있습니다. ClawOps 는 통신망이 함께 보낸
Q.850 원인값을 읽어 hangupCause 로 교정하므로, SIP 코드보다 hangupCause 가 정확합니다.
예제 — 결번 자동 정제
발신 후 통화 결과를 조회해, 다시 걸어도 소용없는 번호를 목록에서 빼는 예제입니다.
DO_NOT_RETRY = {"invalid_number", "number_changed", "incompatible_destination"}
call = client.accounts(account_id).calls.get(call_id)
if call.status != "completed":
cause = getattr(call, "hangup_cause", None)
if cause in DO_NOT_RETRY:
mark_number_invalid(call.to) # 고객 DB 에서 제외
elif getattr(call, "hangup_source", None) in ("app", "system"):
enqueue_retry(call.to) # ClawOps 측 오류 — 재시도
else:
enqueue_retry(call.to, delay_min=30) # 일시적 사유 — 나중에 재시도Status Callback 으로 실시간 처리하려면 종료 이벤트에서 같은 값을 읽으면 됩니다.
@app.route("/status", methods=["POST"])
def status_callback():
if request.form.get("CallStatus") in ("completed", "failed", "busy", "no-answer"):
cause = request.form.get("HangupCause")
if cause in DO_NOT_RETRY:
mark_number_invalid(request.form.get("To"))
return "", 204통화 전환(transfer)의 실패 사유
이 페이지의 hangupCause 는 발신자와 ClawOps 사이의 통화(메인 leg) 에 대한 값입니다.
에이전트나 SIP 단말이 상담원에게 넘긴 전환 leg 는 별도 필드를 씁니다 —
transferHangupCauseQ850 · transferSipResponseCode · transferReasonText,
그리고 다단계 전환의 전체 이력은 transfers[] 입니다.
값을 읽는 법은 통화 전환 결과 를 보세요.
VoiceML <Dial> 은 이 transfer* 필드를 채우지 않습니다. <Dial> 결과는 action 요청의
DialCallStatus 로 받습니다 — VoiceML 참고.