상담 유입 (Conversations)
이 엔드포인트는 운영 환경에서 사용할 수 있습니다. 호출에 필요한 PAT 발급 방법은 아래 사전 요구사항을 참고하세요.
POST /conversations — 고객사 시스템(예: 주문내역 화면)에서 고객이 만든 상담 요청(텍스트 + 이미지)을 제로톡 상담 인박스에 새 상담으로 띄웁니다. 유입된 상담은 위젯으로 들어온 상담과 똑같이 상담원이 이어받고, AI 텍스트 1차 응대가 동작합니다. 발신자는 고객으로 표시됩니다.
사전 요구사항
| 항목 | 요구사항 |
|---|---|
| PAT | 스코프 conversations:write(생성) + messages:read·channels:read(답장 폴링) 포함. 대시보드 → 설정 → 개발자에서 발급 |
| 호출 위치 | 고객사 서버(server-to-server). 브라우저에서 직접 호출 금지(토큰 노출) |
이 API는 서버 전용 시크릿인 PAT(ztpat_…) 로 인증합니다. 웹 위젯에 넣는 Plugin Key(pk_live_…)와는 다른 값입니다.
요청
POST https://api.talk.zeroworks.ai/api/public/v1/conversations
Authorization: Bearer ztpat_...
Content-Type: application/json
본문 필드
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
text | string | ✅ | 상담 본문. 자유 텍스트(최대 100,000자) |
client_request_id | string | ✅ | 멱등키 — 고객사가 직접 만들어 넣는 임의 문자열(정해진 형식 없음, 최대 128자). 재시도 시 중복 상담을 막습니다(아래) |
external_id | string | 고객사 시스템의 고객 식별자(회원ID·주문자ID 등, 최대 255자). 정해진 형식 없이 그대로 저장하고 매칭합니다. 넘기면 같은 고객으로 묶여 이력이 이어지고, 없으면 익명 고객으로 처리합니다. | |
name | string | 고객 이름(최대 100자, 상담원 화면 「고객 정보」에 표시) | |
phone | string | 고객 연락처(최대 64자) | |
image_urls | string[] | 이미지 URL(URL 형식). 최대 10개, 공개 접근 가능, 이미지 형식만 |
아래 명령은 주문 환불 문의를 이미지 한 장과 함께 새 상담으로 만듭니다.
curl -X POST https://api.talk.zeroworks.ai/api/public/v1/conversations \
-H "Authorization: Bearer ztpat_..." \
-H "Content-Type: application/json" \
-d '{
"client_request_id": "order-20250-11-refund-1",
"external_id": "member_8821",
"name": "홍길동",
"text": "주문 20250-11 환불 문의합니다. 상품이 파손되어 왔어요.",
"image_urls": ["https://your-cdn.example.com/uploads/damage.jpg"]
}'
멱등키
네트워크가 끊겨 응답을 못 받으면 재시도하게 됩니다. client_request_id 없이 재시도하면 같은 상담이 두 번 생깁니다.
- 이 값은 고객사가 직접 만들어 넣습니다. 제로톡이 강제하는 형식은 없고(최대 128자), 값을 그대로 저장·매칭만 합니다.
- 요청마다 그 상담에 안정적으로 매핑되는 값을 넣으세요(예:
주문번호 + 문의차수). 매번 랜덤값은 효과가 없습니다. - 같은
client_request_id로 다시 호출하면 새로 만들지 않고 처음 만든 상담을 그대로 반환합니다(아래 응답 참고). - 즉시 재시도를 위한 것으로, 보관 윈도우는 24시간입니다.
- 같은
client_request_id의 첫 요청을 아직 처리하는 중에 다시 보내면409 CONVERSATION_IN_FLIGHT가 옵니다. 잠시 기다렸다가 같은 값으로 다시 보내세요. 첫 요청이 성공했다면 처음 만든 상담을 돌려받습니다.
이미지
- URL만 넘기면 됩니다(파일 업로드 불필요). 서버가 그 URL에서 이미지를 가져와 보관한 뒤 상담에 붙입니다.
- URL은 공개적으로 접근 가능해야 합니다(로그인·서명 없이 GET). 사내망·비공개 주소는 차단됩니다.
- 이미지 형식만 허용됩니다. 최대 10개.
- 일부 이미지를 가져오지 못해도 상담(텍스트)은 생성됩니다. 실패한 이미지는 응답의
image_results에failed와 사유(reason)로 표시되므로, 필요하면 해당 이미지만 확인해서 다시 처리하세요.
응답
201 Created — 상담 생성 성공:
{
"success": true,
"data": {
"channel_id": "018f...",
"contact_id": "018f...",
"message_id": "018f...",
"created_at": "2026-07-25T02:14:00.000Z",
"image_results": [
{ "url": "https://your-cdn.example.com/uploads/damage.jpg", "status": "attached" }
]
}
}
| 필드 | 설명 |
|---|---|
channel_id | 만들어진 상담 id. 답장 조회에 사용(아래) |
contact_id | 연결된 고객 id |
message_id | 방금 넣은 고객 메시지 id |
created_at | 그 메시지 생성 시각(RFC3339). 답장 폴링의 커서로 사용 — GET /channels/{id}/messages?since=<created_at> |
image_results[] | 이미지별 attached/failed(+reason) — 부분 성공 표시 |
같은 client_request_id로 재요청하면 200 OK 로 처음과 같은 { channel_id, contact_id, message_id, created_at }를 반환합니다. 상담은 새로 만들지 않습니다.
답장 받기
이 상담의 고객은 제로톡 채팅창(위젯)에 접속해 있지 않습니다. 따라서 상담원·AI의 답장을 고객사가 되받아 자기 화면에 표시해야 합니다.
GET /channels/{channel_id}/messages를 주기적으로 호출해 새 메시지(상담원·AI 답장)를 가져옵니다. 응답으로 받은 channel_id를 사용합니다.
이 조회는 messages:read + channels:read 두 스코프를 모두 요구합니다(둘 중 하나만 있으면 403). 따라서 PAT 발급 시 conversations:write와 함께 이 둘도 포함하세요.
새 답장만 효율적으로 받으려면 생성 응답의 created_at을 커서로 넘깁니다 — GET /channels/{channel_id}/messages?since=<created_at> 은 그 시각 이후 메시지(=상담원·AI 답장)만 돌려줍니다. 자기가 넣은 메시지는 message_id로 구분합니다.
에러
| HTTP | code | 의미 |
|---|---|---|
| 400 | INVALID_INPUT | text·client_request_id 누락, 필드 길이 초과, image_urls가 URL 형식이 아니거나 10개 초과 |
| 400 | INVALID_JSON | 본문이 JSON이 아니거나, 정의되지 않은 필드가 들어 있음 |
| 401 | MISSING_TOKEN, INVALID_TOKEN | 토큰 없음, 오타, 회수됨, 만료 |
| 403 | INSUFFICIENT_SCOPE | 토큰에 conversations:write가 없음 |
| 409 | OUT_OF_HOURS_BLOCKED | 워크스페이스가 영업시간외 차단 모드일 때(그 시간에는 유입을 받지 않음) |
| 409 | CONVERSATION_IN_FLIGHT | 같은 client_request_id의 요청을 아직 처리하는 중. 잠시 뒤 같은 값으로 다시 보냅니다. |
| 429 | RATE_LIMIT_EXCEEDED | 이 엔드포인트의 워크스페이스 한도(분당 120회) 또는 전체 요청 한도 초과. Retry-After 헤더만큼 기다린 뒤 다시 보냅니다. |
| 503 | INGEST_UNAVAILABLE | 중복 생성 방지 장치를 일시적으로 쓸 수 없음. Retry-After: 1이므로 1초 뒤 같은 client_request_id로 다시 보냅니다. |
전체 에러 규약은 에러 문서를 참고하세요.
연동 체크리스트
- 대시보드에서 PAT 발급(스코프
conversations:write+ 답장 폴링용messages:read·channels:read) → 서버 시크릿에 보관 - 상담 생성 시
POST /conversations호출, 요청마다client_request_id(멱등키) 부여 - 이미지는 공개 URL · 10개 이하 · 이미지 형식
- 응답의
channel_id·created_at저장(답장 폴링 커서로?since=<created_at>) - 답장 수신 = 메시지 조회(폴링,
messages:read+channels:read) 셋업 -
409는code로 구분해 처리:OUT_OF_HOURS_BLOCKED(영업시간외 차단 — 그 시간에는 유입 불가)·CONVERSATION_IN_FLIGHT(첫 요청 처리 중 — 잠시 뒤 같은client_request_id로 재시도) -
429(레이트리밋)·503 INGEST_UNAVAILABLE(일시 장애)은Retry-After만큼 기다린 뒤 같은client_request_id로 재시도