이벤트와 서명

봇에 이벤트가 생기면 봇 관리 > 연동에 저장한 주소로 POST 요청을 보내요. 주소를 저장하고 이벤트를 고르는 방법은 웹훅 설정에 있어요.

이벤트#

이벤트보내는 때
heart누군가 봇에 하트를 눌렀을 때
invite.created봇에 초대 신청이 들어왔을 때
invite.accepted제작자가 초대 신청을 수락했을 때
test연동 화면에서 '테스트 전송'을 눌렀을 때

요청 헤더#

이름설명
Content-Typeapplication/json; charset=utf-8
User-AgentHankari-Webhook/1.0 (+https://hankari.dev/devs/docs/webhook-events)
X-Hankari-Event이벤트 이름(heart, invite.created, invite.accepted, test)
X-Hankari-Delivery전송마다 다른 id(whd_…). 다시 보낼 때도 같은 값이라 중복을 거를 수 있어요.
X-Hankari-Signaturesha256={비밀 키로 만든 본문의 HMAC-SHA256, 16진수}

서명 확인#

웹훅 주소마다 비밀 키가 있어요. 받은 본문을 비밀 키로 HMAC-SHA256 해서 X-Hankari-Signature 값과 비교하면 한카리가 보낸 요청인지 알 수 있어요. 값이 다르면 요청을 버려 주세요.

import crypto from "node:crypto";

// rawBody: 받은 본문 그대로(Buffer). JSON으로 다시 만들면 서명이 달라져요.
export function verifyHankari(rawBody, signature, secret) {
  const expected =
    "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signature ?? "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

응답과 전송 기록#

2xx로 답하면 받은 것으로 봐요. 그 밖의 응답이나 시간 초과는 실패로 봐요. 결과는 봇 관리 > 연동의 '최근 전송 기록'에 남아요. 5초 안에 답이 없거나 연결이 안 되거나 5xx·429로 답하면 1초 뒤, 그다음 4초 뒤에 다시 보내요(최대 3번). 그 밖의 4xx와 리다이렉트는 다시 보내지 않고 따라가지도 않아요.