> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.claw-ops.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.claw-ops.com/_mcp/server.

# 통화 전환 결과

> 통화 조회 응답의 transferTo, transferStatus, transferDuration, transfers 필드를 읽는 방법입니다. 어떤 전환이 기록되는지, VoiceML Dial 결과와 무엇이 다른지 안내합니다.

# 통화 전환 결과

통화를 상담원이나 다른 번호로 넘겼을 때, 그 전환이 어떻게 됐는지가 통화 조회 응답의
`transferTo`, `transferStatus`, `transferDuration` 에 남습니다.

이 필드들은 **읽기 전용 관측 필드**입니다. 값을 지정하는 요청 필드나 VoiceML verb 는 없고,
전환은 에이전트가 통화 중에 실행하며 그 결과가 사후에 채워집니다. 전환이 없었던 통화는
전부 `null` 입니다.

## 어디서 받나요

| 경로                                                     | 필드                                                                                                                                              |
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| 통화 단건 조회 `GET /v1/accounts/{accountId}/calls/{callId}` | `transferTo`, `transferStatus`, `transferDuration`, `transferHangupCauseQ850`, `transferSipResponseCode`, `transferReasonText`, **`transfers`** |
| 통화 목록 조회 `GET /v1/accounts/{accountId}/calls`          | 위와 동일합니다. 단 **`transfers` 는 제외**됩니다                                                                                                             |
| [Status Callback webhook](/webhooks)                   | `TransferStatus`, `TransferTo`, `TransferMode`, `TransferDuration` 등을 실시간으로 받습니다                                                                |

## 어느 전환이 여기에 기록되나요

| 전환 방법                                                  | 기록되나              |
| ------------------------------------------------------ | ----------------- |
| Voice Agent SDK 의 `transfer()` 와 내장 도구 `transfer_call` | 예                 |
| 콘솔에서 만든 에이전트의 **도구 → 통화 전환**                           | 예                 |
| SIP 단말의 **REFER** 전환 (blind, attended)                 | 예                 |
| VoiceML `<Dial>`                                       | **아니오** — 아래를 보세요 |

## `<Dial>` 은 다릅니다

VoiceML 의 `<Dial>` 은 통화 중에 다른 목적지를 붙이는 것이지, 통화를 넘기고 빠지는 전환이
아닙니다. 그래서 위 `transfer*` 필드에는 아무것도 남지 않습니다. 결과는 두 가지로 받습니다.

| 무엇을 알고 싶은가      | 어디서 받나                                                                                                   |
| --------------- | -------------------------------------------------------------------------------------------------------- |
| 연결이 **어떻게 끝났나** | `<Dial action>` 요청의 `DialCallStatus` 입니다. `completed`, `busy`, `no-answer`, `failed`, `canceled` 중 하나입니다 |
| 상대가 **언제 받았나**  | `<Number statusCallback>` 또는 `<Sip statusCallback>` 통지입니다. `answered` 와 `completed` 를 받습니다               |

## 필드

| 필드                        | 타입             | 설명                                                                |
| ------------------------- | -------------- | ----------------------------------------------------------------- |
| `transferTo`              | string \| null | 전환 대상 번호 또는 SIP URI 입니다. 전환이 없었으면 `null` 입니다.                     |
| `transferStatus`          | string \| null | 전환 결과입니다. 아래 값 표를 보세요.                                            |
| `transferDuration`        | number \| null | 전환 통화 시간(초)입니다. 대상이 받은 시점부터 그 전환이 끝날 때까지이며, 연결되지 못했으면 `null` 입니다. |
| `transferHangupCauseQ850` | number \| null | 전환 leg 의 통신망 Q.850 cause 입니다. 사유 미상이면 `null` 입니다.                 |
| `transferSipResponseCode` | number \| null | 전환 leg 의 SIP 응답코드입니다. 사유 미상이면 `null` 입니다.                         |
| `transferReasonText`      | string \| null | 통신망이 준 원본 진단 텍스트입니다. 자유 형식이라 분기 조건으로 쓰지 마세요.                      |
| `transfers`               | array          | 전환 leg 전체 이력입니다. **단건 조회에만** 실립니다.                                |

## `transferStatus` 값

| 값           | 뜻                                                                           |
| ----------- | --------------------------------------------------------------------------- |
| `completed` | 대상이 받아 통화가 이뤄졌고 정상 종료됐습니다.                                                  |
| `no-answer` | 벨은 울렸으나 받지 않았습니다.                                                           |
| `busy`      | 대상이 통화 중입니다.                                                                |
| `canceled`  | 연결되기 전에 취소되거나 중단됐습니다. 원 발신자가 먼저 끊는 경우가 여기 들어갑니다.                            |
| `failed`    | 그 외 실패입니다. 사유는 `transferHangupCauseQ850` 과 `transferSipResponseCode` 로 봅니다. |

진행 중 상태는 이 필드에 나타나지 않습니다. `transferStatus` 는 끝난 전환의 결과만 담습니다.
`initiated`, `ringing`, `connected`, `interrupted` 는 `transfers[].status` 와 Status Callback
의 `transfer` 이벤트에만 존재합니다.

## 다단계 전환과 재시도

한 통화에서 전환을 여러 번 시도할 수 있습니다. 1번 상담원이 받지 않아 2번으로 넘기는 경우입니다.
이때 `transfers` 에는 시도마다 한 건씩 쌓이고, 위 `transfer*` 단일 필드는 그중 **대표 leg 하나**만
보여줍니다.

대표 leg 는 **끝난 leg 중 하나**입니다. `completed` 인 leg 가 있으면 그것을, 없으면 `sequence` 가
가장 큰 leg 를 보여줍니다.

즉 세 번 시도해 마지막에 성공했다면 `transferStatus` 는 `completed` 이고 `transferTo` 는 그 성공한
번호이며, 앞선 두 번의 실패는 `transfers` 에만 남습니다. 전환 시도를 빠짐없이 보려면 `transfers` 를
쓰세요.

| 필드                 | 타입             | 설명                                                                                                                  |
| ------------------ | -------------- | ------------------------------------------------------------------------------------------------------------------- |
| `sequence`         | number         | 이 통화에서 몇 번째 전환 시도인지입니다. 1부터 시작합니다.                                                                                  |
| `to`               | string \| null | 전환 대상입니다.                                                                                                           |
| `mode`             | string \| null | `blind`(즉시 전환), `warm`(대상에게 whisper 안내 후 연결), `refer`와 `refer-attended`(SIP 단말이 건 REFER 전환)입니다.                     |
| `destinationType`  | string \| null | `pstn`(통신망 번호) 또는 `sip`(SIP URI 직결)입니다. 2026-07-10 이전 전환은 `null` 입니다.                                               |
| `status`           | string \| null | `initiated`, `ringing`, `connected`, `completed`, `failed`, `no-answer`, `busy`, `canceled`, `interrupted` 중 하나입니다. |
| `duration`         | number \| null | 연결부터 종료까지의 초입니다. 관측용이며 연결되지 못했으면 `null` 입니다.                                                                        |
| `billable`         | boolean        | 과금 대상 여부입니다. 한 통화에서 최대 한 건만 `true` 입니다.                                                                             |
| `billableDuration` | number \| null | 과금 대상 초입니다.                                                                                                         |
| `hangupCauseQ850`  | number \| null | 이 leg 의 통신망 Q.850 cause 입니다.                                                                                        |
| `sipResponseCode`  | number \| null | 이 leg 의 SIP 응답코드입니다.                                                                                                |
| `reasonText`       | string \| null | 통신망 원본 진단 텍스트입니다.                                                                                                   |
| `startedAt`        | string \| null | 전환을 시작한 시각입니다. 2026-07-10 이전 전환은 `null` 입니다.                                                                        |
| `connectedAt`      | string \| null | 대상이 받은 시각입니다. 연결되지 못했으면 `null` 입니다. 2026-07-10 이전 전환은 연결됐어도 `null` 이니 아래 주의를 보세요.                                   |
| `endedAt`          | string \| null | 이 leg 가 끝난 시각입니다. 2026-07-10 이전 전환은 `null` 입니다.                                                                     |

**2026-07-10 이전 전환은 leg 별 시각과 `destinationType` 이 없습니다.** 그때는 전환 결과를 통화
한 건에 한 줄로만 기록했고 지금의 leg 이력은 그 기록에서 되살린 것이라, `startedAt` ·
`connectedAt` · `endedAt` · `destinationType` 이 전부 `null` 입니다. 연결 여부를 `connectedAt`
으로 판정하면 그 구간을 오분류합니다 — `status` 와 `duration` 을 보세요.

`transferDuration` 과 `transfers[].duration` 은 관측값이지 과금 초가 아닙니다. 청구 기준 초는
`transfers[].billableDuration` 이니 `duration` 을 합산하지 마세요.

## 예시

전환을 두 번 시도해 두 번째에 연결된 통화입니다.

```json
{
  "callId": "CAabcdef1234567890",
  "status": "completed",
  "from": "01012345678",
  "to": "07080588491",
  "direction": "inbound",
  "duration": 184,
  "hangupCause": "normal_clearing",
  "transferTo": "0212345679",
  "transferStatus": "completed",
  "transferDuration": 96,
  "transferHangupCauseQ850": 16,
  "transferSipResponseCode": null,
  "transferReasonText": null,
  "transfers": [
    {
      "sequence": 1,
      "to": "0212345678",
      "mode": "blind",
      "destinationType": "pstn",
      "status": "no-answer",
      "duration": null,
      "billable": false,
      "billableDuration": null,
      "hangupCauseQ850": 19,
      "sipResponseCode": 480,
      "reasonText": null,
      "startedAt": "2026-08-27T04:11:02.000Z",
      "connectedAt": null,
      "endedAt": "2026-08-27T04:11:32.000Z"
    },
    {
      "sequence": 2,
      "to": "0212345679",
      "mode": "blind",
      "destinationType": "pstn",
      "status": "completed",
      "duration": 96,
      "billable": true,
      "billableDuration": 96,
      "hangupCauseQ850": 16,
      "sipResponseCode": null,
      "reasonText": null,
      "startedAt": "2026-08-27T04:11:33.000Z",
      "connectedAt": "2026-08-27T04:11:41.000Z",
      "endedAt": "2026-08-27T04:13:17.000Z"
    }
  ]
}
```

조회는 통화 ID 로 합니다.

```bash
curl "https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/calls/CAabcdef1234567890" \
  -H "Authorization: Bearer sk_..."
```

## 통화가 끝나기 전에 알기

위 필드는 통화가 끝난 뒤에 조회해서 봅니다. 전환이 실패했을 때 바로 다른 상담원으로 재시도하거나
안내 문자를 보내려면 Status Callback 의 `transfer` 이벤트를 쓰세요. 전환 한 건마다 시작, 연결,
종료 순으로 통지됩니다.

`transfer` 는 기본 이벤트에 포함되지 않습니다. 받으려면 기본 이벤트와 함께 직접 나열해야 합니다.

```
initiated ringing answered completed transfer
```

번호의 `statusCallbackEvents` 또는 발신 요청의 `StatusCallbackEvent` 에 위 문자열을 그대로 넣으면
됩니다. 통지에 실리는 파라미터는 다음과 같습니다.

| 파라미터               | 설명                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------- |
| `TransferStatus`   | `initiated`, `connected`, `completed`, `failed`, `no-answer`, `busy`, `canceled`, `interrupted` 중 하나입니다. |
| `TransferSequence` | 이 통화의 몇 번째 전환 시도인지입니다.                                                                                   |
| `TransferTo`       | 전환 대상입니다.                                                                                                |
| `TransferMode`     | 전환 방식입니다.                                                                                                |
| `TransferDuration` | 전환 통화 시간(초)입니다. 종료 이벤트에만 실립니다.                                                                           |
| `TransferReason`   | 에이전트가 파악한 문의 유형입니다. 파악하지 못했으면 파라미터 자체가 오지 않습니다.                                                          |
| `TransferContext`  | Voice Agent SDK 의 `transfer({ context })` 로 넘긴 구조화 데이터입니다. JSON 문자열로 전달됩니다.                              |
| `From`             | 통화의 발신번호입니다.                                                                                             |
| `To`               | 통화의 수신번호입니다.                                                                                             |
| `Direction`        | `inbound` 또는 `outbound` 입니다. `From` 과 `To` 중 어느 쪽이 고객인지 판단하는 근거입니다.                                      |

이 이벤트에는 `CallStatus` 가 실리지 않습니다. 통화 자체의 상태 통지와 구분하려면
`TransferStatus` 필드의 존재 여부로 분기하세요. 또한 같은 종료 이벤트가 두 번 이상 도착할 수
있으므로, `CallId` 와 `TransferSequence`, `TransferStatus` 조합을 키로 삼아 멱등하게 처리하세요.