> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tryvox.co/llms.txt
> Use this file to discover all available pages before exploring further.

# 웹훅 스키마

> 통화 데이터 웹훅 페이로드 스키마를 이벤트별로 확인하세요.

## 개요

이 페이지는 v2 통화 데이터 웹훅을 기준으로 설명합니다.
모든 v2 이벤트는 `{ "event", "webhook_version", "call" }` 구조를 사용합니다.
통화 종료와 분석 완료는 별도 이벤트로 전송됩니다.

<Info>
  비용과 분석 결과는 `call_analyzed`에서 확인하세요.
  `call_ended`에는 포함되지 않습니다.
</Info>

## 이벤트 생명주기

통화 데이터 웹훅은 통화 진행 상태와 분석 완료 상태를 나누어 전달합니다.

```mermaid theme={null}
sequenceDiagram
    participant C as 통화
    participant W as 웹훅 서버
    C->>W: call_started
    loop 통화 중
        C->>W: mid_call
    end
    C->>W: call_ended
    Note over C,W: 종료 상태, 스크립트, 녹음 URL
    C-->>W: call_analyzed
    Note over C,W: 요약, 감정, 추출 결과, 비용
```

<Note>
  `call_analyzed`는 통화 종료 후 비동기로 도착할 수 있습니다.
  `call_ended`에서 비용, 분석 결과, `duration_ms`를 기대하지 마세요.
</Note>

## 공통 구조

| 카테고리     | 필드                                      |
| -------- | --------------------------------------- |
| envelope | `event`, `webhook_version`, `call`      |
| 전화번호     | `from_number`, `to_number`              |
| 시간       | `start_at`, `end_at`, `occurred_at`     |
| 에이전트     | `agent.agent_id`, `agent.agent_version` |
| 상태       | `call_status`, `disconnection_reason`   |
| 분석       | `call.call_analysis` (`call_analyzed`)  |
| 비용       | `call.call_cost` (`call_analyzed`)      |

<Note>
  통화 이벤트는 본문을 `call` 키에 담습니다.
  단, `sms_received`는 예외로 본문을 `sms` 키에 담습니다.
  자세한 내용은 [sms\_received](#sms_received)를 참고하세요.
</Note>

## `call_started`

```json theme={null}
{
  "event": "call_started",
  "webhook_version": "v2",
  "call": {
    "call_id": "3079f46c-d141-4cd9-805f-69f212136b66",
    "agent": {
      "agent_id": "7ea3516d-08f6-4129-ab40-a731e379b320",
      "agent_version": "v3"
    },
    "call_type": "inbound",
    "from_number": "01012345678",
    "to_number": "07012345678",
    "dynamic_variables": {
      "customer_name": "홍길동"
    },
    "metadata": {
      "source": "crm"
    },
    "start_at": 1741842354957,
    "opt_out_sensitive_data_storage": false
  }
}
```

| 필드                                    | 타입             | 설명                             |
| ------------------------------------- | -------------- | ------------------------------ |
| `event`                               | string         | 고정값 `call_started`             |
| `webhook_version`                     | string         | 고정값 `v2`                       |
| `call.call_id`                        | string         | 통화 ID                          |
| `call.agent.agent_id`                 | string         | 에이전트 ID                        |
| `call.agent.agent_version`            | string         | 에이전트 버전입니다. 예: `current`, `v3` |
| `call.call_type`                      | string         | 통화 유형                          |
| `call.from_number`                    | string \| null | 발신 번호                          |
| `call.to_number`                      | string \| null | 수신 번호                          |
| `call.dynamic_variables`              | object         | 통화에 주입된 동적 변수                  |
| `call.metadata`                       | object         | 통화 메타데이터                       |
| `call.start_at`                       | number \| null | 통화 시작 시각입니다. Unix 밀리초입니다.      |
| `call.opt_out_sensitive_data_storage` | boolean        | 통화 데이터 저장 제외 여부                |

## `mid_call`

```json theme={null}
{
  "event": "mid_call",
  "webhook_version": "v2",
  "call": {
    "call_id": "3079f46c-d141-4cd9-805f-69f212136b66",
    "agent": {
      "agent_id": "7ea3516d-08f6-4129-ab40-a731e379b320",
      "agent_version": "v3"
    },
    "occurred_at": 1742158401445,
    "event_type": "call_message",
    "event_data": {
      "role": "user",
      "content": "주문한 제품이 언제 도착하나요?"
    }
  }
}
```

| 필드                         | 타입     | 설명                         |
| -------------------------- | ------ | -------------------------- |
| `event`                    | string | 고정값 `mid_call`             |
| `webhook_version`          | string | 고정값 `v2`                   |
| `call.call_id`             | string | 통화 ID                      |
| `call.agent.agent_id`      | string | 에이전트 ID                    |
| `call.agent.agent_version` | string | 에이전트 버전입니다.                |
| `call.occurred_at`         | number | 이벤트 발생 시각입니다. Unix 밀리초입니다. |
| `call.event_type`          | string | 세부 이벤트 유형입니다.              |
| `call.event_data`          | object | 세부 이벤트 데이터입니다.             |

## `call_ended`

```json theme={null}
{
  "event": "call_ended",
  "webhook_version": "v2",
  "call": {
    "call_id": "3079f46c-d141-4cd9-805f-69f212136b66",
    "agent": {
      "agent_id": "7ea3516d-08f6-4129-ab40-a731e379b320",
      "agent_version": "v3"
    },
    "call_type": "inbound",
    "from_number": "01012345678",
    "to_number": "07012345678",
    "dynamic_variables": {
      "customer_name": "홍길동"
    },
    "metadata": {
      "source": "crm"
    },
    "call_status": "ended",
    "disconnection_reason": "user_hangup",
    "start_at": 1741842354957,
    "end_at": 1741842393999,
    "transcript": [
      {
        "role": "agent",
        "content": "주문번호를 확인해드릴게요.",
        "start_at": 1741842358000,
        "end_at": 1741842361000
      },
      {
        "role": "tool_call_invocation",
        "tool_call_id": "tc_001",
        "name": "lookup_order",
        "arguments": {
          "order_id": "ORD-1234"
        }
      },
      {
        "role": "tool_call_result",
        "tool_call_id": "tc_001",
        "content": "{\"status\":\"shipped\",\"eta\":\"2026-04-30\"}"
      },
      {
        "role": "user",
        "content": "감사합니다.",
        "start_at": 1741842370000,
        "end_at": 1741842371200
      }
    ],
    "recording_url": "https://www.tryvox.co/api/store/download/...",
    "opt_out_sensitive_data_storage": false
  }
}
```

| 필드                                    | 타입             | 설명                                                                                       |
| ------------------------------------- | -------------- | ---------------------------------------------------------------------------------------- |
| `event`                               | string         | 고정값 `call_ended`                                                                         |
| `webhook_version`                     | string         | 고정값 `v2`                                                                                 |
| `call.call_id`                        | string         | 통화 ID                                                                                    |
| `call.agent.agent_id`                 | string         | 에이전트 ID                                                                                  |
| `call.agent.agent_version`            | string         | 에이전트 버전입니다.                                                                              |
| `call.call_type`                      | string         | 통화 유형                                                                                    |
| `call.from_number`                    | string \| null | 발신 번호                                                                                    |
| `call.to_number`                      | string \| null | 수신 번호                                                                                    |
| `call.dynamic_variables`              | object         | 통화에 주입된 동적 변수                                                                            |
| `call.metadata`                       | object         | 통화 메타데이터                                                                                 |
| `call.call_status`                    | string         | 통화 상태입니다. 값은 `ended`, `error`, `canceled`, `not_connected`, `queued`, `ongoing` 중 하나입니다. |
| `call.disconnection_reason`           | string \| null | 종료 사유                                                                                    |
| `call.start_at`                       | number \| null | 통화 시작 시각입니다. Unix 밀리초입니다.                                                                |
| `call.end_at`                         | number \| null | 통화 종료 시각입니다. Unix 밀리초입니다.                                                                |
| `call.transcript`                     | array \| null  | 도구 호출을 포함한 스크립트입니다.                                                                      |
| `call.recording_url`                  | string \| null | 녹음 파일 URL                                                                                |
| `call.opt_out_sensitive_data_storage` | boolean        | 통화 데이터 저장 제외 여부                                                                          |

<Note>
  `call_ended`에는 비용, 분석 결과, `duration_ms`가 포함되지 않습니다.
  통화 시간은 `end_at - start_at`으로 계산하세요.
  비용과 분석 결과는 `call_analyzed`에서 확인하세요.
</Note>

### 녹음 파일 다운로드

`recording_url`은 인증이 필요한 엔드포인트입니다. API 키로 녹음을 내려받는 방법과 파일 형식(스테레오 OGG, 채널 분리)은 [통화 녹음](/docs/operate/monitor/recording#녹음-내려받기)에서 확인하세요.

## 스크립트 형식

`transcript`는 발화와 도구 호출 기록을 한 배열에 담습니다.
도구를 사용하지 않은 통화에는 `agent`와 `user` 항목만 포함될 수 있습니다.

| `role`                 | 주요 필드                               | 설명               |
| ---------------------- | ----------------------------------- | ---------------- |
| `agent`                | `content`, `start_at`, `end_at`     | 에이전트 발화          |
| `user`                 | `content`, `start_at`, `end_at`     | 사용자 발화           |
| `tool_call_invocation` | `tool_call_id`, `name`, `arguments` | 에이전트가 도구를 호출한 기록 |
| `tool_call_result`     | `tool_call_id`, `content`           | 도구 호출 결과         |

<Info>
  `transcript`는 통화 데이터 저장 제외 설정이나 통화 처리 상태에 따라 `null`일 수 있습니다.
</Info>

## `call_analyzed`

```json theme={null}
{
  "event": "call_analyzed",
  "webhook_version": "v2",
  "call": {
    "call_id": "3079f46c-d141-4cd9-805f-69f212136b66",
    "agent": {
      "agent_id": "7ea3516d-08f6-4129-ab40-a731e379b320",
      "agent_version": "v3"
    },
    "call_type": "inbound",
    "from_number": "01012345678",
    "to_number": "07012345678",
    "dynamic_variables": {
      "customer_name": "홍길동"
    },
    "metadata": {
      "source": "crm"
    },
    "call_status": "ended",
    "disconnection_reason": "user_hangup",
    "start_at": 1741842354957,
    "end_at": 1741842393999,
    "transcript": [
      {
        "role": "agent",
        "content": "주문번호를 확인해드릴게요.",
        "start_at": 1741842358000,
        "end_at": 1741842361000
      },
      {
        "role": "tool_call_invocation",
        "tool_call_id": "tc_001",
        "name": "lookup_order",
        "arguments": {
          "order_id": "ORD-1234"
        }
      },
      {
        "role": "tool_call_result",
        "tool_call_id": "tc_001",
        "content": "{\"status\":\"shipped\",\"eta\":\"2026-04-30\"}"
      },
      {
        "role": "user",
        "content": "감사합니다.",
        "start_at": 1741842370000,
        "end_at": 1741842371200
      }
    ],
    "recording_url": "https://www.tryvox.co/api/store/download/...",
    "call_cost": {
      "total_cost": 12
    },
    "call_analysis": {
      "summary": "고객이 주문 배송 상태를 문의했고, 도착 예정일을 안내받았습니다.",
      "user_sentiment": "neutral",
      "custom_analysis_data": [
        { "name": "inquiry_type", "value": "배송 상태 문의" },
        { "name": "resolved", "value": true }
      ]
    },
    "opt_out_sensitive_data_storage": false
  }
}
```

| 필드                                        | 타입                      | 설명                                                                                       |
| ----------------------------------------- | ----------------------- | ---------------------------------------------------------------------------------------- |
| `event`                                   | string                  | 고정값 `call_analyzed`                                                                      |
| `webhook_version`                         | string                  | 고정값 `v2`                                                                                 |
| `call.call_id`                            | string                  | 통화 ID                                                                                    |
| `call.agent.agent_id`                     | string                  | 에이전트 ID                                                                                  |
| `call.agent.agent_version`                | string                  | 에이전트 버전입니다.                                                                              |
| `call.call_type`                          | string                  | 통화 유형                                                                                    |
| `call.from_number`                        | string \| null          | 발신 번호                                                                                    |
| `call.to_number`                          | string \| null          | 수신 번호                                                                                    |
| `call.dynamic_variables`                  | object                  | 통화에 주입된 동적 변수                                                                            |
| `call.metadata`                           | object                  | 통화 메타데이터                                                                                 |
| `call.call_status`                        | string                  | 통화 상태입니다. 값은 `ended`, `error`, `canceled`, `not_connected`, `queued`, `ongoing` 중 하나입니다. |
| `call.disconnection_reason`               | string \| null          | 종료 사유                                                                                    |
| `call.start_at`                           | number \| null          | 통화 시작 시각입니다. Unix 밀리초입니다.                                                                |
| `call.end_at`                             | number \| null          | 통화 종료 시각입니다. Unix 밀리초입니다.                                                                |
| `call.transcript`                         | array \| null           | 도구 호출을 포함한 스크립트입니다.                                                                      |
| `call.recording_url`                      | string \| null          | 녹음 파일 URL                                                                                |
| `call.call_cost`                          | object \| null          | 비용 정보입니다.                                                                                |
| `call.call_cost.total_cost`               | number \| null          | 통화 비용입니다.                                                                                |
| `call.call_analysis`                      | object \| null          | 분석 결과입니다.                                                                                |
| `call.call_analysis.summary`              | string \| null          | 통화 요약                                                                                    |
| `call.call_analysis.user_sentiment`       | string \| null          | 사용자 감정                                                                                   |
| `call.call_analysis.custom_analysis_data` | object \| array \| null | 커스텀 분석 결과                                                                                |
| `call.opt_out_sensitive_data_storage`     | boolean                 | 통화 데이터 저장 제외 여부                                                                          |

## `sms_received`

`sms_received`는 워크스페이스 번호로 문자(SMS/MMS)를 수신할 때 전송됩니다.
**워크스페이스 웹훅 전용**이며 opt-in 설정을 켠 워크스페이스에만 전송됩니다.
본문 키는 통화 이벤트와 달리 `call`이 아니라 `sms`입니다.

```json theme={null}
{
  "event": "sms_received",
  "webhook_version": "v2",
  "sms": {
    "mseq": 12345,
    "from_number": "01012345678",
    "to_number": "07012345678",
    "text": "문의드립니다",
    "received_at": 1765432100000,
    "call_id": null,
    "chat_id": null,
    "attachments": [
      { "file_key": "file_AbC123", "mime_type": "image/jpeg" }
    ]
  }
}
```

| 필드                            | 타입             | 설명                                 |
| ----------------------------- | -------------- | ---------------------------------- |
| `event`                       | string         | 고정값 `sms_received`                 |
| `webhook_version`             | string         | 고정값 `v2`                           |
| `sms.mseq`                    | number         | 수신 문자의 고유 식별자                      |
| `sms.from_number`             | string \| null | 발신 번호                              |
| `sms.to_number`               | string \| null | 문자를 수신한 워크스페이스 번호                  |
| `sms.text`                    | string \| null | 문자 본문                              |
| `sms.received_at`             | number \| null | 수신 시각입니다. Unix 밀리초입니다.             |
| `sms.call_id`                 | string \| null | 통화 중 수신된 문자면 해당 통화 ID              |
| `sms.chat_id`                 | string \| null | 양방향 문자 대화에 속하면 해당 대화 ID            |
| `sms.attachments`             | array          | MMS 이미지 첨부 목록입니다. 첨부가 없으면 빈 배열입니다. |
| `sms.attachments[].file_key`  | string         | 첨부 파일 식별자                          |
| `sms.attachments[].mime_type` | string         | 첨부 파일 MIME 타입                      |

### 첨부 파일 다운로드

`file_key`로 첨부 파일 원본을 받으려면 파일 다운로드 API를 호출하세요.

```bash cURL theme={null}
curl --request GET \
  --url https://client-api.tryvox.co/v3/files/{file_key}/content \
  --header 'Authorization: Bearer <token>' \
  --output attachment.jpg
```

응답 본문이 파일 원본입니다. `Content-Type`은 저장된 MIME 타입(`image/jpeg`, `image/png`, `image/gif`)을 그대로 따릅니다.
같은 워크스페이스가 소유한 `file_key`만 받을 수 있습니다.
전체 파라미터는 [v3 API 참조](/api-reference/v3/introduction)의 **파일 > 파일 다운로드**에서 확인하세요.

<Warning>
  본문 키가 `call`이 아니라 `sms`입니다.
  `event` 키로 분기하는 핸들러는 수정 없이 동작합니다.
  `call` 키를 무조건 읽는 핸들러는 `sms_received`를 별도로 분기하세요.
</Warning>

<Note>
  `sms_received`는 항상 v2 형식으로 전송됩니다. v1 형식은 없습니다.
  서명 방식은 통화 데이터 웹훅과 동일합니다.
  대시보드 **설정 > 웹훅**에서 **수신 문자 웹훅** 토글을 켜면 전송됩니다.
  기본값은 꺼짐이고 켠 이후 수신분부터 전송됩니다.
</Note>

## 서버 구현 체크리스트

* 같은 통화의 같은 이벤트가 다시 도착할 수 있습니다. 중복 저장을 방지하세요.
* v2 수신 스키마에는 최상위 `webhook_version` 필드를 포함하세요.
* `call_ended`에서 비용이나 분석 필드를 기대하지 마세요.
* 분석 결과 저장, 후속 자동화, 비용 집계는 `call_analyzed`에서 실행하세요.
* 통화 결과는 `call_status`와 `disconnection_reason`을 함께 확인하세요.
* 통화 시간은 `end_at - start_at`으로 계산하세요.
* `sms_received`는 본문 키가 `sms`이므로 `call` 키를 무조건 읽는 핸들러는 별도로 분기하세요.

## 관련 문서

* [에이전트 단위 웹훅](/docs/operate/monitor/webhooks/agent) — 설정 방법과 빠른 페이로드 예시
* [워크스페이스 단위 웹훅](/docs/operate/monitor/webhooks/organization) — HMAC 서명 검증과 보안 설정
* [웹훅 개요](/docs/operate/monitor/webhooks/overview) — 인바운드 웹훅과 통화 데이터 웹훅 구분

***

<Accordion title="연관 검색어">
  웹훅 스키마, webhook schema, call\_analyzed, call\_ended, mid\_call, sms\_received, 수신 문자 웹훅, inbound sms webhook, MMS 수신, attachments, 웹훅 페이로드, webhook payload, recording\_url, 녹음 다운로드, recording download, 녹음 파일 URL
</Accordion>
