본문으로 건너뛰기

메시지

채널의 메시지를 읽는 조회 API입니다. 채널 단위로 기간을 지정해 목록을 가져오고, 메시지 ID로 한 건을 조회하고, 첨부 파일은 별도 엔드포인트에서 다운로드 URL을 받습니다.

채널 메시지 목록​

GET /channels/{id}/messages — 채널 내 메시지를 cursor pagination으로 조회합니다.

  • Scope: channels:read + messages:read (둘 다 필요)
  • 쿼리: since(RFC3339, 필수), until(RFC3339, 기본 현재 시각), limit(기본 50, 1~100), cursor(이전 응답의 meta.next_cursor 값)
  • 조회 구간은 (since, until]입니다. since는 배타적이라 경계 시각과 정확히 같은 메시지를 제외하고, until은 포함적입니다.
  • 다음 경우 400 INVALID_QUERY를 반환합니다: since 누락·형식 오류, until 형식 오류, until이 since보다 뒤가 아닌 경우(같은 시각 포함), until - since가 30일 초과, limit이 1~100 범위를 벗어난 경우, cursor 길이 초과.
  • 채널이 이 워크스페이스에 없으면 404 NOT_FOUND를 반환합니다.

아래 요청은 2026-05-01 이후의 메시지를 조회합니다.

curl "https://api.talk.zeroworks.ai/api/public/v1/channels/c1d2.../messages?since=2026-05-01T00:00:00Z" \
-H "Authorization: Bearer ztpat_..."

응답

{
"success": true,
"data": [
{
"id": "msg-1a2b-...",
"channel_id": "c1d2e3f4-...",
"sender_id": "a1b2c3d4-...",
"sender_type": "contact",
"sender_name": "홍길동",
"content_type": "text",
"content": "안녕하세요",
"attachments": [
{ "id": "att-1a2b-...", "type": "image", "filename": "photo.png" }
],
"is_edited": false,
"created_at": "2026-05-01T10:00:00Z",
"updated_at": "2026-05-01T10:00:00Z",
"content_revision": 0
}
],
"meta": { "has_more": true, "next_cursor": "..." }
}

메시지 cursor는 만료가 없습니다 (자세한 내용은 페이지네이션 참고). attachments는 참조(id·type·filename)만 포함하며, 실제 다운로드 URL은 아래 첨부 다운로드에서 조회합니다.

  • 정렬: 메시지는 created_at **내림차순(최신순)**으로 반환됩니다. next_cursor로 다음 페이지를 따라가면 since 경계를 향해 과거 방향으로 이동합니다. 대화를 시간순으로 재구성하려면 클라이언트에서 역순으로 정렬하세요.
  • attachments: 첨부가 없는 메시지는 키 자체가 생략됩니다(빈 배열도 null도 아닙니다).
  • 위 예시는 한 번도 수정되지 않은 메시지라 content_modified_at 키가 생략됐습니다. 수정된 메시지는 "content_revision": 2, "content_modified_at": "2026-05-01T10:05:00.123456Z"처럼 두 키가 함께 실립니다.

필드 값 집합​

필드값
sender_typemember(상담원)·contact(고객)·system(시스템)·bot(봇)·internal(내부)·workflow(워크플로)·external(외부 플랫폼 상담원, 예: 네이버 톡톡)·integration(PAT 기반 아웃바운드 발신)
content_typetext·markdown·image·file·card·button·email·video·audio·system·blocks·sticker·location
attachments[].typeimage·file·video·audio
  • sender_id: 불투명 식별자입니다. 멤버와 고객은 각자의 UUID이고, integration 발신은 토큰 ID입니다. 시스템이 시작한 봇 메시지(영업시간 외 자동 응답·인사말·자동 종료)는 고정 서비스 UUID(00000000-0000-0000-0000-000000000002)를 가지므로, sender_id로 고객 여부를 판정하지 말고 sender_type으로 판정하세요.
  • sender_type·sender_name: 일부 시스템 발신 메시지에서는 빈 문자열("")일 수 있습니다.
  • content_revision: 본문이나 첨부가 바뀔 때마다 커지는 정수입니다. 편집 횟수가 아니며(한 번 저장에 두 번 커질 수 있습니다), "이전에 읽은 값과 다른가"로만 판정하세요. 한 번도 바뀌지 않은 메시지는 0이고 키는 항상 있습니다.
  • content_modified_at: content_revision이 마지막으로 바뀐 시각(RFC 3339, 나노초까지, 후행 0 제거)입니다. 한 번도 바뀌지 않았으면 키 자체가 생략됩니다. 처리한 서버의 시계라 두 시각의 순서가 뒤집힐 수 있으므로 순서 기준은 content_revision입니다.
  • is_edited·updated_at: 본문 변경을 판정하는 데 쓸 수 없습니다. is_edited는 한 번 true가 되면 그대로이고, updated_at은 상태 변경에도 움직입니다. 단, content_revision 도입(v0.4.64, 2026-09-04 prod 배포) 이전에 편집된 메시지는 is_edited: true인데 content_revision: 0으로 나옵니다. 그 이후의 변경부터 content_revision이 커집니다.

단건 조회​

GET /messages/{id} — 단일 메시지를 조회합니다. 응답 data는 목록의 항목 하나와 같은 형태입니다(content_revision·content_modified_at 포함).

  • Scope: messages:read
  • 삭제된 메시지는 404입니다.

아래 요청은 메시지 한 건을 조회합니다.

curl "https://api.talk.zeroworks.ai/api/public/v1/messages/msg-1a2b-..." \
-H "Authorization: Bearer ztpat_..."

첨부 다운로드​

GET /attachments/{id} — 첨부 메타와 다운로드 URL을 조회합니다.

  • Scope: attachments:read + messages:read (둘 다 필요)
  • status='ready'인 첨부만 노출됩니다 (그 외 → 404).
  • url은 5분간 유효한 presigned URL입니다. 만료 시각은 url_expires_at으로 확인하세요.

아래 요청은 첨부 한 건의 메타와 다운로드 URL을 조회합니다.

curl "https://api.talk.zeroworks.ai/api/public/v1/attachments/att-1a2b-..." \
-H "Authorization: Bearer ztpat_..."

응답

{
"success": true,
"data": {
"id": "att-1a2b-...",
"filename": "photo.png",
"content_type": "image/png",
"size_bytes": 10240,
"url": "https://s3.../photo.png?X-Amz-...",
"url_expires_at": "2026-05-01T10:05:00Z",
"created_at": "2026-05-01T10:00:00Z"
}
}