> For the complete documentation index, see [llms.txt](https://api-docs.roundhr.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://api-docs.roundhr.com/round-webhook/webhook.md).

# 라운드 Webhook 개요

## 1. Webhook 이란

라운드 Webhook을 통해 라운드 상에서 이벤트 발생 시 등록하신 callback url 로 알림을 받아보실 수 있습니다.

## 2. Webhook 활용

지원자의 채용 단계 변경, 평가 완료, 면접 일정 확정 등 주요 이벤트 발생 시 등록하신 callback url로 실시간 알림을 받아보실 수 있습니다.

## 3. Webhook 연동

Webhook은 API를 통해 등록, 수정, 삭제할 수 있습니다.

| 기능    | 엔드포인트                      |
| ----- | -------------------------- |
| 목록 조회 | GET /v1/webhooks           |
| 상세 조회 | GET /v1/webhooks/{code}    |
| 등록    | POST /v1/webhooks          |
| 수정    | PATCH /v1/webhooks/{code}  |
| 삭제    | DELETE /v1/webhooks/{code} |

{% hint style="info" %}
상세한 API 명세는 [Webhook API 문서](/round-api/api-reference/webhooks.md)를 참조하세요.
{% endhint %}

현재 지원 가능한 이벤트 목록은 아래와 같습니다.

| 타입                        | 설명                |
| ------------------------- | ----------------- |
| candidate\_stage\_changed | 지원자의 채용 단계가 변경될 때 |
| candidate\_pass           | 지원자가 합격 단계로 이동할 때 |
| feedback\_created         | 평가가 생성될 때         |
| feedback\_completed       | 평가가 완료될 때         |
| interview\_scheduled      | 면접 일정이 확정될 때      |
| form\_submitted           | 지원자가 양식을 제출할 때    |

## 4. 재전송 정책

웹훅 전송이 실패할 경우 (HTTP 200 응답이 아닌 경우), 라운드는 자동으로 재전송을 시도합니다.

| 시도     | 대기 시간         |
| ------ | ------------- |
| 1차 재시도 | 10초 후         |
| 2차 재시도 | 30초 후         |
| 3차 재시도 | 90초 후         |
| 4차 재시도 | 270초 (4.5분) 후 |

{% hint style="warning" %}
최초 전송 포함 최대 5회까지 전송을 시도하며, 모든 시도가 실패할 경우 해당 웹훅 이벤트는 전송되지 않습니다. callback url이 정상적으로 응답하는지 확인해 주세요.
{% endhint %}

## 5. Payload 형태

웹훅 요청은 다음과 같은 형태로 전송됩니다.

```json
{
  "action": "candidate_pass",
  "payload": {
    // 이벤트별 데이터
  }
}
```

## 6. 서명 검증

callback url과 함께 signing key를 등록하시면 웹훅 요청이 라운드에서 발송된 것인지 검증할 수 있습니다.

signing key를 등록하실 경우 아래와 같이 header에 서명이 포함되어 전송됩니다.

```
Round-Webhook-Signature: t=1234567890,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
```

* `t`: 요청 발송 시점의 Unix timestamp
* `v1`: HMAC-SHA256 서명값

### 1) 검증 방법

서명은 `{timestamp}.{payload}` 형태의 문자열을 signing key로 HMAC-SHA256 해시한 값입니다.

**Ruby**

```ruby
timestamp = header['Round-Webhook-Signature'].match(/t=(\d+)/)[1]
received_signature = header['Round-Webhook-Signature'].match(/v1=([a-f0-9]+)/)[1]

expected_signature = OpenSSL::HMAC.hexdigest('SHA256', signing_key, "#{timestamp}.#{payload}")

if expected_signature == received_signature
  # 유효한 요청
end
```

**Python**

```python
import hmac
import hashlib

expected_signature = hmac.new(
    signing_key.encode(),
    f"{timestamp}.{payload}".encode(),
    hashlib.sha256
).hexdigest()

if expected_signature == received_signature:
    # 유효한 요청
```

### 2) Replay Attack 방지

timestamp를 확인하여 오래된 요청을 거부할 수 있습니다. 일반적으로 5분 이내의 요청만 허용하는 것을 권장합니다.

```ruby
if Time.now.to_i - timestamp.to_i > 300
  # 5분 초과된 요청 거부
end
```
