전달
재시도
모든 전달은 내부 큐를 거쳐 이뤄지며, 결과적으로 at-least-once입니다. 큐 적재 후 보통 1초 안에(드물게 부하 시 수십 초 뒤) 첫 전달이 일어납니다.
- 전달 시도 — 한 번의 전달 사이클에서
429·5xx·연결 오류면 최대 3회 시도하며 시도 간 1초·2초 대기합니다 - 재전달 — 한 사이클이 실패하면 큐에 남겨 이벤트 접수 시점부터 최대 약 24시간 다시 시도합니다
성공 판정은 2xx 응답입니다. 한 번의 전달 사이클에서 재시도하는 대상은 429·5xx·연결 오류(타임아웃·연결 실패)이며, 이때만 최대 3회 시도합니다. 4xx(429 제외)는 재시도 없이 한 번에 멈춥니다.
한 번의 전달 사이클이 실패하면 실패 유형(4xx·5xx·네트워크 오류)과 무관하게 모두 동일한 규칙으로 큐에서 다시 시도됩니다 — 초기 수 분간은 짧은 백오프로, 이후에는 약 30분 간격으로 다시 시도하고, 이벤트 접수 시점부터 약 24시간이 지나면 폐기됩니다. 잘못된 페이로드로 4xx가 계속 실패하는 이벤트도 무한히 재시도되지 않고 같은 규칙으로 폐기됩니다.
같은 이벤트가 두 번 이상 도착할 수 있으므로 수신 측 멱등 처리를 권장합니다. 멱등 키는 event_type + workspace_id + 이벤트 식별자 + 봉투 timestamp로 구성하세요. 이벤트 식별자는 메시지 이벤트는 data.message_id, 채널 이벤트는 channel.id 스냅샷입니다(채널 이벤트의 channel_id는 data에서 빠집니다 — 이벤트 참고). 여기서 timestamp는 봉투의 timestamp(같은 이벤트 재전송 간 고정)이며, 서명용 헤더 X-Webhook-Timestamp(재전송마다 갱신)와 다릅니다. 전용 delivery-id 헤더는 없습니다. ZeroTalk도 10분 윈도우 안에서는 중복 발송을 best-effort로 억제하지만, 그 밖에서는 재발송될 수 있습니다.
타임아웃
- 개별 HTTP 요청: 10초
- 전체 전달(재시도 포함) 컨텍스트: 20초
수신 endpoint는 가능한 빨리(권장 5초 이내) 2xx로 응답하고, 무거운 처리는 큐로 비동기화하세요.
순서 보장
웹훅 전달 순서는 보장되지 않습니다. 전달 시도·재전달 때문에 나중에 발생한 이벤트가 먼저 도착할 수 있고, 전역 순번도 없습니다.
- 메시지: 한 채널 안 순서는
data.seq(생성 시 부여되는 채널 순번)로 판단하세요. - 채널 이벤트:
data.version(채널 집계 버전)이 대략적인 순서를 주지만, 한 번의 변경에서 여러 이벤트가 같은version으로 나올 수 있어(예: 종료 시 배정 해제 + 종료) 완전한 단일 순서 키는 아닙니다. 정확한 현재 상태가 필요하면GET /channels/{id}(channels:readscope의 PAT 필요)로 다시 조회하세요. data.created_at은*.created이벤트에만 있어 범용 정렬 키로 쓸 수 없고, 채널을 가로지르는 절대 순서는 봉투timestamp(전송 시각의 근사치)로만 대략 가늠할 수 있습니다.
출발지 IP
ZeroTalk는 웹훅을 고정된 출발지 IP에서 보낸다고 보장하지 않습니다(인프라에 따라 바뀔 수 있습니다). 수신 endpoint는 IP 허용목록이 아니라 서명 검증으로 인증하세요.
자동 비활성화
연속 10회 실패하면 웹훅 상태가 error로 바뀌고 송신이 중단됩니다. 이 카운트는 각 이벤트의 첫 전달 시도 기준이며(첫 시도는 큐를 거칩니다 — 재시도 참고), 이어지는 재전달의 실패는 반영되지 않습니다 — 재전달이 임계 도달을 앞당기지 않습니다. 비활성 기간에 보류됐다가 재활성화 후 처음 전달되는 이벤트의 첫 시도도 같은 카운트에 포함됩니다. 비활성화되면 워크스페이스 관리자(owner/admin)에게 이메일과 대시보드 실시간 알림이 발송됩니다 — 단, 한 번도 성공한 적 없는(설정 중인) 웹훅은 알림하지 않으며, 같은 웹훅에 대한 알림은 24시간에 한 번으로 제한됩니다.
error 상태에서는 자동 복구되지 않으므로(송신이 중단돼 성공 전달이 더 이상 발생하지 않습니다), 사유를 확인한 뒤 수동으로 다시 활성화해야 합니다 — 대시보드 토글 또는 PAT API의 POST /outbound-webhooks/{id}/toggle. 재활성화하면 failure_count가 리셋됩니다.
비활성(error 또는 일시 중지) 기간에 전달 시점이 도래한 미전달분은 곧바로 폐기되지 않고 보류됩니다 — 이벤트 접수 시점부터 24시간 윈도우 안에 재활성화하면 보류분이 전달됩니다. 반면 비활성화 이후 새로 발생한 이벤트는 전송되지 않고 보존되지도 않으므로, 알림을 받으면 가능한 빨리 endpoint를 복구하고 재활성화하세요.
에코 correlation
Public API로 답장을 보내는 콘솔에 한정된 주의 사항입니다.
상담원이 POST /channels/{id}/messages로 보낸 답장은 message.created 웹훅으로 다시 도착합니다. 그런데 웹훅 페이로드에는 전송 시 보낸 client_request_id가 없습니다. 따라서 다음과 같이 message_id로 상관(correlate) 하세요.
- 전송 응답의
data.id(새 메시지 id)를 짧게 유지되는 집합에 저장합니다. message.created웹훅이 도착하면data.message_id가 그 집합에 있는지 확인합니다.- 있으면 자신이 보낸 메시지의 에코이므로 이미 렌더된 것으로 취급해 중복 렌더를 피합니다.
client_request_id는 전송 멱등성(같은 키로 재시도하면 원본 반환) 용도일 뿐, 웹훅 상관 키가 아닙니다.
전달 로그
대시보드 → Webhooks → 해당 웹훅 → Logs에서 성공 여부·HTTP 상태·에러 메시지·소요 시간을 확인할 수 있습니다.
PAT로 웹훅을 등록한 경우 GET /outbound-webhooks/{id}/delivery-logs로도 조회할 수 있습니다.
웹훅 관리 API
웹훅은 대시보드 UI 또는 PAT API로 관리합니다. 외부 BFF·서버에서 토큰으로 관리하려면 Outbound 웹훅 관리 API(webhooks:read/webhooks:write)를 사용하세요. 아래 표의 관리 API는 그와 별개로, 대시보드 인증(JWT)과 integration:manage 권한이 필요한 내부 경로입니다.
| Method | Path | 설명 |
|---|---|---|
POST | /workspaces/me/webhooks | 생성 |
GET | /workspaces/me/webhooks | 목록 |
GET | /workspaces/me/webhooks/{webhookId} | 단건 조회 |
PATCH | /workspaces/me/webhooks/{webhookId} | 수정 |
DELETE | /workspaces/me/webhooks/{webhookId} | 삭제 |
POST | /workspaces/me/webhooks/{webhookId}/regenerate-secret | 시크릿 회전 |
POST | /workspaces/me/webhooks/{webhookId}/toggle | 상태 전환 |
GET | /workspaces/me/webhooks/{webhookId}/delivery-logs | 전달 로그 |