개발자 참고자료

도메인 관찰 목록

DomScan API로 도메인의 만료 및 가용성 변경을 모니터링합니다. 등록된 도메인이 사용 가능해지면 알림을 받습니다.

도메인 관찰 목록

도메인의 만료 및 가용성 변경을 모니터링합니다. 등록된 도메인이 사용 가능해지면 알림을 받습니다.

모니터

Google으로 로그인하여 이메일 알림, 웹훅 등을 포함한 개인화된 도메인 감시 목록에 접근합니다.

이메일, Telegram, Slack, Discord 또는 Webhook을 통해 알림을 받습니다.

GET /v1/watchlist

관찰 목록의 모든 도메인을 조회합니다.

페이지네이션 지원: 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
POST /v1/watchlist

관찰 목록에 도메인을 추가합니다.

요청 본문

{
                "domain": "mydomain.com",
                "notify_email": "[email protected]"
                }

응답 필드

필드 유형
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
}
DELETE /v1/watchlist?domain=mydomain.com

관심 목록에서 제거

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
}
GET /v1/watchlist/expiring?days=30

곧 만료

페이지네이션 지원: 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
GET /v1/watchlist/available

사용 가능

페이지네이션 지원: 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

웹훅 알림 API 가이드 읽기

요금

2xx 응답으로 엔드포인트에 전달된 알림은 건당 2 크레딧입니다. 크레딧은 첫 번째 시도 직전에 예약되며, 전달이 실패하거나 취소되거나 엔드포인트가 삭제되면 환불됩니다. 테스트 이벤트는 무료입니다. 잔액이 부족하면 알림을 건너뛰며 요금은 청구되지 않습니다.

POST /v1/webhooks

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
GET /v1/webhooks

엔드포인트를 상태, 구독 중인 이벤트, 실패 횟수, 시크릿의 마지막 네 글자와 함께 나열하며, 사용 가능한 이벤트 유형과 전달 정책도 함께 반환합니다.

응답 필드

필드 유형
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"
}
PATCH /v1/webhooks/:webhook_id

엔드포인트를 일시 중지하거나 활성화하고, 이벤트를 변경하거나 설명을 수정합니다. 엔드포인트를 활성화하면 실패 횟수가 초기화됩니다.

{ "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"
  }
}
DELETE /v1/webhooks/:webhook_id

엔드포인트를 삭제합니다. 대기 중인 전달은 취소되고 예약된 크레딧은 환불됩니다.

응답 필드

필드 유형
id string
deleted boolean

예제 응답

{
  "id": "example-id",
  "deleted": true
}
POST /v1/webhooks/:webhook_id/test

무료 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
}
POST /v1/webhooks/:webhook_id/rotate-secret

일시 중지된 엔드포인트를 포함해 엔드포인트의 서명 시크릿을 교체합니다. 새 시크릿은 이 응답에서만 반환됩니다. 이후 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
GET /v1/webhooks/:webhook_id/deliveries

쿼리 매개변수

매개변수유형설명
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 또는 브랜드 도메인 하나를 모니터링하며, 받을 이벤트를 직접 선택할 수 있습니다. 이벤트는 서명된 웹훅 엔드포인트와 앱 내 알림으로 전달됩니다.

유형이벤트발생 시점
sslssl.expiring ssl.expired ssl.changedssl.expiring은 호스트명이 제공하는 인증서가 ssl_expiring_days (30, 14, 7 또는 1, 기본값 14) 이내에 만료될 때 인증서와 임계값마다 한 번 발생합니다. ssl.expired는 만료된 인증서마다 한 번 발생합니다. ssl.changed는 새 인증서 핑거프린트가 연속 2회 확인에서 확인될 때 발생하며, 페이로드에 발급자가 변경되었는지 여부가 포함됩니다.
priceprice.droppedTLD의 등록 또는 갱신 가격이 특정 등록기관 또는 최저가 등록기관에서 마지막 알림 이후의 최고 가격보다 drop_percent 이상 떨어지거나 target_price 이하에 도달할 때 발생합니다. 가격은 매일 생성되는 가격 스냅샷에서 가져오며, 각 스냅샷은 한 번만 평가됩니다.
dnsdns.changed모니터링 중인 레코드 유형(A, AAAA, MX, NS, TXT 또는 CNAME)이 어떤 호스트명에서든 연속 2회 확인된 조회에서 동일한 새 응답을 반환할 때 발생합니다.
typosquattyposquat.detected브랜드 도메인과 유사한 도메인이 새로 등록되고 공식 등록 조회로 확인될 때 발생합니다. 유사 도메인에 대한 첫 전체 검사는 기준선만 설정하며 알림을 보내지 않습니다.

정확한 증거가 있을 때만 이벤트가 발생합니다. TLS 핸드셰이크 실패, 실패하거나 시간 초과된 DNS 조회, 누락된 가격, 차단되거나 요청 제한된 조회는 알 수 없음으로 처리되며, 아무것도 변경하지 않고 알림이나 과금도 발생하지 않습니다. 구독의 첫 번째 확인된 검사가 기준선을 설정합니다.

검사는 자동으로 실행됩니다. 인증서는 12시간마다, DNS 레코드는 1시간마다(변경이 처음 감지되고 15분 후 확인 검사 수행), 가격은 매일 생성되는 스냅샷을 기준으로 2시간마다, 유사 도메인은 30개씩 배치로 처리되어 매일 전체를 한 번 검사합니다. 알 수 없음 결과가 나오면 다음 시도가 더 빨리 이루어집니다.

구독 생성과 검사 실행은 무료입니다. 2xx 응답으로 웹훅 엔드포인트에 전달된 알림은 다른 모니터링 알림과 마찬가지로 건당 2 크레딧이 차감됩니다. 전달에 실패한 알림은 환불됩니다. 계정당 최대 100개의 구독을 만들 수 있으며, 이 중 유사 도메인용은 20개까지입니다.

POST /v1/watchlist/alerts

구독을 만듭니다. type에 따라 적용되는 필드가 달라집니다. ssl, dns, typosquat는 domain, price는 tld, registrar, price_type, drop_percent, target_price를 사용합니다. 해당 유형에 맞지 않는 필드는 거부됩니다.

요청 본문

매개변수유형설명
typestringssl, price, dns 또는 typosquat. 필수.
domainstringssl과 dns에서는 모니터링할 호스트명, typosquat에서는 브랜드 도메인.
tldstringprice에서 모니터링할 TLD. 예: com.
registrarstringprice용 등록기관 ID. 생략하면 최저가 등록기관을 모니터링합니다.
eventsstring[]받을 이벤트. 기본값은 해당 유형의 모든 이벤트입니다.
ssl_expiring_daysintegerssl.expiring의 만료 전 일수: 30, 14, 7 또는 1. 기본값 14.
price_typestringregistration(기본값) 또는 renewal.
drop_percentnumber이 비율 이상 하락하면 알림을 보냅니다. 1에서 95 사이.
target_pricenumberUSD 기준 가격이 이 금액 이하에 도달하면 알림을 보냅니다. 가격 구독에는 drop_percent, target_price 또는 둘 다 필요합니다.
record_typesstring[]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
GET /v1/watchlist/alerts

구독 목록을 최신 확인 증거와 검사 상태, 유형별 지원 이벤트, 검사 일정, 알림 가격과 함께 가져옵니다.

응답 필드

필드 유형
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": {}
  }
}
GET /v1/watchlist/alerts/:subscription_id

구독 하나를 최신 확인 증거와 가장 최근 이벤트 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": {}
    }
  ]
}
PATCH /v1/watchlist/alerts/:subscription_id

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"
  }
}
DELETE /v1/watchlist/alerts/:subscription_id

구독을 삭제합니다. 아직 전송되지 않은 이벤트는 폐기되며 과금되지 않습니다.

응답 필드

필드 유형
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"
  }
}