본문으로 건너뛰기

상담 콘솔 임베드 가이드

외부 서비스에 자체 상담 콘솔을 붙이는 엔드투엔드 레시피입니다. ZeroTalk의 Outbound 웹훅으로 이벤트를 받아 자신의 콘솔로 중계하고, Public API(PAT)로 대화 내역을 읽고 답장을 보냅니다.

아키텍처​

PAT는 비밀 값이며 워크스페이스 전체를 읽고 쓸 수 있고, Public API는 CORS를 허용하지 않습니다. 따라서 BFF(Backend for Frontend) 를 반드시 두고, 브라우저는 BFF와만 통신합니다.

  • ZeroTalk → BFF: 서명된 웹훅 이벤트 (수신)
  • BFF → 콘솔: 자체 WebSocket/SSE로 중계
  • BFF → ZeroTalk: PAT로 내역 조회 + 답장 전송

단계별 레시피​

1. PAT 발급​

워크스페이스 Owner 권한으로 대시보드 채팅 설정 → 연동 / 개발 → 개발자에서 토큰을 발급합니다 (인증 참고). 콘솔에 권장하는 scope 세트는 다음과 같습니다.

Scope용도
channels:read + messages:read내역 조회 (두 scope가 모두 필요)
messages:write답장 전송
attachments:read (+ messages:read)첨부 다운로드(읽기)
channels:read + channels:write채널 목록·상세 + 읽음/배정/종료
contacts:read고객 정보 표시
members:read담당자 매핑·표시
macros:read (선택)매크로(상용구)
webhooks:read + webhooks:write (선택)웹훅 자가 등록·모니터링
주의

쓰기 전용 토큰은 내역을 렌더할 수 없습니다. 반드시 read scope를 함께 부여하세요.

2. PAT를 BFF에 저장​

토큰은 서버 사이드에만 보관합니다. 브라우저·콘솔 클라이언트에 절대 노출하지 마세요.

3. 웹훅 등록​

BFF의 공개 HTTPS URL을 가리키는 웹훅을 POST /outbound-webhooks로 등록하고, 응답에서 1회만 반환되는 secret을 서버에 저장합니다. (대시보드 채팅 설정 → 연동 / 개발 → Webhook 설정에서 등록해도 됩니다.)

4. 이벤트 중계​

BFF는 수신한 각 이벤트를 아래 순서로 처리합니다.

  1. 서명을 검증합니다 (raw body로 HMAC-SHA256, sha256= 접두사 비교).
  2. 멱등 처리로 중복 제거합니다 (at-least-once이므로 같은 이벤트가 두 번 올 수 있음).
  3. 자체 WS/SSE로 콘솔에 중계합니다.
  4. UI는 수신 순서가 아니라 한 채널 안 메시지는 data.seq(채널 순번)로 정렬합니다 — data.created_at은 message.created 등 일부 이벤트에만 있고, 채널 간 전역 순서는 가정하지 마세요 (순서 보장).

5. 렌더​

화면엔드포인트
대화 목록GET /channels
대화 내역GET /channels/{id}/messages?since=…
고객 정보GET /contacts/{id}
담당자("누가 처리 중")채널의 assigned_member_id + 웹훅 envelope의 assigned_member 스냅샷

6. 운영(답장·읽음·배정·종료)​

메시징 쓰기 API로 대화를 조작합니다.

  • 답장: POST /channels/{id}/messages — 상담원 귀속은 sender_member_id로, 생략하면 토큰의 integration 신원으로 귀속됩니다.
  • 읽음: POST /channels/{id}/read
  • 배정: POST /channels/{id}/assign — 행위자(actor_member_id)를 지정하면 그 상담원이 channel:operate 권한을 가져야 합니다. Viewer 역할 멤버로 매핑하면 403 FORBIDDEN으로 거부됩니다.
  • 종료/재개: POST /channels/{id}/close · /reopen

배정·종료/재개는 답장의 sender_member_id처럼 행위자 actor_member_id가 선택입니다 — 생략하면 토큰 자신이, 지정하면 그 상담원이 한 일로 남습니다. 읽음만은 actor_member_id가 필수입니다(누락 시 400 INVALID_BODY). 정확한 요청 본문은 메시징 쓰기 API를 참고하세요.

7. 매크로(상용구)​

GET /macros로 템플릿을 읽고, 변수 치환은 BFF에서 수행한 뒤 렌더된 텍스트를 POST /channels/{id}/messages로 전송합니다. 서버 측 "매크로 적용" 엔드포인트는 없습니다.

8. 에코 처리​

전송한 답장은 message.created 웹훅으로 되돌아옵니다. 웹훅에는 client_request_id가 없으므로 전송 응답의 data.id 를 웹훅의 data.message_id와 대조해 자신의 에코를 식별하고 중복 렌더를 막으세요 (에코 correlation 참고).

9. 웹훅 헬스 모니터링​

GET /outbound-webhooks/{id}의 status·failure_count·last_delivered_at·error_message를 주기적으로 폴링하거나 전달 로그를 확인합니다. 연속 10회 실패 시 웹훅이 status=error로 자동 비활성화되므로, error를 감지하면 원인을 고친 뒤 toggle로 재활성화하세요(failure_count가 리셋됩니다).

알려진 제약​

  • 첨부 전송 미지원 — 첨부 다운로드(읽기)는 되지만, 첨부를 보내는 기능은 없습니다 (Phase 3 예정). 본문은 text·markdown만 가능합니다.
  • 리치 블록·버튼 전송 미지원 — text·markdown 외 메시지 형식은 보낼 수 없습니다.
  • 내부 메모 송수신 미지원 — 상담원 내부 메모는 전송할 수 없고, 웹훅으로도 수신되지 않습니다 (필터링됨).
  • 읽음 확인·타이핑·실시간 presence 이벤트 없음 — 동시 응대 충돌 UX는 assigned_member로 직접 구성하세요.
  • 1 PAT = 워크스페이스 전체 — 팀·채널 단위 scope가 없습니다. 콘솔을 자신의 하위 테넌트에게 재판매(resale)하는 격리 용도로는 적합하지 않습니다 (Phase 3 예정).
  • sender_member_id 매핑 필요 — 상담원 귀속을 쓰려면 내 상담원을 ZeroTalk membership id에 매핑해야 합니다. 생략하면 토큰의 integration 신원으로 귀속됩니다.