가동 상태(heartbeat)

POST/v1/bots/{id}/heartbeat

봇이 켜져 있다고 알려요. 이 요청이 오면 가동 상태가 "가동 중"으로 바뀌어요. 봇이 켜져 있는 동안 주기적으로 보내 주세요. 처음 성공한 호출은 봇 연결도 함께 마쳐요.

마지막 heartbeat 뒤 10분 동안 소식이 없으면 오프라인으로 바뀌어요. 1~5분마다 보내는 걸 권해요.

경로 변수#

이름설명
id봇 id. bot_으로 시작해요. 봇 관리 › 연동이나 토큰 화면에서 복사할 수 있어요.

요청 헤더#

이름필수설명
Authorization필수Bearer {개발자 토큰}
Content-Type선택application/json (본문을 보낼 때만)

토큰 하나로 내가 소유했거나 '개발 도구' 권한을 받은 봇 모두에 보낼 수 있어요. 토큰은 인증에서 설명해요.

요청 본문#

본문은 없어도 돼요. 헤더만 실어 보내면 돼요.

curl -X POST "https://hankari.dev/v1/bots/$BOT_ID/heartbeat" \
  -H "Authorization: Bearer $HANKARI_TOKEN"

응답#

200 OK
{
  "status": "online",
  "reportedAt": "2026-09-14T06:02:11.000Z"
}

reportedAt은 한카리가 요청을 받은 시각(UTC)이에요. 토큰이 잘못되면 401을, 봇 id가 틀렸거나 그 봇을 다룰 권한이 없으면 404를 돌려줘요. 오류 모양은 인증 › 오류 응답에 있어요.

주기적으로 보내기#

봇이 켜질 때 한 번 보내고, 그 뒤로는 타이머로 1~5분마다 보내요. 요청이 실패해도 다음 차례에 다시 보내면 돼요. 봇이 꺼질 때 따로 알릴 필요는 없어요 — 신호가 끊기면 한카리가 오프라인으로 바꿔요.

메신저봇R#

스크립트를 다시 컴파일하면 타이머가 겹치지 않게 onStartCompile에서 멈춰요.

const HANKARI_TOKEN = "hkd_…";
const BOT_ID = "bot_…";
const HEARTBEAT_MS = 3 * 60 * 1000; // 3분마다

function sendHeartbeat() {
  try {
    org.jsoup.Jsoup.connect("https://hankari.dev/v1/bots/" + BOT_ID + "/heartbeat")
      .header("Authorization", "Bearer " + HANKARI_TOKEN)
      .ignoreContentType(true)
      .ignoreHttpErrors(true)
      .timeout(10000)
      .method(org.jsoup.Connection.Method.POST)
      .execute();
  } catch (e) {
    // 실패해도 다음 차례에 다시 보내요
  }
}

// 채팅 처리와 따로 도는 타이머라 봇이 느려지지 않아요.
const heartbeatTimer = new java.util.Timer(true);
heartbeatTimer.scheduleAtFixedRate(
  new java.util.TimerTask({ run: sendHeartbeat }),
  0,
  HEARTBEAT_MS,
);

function onStartCompile() {
  heartbeatTimer.cancel();
}

Node.js#

Node 18 이상에 들어 있는 fetch를 써요.

const HANKARI_TOKEN = process.env.HANKARI_TOKEN;
const BOT_ID = process.env.HANKARI_BOT_ID;

async function heartbeat() {
  try {
    await fetch(`https://hankari.dev/v1/bots/${BOT_ID}/heartbeat`, {
      method: "POST",
      headers: { Authorization: `Bearer ${HANKARI_TOKEN}` },
      signal: AbortSignal.timeout(10_000),
    });
  } catch {
    // 실패해도 다음 차례에 다시 보내요
  }
}

heartbeat();
setInterval(heartbeat, 3 * 60 * 1000); // 3분마다

Python (Iris)#

requests를 써요. 타이머는 데몬 스레드라 봇이 끝나면 함께 끝나요.

import threading
import requests

def heartbeat():
    try:
        requests.post(
            f"https://hankari.dev/v1/bots/{BOT_ID}/heartbeat",
            headers={"Authorization": "Bearer " + HANKARI_TOKEN},
            timeout=10,
        )
    except requests.RequestException:
        pass  # 실패해도 다음 차례에 다시 보내요
    timer = threading.Timer(180, heartbeat)  # 3분마다
    timer.daemon = True
    timer.start()

heartbeat()

방 수는 어떻게 세나요#

방 수는 봇이 보고하지 않아요. 한카리 초대 신청으로 봇이 들어간 방을 한카리가 직접 세요. 제작자가 '입장시켰어요'를, 신청자가 '봇이 들어왔어요'를 모두 눌러 입장 완료가 된 신청 하나가 방 하나예요. 같은 방에 다시 들어가도 한 번만 세요.

예전의 POST /v1/bots/stats(방 수 보고), POST /v1/bots/verify(첫 연결), 봇 토큰으로 보내던 POST /v1/bots/heartbeat는 없어졌어요. 부르면 410 Gone을 돌려줘요. 모두 개발자 토큰과 POST /v1/bots/{id}/heartbeat로 바꿔 주세요.