webPulse

Developer API

API Key로 Monitor를 프로그래밍 방식으로 관리하고, Webhook으로 변경 이벤트를 자신의 시스템에 연동하세요.

인증

Dashboard의 API Keys 페이지에서 발급한 키를 Authorization 헤더에 담아 보냅니다. 키 원문은 발급 시 한 번만 표시되며 이후에는 다시 확인할 수 없으니 안전한 곳에 저장해두세요.

Authorization: Bearer wt_xxxxxxxxxxxxxxxxxxxxxxxx

키가 없거나, 형식이 올바르지 않거나, 폐기(revoke)된 키로 요청하면 모두 401이 반환됩니다.

Endpoints

GET/api/v1/monitors목록 조회
POST/api/v1/monitors생성
GET/api/v1/monitors/:id단건 조회
PATCH/api/v1/monitors/:id수정
DELETE/api/v1/monitors/:id삭제
POST/api/v1/monitors/:id/check즉시 체크 실행

모든 요청/응답 바디는 JSON입니다. 목록 조회는 페이지네이션 없이 해당 계정의 전체 Monitor를 최신순으로 반환합니다.

Monitor 객체

생성/조회/수정 응답은 아래 필드를 가진 monitor 객체를 반환합니다.

idstringMonitor 고유 ID
namestring이름 (최대 100자)
urlstring감시 대상 URL (최대 2048자)
cssSelectorstring | null감시 영역을 좁히는 CSS Selector (최대 500자)
renderingMode"static" | "dynamic"정적 HTML 또는 Playwright 렌더링. dynamic은 Pro 이상 플랜 필요
intervalMinutesnumber체크 주기(분). 5 ~ 10080(7일). 플랜별 최소값 있음
status"active" | "paused" | "error"연속 5회 체크 실패 시 자동으로 paused로 전환됨
lastHashstring | null가장 최근 콘텐츠의 SHA256 해시
lastCheckedAtstring | null마지막 체크 시각 (ISO 8601)
lastErrorstring | null마지막 체크 실패 사유
consecutiveFailuresnumber연속 실패 횟수
notifyEmailboolean변경 시 이메일 알림 여부
webhookUrlstring | null변경 이벤트를 받을 Webhook URL
webhookSecretstring | nullWebhook 서명 검증용 Secret. webhookUrl 설정 시 자동 발급됨
createdAtstring생성 시각 (ISO 8601)
updatedAtstring마지막 수정 시각 (ISO 8601)

요청 예시

Monitor 생성

curl -X POST https://your-app.com/api/v1/monitors \
  -H "Authorization: Bearer wt_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "채용 공고",
    "url": "https://example.com/careers",
    "renderingMode": "static",
    "intervalMinutes": 60,
    "cssSelector": ".job-list",
    "notifyEmail": true,
    "webhookUrl": "https://your-app.com/webhooks/webpulse"
  }'

# 201 Created
{
  "monitor": {
    "id": "b3f1c2d4-...",
    "name": "채용 공고",
    "url": "https://example.com/careers",
    "cssSelector": ".job-list",
    "renderingMode": "static",
    "intervalMinutes": 60,
    "status": "active",
    "lastHash": null,
    "lastCheckedAt": null,
    "lastError": null,
    "consecutiveFailures": 0,
    "notifyEmail": true,
    "webhookUrl": "https://your-app.com/webhooks/webpulse",
    "webhookSecret": "whsec_...",
    "createdAt": "2026-08-14T02:00:00.000Z",
    "updatedAt": "2026-08-14T02:00:00.000Z"
  }
}

Monitor 수정 (일시정지)

curl -X PATCH https://your-app.com/api/v1/monitors/b3f1c2d4-... \
  -H "Authorization: Bearer wt_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "status": "paused" }'

createMonitor와 동일한 필드를 부분적으로 보낼 수 있습니다(name, url, cssSelector, renderingMode, intervalMinutes, notifyEmail, webhookUrl). statusactive/paused만 직접 바꿀 수 있고, error는 연속 실패 시 시스템이 자동으로 설정합니다.

즉시 체크 실행

curl -X POST https://your-app.com/api/v1/monitors/b3f1c2d4-.../check \
  -H "Authorization: Bearer wt_xxxxxxxxxxxxxxxxxxxxxxxx"

# 200 OK
{ "monitorId": "b3f1c2d4-...", "changed": false }

예약된 체크를 기다리지 않고 즉시 실행합니다. 일시정지된 Monitor는409를 반환합니다.

Monitor 삭제

curl -X DELETE https://your-app.com/api/v1/monitors/b3f1c2d4-... \
  -H "Authorization: Bearer wt_xxxxxxxxxxxxxxxxxxxxxxxx"

# 204 No Content

에러 응답

실패한 요청은 아래 형식으로 응답합니다. 입력값 검증 실패 시에는details에 필드별 오류가 함께 담깁니다.

{ "error": "Free 플랜은 Monitor를 최대 3개까지 등록할 수 있습니다." }
400Bad Request입력값 검증 실패, 안전하지 않은 URL(SSRF 위험)
401UnauthorizedAPI Key 누락/형식 오류/폐기됨
403Forbidden플랜 한도 초과 (Monitor 개수, Dynamic 개수, 최소 주기)
404Not Found존재하지 않거나 다른 계정 소유의 Monitor
409Conflict일시정지된 Monitor에 즉시 체크 요청
500Internal Server Error서버 내부 오류

플랜 제한

API로 생성/수정하는 Monitor도 대시보드와 동일한 플랜 제한을 받습니다. 한도를 넘으면 403과 함께 사유가 담긴 메시지를 반환합니다.

PlanMonitor 최대최소 체크 주기Dynamic 최대
Free3개60분불가
Starter20개15분불가
Pro20개15분5개
Business100개5분30개

URL 제약 (SSRF 방어)

urlwebhookUrl 모두 내부망 접근을 막기 위해 localhost, 127.0.0.1, 169.254.0.0/16 등 사설 IP 대역으로는 등록할 수 없습니다. 로컬 개발 서버로 Webhook을 테스트하려면 ngrok 같은 터널링 도구로 공인 URL을 발급받아 사용하세요. 리다이렉트가 발생하는 경우 최종 목적지 주소에도 동일한 제약이 적용됩니다.

Webhook 페이로드

변경이 감지되면 등록한 webhookUrl로 아래와 같은 JSON을 POST합니다. Monitor 생성/조회 응답의 webhookSecret으로 서명한 값이 X-WebPulse-Signature 헤더에 담깁니다.

POST /webhooks/webpulse
Content-Type: application/json
X-WebPulse-Signature: <HMAC-SHA256(secret, body)>

{
  "event": "monitor.changed",
  "monitorId": "b3f1...",
  "monitorName": "채용 공고",
  "url": "https://example.com/careers",
  "changeEventId": "9ac2...",
  "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "timestamp": "2026-08-14T02:00:00.000Z"
}

이 payload에는 실제로 무엇이 바뀌었는지(before/after 내용)는 포함되지 않습니다. 변경 내용은 changeEventId로 대시보드의 Monitor 상세 페이지에서 확인해야 합니다. 또한 현재 Webhook 전송은 실패 시 자동 재시도하지 않습니다 — 응답 코드가 2xx가 아니면 실패로 기록되고 다음 변경 감지까지 재전송되지 않으니, 수신 엔드포인트를 안정적으로 유지하는 게 중요합니다.

서명 검증 예시 (Node.js):

import { createHmac, timingSafeEqual } from "node:crypto";

function isValidSignature(body: string, signature: string, secret: string) {
  const expected = createHmac("sha256", secret).update(body).digest("hex");
  return timingSafeEqual(Buffer.from(signature, "hex"), Buffer.from(expected, "hex"));
}