도메인 관찰 목록
DomScan API로 도메인의 만료 및 가용성 변경을 모니터링합니다. 등록된 도메인이 사용 가능해지면 알림을 받습니다.
도메인 관찰 목록
도메인의 만료 및 가용성 변경을 모니터링합니다. 등록된 도메인이 사용 가능해지면 알림을 받습니다.
Google으로 로그인하여 이메일 알림, 웹훅 등을 포함한 개인화된 도메인 감시 목록에 접근합니다.
이메일, Telegram, Slack, Discord 또는 Webhook을 통해 알림을 받습니다.
관찰 목록의 모든 도메인을 조회합니다.
페이지네이션 지원: limit(1~100)을 보내고 next_cursor를 cursor로 다시 전달하세요. 응답에는 has_more와 next_cursor가 포함됩니다. limit이 없으면 전체 목록이 반환됩니다. 페이지네이션을 참고하세요.
예제 응답
{
"watchlist": [
{
"domain": "startup.com",
"added_at": "2024-01-15T10:30:00Z",
"status": "registered",
"expiry_date": "2025-01-15T00:00:00Z",
"days_until_expiry": 287,
"last_checked": "2024-03-01T12:00:00Z",
"notify_email": "[email protected]",
"check_count": 4
}
],
"total": 1,
"updated_at": "2024-03-01T12:00:00Z"
}
응답 필드
| 필드 | 유형 |
|---|---|
has_more |
boolean |
next_cursor |
string | null |
watchlist[] |
object[] |
watchlist[] |
object |
watchlist[].domain |
string |
watchlist[].added_at |
string |
watchlist[].status |
string |
watchlist[].last_checked |
string |
watchlist[].expiry_date |
string |
watchlist[].days_until_expiry |
integer |
watchlist[].notify_email |
string |
watchlist[].check_count |
integer |
total |
integer |
updated_at |
string |
응답 필드
| 필드 | 유형 |
|---|---|
success |
boolean |
message |
string |
watchlist[] |
object[] |
watchlist[] |
object |
watchlist[].domain |
string |
watchlist[].added_at |
string |
watchlist[].status |
string |
watchlist[].last_checked |
string |
watchlist[].expiry_date |
string |
watchlist[].days_until_expiry |
integer |
watchlist[].notify_email |
string |
watchlist[].check_count |
integer |
total |
integer |
예제 응답
{
"success": true,
"message": "Added example.org to watchlist",
"watchlist": [
{
"domain": "example.com",
"added_at": "2026-06-02T09:12:00.000Z",
"last_checked": "2026-10-09T03:00:12.000Z",
"status": "expiring_soon",
"expiry_date": "2026-12-18T14:22:08Z",
"days_until_expiry": 70,
"notify_email": "[email protected]"
},
{
"domain": "example.org",
"added_at": "2026-10-09T10:15:30.000Z",
"status": "unknown",
"notify_email": "[email protected]"
}
],
"total": 2
}
관심 목록에서 제거
curl -X DELETE -H "X-API-Key: your-api-key" "https://domscan.net/v1/watchlist?domain=mydomain.com"
응답 필드
| 필드 | 유형 |
|---|---|
success |
boolean |
message |
string |
domain |
string |
watchlist[] |
object[] |
watchlist[] |
object |
watchlist[].domain |
string |
watchlist[].added_at |
string |
watchlist[].status |
string |
watchlist[].last_checked |
string |
watchlist[].expiry_date |
string |
watchlist[].days_until_expiry |
integer |
watchlist[].notify_email |
string |
watchlist[].check_count |
integer |
total |
integer |
예제 응답
{
"success": true,
"message": "Request completed",
"domain": "example.com",
"watchlist": [
{
"domain": "example.com",
"added_at": "2026-08-27T12:00:00Z",
"status": "registered",
"last_checked": "2026-08-27T12:00:00Z",
"expiry_date": "2026-08-27T12:00:00Z",
"days_until_expiry": 1,
"notify_email": "[email protected]",
"check_count": 1
}
],
"total": 1
}
곧 만료
페이지네이션 지원: limit(1~100)을 보내고 next_cursor를 cursor로 다시 전달하세요. 응답에는 has_more와 next_cursor가 포함됩니다. limit이 없으면 전체 목록이 반환됩니다. 페이지네이션을 참고하세요.
예제 응답
{
"expiring_domains": [
{
"domain": "renewal-window.com",
"status": "expiring_soon",
"expiry_date": "2026-05-12T00:00:00Z",
"days_until_expiry": 28,
"check_count": 11
}
],
"total": 1,
"threshold_days": 30
}
응답 필드
| 필드 | 유형 |
|---|---|
has_more |
boolean |
next_cursor |
string | null |
expiring_domains[] |
object[] |
expiring_domains[] |
object |
expiring_domains[].domain |
string |
expiring_domains[].added_at |
string |
expiring_domains[].status |
string |
expiring_domains[].last_checked |
string |
expiring_domains[].expiry_date |
string |
expiring_domains[].days_until_expiry |
integer |
expiring_domains[].notify_email |
string |
expiring_domains[].check_count |
integer |
total |
integer |
threshold_days |
integer |
사용 가능
페이지네이션 지원: limit(1~100)을 보내고 next_cursor를 cursor로 다시 전달하세요. 응답에는 has_more와 next_cursor가 포함됩니다. limit이 없으면 전체 목록이 반환됩니다. 페이지네이션을 참고하세요.
예제 응답
{
"available_domains": [
{
"domain": "startupdrop.ai",
"status": "available",
"last_checked": "2026-04-14T08:30:00Z",
"check_count": 18
}
],
"total": 1,
"message": "관심 목록의 이러한 도메인이 이제 등록 가능합니다!"
}
응답 필드
| 필드 | 유형 |
|---|---|
has_more |
boolean |
next_cursor |
string | null |
available_domains[] |
object[] |
available_domains[] |
object |
available_domains[].domain |
string |
available_domains[].added_at |
string |
available_domains[].status |
string |
available_domains[].last_checked |
string |
available_domains[].expiry_date |
string |
available_domains[].days_until_expiry |
integer |
available_domains[].notify_email |
string |
available_domains[].check_count |
integer |
total |
integer |
message |
string |
알림 웹훅
모니터링 알림을 서명된 JSON POST 요청으로 내 HTTPS 엔드포인트에서 받을 수 있습니다. 엔드포인트는 API 키로 관리하거나, 로그인한 상태에서 모니터 설정에서 관리할 수 있습니다.
이벤트 유형
| 모니터 | 이벤트 |
|---|---|
| 감시 목록의 가용성, 만료, 상태 | domain.available domain.expiring_30 domain.expiring_14 domain.expiring_7 domain.expiring_1 domain.status_change |
| 도메인 변경 모니터링 | domain.dns_changed domain.certificate_changed domain.registration_changed domain.hosting_changed domain.technology_changed domain.email_security_changed |
| 브랜드 모니터링(유사 도메인 신규 등록) | brand.threat_detected |
| 관심 목록 알림 구독 (인증서, 가격, DNS 레코드, 유사 도메인) | ssl.expiring ssl.expired ssl.changed price.dropped dns.changed typosquat.detected |
| 비동기 작업(무료, notify_webhook으로 생성한 작업에만 해당) | job.completed job.failed job.cancelled |
| 테스트 이벤트(무료) | webhook.test |
요금
2xx 응답으로 엔드포인트에 전달된 알림은 건당 2 크레딧입니다. 크레딧은 첫 번째 시도 직전에 예약되며, 전달이 실패하거나 취소되거나 엔드포인트가 삭제되면 환불됩니다. 테스트 이벤트는 무료입니다. 잔액이 부족하면 알림을 건너뛰며 요금은 청구되지 않습니다.
HTTPS 엔드포인트를 등록합니다. URL은 공개 주소로 해석되어야 합니다. events를 생략하거나 ["*"]를 전달하면 모든 이벤트 유형을 받습니다. 서명 시크릿은 이 응답에서만 반환됩니다.
예제 요청
curl -X POST "https://domscan.net/v1/webhooks" \
-H "X-API-Key: $DOMSCAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.example.com/domscan",
"events": ["domain.expiring_30", "domain.available", "domain.dns_changed"]
}'
예제 응답
{
"endpoint": {
"id": "whe_3f1c0a9b8e7d6c5b4a39281706f5e4d3",
"url": "https://hooks.example.com/domscan",
"events": ["domain.available", "domain.expiring_30", "domain.dns_changed"],
"status": "active",
"secret_hint": "9c2e"
},
"secret": "whsec_..."
}
응답 필드
| 필드 | 유형 |
|---|---|
endpoint |
object |
endpoint.id |
string |
endpoint.url |
string |
endpoint.description |
string | null |
endpoint.events[] |
string[] |
endpoint.status |
string |
endpoint.disabled_reason |
string | null |
endpoint.consecutive_failures |
integer |
endpoint.secret_hint |
string |
endpoint.previous_secret_expires_at |
string | null |
endpoint.secret_rotated_at |
string | null |
endpoint.last_success_at |
string | null |
endpoint.last_failure_at |
string | null |
endpoint.last_error |
string | null |
endpoint.created_at |
string |
endpoint.updated_at |
string |
endpoint.disabled_at |
string | null |
secret |
string |
엔드포인트를 상태, 구독 중인 이벤트, 실패 횟수, 시크릿의 마지막 네 글자와 함께 나열하며, 사용 가능한 이벤트 유형과 전달 정책도 함께 반환합니다.
응답 필드
| 필드 | 유형 |
|---|---|
endpoints[] |
object[] |
endpoints[] |
object |
endpoints[].id |
string |
endpoints[].url |
string |
endpoints[].description |
string | null |
endpoints[].events[] |
string[] |
endpoints[].status |
string |
endpoints[].disabled_reason |
string | null |
endpoints[].consecutive_failures |
integer |
endpoints[].secret_hint |
string |
endpoints[].previous_secret_expires_at |
string | null |
endpoints[].secret_rotated_at |
string | null |
endpoints[].last_success_at |
string | null |
endpoints[].last_failure_at |
string | null |
endpoints[].last_error |
string | null |
endpoints[].created_at |
string |
endpoints[].updated_at |
string |
endpoints[].disabled_at |
string | null |
available_events[] |
string[] |
all_events |
string |
test_event |
string |
policy |
object |
policy.secret_rotation_grace_seconds |
integer |
policy.secret_rotation_credits |
integer |
policy.credits_per_delivered_alert |
integer |
policy.test_event_credits |
integer |
policy.job_event_credits |
integer |
policy.failed_deliveries_charged |
boolean |
policy.max_endpoints |
integer |
policy.max_attempts |
integer |
policy.disable_after_consecutive_failures |
integer |
policy.signature_tolerance_seconds |
integer |
예제 응답
{
"endpoints": [
{
"id": "example-id",
"url": "https://example.com",
"events": [
"example"
],
"status": "active",
"secret_hint": "example",
"created_at": "2026-08-27T12:00:00Z",
"description": "example",
"disabled_reason": "customer",
"consecutive_failures": 1,
"previous_secret_expires_at": "2026-08-27T12:00:00Z",
"secret_rotated_at": "2026-08-27T12:00:00Z",
"last_success_at": "2026-08-27T12:00:00Z",
"last_failure_at": "2026-08-27T12:00:00Z",
"last_error": "example",
"updated_at": "2026-08-27T12:00:00Z",
"disabled_at": "2026-08-27T12:00:00Z"
}
],
"available_events": [
"domain.available"
],
"policy": {
"credits_per_delivered_alert": 2,
"test_event_credits": 0,
"failed_deliveries_charged": false,
"max_endpoints": 1,
"max_attempts": 1,
"disable_after_consecutive_failures": 1,
"signature_tolerance_seconds": 1,
"secret_rotation_grace_seconds": 86400,
"secret_rotation_credits": 0,
"job_event_credits": 0
},
"all_events": "*",
"test_event": "webhook.test"
}
엔드포인트를 일시 중지하거나 활성화하고, 이벤트를 변경하거나 설명을 수정합니다. 엔드포인트를 활성화하면 실패 횟수가 초기화됩니다.
{ "enabled": true, "events": ["*"] }
응답 필드
| 필드 | 유형 |
|---|---|
endpoint |
object |
endpoint.id |
string |
endpoint.url |
string |
endpoint.description |
string | null |
endpoint.events[] |
string[] |
endpoint.status |
string |
endpoint.disabled_reason |
string | null |
endpoint.consecutive_failures |
integer |
endpoint.secret_hint |
string |
endpoint.previous_secret_expires_at |
string | null |
endpoint.secret_rotated_at |
string | null |
endpoint.last_success_at |
string | null |
endpoint.last_failure_at |
string | null |
endpoint.last_error |
string | null |
endpoint.created_at |
string |
endpoint.updated_at |
string |
endpoint.disabled_at |
string | null |
예제 응답
{
"endpoint": {
"id": "example-id",
"url": "https://example.com",
"events": [
"example"
],
"status": "active",
"secret_hint": "example",
"created_at": "2026-08-27T12:00:00Z",
"description": "example",
"disabled_reason": "customer",
"consecutive_failures": 1,
"previous_secret_expires_at": "2026-08-27T12:00:00Z",
"secret_rotated_at": "2026-08-27T12:00:00Z",
"last_success_at": "2026-08-27T12:00:00Z",
"last_failure_at": "2026-08-27T12:00:00Z",
"last_error": "example",
"updated_at": "2026-08-27T12:00:00Z",
"disabled_at": "2026-08-27T12:00:00Z"
}
}
엔드포인트를 삭제합니다. 대기 중인 전달은 취소되고 예약된 크레딧은 환불됩니다.
응답 필드
| 필드 | 유형 |
|---|---|
id |
string |
deleted |
boolean |
예제 응답
{
"id": "example-id",
"deleted": true
}
무료 webhook.test 이벤트를 한 번 보내고 결과를 반환합니다. 테스트 이벤트는 재시도되지 않으며 자동 일시 중지 횟수에도 포함되지 않습니다.
응답 필드
| 필드 | 유형 |
|---|---|
delivery |
object |
delivery.id |
string |
delivery.endpoint_id |
string |
delivery.event_id |
string |
delivery.event_type |
string |
delivery.status |
string |
delivery.attempts |
integer |
delivery.next_attempt_at |
string | null |
delivery.last_attempt_at |
string | null |
delivery.response_status |
integer | null |
delivery.last_error |
string | null |
delivery.credits_charged |
integer |
delivery.refunded |
boolean |
delivery.created_at |
string |
delivery.delivered_at |
string | null |
delivered |
boolean |
예제 응답
{
"delivery": {
"id": "example-id",
"endpoint_id": "example",
"event_id": "example",
"event_type": "domain",
"status": "pending",
"attempts": 1,
"next_attempt_at": "2026-08-27T12:00:00Z",
"last_attempt_at": "2026-08-27T12:00:00Z",
"response_status": 1,
"last_error": "example",
"credits_charged": 1,
"refunded": false,
"created_at": "2026-08-27T12:00:00Z",
"delivered_at": "2026-08-27T12:00:00Z"
},
"delivered": false
}
일시 중지된 엔드포인트를 포함해 엔드포인트의 서명 시크릿을 교체합니다. 새 시크릿은 이 응답에서만 반환됩니다. 이후 24시간 동안 모든 전달은 새 시크릿과 이전 시크릿으로 모두 서명됩니다. 교체는 무료입니다.
예제 요청
curl -X POST "https://domscan.net/v1/webhooks/whe_3f1c0a9b8e7d6c5b4a39281706f5e4d3/rotate-secret" \
-H "X-API-Key: $DOMSCAN_API_KEY"
예제 응답
{
"endpoint": {
"id": "whe_3f1c0a9b8e7d6c5b4a39281706f5e4d3",
"status": "active",
"secret_hint": "4b7a",
"previous_secret_expires_at": "2026-10-11T12:00:00.000Z"
},
"secret": "whsec_...",
"previous_secret_expires_at": "2026-10-11T12:00:00.000Z",
"grace_period_seconds": 86400
}
응답 필드
| 필드 | 유형 |
|---|---|
endpoint |
object |
endpoint.id |
string |
endpoint.url |
string |
endpoint.description |
string | null |
endpoint.events[] |
string[] |
endpoint.status |
string |
endpoint.disabled_reason |
string | null |
endpoint.consecutive_failures |
integer |
endpoint.secret_hint |
string |
endpoint.previous_secret_expires_at |
string | null |
endpoint.secret_rotated_at |
string | null |
endpoint.last_success_at |
string | null |
endpoint.last_failure_at |
string | null |
endpoint.last_error |
string | null |
endpoint.created_at |
string |
endpoint.updated_at |
string |
endpoint.disabled_at |
string | null |
secret |
string |
previous_secret_expires_at |
string |
grace_period_seconds |
integer |
쿼리 매개변수
| 매개변수 | 유형 | 설명 |
|---|---|---|
| limit | integer | 반환할 전달 내역 수이며 1에서 100까지입니다. 기본값은 50입니다. |
최근 전달 내역을 상태, 시도 횟수, HTTP 응답, 청구된 크레딧, 환불과 함께 나열합니다. 전달 기록은 30일 동안 보관됩니다.
응답 필드
| 필드 | 유형 |
|---|---|
endpoint_id |
string |
deliveries[] |
object[] |
deliveries[] |
object |
deliveries[].id |
string |
deliveries[].endpoint_id |
string |
deliveries[].event_id |
string |
deliveries[].event_type |
string |
deliveries[].status |
string |
deliveries[].attempts |
integer |
deliveries[].next_attempt_at |
string | null |
deliveries[].last_attempt_at |
string | null |
deliveries[].response_status |
integer | null |
deliveries[].last_error |
string | null |
deliveries[].credits_charged |
integer |
deliveries[].refunded |
boolean |
deliveries[].created_at |
string |
deliveries[].delivered_at |
string | null |
예제 응답
{
"endpoint_id": "example",
"deliveries": [
{
"id": "example-id",
"endpoint_id": "example",
"event_id": "example",
"event_type": "domain",
"status": "pending",
"attempts": 1,
"next_attempt_at": "2026-08-27T12:00:00Z",
"last_attempt_at": "2026-08-27T12:00:00Z",
"response_status": 1,
"last_error": "example",
"credits_charged": 1,
"refunded": false,
"created_at": "2026-08-27T12:00:00Z",
"delivered_at": "2026-08-27T12:00:00Z"
}
]
}
요청 형식
각 알림은 JSON 본문이 있는 POST 요청입니다. 같은 이벤트의 id 필드는 바뀌지 않고 X-DomScan-Event-Id에도 똑같이 들어 있으므로, 이미 처리한 재시도는 무시할 수 있습니다.
POST /domscan HTTP/1.1
Content-Type: application/json
X-DomScan-Event: domain.expiring_30
X-DomScan-Event-Id: evt_6f1d2c3b4a5948e7b6c5d4e3f2a1b0c9
X-DomScan-Timestamp: 1791633600
X-DomScan-Signature: sha256=...
{
"id": "evt_6f1d2c3b4a5948e7b6c5d4e3f2a1b0c9",
"type": "domain.expiring_30",
"created": "2026-10-10T12:00:00.000Z",
"data": {
"domain": "acme.io",
"previous_status": "registered",
"current_status": "expiring_soon",
"expiry_date": "2026-11-09T00:00:00Z",
"days_until_expiry": 30,
"checked_at": "2026-10-10T12:00:00.000Z"
}
}
서명 검증
엔드포인트 시크릿을 사용해 X-DomScan-Timestamp 값, 마침표, 원본 요청 본문을 차례로 이어 붙인 데이터의 HMAC-SHA256을 계산하세요. 결과를 X-DomScan-Signature와 상수 시간으로 비교하고, 타임스탬프가 5분보다 오래된 요청은 거부하세요.
아래 샘플은 헤더의 모든 서명을 확인하므로 시크릿을 교체하는 중에도 계속 동작합니다.
import crypto from 'node:crypto';
// rawBody: the request body exactly as received, before JSON parsing.
function verifyDomScanWebhook(rawBody, headers, secret) {
const timestamp = headers['x-domscan-timestamp'];
const header = headers['x-domscan-signature'] || '';
if (!/^\d{10}$/.test(timestamp || '')) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = Buffer.from('sha256=' + crypto
.createHmac('sha256', secret)
.update(timestamp + '.' + rawBody)
.digest('hex'));
// One entry normally; two during a secret rotation (new secret first).
return header.split(',').some((entry) => {
const candidate = Buffer.from(entry.trim());
return candidate.length === expected.length &&
crypto.timingSafeEqual(candidate, expected);
});
}
서명 시크릿 교체
교체 후 24시간의 유예 기간에는 X-DomScan-Signature에 쉼표로 구분된 서명 두 개가 들어 있으며, 아래 예시처럼 새 시크릿의 서명이 먼저 옵니다. 항목 중 하나라도 신뢰하는 시크릿과 일치하면 요청을 받아들이고, 새 시크릿을 배포한 뒤에 이전 시크릿에 대한 신뢰를 중단하세요. 유예 기간 중 다시 교체하면 더 오래된 이전 시크릿은 즉시 폐기됩니다.
X-DomScan-Signature: sha256=<new>,sha256=<previous>
재시도와 자동 일시 중지
알림을 수신했음을 알리려면 8초 안에 2xx 상태 코드를 반환하세요. 리디렉션, 그 밖의 상태 코드, 타임아웃은 지수 백오프(1, 4, 16, 64, 256분)로 재시도하며 총 6회까지 시도합니다. 연속 15회 실패하면 엔드포인트가 일시 중지되며, PATCH 또는 모니터 설정에서 다시 활성화할 수 있습니다.
반복된 실패로 엔드포인트가 일시 중지되면 엔드포인트 소유자에게 엔드포인트 호스트, 마지막 오류, 모니터 설정 링크가 담긴 이메일이 한 통 발송됩니다. 엔드포인트를 수정한 뒤 모니터 설정에서, 또는 PATCH로 enabled를 true로 설정해 다시 활성화하세요. 활성화하면 실패 횟수가 0으로 초기화됩니다.
관심 목록 알림 구독
관심 목록의 항목에 원하는 알림을 구독하세요. 각 구독은 호스트명, TLD 또는 브랜드 도메인 하나를 모니터링하며, 받을 이벤트를 직접 선택할 수 있습니다. 이벤트는 서명된 웹훅 엔드포인트와 앱 내 알림으로 전달됩니다.
| 유형 | 이벤트 | 발생 시점 |
|---|---|---|
ssl | ssl.expiring ssl.expired ssl.changed | ssl.expiring은 호스트명이 제공하는 인증서가 ssl_expiring_days (30, 14, 7 또는 1, 기본값 14) 이내에 만료될 때 인증서와 임계값마다 한 번 발생합니다. ssl.expired는 만료된 인증서마다 한 번 발생합니다. ssl.changed는 새 인증서 핑거프린트가 연속 2회 확인에서 확인될 때 발생하며, 페이로드에 발급자가 변경되었는지 여부가 포함됩니다. |
price | price.dropped | TLD의 등록 또는 갱신 가격이 특정 등록기관 또는 최저가 등록기관에서 마지막 알림 이후의 최고 가격보다 drop_percent 이상 떨어지거나 target_price 이하에 도달할 때 발생합니다. 가격은 매일 생성되는 가격 스냅샷에서 가져오며, 각 스냅샷은 한 번만 평가됩니다. |
dns | dns.changed | 모니터링 중인 레코드 유형(A, AAAA, MX, NS, TXT 또는 CNAME)이 어떤 호스트명에서든 연속 2회 확인된 조회에서 동일한 새 응답을 반환할 때 발생합니다. |
typosquat | typosquat.detected | 브랜드 도메인과 유사한 도메인이 새로 등록되고 공식 등록 조회로 확인될 때 발생합니다. 유사 도메인에 대한 첫 전체 검사는 기준선만 설정하며 알림을 보내지 않습니다. |
정확한 증거가 있을 때만 이벤트가 발생합니다. TLS 핸드셰이크 실패, 실패하거나 시간 초과된 DNS 조회, 누락된 가격, 차단되거나 요청 제한된 조회는 알 수 없음으로 처리되며, 아무것도 변경하지 않고 알림이나 과금도 발생하지 않습니다. 구독의 첫 번째 확인된 검사가 기준선을 설정합니다.
검사는 자동으로 실행됩니다. 인증서는 12시간마다, DNS 레코드는 1시간마다(변경이 처음 감지되고 15분 후 확인 검사 수행), 가격은 매일 생성되는 스냅샷을 기준으로 2시간마다, 유사 도메인은 30개씩 배치로 처리되어 매일 전체를 한 번 검사합니다. 알 수 없음 결과가 나오면 다음 시도가 더 빨리 이루어집니다.
구독 생성과 검사 실행은 무료입니다. 2xx 응답으로 웹훅 엔드포인트에 전달된 알림은 다른 모니터링 알림과 마찬가지로 건당 2 크레딧이 차감됩니다. 전달에 실패한 알림은 환불됩니다. 계정당 최대 100개의 구독을 만들 수 있으며, 이 중 유사 도메인용은 20개까지입니다.
구독을 만듭니다. type에 따라 적용되는 필드가 달라집니다. ssl, dns, typosquat는 domain, price는 tld, registrar, price_type, drop_percent, target_price를 사용합니다. 해당 유형에 맞지 않는 필드는 거부됩니다.
요청 본문
| 매개변수 | 유형 | 설명 |
|---|---|---|
| type | string | ssl, price, dns 또는 typosquat. 필수. |
| domain | string | ssl과 dns에서는 모니터링할 호스트명, typosquat에서는 브랜드 도메인. |
| tld | string | price에서 모니터링할 TLD. 예: com. |
| registrar | string | price용 등록기관 ID. 생략하면 최저가 등록기관을 모니터링합니다. |
| events | string[] | 받을 이벤트. 기본값은 해당 유형의 모든 이벤트입니다. |
| ssl_expiring_days | integer | ssl.expiring의 만료 전 일수: 30, 14, 7 또는 1. 기본값 14. |
| price_type | string | registration(기본값) 또는 renewal. |
| drop_percent | number | 이 비율 이상 하락하면 알림을 보냅니다. 1에서 95 사이. |
| target_price | number | USD 기준 가격이 이 금액 이하에 도달하면 알림을 보냅니다. 가격 구독에는 drop_percent, target_price 또는 둘 다 필요합니다. |
| record_types | string[] | dns에서 모니터링할 레코드 유형. 기본값은 A, AAAA, MX, NS, TXT, CNAME입니다. |
예제 요청
curl -X POST "https://domscan.net/v1/watchlist/alerts" \
-H "X-API-Key: $DOMSCAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "price",
"tld": "com",
"registrar": "porkbun",
"price_type": "renewal",
"drop_percent": 10,
"target_price": 9.5
}'
예제 응답
{
"subscription": {
"id": "mas_8c1f0e2d3b4a59687766554433221100",
"type": "price",
"target": "com",
"registrar": "porkbun",
"events": ["price.dropped"],
"status": "active",
"price_type": "renewal",
"drop_percent": 10,
"target_price": 9.5,
"currency": "USD",
"observed": null,
"last_check_status": null,
"next_check_at": "2026-10-10T12:00:00.000Z"
}
}
응답 필드
| 필드 | 유형 |
|---|---|
subscription |
object |
subscription.id |
string |
subscription.type |
string |
subscription.target |
string |
subscription.registrar |
string | null |
subscription.events[] |
string[] |
subscription.status |
string |
subscription.ssl_expiring_days |
integer | null |
subscription.price_type |
string | null |
subscription.drop_percent |
number | null |
subscription.target_price |
number | null |
subscription.currency |
string | null |
subscription.record_types[] |
string[] |
subscription.observed |
object | null |
subscription.last_check_at |
string | null |
subscription.last_check_status |
string | null |
subscription.last_error |
string | null |
subscription.next_check_at |
string | null |
subscription.created_at |
string |
subscription.updated_at |
string |
구독 목록을 최신 확인 증거와 검사 상태, 유형별 지원 이벤트, 검사 일정, 알림 가격과 함께 가져옵니다.
응답 필드
| 필드 | 유형 |
|---|---|
subscriptions[] |
object[] |
subscriptions[] |
object |
subscriptions[].id |
string |
subscriptions[].type |
string |
subscriptions[].target |
string |
subscriptions[].registrar |
string | null |
subscriptions[].events[] |
string[] |
subscriptions[].status |
string |
subscriptions[].ssl_expiring_days |
integer | null |
subscriptions[].price_type |
string | null |
subscriptions[].drop_percent |
number | null |
subscriptions[].target_price |
number | null |
subscriptions[].currency |
string | null |
subscriptions[].record_types[] |
string[] |
subscriptions[].observed |
object | null |
subscriptions[].last_check_at |
string | null |
subscriptions[].last_check_status |
string | null |
subscriptions[].last_error |
string | null |
subscriptions[].next_check_at |
string | null |
subscriptions[].created_at |
string |
subscriptions[].updated_at |
string |
total |
integer |
available_types |
object |
available_types.ssl[] |
string[] |
available_types.price[] |
string[] |
available_types.dns[] |
string[] |
available_types.typosquat[] |
string[] |
policy |
object |
policy.credits_per_delivered_alert |
integer |
policy.check_credits |
integer |
policy.unknown_checks_charged |
boolean |
policy.max_subscriptions |
integer |
policy.max_typosquat_subscriptions |
integer |
policy.ssl_expiring_days[] |
integer[] |
policy.default_ssl_expiring_days |
integer |
policy.record_types[] |
string[] |
policy.price_types[] |
string[] |
policy.check_interval_minutes |
object |
policy.confirmation_checks |
object |
예제 응답
{
"subscriptions": [
{
"id": "example-id",
"type": "ssl",
"target": "example",
"registrar": "example",
"events": [
"ssl.expiring"
],
"status": "active",
"ssl_expiring_days": 30,
"price_type": "registration",
"drop_percent": 0.5,
"target_price": 0.5,
"currency": "USD",
"record_types": [
"A"
],
"observed": {},
"last_check_at": "2026-08-27T12:00:00Z",
"last_check_status": "baseline",
"last_error": "example",
"next_check_at": "2026-08-27T12:00:00Z",
"created_at": "2026-08-27T12:00:00Z",
"updated_at": "2026-08-27T12:00:00Z"
}
],
"total": 1,
"available_types": {
"ssl": [
"ssl.expiring"
],
"price": [
"price.dropped"
],
"dns": [
"dns.changed"
],
"typosquat": [
"typosquat.detected"
]
},
"policy": {
"credits_per_delivered_alert": 2,
"check_credits": 0,
"unknown_checks_charged": false,
"max_subscriptions": 1,
"check_interval_minutes": {},
"max_typosquat_subscriptions": 1,
"ssl_expiring_days": [
1
],
"default_ssl_expiring_days": 1,
"record_types": [
"A"
],
"price_types": [
"registration"
],
"confirmation_checks": {}
}
}
구독 하나를 최신 확인 증거와 가장 최근 이벤트 20개와 함께 가져옵니다.
응답 필드
| 필드 | 유형 |
|---|---|
subscription |
object |
subscription.id |
string |
subscription.type |
string |
subscription.target |
string |
subscription.registrar |
string | null |
subscription.events[] |
string[] |
subscription.status |
string |
subscription.ssl_expiring_days |
integer | null |
subscription.price_type |
string | null |
subscription.drop_percent |
number | null |
subscription.target_price |
number | null |
subscription.currency |
string | null |
subscription.record_types[] |
string[] |
subscription.observed |
object | null |
subscription.last_check_at |
string | null |
subscription.last_check_status |
string | null |
subscription.last_error |
string | null |
subscription.next_check_at |
string | null |
subscription.created_at |
string |
subscription.updated_at |
string |
events[] |
object[] |
events[] |
object |
events[].id |
string |
events[].event_type |
string |
events[].detected_at |
string |
events[].published_at |
string | null |
events[].data |
object |
예제 응답
{
"subscription": {
"id": "example-id",
"type": "ssl",
"target": "example",
"registrar": "example",
"events": [
"ssl.expiring"
],
"status": "active",
"ssl_expiring_days": 30,
"price_type": "registration",
"drop_percent": 0.5,
"target_price": 0.5,
"currency": "USD",
"record_types": [
"A"
],
"observed": {},
"last_check_at": "2026-08-27T12:00:00Z",
"last_check_status": "baseline",
"last_error": "example",
"next_check_at": "2026-08-27T12:00:00Z",
"created_at": "2026-08-27T12:00:00Z",
"updated_at": "2026-08-27T12:00:00Z"
},
"events": [
{
"id": "example-id",
"event_type": "ssl.expiring",
"detected_at": "2026-08-27T12:00:00Z",
"published_at": "2026-08-27T12:00:00Z",
"data": {}
}
]
}
enabled로 구독을 일시 중지하거나 다시 시작하고, events, ssl_expiring_days, drop_percent, target_price, record_types를 변경합니다. 새 목표 가격은 이후의 가격 변동에 대해서만 알림을 보냅니다.
{ "enabled": false }
응답 필드
| 필드 | 유형 |
|---|---|
subscription |
object |
subscription.id |
string |
subscription.type |
string |
subscription.target |
string |
subscription.registrar |
string | null |
subscription.events[] |
string[] |
subscription.status |
string |
subscription.ssl_expiring_days |
integer | null |
subscription.price_type |
string | null |
subscription.drop_percent |
number | null |
subscription.target_price |
number | null |
subscription.currency |
string | null |
subscription.record_types[] |
string[] |
subscription.observed |
object | null |
subscription.last_check_at |
string | null |
subscription.last_check_status |
string | null |
subscription.last_error |
string | null |
subscription.next_check_at |
string | null |
subscription.created_at |
string |
subscription.updated_at |
string |
예제 응답
{
"subscription": {
"id": "example-id",
"type": "ssl",
"target": "example",
"registrar": "example",
"events": [
"ssl.expiring"
],
"status": "active",
"ssl_expiring_days": 30,
"price_type": "registration",
"drop_percent": 0.5,
"target_price": 0.5,
"currency": "USD",
"record_types": [
"A"
],
"observed": {},
"last_check_at": "2026-08-27T12:00:00Z",
"last_check_status": "baseline",
"last_error": "example",
"next_check_at": "2026-08-27T12:00:00Z",
"created_at": "2026-08-27T12:00:00Z",
"updated_at": "2026-08-27T12:00:00Z"
}
}
구독을 삭제합니다. 아직 전송되지 않은 이벤트는 폐기되며 과금되지 않습니다.
응답 필드
| 필드 | 유형 |
|---|---|
id |
string |
deleted |
boolean |
예제 응답
{
"id": "example-id",
"deleted": true
}
dns.changed 이벤트 예시
{
"id": "evt_2b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e",
"type": "dns.changed",
"created": "2026-10-10T12:15:00.000Z",
"data": {
"domain": "partner-shop.example",
"changes": [
{
"record_type": "MX",
"before": ["10 mx1.mail.example"],
"after": ["10 mx.other-mail.example"],
"added": ["10 mx.other-mail.example"],
"removed": ["10 mx1.mail.example"],
"first_seen_at": "2026-10-10T12:00:00.000Z"
}
],
"confirmed_checks": 2,
"confirmed_at": "2026-10-10T12:15:00.000Z",
"subscription_id": "mas_8c1f0e2d3b4a59687766554433221100"
}
}