메시징 쓰기
상담 콘솔이 대화를 운영하기 위한 쓰기 엔드포인트입니다 — 답장 전송, 읽음 처리, 담당자 배정, 채널 종료/재개. 읽기 엔드포인트와 같은 Base URL·봉투·에러 규약을 따릅니다.
쓰기 엔드포인트는 BFF(서버 사이드)에서만 호출하세요. Public API는 CORS를 허용하지 않으며, PAT는 워크스페이스 전체를 읽고 쓸 수 있는 비밀 값입니다.
답장 전송
POST /channels/{id}/messages — 채널에 메시지를 전송합니다.
- Scope:
messages:write - Body
| 필드 | 타입 | 설명 |
|---|---|---|
content_type | text | markdown | 본문 형식 |
content | string | 메시지 본문 (1–2000자, 초과 시 400 INVALID_BODY) |
sender_member_id | string · 선택 | 발신 상담원 membership ID. 생략하면 토큰의 integration 신원으로 귀속됩니다 (하이브리드 귀속, 아래 참고) |
client_request_id | string · 선택 | 멱등성 키 (최대 128자). 같은 값으로 재전송하면 원본 메시지를 반환합니다 |
curl -X POST "https://api.talk.zeroworks.ai/api/public/v1/channels/c1d2.../messages" \
-H "Authorization: Bearer ztpat_..." \
-H "Content-Type: application/json" \
-d '{
"content_type": "text",
"content": "안녕하세요, 무엇을 도와드릴까요?",
"sender_member_id": "m1n2o3-...",
"client_request_id": "req-7f3a..."
}'
응답 — 신규 생성 시 201, 멱등 중복 시 200(deduplicated: true).
{
"success": true,
"data": {
"id": "msg-9z8y-...",
"channel_id": "c1d2e3f4-...",
"sender_id": "00000000-0000-0000-0000-...",
"sender_type": "integration",
"sender_name": "ztpat_a1b2c3",
"content_type": "text",
"content": "안녕하세요, 무엇을 도와드릴까요?",
"created_at": "2026-06-02T01:23:45Z",
"updated_at": "2026-06-02T01:23:45Z",
"client_request_id": "req-7f3a...",
"deduplicated": false
}
}
하이브리드 귀속
sender_member_id를 지정하면 해당 상담원으로 귀속됩니다. 그 상담원은message:write권한이 있어야 하며, 호출 측은 자신의 상담원을 ZeroTalk membership ID에 매핑해야 합니다.sender_member_id를 생략하면 토큰의 integration 신원으로 귀속됩니다 — 메시지의sender_type은integration, 표시 이름(sender_name)은 토큰 프리픽스(secret 앞 12자, 예:ztpat_a1b2c3)입니다 (상담원 측 렌더링은 이벤트 문서의 sender_type 참고).
에코와 멱등성
- 전송한 답장은
message.created웹훅으로 되돌아옵니다. 웹훅에는client_request_id가 없으므로, 응답의data.id를 웹훅의data.message_id와 대조해 자신의 전송을 식별하세요. client_request_id는 전송 멱등성 용도입니다 — 실패한POST를 같은 키로 재시도하면 새 메시지를 만들지 않고 원본을200(deduplicated: true)으로 반환합니다. 웹훅 상관(correlation) 키로는 쓰지 마세요.
읽음 처리
POST /channels/{id}/read — 채널을 특정 메시지까지 읽음 처리합니다.
- Scope:
channels:write - Body:
{ "actor_member_id": "...", "message_id": "..." } - 응답:
204 No Content
curl -X POST "https://api.talk.zeroworks.ai/api/public/v1/channels/c1d2.../read" \
-H "Authorization: Bearer ztpat_..." \
-H "Content-Type: application/json" \
-d '{ "actor_member_id": "m1n2o3-...", "message_id": "msg-9z8y-..." }'
종료 / 재개
POST /channels/{id}/close · POST /channels/{id}/reopen — 채널을 종료하거나 재개합니다.
- Scope:
channels:write - Body:
{ "actor_member_id": "..." } - 응답:
200,data는 갱신된 채널 객체(채널 조회와 동일 스키마) — 변경된status를 별도 GET 없이 확인할 수 있습니다.
curl -X POST "https://api.talk.zeroworks.ai/api/public/v1/channels/c1d2.../close" \
-H "Authorization: Bearer ztpat_..." \
-H "Content-Type: application/json" \
-d '{ "actor_member_id": "m1n2o3-..." }'
종료·재개는 각각 channel.closed·channel.reopened 웹훅을 발생시킵니다.
담당자 배정
POST /channels/{id}/assign — 채널 담당자를 지정하거나 해제합니다.
- Scope:
channels:write(그리고actor_member_id상담원에게channel:operate권한 필요) - Body:
{ "actor_member_id": "...", "member_id": "..." }—member_id를null로 보내면 배정이 해제됩니다. - 응답:
200,data는 갱신된 채널 객체(채널 조회와 동일 스키마) — 변경된assigned_member_id를 별도 GET 없이 확인할 수 있습니다.
curl -X POST "https://api.talk.zeroworks.ai/api/public/v1/channels/c1d2.../assign" \
-H "Authorization: Bearer ztpat_..." \
-H "Content-Type: application/json" \
-d '{ "actor_member_id": "m1n2o3-...", "member_id": "p4q5r6-..." }'
배정 변경은 channel.assigned 웹훅을 발생시킵니다. 현재 담당자는 채널 조회의 assigned_member_id와 웹훅 envelope의 assigned_member 스냅샷에서 확인합니다.
참고
- 답장·채널 조작 결과는 모두 Outbound 웹훅으로 반영됩니다. 콘솔 전체 흐름은 상담 콘솔 임베드 가이드를 참고하세요.
- 현재 첨부 전송, 내부 메모 전송, 리치 블록/버튼은 지원하지 않습니다 (text·markdown 본문만). 알려진 제약 참고.