Dashboard의 API Keys 페이지에서 발급한 키를 Authorization 헤더에 담아 보냅니다. 키 원문은 발급 시 한 번만 표시되며 이후에는 다시 확인할 수 없으니 안전한 곳에 저장해두세요.
Authorization: Bearer wt_xxxxxxxxxxxxxxxxxxxxxxxx키가 없거나, 형식이 올바르지 않거나, 폐기(revoke)된 키로 요청하면 모두 401이 반환됩니다.
/api/v1/monitors목록 조회/api/v1/monitors생성/api/v1/monitors/:id단건 조회/api/v1/monitors/:id수정/api/v1/monitors/:id삭제/api/v1/monitors/:id/check즉시 체크 실행모든 요청/응답 바디는 JSON입니다. 목록 조회는 페이지네이션 없이 해당 계정의 전체 Monitor를 최신순으로 반환합니다.
생성/조회/수정 응답은 아래 필드를 가진 monitor 객체를 반환합니다.
idstringMonitor 고유 IDnamestring이름 (최대 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 URLwebhookSecretstring | 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). status는 active/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존재하지 않거나 다른 계정 소유의 Monitor409Conflict일시정지된 Monitor에 즉시 체크 요청500Internal Server Error서버 내부 오류API로 생성/수정하는 Monitor도 대시보드와 동일한 플랜 제한을 받습니다. 한도를 넘으면 403과 함께 사유가 담긴 메시지를 반환합니다.
| Plan | Monitor 최대 | 최소 체크 주기 | Dynamic 최대 |
|---|---|---|---|
| Free | 3개 | 60분 | 불가 |
| Starter | 20개 | 15분 | 불가 |
| Pro | 20개 | 15분 | 5개 |
| Business | 100개 | 5분 | 30개 |
url과 webhookUrl 모두 내부망 접근을 막기 위해 localhost, 127.0.0.1, 169.254.0.0/16 등 사설 IP 대역으로는 등록할 수 없습니다. 로컬 개발 서버로 Webhook을 테스트하려면 ngrok 같은 터널링 도구로 공인 URL을 발급받아 사용하세요. 리다이렉트가 발생하는 경우 최종 목적지 주소에도 동일한 제약이 적용됩니다.
변경이 감지되면 등록한 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"));
}