CLOSER에서는 메시지 수신/발신, 고객 추가/삭제에 대한 이벤트들을 전달하는 webhook을 제공합니다.
Webhook 연동에 도움이 필요하시다면 support@closer.ai로 문의해주세요.
본 문서에서는 Webhook의 포맷에 따라 목적에 맞는 API를 개발하세요.
CLOSER Bot에서 개발하신 API의 URL을 등록합니다.
CLOSER의 Bot을 사용시 발생하는 이벤트를 개발하신 API로 전송합니다.
Builder > 봇 설정 > Webhook 관리에서 Webhook URL을 등록/수정/삭제 하실 수 있습니다
등록하신 Webhook URL이 동작하지 않는 경우 Builder에서 Webhook 전송이 자동으로 비활성화 됩니다
Key | Value |
user-agent | CLOSER/webhook |
content-type | application/json |
{"id": "00000000-0000-0000-0000-000000000000","webhookId": "00000000-0000-0000-0000-000000000000","webhookUrl": "http://your.webhook.com","messages": [{"id": "00000000-0000-0000-0000-000000000000","sourceId": "Bxxxxx","sourceType": "bot","event": "bot.end_user.updated","data": {"endUser": {"createdAt": "2018-09-04T07:06:53.047Z","deletedAt": null,"id": "00000000-0000-0000-0000-000000000000","botId": "Bxxxxx","lastMessageId": "00000000-0000-0000-0000-000000000000","params": {},"platform": "web","userKey": "userKey","lastConversationId": "00000000-0000-0000-0000-000000000000","updatedAt": "2018-09-05T06:45:19.087Z"}},"timestamp": 1536129919092}, {"id": "00000000-0000-0000-0000-000000000001","sourceId": "Bxxxxx","sourceType": "bot","event": "bot.conversation.created","data": {"conversation": {"endUserId": "00000000-0000-0000-0000-000000000000","createdAt": "2018-09-05T06:45:19.102Z","navigation": {},"context": {"navigation": {},"conversationId": "00000000-0000-0000-0000-000000000000","botId": "Bxxxxx","params": {},"platform": "web","userKey": "userKey"},"id": "00000000-0000-0000-0000-000000000000","botId": "Bxxxxx","params": {},"userKey": "userKey","platform": "web","updatedAt": "2018-09-05T06:45:19.102Z"}},"timestamp": 1536129919116}]}
{"id": "00000000-0000-0000-0000-000000000000","webhookId": "00000000-0000-0000-0000-000000000000","webhookUrl": "http://your.webhook.com","messages": [{"id": "00000000-0000-0000-0000-000000000000","sourceId": "Bxxxxx","sourceType": "bot","event": "bot.message.sent","data": {"message": {"endUserId": "00000000-0000-0000-0000-000000000000","data": {"text": "상담원 메시지","type": "text"},"requestId": "00000000-0000-0000-0000-000000000000","meta": {"sender": {"userKey": "Uxxxxx","platform": "closer-chat"}},"conversationId": "00000000-0000-0000-0000-000000000000","id": "00000000-0000-0000-0000-000000000000","isUser": false,"timestamp": 1536130434645}},"timestamp": 1536130434656}]}
{"id": "00000000-0000-0000-0000-000000000000","webhookId": "00000000-0000-0000-0000-000000000000","webhookUrl": "http://your.webhook.com","messages": [{"id": "00000000-0000-0000-0000-000000000000","sourceId": "Bxxxxx","sourceType": "bot","event": "bot.message.sent","data": {"message": {"endUserId": "00000000-0000-0000-0000-000000000000","data": {"text": "테스트용 봇 메시지","type": "text"},"conversationId": "00000000-0000-0000-0000-000000000000","meta": null,"id": "00000000-0000-0000-0000-000000000000","isUser": false,"timestamp": 1536129919339}},"timestamp": 1536129919373}]}
{"id": "00000000-0000-0000-0000-000000000000","webhookId": "00000000-0000-0000-0000-000000000000","webhookUrl": "http://your.webhook.com","messages": [{"id": "00000000-0000-0000-0000-000000000000","sourceId": "Bxxxxx","sourceType": "bot","event": "bot.message.received","data": {"message": {"endUserId": "00000000-0000-0000-0000-000000000000","data": {"text": "고객 메시지","type": "text"},"requestId": "00000000-0000-0000-0000-000000000000","conversationId": "00000000-0000-0000-0000-000000000000","meta": null,"id": "00000000-0000-0000-0000-000000000000","isUser": true,"timestamp": 1536130242636}},"timestamp": 1536130243609}]}
키 | 타입 | 필수 | 설 |
id | UUID | Y | Delivery ID |
webhookId | UUID | Y | Webhook ID |
webhookUrl | String | Y | Webhook URL |
messages | Array(Object(EVENT)) | Y | Event 오브젝트의 배열. 일정 시간동안 발생한 이벤트를 배열로 묶어 전달합니다. |
키 | 타입 | 필수 | 설명 |
id | UUID | Y | Event ID |
event | String(EVENT_TYPE) | Y | Event 구분 |
sourceType | String('bot') | Y | Event를 발행한 소스 |
sourceId | String(BOT.id) | Y | Event 발행한 타입의 아이디. 'bot'인 경 Bot ID |
timestamp | UNIX Timestamp with milliseconds | Y | Event 발생 시간 |
data | Object(EVENT.DATA) | Y | Event의 데이터 |
키 | 타입 | 필수 | 설명 |
bot | Object(BOT) | C | event가 bot인 경우 필수 |
endUser | Object(ENDUSER) | C | event가 bot.end_user인 경우 필수 |
conversation | Object(CONVERSATION) | C | event가 bot.conversation인 경우 필 |
message | Object(MESSAGE) | C | event가 bot.message인 경우 필수 |
키 | 타입 | 필수 | 설명 |
id | String | Y | Bot의 ID |
title | String(30) | Y | Bot의 이름 |
description | String(100) | N | Bot의 설명 |
integration | Object(BOT.INTEGRATION) | N | Bot의 연동 정보 |
preference | Object(BOT.PREFERENCE) | N | Bot의 설정 정보 |
data | Object(BOT.DATA) | N | Bot 동작에 필요한 데이터 |
createdAt | String(DateTime) | Y | 생성 날짜 |
updatedAt | String(DateTime) | Y | 업데이트 날짜 |
deletedAt | String(DateTime) | N | 삭제 날짜 |
키 | 타입 | 필수 | 설명 |
id | UUID | Y | EndUser의 ID |
botId | String(BOT.id) | Y | Bot의 ID |
platform | String(PLATFORM_TYPE) | Y | 메신저 타입 |
userKey | String(90) | Y | 사용자 고유 키값 |
params | Object(Dictionary) | N | 대화에서 사용하는 파라미터 |
lastMessageId | UUID(MESSAGE.id) | N | 마지막 메시지의 ID |
lastConversationId | UUID(CONVERSATION.id) | N | 마지막 대화의 ID |
lastConversation | Object(CONVERSATION) | N | 마지막 대화 Object |
createdAt | String(DateTime) | Y | 생성 날짜 |
updatedAt | String(DateTime) | Y | 업데이트 날짜 |
deletedAt | String(DateTime) | N | 삭제 날짜 |
키 | 타입 | 필수 | 설명 |
id | UUID | Y | Conversation의 ID |
botId | String(BOT.id) | Y | Bot의 ID |
endUserId | UUID(ENDUSER.id) | Y | EndUser의 ID |
platform | String(PLATFORM_TYPE) | Y | 메신저 타입 |
userKey | String(90) | Y | 사용자의 고유 키값 |
params | Object(Dictionary) | N | 대화에서 사용하는 파라미터 |
context | Object(CONTEXT) | N | 대화의 정보 |
navigation | Object(CONTEXT.NAVIGATION) | N | 대화의 위치 |
createdAt | String(DateTime) | Y | 생성 날짜 |
updatedAt | String(DateTime) | Y | 업데이트 날짜 |
키 | 타입 | 필수 | 설명 |
id | UUID | Y | Message의 ID |
endUserId | UUID(ENDUSER.id) | Y | EndUser의 ID |
conversationId | UUID(CONVERSATION.id) | Y | Conversation의 ID |
isUser | Boolean | Y | true인 경우 고객, false인 경우 봇이나 상담원 |
meta | Object(MESSAGE.META) | N | 상담원이 경우 meta에 상담원 정보가 포함됨 |
data | Object(MESSAGE.DATA) | Y | 메시지의 데이터 |
timestamp | UNIX Timestamp with milliseconds | Y | 메시지 발행 시간 |
키 | 타입 | 필수 | 설명 |
type | String(MESSAGE_TYPE) | Y | MESSAGE의 타입 |
text | String(1000) | C | text 타입인 경우 필수 |
media | Object(MESSAGE.DATA.MEDIA) | C | media 타입인 경우 필수 |
cards | Array(Object(MESSAGE.DATA.CARD)) | C | cards 타입인 경우 필수 |
location | Object(MESSAGE.DATA.LOCATION) | C | location 타입인 경우 필수 |
button | Object(MESSAGE.DATA.BUTTON) | N | 메시지에 포함된 버튼으로 KEYBOARD.BUTTON과는 형식과 동작이 다름. 링크 삽입 가능 |
키 | 타입 | 필수 | 설명 |
sender | Object(MESSAGE.META.SENDER) | N | 메시지를 전송한 전송자의 정보 |
키 | 타입 | 필수 | 설명 |
contentType | 'image', 'video', 'audio', 'link' | Y | 이미지, 동영상, 오디오, 링크 |
uri | String | Y | 이미지, 동영상, 오디오, 링크의 URL |
키 | 타입 | 필수 | 설명 |
label | String(255) | Y | 버튼 인터페이스에 노출할 이름 |
uri | String | N | 버튼이 링크로 동작 시 URL, 없으면 키보드 입력 동작 |
키 | 타입 | 필수 | 설명 |
title | String(50) | Y | 카드의 제목 |
description | String(500) | N | 카드의 설명 |
media | Object(MESSAGE.DATA.MEDIA) | N | 카드에 포함될 미디어 |
uri | String | N | 카드 선택시 이동할 링크 URL |
buttons | Array(Object(MESSAGE.DATA.BUTTON)) | N | 카드에 포함된 버튼 리스트 |
키 | 타입 | 필수 | 설명 |
title | String(50) | N | 위치의 이름 |
latitude | Number | Y | GPS Latitude |
longitude | Number | Y | GPS longitude |
키 | 타입 | 필수 | 설명 |
userKey | String(90) | Y | SENDER 사용 시 필수. 전송자의 ID |
platform | String(100) | Y | SENDER 사용 시 필수. 전송자의 플랫폼 |
CLOSER의 입력 Object로, 사용자의 입력 타입을 표현합니다.
text인 경우 사용자는 text를 입력할 수 있고, number인 경우 제약조건을 포함합니다.
buttons는 사용자의 입력을 button으로 받을 수 있도록 필요한 데이터를 포함합니다.
text : 사용자가 입력한 텍스트를 그대로 메시지에 전송합니다.
buttons : 사용자가 선택한 button의 label의 텍스트를 메시지에 전송합니다.
number : text와 동일하지만, 조건을 Front에서 검증하도록 개발할 수 있습니다.
키 | 타입 | 필수 | 설명 |
type | 'text', 'number', 'buttons' | Y | 텍스트, 숫자, 버튼 입력 |
min | Number | C | number 타입인 경우에 필수, 최소값 |
max | Number | C | number 타입인 경우에 필수, 최대값 |
parse | Boolean | N | false인 경우 숫자만 입력 가능, true인 경우 주어진 문자열에서 숫자만 읽어들임 |
integer | Boolean | N | false인 경우 Integer만 입력 가능 |
buttons | Array(Object(KEYBOARD.BUTTON)) | C | buttons 타입인 경우에 필수 |
키 | 타입 | 필수 | 설명 |
label | String(255) | Y | 버튼 인터페이스에 노출할 이름 |
params | Object(Dictionary) | N | 버튼 선택 시 저장되는 파라미터. key - value dictionary 타입 |
CLOSER에서 대화를 진행하는데 필요한 정보입니다. SDK의 WebChatClient가 Open되면 Context를 message listener에 전송합니다.
키 | 타입 | 필수 | 설명 |
botId | String | Y | Bot의 ID |
conversationId | UUID | Y | 대화의 ID. CLOSER에서 자동으로 생성됨 |
endUserId | UUID | Y | 최종사용자의 ID. CLOSER에서 자동으로 생성됨 |
navigation | Object(CONTEXT.NAVIGATION) | N | 현재 대화의 위치를 표현하는 오브젝트 |
params | Object(Dictionary) | N | 현재 대화에서 사용하고 있는 파라미터 |
platform | String(PLATFORM_TYPE) | Y | 플랫폼 타입 |
userKey | String(90) | Y | 최종사용자 식별 키. SDK Open시 주입한 값 |
키 | 타입 | 필수 | 설명 |
current | Object(CONTEXT.NAVIGATION.NODE) | Y | 현 노드의 정보 |
prev | Object(CONTEXT.NAVIGATION.NODE) | N | 이전 노드의 정보 |
키 | 타입 | 필수 | 설명 |
flowId | Number | Y | 현재 노드의 플로우 ID |
nodeId | Number | Y | 현재 노드의 ID |
visitCount | Number | N | 최종사용자가 노드에 방문한 수 |
키 | 타입 | 필수 | 설명 |
id | String | Y | 상담원의 User ID |
profile | Object(AGENT.PROFILE) | N | 상담원의 profile 정보 |
키 | 타입 | 필수 | 설명 |
displayName | String(30) | N | 상담원의 DisplayName |
picture | URL | N | 상담원의 프로필 이미지 URL |
타입 | 설명 |
bot.updated | Bot의 정보 업데이트 |
bot.deleted | Bot이 삭제됨 |
bot.end_user.created | 새로운 EndUser 생성 |
bot.end_user.updated | EndUser의 정보 업데이트 |
bot.end_user.deleted | EndUser가 삭제됨(친구삭제 등) |
bot.conversation.created | 새로운 Conversation 생성 |
bot.conversation.updated | Conversation의 정보 업데이트 |
bot.conversation.deleted | Conversation이 삭제됨(대화 만료) |
bot.conversation.agent_call_requested | 상담원에게 상담 요청 |
bot.conversation.agent_call_connected | 상담 시작 |
bot.conversation.agent_call_cancelled | 상담원에게 상담요청을 고객이 취소 |
bot.conversation.agent_call_disconnected | 상담 종료 |
bot.message.sent | 메시지 전송(봇, 상담원) |
bot.message.received | 메시지 수신(사용자) |
타입 | 설명 |
kakao | 카카오톡 스마트 API |
kakaobiz | 카카오 상담톡 |
페이스북 메신저 | |
line | 라인 |
navertalk | 네이버톡톡 |
bizchat | SMS 문자 메시지 채팅 BizChat |
위챗 | |
web | 웹챗 |
test | 테스트용 챗 |
타입 | 설명 |
text | 텍스트 메시지 |
media | 이미지, 동영상, 오디오 등의 미디어 |
cards | 카드 타입 리스트 (Carousel로 사용) |
location | 위치 정보 (latitude, longitude) |