---
title: "웹훅 엔드포인트"
description: "엔드포인트별 시크릿 및 이벤트 필터를 사용하여 여러 웹훅 URL을 관리합니다."
---

엔드포인트 기반 웹훅 시스템을 사용하면 조직별로 **여러**
대상을 등록할 수 있으며, 각 대상에는 고유한 시크릿, 상태,
이벤트 유형 하위 집합에 대한 구독이 있습니다. 이는 모든 신규 통합에
권장되는 모델입니다.

하위 호환성을 위해 유지되지만 조직당 하나의 URL만 지원하는
[레거시 단일 URL 웹훅](/api-reference/organizations#legacy-single-url-webhook)과 비교하세요.

## 엔드포인트

| 메서드 | 경로 | 필수 역할 | 설명 |
|--------|------|-----------|------|
| `GET` | `/v1/developer/webhook-endpoints` | `admin+` | 엔드포인트 목록 조회 |
| `POST` | `/v1/developer/webhook-endpoints` | `admin+` | 엔드포인트 생성 |
| `PATCH` | `/v1/developer/webhook-endpoints/{endpoint_id}` | `admin+` | 라벨 / URL / 이벤트 / 상태 업데이트 |
| `DELETE` | `/v1/developer/webhook-endpoints/{endpoint_id}` | `admin+` | 엔드포인트 삭제 |
| `POST` | `/v1/developer/webhook-endpoints/{endpoint_id}/rotate-secret` | `admin+` | 서명 시크릿 교체 |
| `POST` | `/v1/developer/webhook-endpoints/{endpoint_id}/test` | `admin+` | 서명된 테스트 전송 발송 |
| `GET` | `/v1/developer/webhook-deliveries` | `admin+` | 최근 엔드포인트 및 레거시 전송 결과 확인 |

## 엔드포인트 객체

```json
{
  "id": "c4d5e6f7-...",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "agent_id": 42,
  "agent_name": "Support Agent",
  "secret_hint": "a1b2…9f0e",
  "paused_at": null,
  "pause_last_error": "",
  "pause_undelivered_count": null,
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z"
}
```

| 필드 | 유형 | 설명 |
|-------|------|-------------|
| `id` | UUID | 엔드포인트 ID |
| `label` | 문자열 | 표시 이름, 1~120자 |
| `url` | 문자열 | HTTPS URL, 개발 환경에서는 `http://localhost` 허용 |
| `events` | 문자열 배열 | 구독한 이벤트 유형([유효한 값](#valid-event-types) 참조). 빈 배열은 명시적으로만 구독 가능한 턴별 이벤트(`telephony.turn` / `web.turn`)를 제외한 모든 이벤트를 구독합니다. |
| `status` | 문자열 | `active`, `disabled`(수동 일시 중지) 또는 `failing`(단일 2xx 응답 없이 전송이 24시간 재시도 일정을 모두 소진하면 자동 설정) |
| `agent_id` | 정수 \| null | 이 엔드포인트가 범위로 지정된 에이전트입니다. `null`은 조직 전체를 의미합니다. |
| `agent_name` | 문자열 \| null | 범위로 지정된 에이전트의 이름이며, 조직 전체 엔드포인트의 경우 `null`입니다. |
| `secret_hint` | 문자열 | 줄임표(`a1b2…9f0e`)가 포함된 서명 시크릿의 처음 4자와 마지막 4자입니다. 전체 값을 노출하지 않고 로컬에 저장한 시크릿을 대조하기에 충분합니다. |
| `paused_at` | 타임스탬프 \| null | ThunderPhone이 엔드포인트를 `failing`으로 설정한 시점입니다. `active` 또는 `disabled` 상태에서는 `null`입니다. |
| `pause_last_error` | 문자열 | 엔드포인트가 일시 중지되었을 때의 마지막 전송 오류입니다. 예: `HTTP 503: Service Unavailable`. `failing`이 아니면 비어 있습니다. |
| `pause_undelivered_count` | 정수 \| null | 엔드포인트가 일시 중지되었을 때 집계된, 마지막 성공 전송 이후 전송되지 않은 이벤트입니다. |
| `created_at`, `updated_at` | 타임스탬프 | |

<Note>
  엔드포인트의 전체 `secret`은 생성 시 **한 번만** 반환되며
  이후에는 다시 반환되지 않습니다. 안전하게 저장하세요. 분실한 경우
  [교체](#rotate-the-signing-secret)하여 새 값을 받으세요.
</Note>

### 유효한 이벤트 유형

`events`는 다음의 정확한 집합을 기준으로 검증됩니다. 목록에 없는 값은
`400`을 반환합니다. 각 유형의 페이로드 형식은 [이벤트 카탈로그](/ko/webhooks/events)를
참조하세요.

- `telephony.incoming`, `telephony.complete`, `telephony.tool`, `telephony.turn`
- `web.incoming`, `web.complete`, `web.tool`, `web.turn`
- `sms.sent`, `sms.failed`
- `sms.received`(예약됨, 아직 발생하지 않음)
- `call.graded`, `call.data_extracted`, `call.transfer_completed`
- `campaign.completed`
- `issue.reported`, `issue.escalated`
- `test-call.completed`
- `alert.triggered`

`issue.escalated`에는 에이전트 컨텍스트가 없으며 조직 전체 엔드포인트에만
전송됩니다.

`voice.ready` 및 `voice.failed`는 명시적으로 선택할 수 없습니다. 이를 수신하려면
`events: []`로 조직 전체 엔드포인트를 생성하세요. 빈 이벤트 목록은 명시적으로 선택해야 하는
`telephony.turn` 및 `web.turn`을 제외한 모든 지원 이벤트를 수신합니다.

### 엔드포인트 상태

- `active` — 전송이 정상적으로 이루어집니다.
- `disabled` — `PATCH`를 통해 수동으로 일시 중지된 상태입니다. 요청이 전송되지 않습니다. ThunderPhone은 `disabled` 엔드포인트의 상태를 변경하지 않으며, `active`로 다시 전환할지는 항상 사용자가 결정합니다.
- `failing` — 엔드포인트로의 전송이 2xx 응답을 한 번도 받지 못한 채 전체 재시도 일정(24시간 동안 8회 시도)을 모두 소진하면 자동으로 설정됩니다. 실패 상태의 엔드포인트에는 추가 트래픽이 전송되지 않습니다. 이 경우 조직의 소유자와 관리자에게 이메일을 보내며, 대시보드에는 일시 중지된 엔드포인트와 함께 다시 활성화 버튼이 표시됩니다. 엔드포인트를 수정한 후 상태를 `PATCH`로 다시 `active`로 변경하면, 재시도 일정이 아직 만료되지 않은 전송은 중단된 지점부터 재개됩니다.

---

## 엔드포인트 목록 조회

<CodeGroup>
```bash cURL
curl https://api.thunderphone.com/v1/developer/webhook-endpoints \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

[엔드포인트 객체](#endpoint-object) 배열을 반환합니다.
`?agent_id=42`를 전달하면 해당 에이전트로 범위가 지정된 엔드포인트만 반환합니다.

### 에이전트 범위 엔드포인트

조직 전체 엔드포인트는 일치하는 모든 이벤트를 수신합니다. `agent_id`가 있는 엔드포인트는
해당 에이전트가 처리한 통화에 대한 일치 이벤트만 수신합니다.
`alert.triggered`처럼 에이전트 컨텍스트가 없는 이벤트는 해당 엔드포인트에 도달하지 않습니다. 이러한
엔드포인트는 에이전트 빌더의 **웹훅** 섹션에서도 생성하고 관리할 수 있습니다.

---

## 엔드포인트 만들기

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label":  "Production — Call events",
    "url":    "https://example.com/thunderphone/hook",
    "events": ["telephony.incoming", "telephony.complete"]
  }'
```

```python Python
result = requests.post(
    "https://api.thunderphone.com/v1/developer/webhook-endpoints",
    headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
    json={
        "label":  "Production — Call events",
        "url":    "https://example.com/thunderphone/hook",
        "events": ["telephony.incoming", "telephony.complete"],
    },
).json()
secret = result["secret"]
endpoint_id = result["id"]
```
</CodeGroup>

### 요청 필드

| 필드 | 유형 | 필수 | 설명 |
|-------|------|----------|-------------|
| `label` | 문자열 | 예 | 1–120자 |
| `url` | 문자열 | 예 | HTTPS URL(`localhost` / `127.0.0.1`에만 `http` 허용) |
| `events` | 배열 | 아니요 | 비어 있거나 생략하면 명시적 구독이 필요한 `telephony.turn` / `web.turn`을 제외한 모든 이벤트를 구독합니다. [유효한 이벤트 유형](#valid-event-types)에 나열된 값을 사용해야 하며, 중복 항목은 제거됩니다 |
| `agent_id` | 정수 \| null | 아니요 | 이 조직의 에이전트로 전송 범위를 제한합니다. 조직 전체 엔드포인트로 설정하려면 생략하거나 `null`을 사용합니다 |

[엔드포인트 객체](#endpoint-object)와 원시 서명 키(48자 16진수 문자열)가 포함된
추가 최상위 `secret` 필드를 포함하여 `201 Created`를 반환합니다.

```json
{
  "id": "c4d5e6f7-…",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "secret_hint": "a1b2…9f0e",
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z",
  "secret": "a1b2c37e08d94f5b16a2c8d90e7f3a4b5c6d7e8f90a19f0e"
}
```

<Warning>
  `secret`은 **생성 시에만** 반환됩니다. 이후 `GET` 응답에는
  `secret_hint`만 포함됩니다. 응답을 닫기 전에 전체 값을 시크릿
  관리자에 복사합니다.
</Warning>

---

## 엔드포인트 업데이트

<CodeGroup>
```bash cURL
curl -X PATCH https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label":  "Production — Call + Grade events",
    "events": ["telephony.incoming", "telephony.complete", "call.graded"]
  }'
```
</CodeGroup>

| 필드 | 유형 | 설명 |
|-------|------|-------------|
| `label` | 문자열 | |
| `url` | 문자열 | |
| `events` | 배열 | |
| `status` | 문자열 | `active` 또는 `disabled`입니다. 서버가 `failing`으로 표시한 엔드포인트를 다시 활성화하려면 `active`로 설정합니다 |
| `agent_id` | 정수 \| null | 엔드포인트 범위를 제한하려면 에이전트 ID를 설정하고, 조직 전체로 설정하려면 `null`을 사용합니다 |

업데이트된 [엔드포인트 객체](#endpoint-object)와 함께 `200 OK`를 반환합니다.

---

## 서명 시크릿 교체

엔드포인트의 서명 시크릿을 교체합니다. 예를 들어 시크릿을 분실했거나
유출되었을 수 있는 경우에 사용합니다. 에이전트 범위 엔드포인트의 경우
대시보드에서도 사용할 수 있습니다. 에이전트의 **웹훅** 섹션을 열고
엔드포인트에서 **시크릿 재생성**을 선택합니다. 조직 전체 엔드포인트는
API를 통해 교체합니다.

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../rotate-secret \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```
</CodeGroup>

| 필드 | 유형 | 필수 | 설명 |
|-------|------|----------|-------------|
| `include_copies` | 불리언 | 아니요 | 기본값은 `true`입니다. 다른 에이전트에 있는 이 엔드포인트의 복사본처럼 동일한 URL과 동일한 현재 시크릿을 사용하는 조직의 다른 엔드포인트에도 새 시크릿을 제공합니다. 따라서 하나의 수신기가 하나의 시크릿으로 계속 검증할 수 있습니다. |

`200 OK`를 반환합니다.

```json
{
  "endpoint": { "id": "c4d5e6f7-...", "secret_hint": "7f3a…c21d", "...": "..." },
  "secret": "7f3a90b2c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5c21d",
  "rotated_endpoint_ids": ["c4d5e6f7-..."]
}
```

| 필드 | 유형 | 설명 |
|-------|------|-------------|
| `endpoint` | 객체 | 새 `secret_hint`가 포함된 [엔드포인트 객체](#endpoint-object)입니다. |
| `secret` | 문자열 | 새 서명 시크릿입니다. 이 응답에서만 반환됩니다. |
| `rotated_endpoint_ids` | UUID 배열 | 이제 새 시크릿을 사용하는 모든 엔드포인트입니다. |

<Warning>
  이전 시크릿은 즉시 사용이 중단됩니다. 재시도를 포함한 다음 전송은
  새 시크릿으로 서명됩니다. 수신기에 새 시크릿이 적용되기 전까지는
  전송이 서명 검사를 통과하지 못합니다. 수신기가 이에 대해 2xx가 아닌
  상태로 응답하면 일반적인 24시간 일정에 따라 재시도되므로 수신기를
  즉시 업데이트합니다. 수신기를 단계적으로 배포하는 경우 배포 중에는
  두 시크릿을 모두 허용하도록 구성합니다. SDK 검증 도우미는 시크릿
  목록을 받습니다([웹훅 서명 검증](/ko/guides/verify-webhook-signatures) 참고).
</Warning>

---

## 테스트 전송 보내기

표준 전송 파이프라인을 사용하여 하나의 엔드포인트로 합성 `webhook.test` 이벤트를 전송합니다. 여기에는 정규 JSON 직렬화, 두 서명 헤더, 전송 기록 및 재시도 관리가 포함됩니다.
테스트는 `events` 필터와 관계없이 선택한 엔드포인트를 대상으로 합니다.

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../test \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

엔드포인트는 다음과 같은 엔벨로프를 수신합니다.

```json
{
  "data": {
    "message": "ThunderPhone webhook test",
    "sent_at": "2026-07-17T20:12:34.567890+00:00"
  },
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "type": "webhook.test"
}
```

대상에서 오류를 반환하더라도 API는 첫 번째 시도 후 `200 OK`를 반환합니다.
전송 결과는 `success`, `status`, `response_code`, `error`를 확인하십시오.

```json
{
  "success": true,
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "event_type": "webhook.test",
  "status": "delivered",
  "response_code": 204,
  "error": ""
}
```

`webhook.test`는 합성 이벤트이므로 엔드포인트의 `events` 구독에 추가할 수 없습니다.
첫 번째 시도가 실패하면 ThunderPhone은 약 1분 후 한 번 재시도한 다음 중지합니다. 이후 전송은
[전송 디버깅](#debug-deliveries)에서 `status: "failed"`로 표시됩니다. 테스트 전송은 엔드포인트를
`failing` 상태로 표시하지 않습니다.

실제 이벤트 형태에 대한 트리거를 구성하려면 선택 사항인
`event_type`을 전달하십시오. 전송은 계속 합성 이벤트이며 `"sample": true`를 포함합니다.
통화 관련 샘플은 `call_id: 0` 및 `agent_id: 0`을 사용합니다.

```bash
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../test \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event_type":"call.graded"}'
```

`event_type`은 [유효한 이벤트 유형](#valid-event-types)의 모든 값을 허용합니다.
생략하면 일반 `webhook.test` 동작이 유지됩니다.

---

## 엔드포인트 삭제하기

<CodeGroup>
```bash cURL
curl -X DELETE https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

`204 No Content`를 반환합니다. URL로의 전송은 즉시 중지되며,
진행 중인 재시도는 중단됩니다.

---

## 전송 디버깅

웹훅이 전송되지 않았다고 결론 내리기 전에
[`GET /v1/developer/webhook-deliveries`](/api-reference/webhook-deliveries)를 확인하십시오.
이 API는 통화 ID, URL 오리진, HTTP 상태, 시도 횟수, 허용 목록에 포함된 실패 범주 및 다음
재시도 시간을 포함하여 두 웹훅 시스템의 최근 시도를 보여 줍니다. 이벤트 페이로드, 트랜스크립트,
저장된 오류 텍스트, 응답 본문 또는 URL 경로는 반환하지 않습니다.

**에이전트 → 에이전트 선택 → 웹훅 →
최근 전송**에서도 동일한 최근 기록을 확인할 수 있습니다. 행에는 엔드포인트 레이블과 최신
시도에 사용된 URL 오리진이 표시됩니다. 이는 변경 불가능한 감사 로그가 아닌 운영 상태이므로 엔드포인트를
삭제하면 해당 전송 행도 삭제됩니다.

n8n `404`의 경우 먼저 워크플로가 활성 상태이고 `POST`를 허용하며 테스트 URL이 아닌
프로덕션 웹훅 URL을 사용하는지 확인하십시오. `401` 또는 `403`은 인증 또는 서명 검증 문제를
나타냅니다. 시간 초과는 대상 지연 시간 또는 가용성 문제를 나타내며, TLS 오류는 인증서 체인,
호스트 이름 또는 만료 문제를 나타냅니다.

---

## 관련 항목

<CardGroup cols={2}>
  <Card title="이벤트 카탈로그" icon="list" href="/ko/webhooks/events">
    구독할 수 있는 전체 `events` 값 목록입니다.
  </Card>
  <Card title="웹훅 개요" icon="bolt" href="/ko/webhooks/overview">
    서명 검증 및 전송 의미 체계입니다.
  </Card>
</CardGroup>
