메시지 이벤트
Description
상담방에서 오간 메시지(CHAT)를 등록하신 수신 URL 로 발송합니다.
공통 규격(서명 검증 · 응답 규약 · 재시도 · 중복 처리)은 기본 정보를 먼저 확인해 주세요.
발송 시점
- 고객이 메시지를 보냈을 때
- 상담사가 메시지를 보냈을 때
- 봇·자동 메시지가 발송될 때 (상담 종료 안내, 근무 외 자동 안내, FAQ 자동답변 등)
발신 주체는 본문의 userType 으로 구분합니다.
봇·자동 메시지(상담 종료 안내, 근무 외·부재중 자동 안내, 챗봇·시나리오, 보이스피싱 경고, FAQ 자동답변 등)도 발송됩니다.
다만 채널·메시지 종류에 따라 일부 자동 메시지는 웹훅이 발송되지 않을 수 있습니다.
고객 식별자(uid) 없이 시작된 상담방은 CHAT 이벤트가 발송되지 않을 수 있고, 발송되는 경우 customerUid 가 빈 문자열 "" 로 옵니다(같은 상담방의 ROOM 이벤트는 발송됩니다). 빈 customerUid 는 고객 식별자로 쓰지 말고 상담방은 roomId 로 구분해 주세요.
Endpoint
Body
| Field Name | Type | Description |
|---|---|---|
| eventType | String | 이벤트 유형 (CHAT) — 구독별 적용 |
| issuedAt | Timestamp | 이벤트 발생 시간 — 구독별 적용 |
| eventId | String | 이벤트 고유 ID — 중복 수신 제거 키 (구독별 적용) |
| id | BigInt! | 메시지 ID |
| siteId | BigInt | 사이트 ID (구독별 적용) |
| roomId | String! | 상담방 ID |
| roomEndMessage | Boolean! | 상담 종료 메시지 여부 |
| type | String! | 메시지 유형 — 현재는 'C'(상담 채팅 메시지)만 발송. 추후 값이 추가될 수 있으니 미지의 값은 무시 처리 권장 |
| userType | String! | 발신 주체 — 아래 코드 정의 참고 |
| contents | String! | 메시지 본문 — contentsType 에 따라 평문이 아닐 수 있습니다(JSON 문자열 또는 파일 URL). 본문 형태 참고 |
| contentsType | String! | 본문 유형 — contents 의 해석 방법을 결정합니다. 값별 형태는 본문 형태 참고 |
| customerUid | String! | 고객 UID — uid 없이 시작된 상담방은 빈 문자열 "" |
| msgId | String! | 메시지 고유 키 (참고값 — 중복 제거에는 eventId 사용) |
| sendDate | String! | 발송 시각 |
ROOM 이벤트와 본문 구조가 다릅니다.
ROOM 은 eventType · appCredential · data 로 감싼 형태이고,
CHAT 은 위 필드들이 최상위에 평평하게 놓입니다(eventType·issuedAt 은 어휘만 맞춘 것입니다).
서명 검증 방식(본문 원문 HMAC)은 두 이벤트가 동일합니다.
본문 형태 (contentsType × contents)
contents 를 항상 평문으로 다루면 이미지 URL·버튼 정보가 사용자에게 그대로 노출됩니다.
contentsType 을 먼저 확인하고 그 값에 맞게 contents 를 해석해 주세요.
contentsType |
contents 형태 |
비고 |
|---|---|---|
text |
평문 문자열 | 가장 흔한 형태 |
template |
JSON 문자열(대부분) | 버튼·이미지를 포함한 구조화 메시지. 아래 필드표 참고. ⚠️ JSON 형식이 아닌 원문이 그대로 올 수도 있으니 파싱 실패 시 평문으로 처리해 주세요 |
normal |
JSON 문자열(대부분) — { "text": …, "image_url": …, "link": { "name": [], "url": [] } } |
구버전 상담방(ver 1.0)에서만 발생합니다. ⚠️ 여기도 JSON 이 아닌 원문이 올 수 있습니다 |
image · audio · video · file |
파일 URL 문자열 | 원본 파일명·미디어 타입은 본문에 포함되지 않습니다 |
chatbot · awesomebot · scenario |
JSON 문자열(봇 메시지) | 봇·시나리오 메시지입니다. 내부 유형에 따라 userType 이 B(봇 발화) 또는 C(고객 답변)로 전달되며, 그 밖의 유형은 원래 발신 주체를 유지합니다 |
| 그 외 / 미지의 값 | 평문 문자열로 처리 권장 | 값이 추가될 수 있습니다 |
template 의 contents JSON 필드
| 필드 | 설명 |
|---|---|
type |
템플릿 유형 — TEXT · IMAGE · CAROUSEL |
message |
텍스트 본문. CAROUSEL 은 카드가 있으면 첫 카드의 본문, 카드가 없으면 기본 답변 본문입니다 |
image |
이미지 정보 객체 { "imageUrl": … }. 이미지 URL 이 있으면 포함되며 CAROUSEL 에도 함께 올 수 있습니다 |
buttonList |
버튼 목록 |
quickReplyList |
빠른 답장 목록 |
carouselBlocks |
캐러셀 카드 목록. 카드마다 header · message 와 선택적으로 image · buttonList 등을 가집니다. CAROUSEL 이라도 카드 데이터가 없으면 필드가 아예 없거나 빈 배열 [] 로 올 수 있으니 두 경우를 함께 처리해 주세요 |
isLocked |
내부 처리용 플래그 |
필드는 확장될 수 있으므로 미지의 필드는 무시하도록 구현해 주세요.
긴 메시지는 여러 건으로 나뉘어 발송됩니다.
본문에 분할 구분자가 포함된 경우 한 메시지가 여러 건의 웹훅으로 나뉩니다. 이때
buttonList · quickReplyList 는 마지막 건에만 담기고, 두 번째 건 이후의
type: "IMAGE" 는 TEXT 로 바뀌어 image 가 제거됩니다. 버튼·이미지를 기다리는
로직은 이 점을 고려해 주세요.
Example
Success
{
"eventType": "CHAT",
"issuedAt": 1785114900.123,
"eventId": "9b1d7c42-6e05-4a83-b1f7-2c9d84e05a13",
"id": 88214417,
"siteId": 900001,
"roomId": "btYhiv7WkwfOSLoN164a61561f3665",
"roomEndMessage": false,
"type": "C",
"userType": "C",
"contents": "주문한 상품 언제 배송되나요?",
"contentsType": "text",
"customerUid": "test_user_01",
"msgId": "20260727T101500-0001",
"sendDate": "2026-07-27 10:15:00"
}
{
"eventType": "CHAT",
"issuedAt": 1785114930.456,
"eventId": "1c8f2a90-4d37-4b6e-8f02-77ac5b3e9d41",
"id": 88214418,
"siteId": 900001,
"roomId": "btYhiv7WkwfOSLoN164a61561f3665",
"roomEndMessage": false,
"type": "C",
"userType": "H",
"contents": "안녕하세요, 확인 도와드리겠습니다.",
"contentsType": "text",
"customerUid": "test_user_01",
"msgId": "20260727T101530-0002",
"sendDate": "2026-07-27 10:15:30"
}
코드 정의
userType
| 값 | 설명 |
|---|---|
C |
고객 |
H |
상담사 |
S |
매니저 |
M |
관리자 |
B |
봇·자동 (상담 종료 안내, 근무 외·부재중 자동 안내, 챗봇·시나리오, 보이스피싱 경고) — 수신 빈도 높음 |
A |
FAQ 자동답변 |