상담방 이벤트
Description
상담방(ROOM)의 상태 변화를 등록하신 수신 URL 로 발송합니다.
공통 규격(서명 검증 · 응답 규약 · 재시도 · 중복 처리)은 기본 정보를 먼저 확인해 주세요.
발송 시점
- 신규 상담방 생성 시
- 상담방 상태 변경 시 — 전달되는 값은
data.status(RoomStatus)이며, 요구 상태명과의 대응은 상태 값 읽는 법 참고 - 상담사 변경 시
- 상담방 분류 변경 시
- 상담방 태그 변경 시
- 상담방 플래그 변경 시 (구독별 적용 — 적용 전에는 플래그 변경만으로는 이벤트가 발생하지 않습니다)
상태 값은 발화 주체에 따라 오갑니다.
RECEIPT_COUNSEL(문의) ↔ COUNSELOR_IN_PROGRESS(응대) 는 고정된 단계가 아니라
마지막 발화자에 따라 토글됩니다. 따라서 상태 변경 이벤트의 발생 빈도는
대화 메시지 빈도와 비슷한 수준이 될 수 있습니다.
상태 값 읽는 법
전달되는 값은 data.status 하나이며, 아래와 같이 대응됩니다.
| 알고 싶은 것 | 판별 방법 |
|---|---|
| 신규 상담방 생성 | 수신측에서 data.roomId 를 기록해 두고, 처음 보는 roomId 를 신규로 판단해 주세요. 단, 이는 그 구독이 처음 관측한 상담방이라는 뜻입니다 — 구독 등록 이전부터 진행 중이던 상담방도 첫 이벤트에서 처음 보이므로, 구독 이후 생성된 방만 신규로 보려면 createdAt 이 구독 등록 시각 이후인지 함께 확인해 주세요. 이벤트 자체에는 전용 플래그가 없습니다 — changedFields: null 은 생성 외에도 비교 기준이 없는 여러 경우(스냅샷 만료·규격 전환 직후 등)에 나오고, createdAt 과 수신 시각의 차이도 기준이 되지 못합니다(재발송으로 약 27초 이상 늦게 도착할 수 있고, 생성 직후의 후속 이벤트도 같은 창에 들어옵니다) |
| 접수 · 대기 | 둘은 내부적으로 같은 상태이며 RECEIPT_COUNSEL 로 전달됩니다(고객 발화 후 상담사 응대 전). 두 단계를 나누어 구분할 수는 없습니다 |
| 진행중 | COUNSELOR_IN_PROGRESS(상담사 응대 중) 또는 CHATBOT_IN_PROGRESS(봇 상담 중) |
| 봇 상담 대기 | WAIT_COUNSEL |
| 종료 | FINISHED_BY_COUNSELOR · FINISHED_BY_CHATBOT — 이때 isCloseRoom 이 true 이고 roomEndType · roomEndOption 에 종료 처리자·옵션이 담깁니다. 드물게 아래 목록에 없는 종료 코드가 기록된 상담방이 있어, 그 경우 두 필드는 null 로 전달됩니다 |
| 고객 삭제 | DELETED_BY_CUSTOMER — 고객이 상담방을 삭제한 상태입니다. ⚠️ 이 경우 isCloseRoom 은 false 이고 roomEndType · roomEndOption 은 null 이므로, 종료 여부를 isCloseRoom 만으로 판단하면 삭제된 방을 열린 방으로 처리하게 됩니다 — status 와 deletedAt 을 함께 확인해 주세요 |
값의 전체 목록은 이 문서 아래 코드 정의의 RoomStatus 표를 확인해 주세요.
짧은 시간 안에 연속된 상태 변화는 하나로 합쳐져 도착할 수 있습니다.
상태 변화는 일정 주기로 모아서 발송되며, 그 주기 안에 같은 상담방이 여러 번 바뀌면
마지막 상태 한 건만 전달됩니다. 예를 들어 문의 → 응대 → 문의 처럼 되돌아온 경우
최종 상태가 직전과 같아 이벤트가 발송되지 않을 수 있고, A → B → C 인 경우
중간 상태 B 는 전달되지 않습니다.
따라서 모든 상태 전이를 빠짐없이 받는 용도로는 사용하실 수 없습니다. 이벤트는 "이 상담방이 바뀌었고 지금 상태는 이렇다"는 알림으로 사용해 주시고, 전이 이력이 필요하시면 별도로 문의해 주세요.
Endpoint
Body
| Field Name | Type | Description | ||
|---|---|---|---|---|
| eventType | EventType! | 이벤트 유형 (ROOM) |
||
| eventId | String | 이벤트 고유 ID — 중복 수신 제거 키 (구독별 적용) | ||
| issuedAt | Timestamp! | 이벤트 발생 시간 | ||
| changedFields | [String] | 직전 상태 대비 변경된 data 필드 이름 목록 — null·빈 배열 가능 (아래 참고) (구독별 적용) |
||
| appCredential | CredentialData! | 앱 인증 정보 | ||
| key | String! | 앱 키 | ||
| expireAt | Timestamp! | 발송 시각 + 60초 (Unix epoch, 초). 재시도 시 재계산되므로 issuedAt+60 과 다를 수 있습니다. 재전송·리플레이 방지 참고값이며, 만료 검증 여부는 수신측 구현에 맡깁니다. |
||
| data | EventData! | 상담방 이벤트 | ||
| roomId | String! | 상담방 ID | ||
| siteId | BigInt! | 사이트 ID | ||
| status | RoomStatus! | 상담방 상태 | ||
| title | String! | 상담방 제목 | ||
| managerId | BigInt! | 매니저 ID | ||
| counselorId | BigInt! | 상담사 ID | ||
| customer | Customer! | 고객 정보 | ||
| id | BigInt! | 고객 ID | ||
| uid | String | 고객 UID | ||
| uuid | String! | 고객 UUID | ||
| categoryId | Int! | 대분류 ID | ||
| categoryName | String! | 대분류 이름 | ||
| subCategoryId | Int! | 중분류 ID | ||
| subCategoryName | String! | 중분류 이름 | ||
| extraCategoryName | String | 소분류 이름 | ||
| roomEndType | RoomEndType | 상담방 종료 처리자 | ||
| roomEndOption | RoomEndOption | 상담방 종료 옵션 | ||
| isCloseRoom | Boolean! | 상담방 종료 여부 | ||
| createdAt | Timestamp! | 상담방 생성 시간 | ||
| closedAt | Timestamp | 상담방 종료 시간 | ||
| deletedAt | Timestamp | 상담방 삭제 시간 | ||
| channelType | ChannelType | 상담 채널. 아래 목록에 없는 채널 코드가 오면 null 이 전달됩니다 |
||
| tags | [RoomTag!]! | 상담방에 등록된 태그 정보 | ||
| id | Int! | 태그 ID | ||
| name | String! | 태그 이름 | ||
| flag | Int | 상담방 플래그 값 (구독별 적용) | ||
| parameter1 ~ parameter10 | String | 채팅 진입 시 전달한 커스텀 파라미터 값 — 각 최대 20자, 값이 없으면 빈 문자열 "" (구독별 적용, 아래 참고) |
changedFields
data 안에서 직전 이벤트 대비 값이 바뀐 필드 이름들입니다.
"무엇이 바뀌어서 온 이벤트인지"를 이 목록으로 판별하실 수 있습니다.
null 은 '비교 기준이 없다'는 뜻입니다.
신규 상담방·직전 스냅샷 만료·구독 규격 전환 직후처럼 비교할 직전 상태가 없을 때 null 로 전달됩니다.
이때는 data 전체를 변경된 것으로 간주해 주세요.
드물게 빈 배열 [] 로 도착할 수도 있습니다. 이때도 null 과 마찬가지로
data 전체를 기준으로 처리해 주세요 — 값이 실제로 바뀌지 않았을 수 있습니다.
changedFields 는 보조 힌트이고, 정확한 현재 상태는 언제나 data 입니다.
상태 판단은 data 를 기준으로 하시고, changedFields 는 분기 처리에만 사용하시길 권장합니다.
도착 순서가 발생 순서와 다를 수 있습니다 — issuedAt 으로 정렬해 주세요.
전송이 실패한 이벤트는 지연 재발송 큐를 거쳐 나중에 다시 도착합니다. 그 사이 같은 상담방의
더 최신 이벤트가 먼저 도착할 수 있고, 두 이벤트는 서로 다른 eventId 라 중복 제거로
걸러지지 않습니다. 도착 순서대로 그대로 반영하면 최신 상태가 과거 상태로 되돌아갑니다.
상담방 상태를 저장하신다면 roomId 별로 마지막으로 반영한 issuedAt 보다 오래된 이벤트는
무시해 주세요. issuedAt 은 이벤트를 발행한 시점에 정해져 재전송 중에도 바뀌지 않으며,
같은 상담방에서는 변화가 늦게 일어난 이벤트일수록 큰 값을 갖습니다 — 그래서 정렬 기준으로
쓸 수 있습니다. (매 발송 시각으로 재계산되는 appCredential.expireAt 과 다릅니다.)
상담방 플래그 (flag)
flag 는 단일 열거값입니다 (비트 조합이 아닙니다).
하나의 값이 하나의 플래그 상태를 나타내며, 기본값 7 은 플래그 없음을 의미합니다.
값은 상담 화면에서 설정한 플래그에 대응합니다. 값이 바뀌면 changedFields 에 flag 가 포함됩니다.
커스텀 파라미터 (parameter1 ~ parameter10)
채팅 진입 URL(또는 상담 생성 API)로 전달한 parameter1 ~ parameter10 값이 그대로 실립니다.
상담사 화면의 기타정보 탭에 보이는 값과 같습니다. 유입 경로·캠페인 키처럼 고객사 시스템의 기록과
상담방을 연결하는 용도로 사용하실 수 있습니다.
채팅 진입 URL 로 전달하는 방법
params 하나의 값에 이름=값 을 쉼표(,)로 이어 붙여 전달합니다. 고객 UID(site_uid)도 같은 자리에 넣습니다.
¶meter1=ad_0001처럼 개별 쿼리로 붙이면 저장되지 않습니다.- 값에 한글이 있으면 URL 인코딩해 주세요. 쉼표(
,)와 앰퍼샌드(&)는 인코딩해도 값 안에 쓸 수 없습니다(뒤 항목까지 유실됩니다) — 이런 문자가 든 값은 20자 이내 대체 키로 전달해 주세요.
각 값은 최대 20자이고, 전달하지 않은 항목은 빈 문자열로 옵니다.
20자를 넘는 추적값(예: 광고 클릭 ID)은 고객사에서 20자 이내의 키로 바꿔 전달하고, 고객사 시스템에서 원래 값과 매핑해 주세요.
값은 상담 도중 바뀔 수 있습니다.
고객정보 수정 API 등으로 값이 바뀌면 그 다음 상담방 이벤트에 바뀐 값이 실리고, changedFields 에
해당 항목(예: parameter1)이 포함됩니다.
Example
Success
{
"eventType": "ROOM",
"eventId": "3f6c5b1e-8a2d-4f7b-9c31-5e0a7d2b4c88",
"issuedAt": 1785114840.077562,
"changedFields": ["status", "counselorId"],
"appCredential": {
"key": "TEST_APP_KEY",
"expireAt": 1785114900
},
"data": {
"roomId": "btYhiv7WkwfOSLoN164a61561f3665",
"siteId": 900001,
"status": "COUNSELOR_IN_PROGRESS",
"title": "테스트 상담방",
"managerId": 5152,
"counselorId": 5154,
"customer": {
"id": 511513,
"uid": "test_user_01",
"uuid": "900001_byqvB20230314022956"
},
"categoryId": 15516,
"categoryName": "대분류 1",
"subCategoryId": 151615,
"subCategoryName": "중분류 1-2",
"extraCategoryName": "",
"roomEndType": null,
"roomEndOption": null,
"isCloseRoom": false,
"createdAt": 1785114839,
"closedAt": null,
"deletedAt": null,
"channelType": "HAPPYTALK",
"tags": [
{ "id": 5015, "name": "태그1" },
{ "id": 5625, "name": "태그6" }
],
"flag": 7,
"parameter1": "ad_0001",
"parameter2": "",
"parameter3": "",
"parameter4": "",
"parameter5": "",
"parameter6": "",
"parameter7": "",
"parameter8": "",
"parameter9": "",
"parameter10": ""
}
}
코드 정의
RoomStatus
| 값 | 설명 |
|---|---|
WAIT_COUNSEL |
봇 상담 대기 |
CHATBOT_IN_PROGRESS |
봇 상담 중 |
RECEIPT_COUNSEL |
문의 (고객 발화) |
COUNSELOR_IN_PROGRESS |
응대 (상담사 발화) |
FINISHED_BY_COUNSELOR |
상담사 종료 |
DELETED_BY_CUSTOMER |
고객 삭제 |
FINISHED_BY_CHATBOT |
봇 상담 종료 |
RoomEndType
| 값 | 설명 |
|---|---|
COUNSELOR |
상담사 종료 |
CUSTOMER |
고객 종료 |
MANAGER |
매니저 종료 |
RoomEndOption
| 값 | 설명 |
|---|---|
NOT_AUTO_END |
자동 종료 아님 |
AUTO_END |
자동 종료 |
AUTO_END_AFTER_THIRTY_DAYS |
30일 경과 자동 종료 |
ChannelType
| 값 | 설명 |
|---|---|
HAPPYTALK |
해피톡 |
NAVER |
네이버 톡톡 |
KAKAOTALK |
카카오톡 상담톡 |
FACEBOOK |
페이스북 |
EMAIL |
이메일 |
SMS |
SMS |
NAVER_LINE |
라인 |
INSTAGRAM |
인스타그램 |