CollabOps

수신 웹훅

외부 도구가 HTTP 요청 한 번으로 채널에 메시지를 올리는 방법 — 요청 형식, 응답, 오류, 상한, 스레드

수신 웹훅은 CI 파이프라인, 모니터링 도구, 사내 스크립트 같은 외부 도구가 HTTP 요청 한 번으로 채널에 메시지를 올리는 주소입니다. 이 문서는 요청을 어떻게 보내고, 어떤 응답이 오고, 무엇이 제한되는지 설명합니다. 본문에 쓸 수 있는 서식과 토큰은 표현 레퍼런스에, 복사해서 바로 쓸 수 있는 예시는 예제에 있습니다. 외부 도구가 같은 URL 과 시크릿으로 채널 대화를 읽어 가는 방법은 채널 읽기에 있습니다.

발급하기

채널 관리자가 채널 화면에서 발급합니다. 한 채널에 웹훅을 여러 개 만들 수 있으니 도구마다 따로 발급하면 어느 도구가 보낸 메시지인지 채널에서 바로 구분됩니다.

  1. 채널 메뉴에서 채널 설정을 눌러 채널 편집 창을 엽니다. 아래쪽 웹훅 버튼을 누르면 웹훅 관리하기 창이 열립니다.

채널 편집 창 아래쪽의 웹훅 버튼

그림 1 — 채널 편집 창의 웹훅 버튼
  1. + 발급하기를 누르고 웹훅 프로필 표시에 채널에 보일 이름을 적습니다. 이름은 같은 채널 안에서 겹치면 안 됩니다. 프로필 사진은 선택이고, 메시지는 이 이름과 사진으로 올라갑니다.

  2. 외부 도구가 이 채널의 대화도 읽어야 하면 채널 대화 읽기 허용을 켭니다. 기본은 꺼져 있고, 켜면 같은 URL 과 시크릿으로 채널 읽기를 할 수 있습니다. 발급한 뒤에도 바꿀 수 있습니다.

웹훅 발급하기 창 — 프로필 사진, 웹훅 프로필 표시, 채널 대화 읽기 허용, 채팅 미리보기

그림 2 — 웹훅 발급하기 창
  1. 저장을 누르면 URL, 시크릿, 그리고 붙여 넣어 바로 시험할 수 있는 curl 명령(보내보기)이 나옵니다.

웹훅이 생성되었어요 창 — URL, 시크릿, 보내보기

그림 3 — 발급 직후 화면 (값은 가렸습니다)

발급이 끝나면 두 가지 값을 받습니다.

값모양설명
URLhttps://collabops.ai/api/v2/integration/webhook/<토큰>메시지를 보낼 주소입니다. 경로의 토큰이 게시할 채널을 정합니다.
시크릿문자열Authorization: Bearer <시크릿> 헤더로 보냅니다. 발급 직후 한 번만 보입니다.

URL 과 시크릿은 서로 다른 값이고 둘 다 비밀입니다. 저장소에 커밋하지 말고 CI 의 시크릿 저장소에 각각 넣으세요. 시크릿은 다시 볼 수 없으므로 잃어버렸다면 웹훅을 삭제하고 새로 발급합니다. 삭제하면 기존 URL 은 즉시 무효가 됩니다.

self-hosted 로 설치했다면 https://collabops.ai 자리에 설치한 서버 주소가 들어갑니다. 발급 화면에 보이는 URL 을 그대로 쓰면 됩니다.

켜기 · 끄기 · 이름 변경 · 삭제

웹훅 관리하기 창의 카드마다 켜기/끄기 스위치와 ⋯ 메뉴가 있습니다. ⋯ 메뉴에서 전송 기록, 채널 대화 읽기 허용, 이름 변경, 삭제를 고릅니다. 전송 기록은 채널 멤버 누구나 볼 수 있고, 나머지는 채널 관리자만 바꿀 수 있습니다.

웹훅 카드의 켜기/끄기 스위치와 ⋯ 메뉴

그림 4 — 웹훅 카드와 ⋯ 메뉴
하는 일결과
끄기URL 과 시크릿은 그대로입니다. 꺼져 있는 동안 오는 요청은 401 로 거절되고, 다시 켜면 같은 URL 로 받습니다.
삭제되돌릴 수 없습니다. URL 은 즉시 무효가 되고 이후 요청은 404 입니다.
채널이 삭제됨웹훅이 자동으로 꺼집니다. 이후 요청은 401 입니다.

요청 형식

항목값필수
메서드POST예
Authorization 헤더Bearer <시크릿>예
Content-Type 헤더application/json권장
Idempotency-Key 헤더200자 이하 문자열. 재전송돼도 한 번만 게시합니다 (아래 중복 방지)아니오
본문JSON 객체, 64 KiB 이하예
curl -X POST "https://collabops.ai/api/v2/integration/webhook/<토큰>" \
  -H "Authorization: Bearer <시크릿>" \
  -H "Content-Type: application/json" \
  -d '{"text": "**배포 완료** `web` 0.4.2"}'

본문 — text 와 blocks

본문은 두 형식 중 정확히 하나를 씁니다. text 와 blocks 를 함께 넣거나 둘 다 빼면 422 입니다.

형식언제 쓰나받는 필드
text대부분의 알림. 마크다운으로 충분할 때text · title · parent_delivery_id
blocks글자색, 토글, 스프린트 참조처럼 마크다운으로 표현할 수 없는 것이 필요할 때blocks · parent_delivery_id

text 형식

필드타입필수설명
textstring예마크다운입니다. 토큰을 쓰면 이슈 칩과 날짜 칩이 됩니다.
titlestring아니오채널 목록의 마지막 메시지 미리보기와 알림에만 쓰이고 메시지 본문에는 나타나지 않습니다. 없으면 본문에서 만듭니다.
parent_delivery_id양의 정수아니오이 메시지를 답글로 붙일 원글의 delivery_id 입니다 (아래 스레드).

blocks 형식

필드타입필수설명
blocksarray예블록 배열입니다. 블록마다 id 와 type 이 필요합니다.
parent_delivery_id양의 정수아니오text 형식과 같습니다.

블록 종류와 모양은 표현 레퍼런스에 있습니다.

표에 없는 필드는 받지 않습니다. blocks 형식에 title 을 넣거나 status 같은 필드를 덧붙이면 무시되지 않고 422 로 거절됩니다. 받아 놓고 조용히 버리면 보낸 쪽이 왜 화면에 안 보이는지 알 수 없기 때문입니다.

응답

요청을 받으면 게시를 기다리지 않고 바로 202 Accepted 를 돌려줍니다. 채널 게시는 그 뒤에 비동기로 이루어집니다.

{"delivery_id": 1234, "deduped": false}
필드설명
delivery_id이 요청의 수신 기록 번호입니다. 스레드로 이어 보낼 때 parent_delivery_id 로 씁니다.
deduped같은 Idempotency-Key 로 이미 받은 요청이면 true 입니다. 이때 delivery_id 는 처음 받은 기록의 번호입니다.

202 는 받았다는 뜻이지 채널에 올라갔다는 뜻이 아닙니다. 게시 결과는 아래 전송 결과 확인의 전송 기록에서 봅니다.

오류 응답

실패하면 아래 모양의 JSON 이 옵니다. error.title 에 거절 사유가, error.request_id 에 문의할 때 알려 줄 추적 번호가 들어 있습니다. 같은 추적 번호가 X-Request-Id 응답 헤더에도 실립니다.

{
  "error": {
    "code": "VALIDATION_ERROR",
    "title": "요청 형식이 올바르지 않습니다: exactly one of text or blocks is required",
    "request_id": "3f1c9a52-8e0b-4c1d-9f7a-2b6e4d8c1a90",
    "upstream_status": 422
  }
}
상태언제어떻게 하나
401시크릿이 틀렸거나 Authorization 헤더가 없을 때, 웹훅이 꺼져 있을 때 (채널이 삭제돼 자동으로 꺼진 경우 포함)시크릿을 고치거나 웹훅을 켠 뒤 보냅니다.
404URL 의 토큰에 해당하는 웹훅이 없을 때 (삭제된 웹훅 포함)새로 발급한 URL 로 보냅니다.
413요청 전체가 1 MiB 를 넘을 때본문을 줄입니다.
422본문이 JSON 이 아니거나, 필드가 맞지 않거나, 상한을 넘었거나, parent_delivery_id 를 쓸 수 없을 때error.title 의 사유대로 본문을 고칩니다. 그대로 다시 보내면 또 422 입니다.
429웹훅 하나에 분당 60회를 넘었을 때Retry-After 헤더의 초만큼 기다린 뒤 보냅니다.
503 · 502 · 504일시적인 내부 오류나 응답 지연잠시 뒤 같은 요청을 다시 보냅니다. Idempotency-Key 를 붙여 두면 두 번 게시될 걱정이 없습니다.

상한

무엇상한넘으면
본문 크기64 KiB (65,536바이트, 받은 본문 그대로 셈)422
요청 전체 크기1 MiB413
블록 수200개422
전송 빈도웹훅 하나당 분당 60회429
Idempotency-Key 길이200자422

블록 수는 변환된 뒤의 블록으로 셉니다. text 형식도 마크다운이 블록으로 바뀐 뒤의 개수입니다. 문단, 제목, 목록 항목은 하나가 블록 하나이고, 표는 셀 하나가 블록 하나입니다. 3열 10행 표는 그것만으로 30블록입니다. 공백뿐인 text 처럼 블록이 하나도 나오지 않는 본문도 422 로 거절됩니다.

긴 보고는 한 메시지에 몰아넣지 말고 스레드로 나눠 보내세요.

중복 방지

네트워크 오류로 응답을 못 받으면 발신 도구는 같은 요청을 다시 보내게 됩니다. Idempotency-Key 헤더에 알림마다 고유한 값을 넣어 두면 같은 키로 다시 와도 채널에는 한 번만 올라갑니다. 두 번째 응답은 deduped: true 와 처음 받은 delivery_id 를 돌려줍니다.

키를 넣지 않으면 요청마다 새 메시지가 됩니다. 커밋 SHA 와 이벤트 종류를 이은 deploy-3f9c2a71-success 처럼 같은 알림이면 늘 같은 값이 나오도록 만드세요. 401·422 처럼 거절된 요청은 키를 기억하지 않으므로, 본문을 고쳐 같은 키로 다시 보내면 정상적으로 처리됩니다.

스레드로 이어 보내기

응답으로 받은 delivery_id 를 다음 요청의 parent_delivery_id 에 넣으면 그 메시지의 답글로 올라갑니다. 채팅 내부의 메시지 번호는 몰라도 됩니다.

원글 상태결과
채널에 올라감답글로 붙습니다.
아직 게시 중원글이 올라갈 때까지 기다렸다가 붙습니다. 응답은 202 입니다.
원글 자체가 답글원글이 속한 스레드에 붙습니다. 답글의 답글은 만들어지지 않습니다.
게시에 실패함이 메시지도 게시되지 않습니다. 응답은 202 이고 전송 기록에 남습니다.
다른 웹훅의 번호이거나 없는 번호422
접수 단계에서 거절된 요청422

전송 결과 확인

웹훅 관리하기 창의 카드마다 마지막 수신 상태가 보이고, ⋯ 메뉴의 전송 기록에서 요청 한 건 한 건의 결과를 최신순으로 볼 수 있습니다. 한 건마다 받은 시각, 상태, 본문 형식(텍스트·블록), 스레드 답글 여부가 나옵니다. 게시된 건은 메시지 보기로 채널의 그 메시지를 열 수 있습니다. 거절된 건에는 error.title 의 콜론 뒤에 붙는 것과 같은 영문 사유가 보이고, 본문 검증에 실패한 건은 원문 보기로 보낸 JSON 을 확인할 수 있습니다.

전송 기록 — 성공한 텍스트 요청 1건과 JSON 이 아니어서 거절된 요청 1건

그림 5 — 전송 기록
화면 표시상태 값뜻
접수됨accepted받았고 아직 게시 전입니다.
성공ok채널에 올라갔습니다.
부모 메시지 대기waiting_parent원글이 게시되기를 기다리는 답글입니다.
부모 메시지 실패parent_failed원글 게시가 실패해 이 답글도 올리지 않았습니다. 새 요청으로 다시 보냅니다.
채팅 전송 실패chat_error게시 단계에서 실패했습니다.
채널 없음channel_gone채널이 사라졌습니다. 웹훅은 자동으로 꺼집니다.
인증 실패unauthorized401 로 거절됐습니다.
요청 과다rate_limited429 로 거절됐습니다. 1분 안에서 처음 넘은 요청만 남습니다.
형식 오류invalid_payload422 로 거절됐습니다.
용량 초과too_large본문 64 KiB 또는 블록 200개를 넘어 422 로 거절됐습니다. 본문은 남기지 않습니다.

웹훅을 찾지 못한 404, 1 MiB 를 넘은 413, 일시적인 5xx 는 기록되지 않으므로 발신 쪽 로그에서 응답 코드를 확인하세요.

목차