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

# Webhook 엔드포인트

> 엔드포인트별 시크릿 및 이벤트 필터를 사용하여 여러 Webhook 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}/test` | `admin+` | 서명된 테스트 전달 전송             |

## 엔드포인트 객체

```json theme={null}
{
  "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"
}
```

| 필드                         | 유형        | 설명                                                                                               |
| -------------------------- | --------- | ------------------------------------------------------------------------------------------------ |
| `id`                       | UUID      | 엔드포인트 ID                                                                                         |
| `label`                    | string    | 표시 이름, 1\~120자                                                                                   |
| `url`                      | string    | HTTPS URL, 개발 환경에서는 `http://localhost` 허용                                                        |
| `events`                   | 문자열 배열    | 구독하는 이벤트 유형([유효한 값](#valid-event-types) 참조). 빈 배열은 모든 이벤트를 구독합니다                                 |
| `status`                   | string    | `active`, `disabled`(수동 일시 중지), 또는 `failing`(전달이 단 한 번의 2xx도 받지 못한 채 24시간 재시도 일정을 모두 소진하면 자동 설정) |
| `secret_hint`              | string    | 줄임표가 포함된 서명 시크릿의 처음 4자와 마지막 4자(`a1b2…9f0e`) — 전체 값을 노출하지 않고 로컬에 저장한 시크릿을 대조하기에 충분합니다             |
| `created_at`, `updated_at` | timestamp |                                                                                                  |

<Note>
  엔드포인트의 전체 `secret`은 생성 시 **한 번만** 반환되며
  이후에는 다시 반환되지 않습니다. 안전하게 저장하세요. 잃어버린 경우 엔드포인트를 삭제하고
  다시 생성해야 합니다.
</Note>

### 유효한 이벤트 유형

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

* `telephony.incoming`, `telephony.complete`, `telephony.tool`
* `web.incoming`, `web.complete`, `web.tool`
* `call.graded`
* `issue.reported`
* `test-call.completed`
* `alert.triggered`

### 엔드포인트 상태

* `active` — 전달이 정상적으로 진행됩니다.
* `disabled` — `PATCH`를 통해 수동으로 일시 중지됩니다. 요청이 전송되지 않습니다. ThunderPhone은
  `disabled` 엔드포인트의 상태를 변경하지 않으며, 다시
  `active`로 전환할지는 항상 사용자가 결정합니다.
* `failing` — 엔드포인트로의 전달이 단 한 번의 2xx도 받지 못한 채
  전체 재시도 일정(24시간 동안 8회 시도)을 모두 소진하면 자동으로 설정됩니다. 실패 상태의 엔드포인트에는 추가 트래픽이 전달되지 않습니다.
  엔드포인트를 수정한 후 `PATCH`로 상태를 다시 `active`로 변경하세요.
  재시도 일정이 아직 만료되지 않은 전달은 중단된 지점부터 다시 진행됩니다.

***

## 엔드포인트 나열

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

[엔드포인트 객체](#endpoint-object) 배열을 반환합니다.

***

## 엔드포인트 만들기

<CodeGroup>
  ```bash cURL theme={null}
  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 theme={null}
  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 (`http`는 `localhost` / `127.0.0.1`에서만 허용)                                        |
| `events` | 배열  | 아니요 | 비어 있거나 생략하면 모든 이벤트를 구독합니다. [유효한 이벤트 유형](#valid-event-types)에 나열된 값을 사용해야 하며, 중복 항목은 제거됩니다. |

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

```json theme={null}
{
  "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 theme={null}
  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`로 설정합니다. |

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

***

## 테스트 전송 보내기

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

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

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

```json theme={null}
{
  "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 theme={null}
{
  "success": true,
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "event_type": "webhook.test",
  "status": "delivered",
  "response_code": 204,
  "error": ""
}
```

`webhook.test`는 합성 이벤트이며 엔드포인트의 `events` 구독에 추가할 수 없습니다.
첫 번째 시도가 실패하면 일반 이벤트 전송과 동일한 재시도 일정이 적용됩니다.

***

## 엔드포인트 삭제

<CodeGroup>
  ```bash cURL theme={null}
  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로의 전송이 즉시 중단되며,
진행 중인 재시도는 취소됩니다.

***

## 관련

<CardGroup cols={2}>
  <Card title="이벤트 카탈로그" icon="list" href="/ko/webhooks/events">
    구독할 수 있는 전체 `events` 값 목록입니다.
  </Card>

  <Card title="웹훅 개요" icon="bolt" href="/ko/webhooks/overview">
    서명 검증 및 전송 의미 체계입니다.
  </Card>
</CardGroup>
