새로운 문서를 작성 중입니다.새 문서로 이동
ClawOps Docs

Status Callback

통화 상태 변경 시 전송되는 Status Callback의 이벤트 종류와 파라미터를 안내합니다.

Status Callback은 통화 상태가 변경될 때마다 지정한 URL로 이벤트를 전송합니다.

  • 발신(outbound): 통화 생성 시 status_callback 파라미터로 통화마다 설정합니다.
  • 수신(inbound): 외부에서 걸려오는 통화는 발신 시점이 없으므로, 전화번호 설정의 "수신 통화 상태 webhook"(status_callback)에 URL을 미리 등록합니다. 대시보드 전화번호 상세 또는 번호 수정 API의 status_callback 으로 설정하며, 그 번호로 걸려오는 모든 통화의 상태 전이가 통지됩니다.
call = client.calls.create(
    to="01012345678",
    from_="07052358010",
    url="https://my-app.com/twiml",
    status_callback="https://my-app.com/status",
    status_callback_event="initiated ringing answered completed",
)

이벤트 종류

status_callback_event에 수신할 이벤트를 공백으로 구분하여 지정합니다.

파라미터타입필수설명
initiatedevent선택통화가 시작됨 (발신 시작)
ringingevent선택상대방 전화벨이 울리는 중
answeredevent선택상대방이 전화를 받음
completedevent선택통화가 종료됨
transferevent선택호전환 진행 상황 — 전환 시작·연결·종료마다 전송.

지정하지 않으면 initiated ringing answered completed 가 적용됩니다. transfer 는 여기에 포함되지 않으므로, 호전환 통지를 받으려면 네 개와 함께 직접 나열해야 합니다.

initiated ringing answered completed transfer

대시보드에서는 전화번호 상세 → 인바운드 라우팅 → 수정에서 체크박스로 켤 수 있습니다.

호전환 이벤트 (transfer)

호전환이 어떻게 됐는지 통화가 끝나기 전에 알 수 있습니다. 전환이 실패하면 다른 상담원으로 재시도하거나 안내 문자를 보내는 식으로 바로 이어갈 수 있습니다.

전환 한 건마다 시작(initiated) → 연결(connected) → 종료(completed / failed / no-answer / busy / canceled) 순으로 전송됩니다. 연결되지 못하면 connected 없이 시작과 종료만 옵니다.

파라미터타입필수설명
TransferStatusstring필수initiated(전환 시작) / connected(상대 응답, 통화 연결) / completed(정상 종료) / failed / no-answer / busy / canceled / interrupted(통화가 비정상 종료돼 시스템이 정리)
TransferSequencestring필수이 통화의 몇 번째 전환 시도인지 (1부터). 다단 전환에서 어느 시도의 통지인지 구분합니다
TransferTostring선택전환 대상 번호
TransferModestring선택전환 방식
TransferDurationstring선택전환 통화 시간(초) — 종료 이벤트에만 포함
TransferReasonstring선택에이전트가 파악한 문의 유형. 파악하지 못했으면 파라미터 자체가 오지 않습니다
TransferContextstring선택Voice Agent SDK 의 transfer({ context }) 로 직접 넘긴 구조화 데이터(JSON 문자열). 넘긴 그대로 전달되며, 넘기지 않았으면 파라미터 자체가 오지 않습니다
TransferStartedAtstring선택이 전환 시도를 시작한 시각(ISO 8601, UTC)
TransferAnsweredAtstring선택대상이 전화를 받은 시각(ISO 8601, UTC). 받지 않았으면 파라미터 자체가 오지 않습니다. TransferStatus 가 failed·canceled·no-answer 여도 이 값이 있으면 담당자는 받은 것입니다(연결 전 안내 도중 종료)
TransferConnectedAtstring선택발신자와 대상이 연결된 시각(ISO 8601, UTC). 연결 전 안내(warm 전환)가 있으면 안내가 끝난 뒤 시각이라 TransferAnsweredAt 보다 늦습니다
TransferEndedAtstring선택이 전환 시도가 끝난 시각(ISO 8601, UTC) — 종료 이벤트에만 포함
TransferTimeoutstring선택이 전환에 적용한 대기 한도(초). 대상이 이 시간 안에 받지 않으면 no-answer 로 끝납니다(SIP REFER 전환은 failed)
TransferSipResponseCodestring선택통신망이 알려 준 SIP 응답코드 — 종료 이벤트에만, 값을 알 때만 포함
TransferHangupCauseQ850string선택통신망이 알려 준 Q.850 종료 사유 — 종료 이벤트에만, 값을 알 때만 포함
Fromstring선택통화의 발신번호
Tostring선택통화의 수신번호
Directionstring선택inbound / outbound — From·To 중 어느 쪽이 고객인지 판단하는 근거입니다

이 이벤트는 아래 "요청 파라미터" 를 따르지 않습니다. CallId · AccountId · Timestamp · From · To · Direction 과 위 Transfer* 필드만 실립니다 — CallStatus 는 없습니다. 통화 자체의 상태 통지와 구분하려면 TransferStatus 필드의 존재 여부로 분기하세요.

TransferReason 과 TransferContext 는 출처가 다릅니다. 앞은 에이전트가 통화 중 파악한 내용이고, 뒤는 SDK 로 직접 넘긴 값이 그대로 전달된 것입니다. 둘 다 값이 없으면 파라미터 자체가 오지 않으므로, 읽기 전에 존재 여부를 확인하세요.

담당자가 받기까지 걸린 시간은 TransferAnsweredAt - TransferStartedAt 입니다. TransferConnectedAt 은 연결 전 안내가 끝난 뒤 시각이라 이 계산에 쓰면 안내 길이만큼 길게 나옵니다. Timestamp 는 웹훅을 보낸 시각이므로 전환 시각으로 쓰지 마세요.

같은 종료 이벤트가 두 번 이상 도착할 수 있습니다(전환 종료 처리가 여러 경로에서 겹칠 때). CallId + TransferSequence + TransferStatus 조합을 키로 삼아 멱등하게 처리하세요.

요청 파라미터

기본 파라미터(CallId, AccountId, Direction)에 추가로 다음 파라미터가 포함됩니다.

파라미터타입필수설명
CallStatusstring필수현재 통화 상태. 진행: initiated/ringing/answered. 종료(completed 이벤트의 실제 사유): completed/busy/no-answer/failed/canceled/rejected. rejected/busy 는 통화가 연결되지 않고 거절된 경우이며, 이때 Duration 은 0 입니다. Twilio 는 거절한 통화를 no-answer 로 보내지만 ClawOps 는 rejected 로 보냅니다.
Fromstring필수통화 발신번호
Tostring필수수신번호
ForwardedFromstring선택착신전환으로 들어온 수신 통화에서, 발신자가 원래 건 번호. 여러 번호를 ClawOps 번호 하나로 착신전환했을 때 어느 번호로 걸려온 전화인지 구분합니다. 착신전환을 실행한 통신사가 전환 정보를 함께 보내온 경우에만 실리며, 직접 걸려온 통화와 발신 통화에는 파라미터 자체가 오지 않습니다
CallerIdRestrictedstring선택발신자가 번호 표시제한(`*23#` 등)을 걸고 건 통화면 `true`, 아니면 `false`. 번호는 `From` 에 그대로 전달되고, 표시제한 여부만 이 값으로 알려 드립니다. 통신사가 표시제한 여부를 보내지 않은 통화는 `false` 로 올 수 있습니다. 수신 통화의 상태 통지에만 실리며, 발신 통화와 전환 상태 통지(`TransferStatus`)에는 파라미터 자체가 오지 않습니다
Durationstring선택통화 시간 (초) — completed 이벤트에서만 포함
Timestampstring필수이벤트 발생 시각 (ISO 8601)
Directionstring필수inbound(수신) 또는 outbound(발신)
AnsweredBystring선택AMD(자동응답기 감지) 결과 — machine_detection 을 켠 발신 통화의 completed 이벤트에만 포함. human(사람) / machine(자동응답기·음성사서함) / unknown(판정 불가)
HangupCausestring선택통화 종료 사유 — 종료 이벤트에만 포함. invalid_number(결번) / no_answer / user_busy / network_out_of_order 등. 전체 목록은 아래 참고
HangupCauseQ850string선택통신망 Q.850 cause code (1=결번, 16=정상해제, 17=통화중, 19=무응답, 38=망장애 등)
SipResponseCodestring선택종료를 유발한 SIP 응답코드 (404=없는 번호, 486=통화중, 500=망 오류 등). 응답코드 없이 끝난 통화는 미포함
HangupSourcestring선택종료 책임 주체 — carrier(통신망) / callee(수신 측) / caller(발신 측) / app·system(ClawOps 측). 정상 종료에서는 먼저 끊은 쪽의 역할입니다 — 착신 통화에서 상대가 끊으면 caller, 여러분의 앱이 끊으면 callee. 판정하지 못하면 미포함
ParentCallIdstring선택원래 통화의 ID — <Dial> 로 연결된 상대(수신 leg)의 통지에만 포함됩니다. 이때 CallId 는 그 연결만의 ID 이고, From/To 는 그 연결의 발신·수신번호입니다

<Dial> 로 연결한 상대의 상태도 따로 받을 수 있습니다 — <Number> / <Sip> 에 statusCallback 을 지정하면 그 목적지가 받은 시점(answered)과 끝난 시점(completed)이 통지됩니다. 이 통지에는 ParentCallId 가 함께 실려 어느 통화의 연결인지 구분됩니다. 자세한 내용은 VoiceML <Number> 를 참고하세요.

CallStatus: "failed" 는 결번·망 오류·시스템 오류를 모두 포함하는 대분류입니다. 결번인지 일시적 오류인지는 HangupCause 로 구분하세요 — 통화 실패 사유 에 전체 목록과 재시도 판단 기준이 있습니다.

종료 사유 필드들은 통화가 끝난 이벤트(completed / busy / no-answer / failed / canceled / rejected)에만 포함됩니다. 사유를 확정하지 못한 통화에서는 필드가 생략됩니다 — 값이 있을 때만 보내며, 없는 사유를 임의로 채우지 않습니다.

예제

from flask import Flask, request

app = Flask(__name__)

@app.route("/status", methods=["POST"])
def status_callback():
    call_id = request.form.get("CallId")
    status = request.form.get("CallStatus")
    duration = request.form.get("Duration")

    print(f"통화 {call_id}: {status}")
    if status == "completed" and duration:
        print(f"  통화 시간: {duration}초")

    # 연결되지 않은 통화는 사유를 보고 재시도 여부를 정합니다.
    if status == "failed":
        cause = request.form.get("HangupCause")
        if cause == "invalid_number":
            print("  결번 — 목록에서 제외")
        elif request.form.get("HangupSource") in ("app", "system"):
            print("  ClawOps 측 오류 — 재시도")

    return "", 204

Status Callback 요청에도 X-Signature 헤더가 포함됩니다. 서명 검증 가이드를 참고하여 요청의 무결성을 확인하세요.