Entwickler-Referenz

Domain-Beobachtungsliste

DomScan-API: Überwachen Sie Domänen auf Ablauf und Verfügbarkeitsänderungen. Erhalten Sie Benachrichtigungen, wenn registrierte Domänen verfügbar werden.

Domain-Beobachtungsliste

Überwachen Sie Domänen auf Ablauf und Verfügbarkeitsänderungen. Erhalten Sie Benachrichtigungen, wenn registrierte Domänen verfügbar werden.

Überwachung

Melden Sie sich mit Google an, um auf Ihre personalisierte Domain-Watchlist mit E-Mail-Benachrichtigungen, Webhooks und mehr zuzugreifen.

Erhalten Sie Benachrichtigungen per E-Mail, Telegram, Slack, Discord oder Webhook.

GET /v1/watchlist

Rufen Sie alle Domänen in Ihrer Beobachtungsliste ab.

Paginiert: Sende limit (1 bis 100) und gib next_cursor als cursor zurück. Antworten enthalten has_more und next_cursor. Ohne limit wird die gesamte Liste zurückgegeben. Siehe Pagination.

Beispielantwort

{
                "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"
                }

Antwortfelder

Feld Typ
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

Fügen Sie eine Domäne zu Ihrer Beobachtungsliste hinzu.

Anfragetext

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

Antwortfelder

Feld Typ
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

Beispielantwort

{
  "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

Von Watchlist entfernen

curl -X DELETE -H "X-API-Key: your-api-key" "https://domscan.net/v1/watchlist?domain=mydomain.com"

Antwortfelder

Feld Typ
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

Beispielantwort

{
  "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

Läuft bald ab

Paginiert: Sende limit (1 bis 100) und gib next_cursor als cursor zurück. Antworten enthalten has_more und next_cursor. Ohne limit wird die gesamte Liste zurückgegeben. Siehe Pagination.

Beispielantwort

{
                "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
                }

Antwortfelder

Feld Typ
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

Verfügbar

Paginiert: Sende limit (1 bis 100) und gib next_cursor als cursor zurück. Antworten enthalten has_more und next_cursor. Ohne limit wird die gesamte Liste zurückgegeben. Siehe Pagination.

Beispielantwort

{
                "available_domains": [
                {
                "domain": "startupdrop.ai",
                "status": "available",
                "last_checked": "2026-04-14T08:30:00Z",
                "check_count": 18
                }
                ],
                "total": 1,
                "message": "Diese Domains aus Ihrer Beobachtungsliste sind jetzt zur Registrierung verfügbar!"
                }

Antwortfelder

Feld Typ
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

Alarm-Webhooks

Empfangen Sie Überwachungsalarme als signierte JSON-POST-Anfragen an Ihren eigenen HTTPS-Endpunkten. Verwalten Sie Endpunkte mit einem API-Schlüssel oder, wenn Sie angemeldet sind, in den Monitor-Einstellungen.

Ereignistypen

MonitorEreignisse
Verfügbarkeit, Ablauf und Status der Watchlistdomain.available domain.expiring_30 domain.expiring_14 domain.expiring_7 domain.expiring_1 domain.status_change
Überwachung von Domain-Änderungendomain.dns_changed domain.certificate_changed domain.registration_changed domain.hosting_changed domain.technology_changed domain.email_security_changed
Markenüberwachung (neue ähnliche Registrierungen)brand.threat_detected
Alarm-Abonnements der Beobachtungsliste (Zertifikate, Preise, DNS-Einträge, ähnliche Domains)ssl.expiring ssl.expired ssl.changed price.dropped dns.changed typosquat.detected
Asynchrone Jobs (kostenlos, nur für Jobs, die mit notify_webhook erstellt wurden)job.completed job.failed job.cancelled
Testereignis (kostenlos)webhook.test

Leitfaden zur Webhook-Alarm-API lesen

Preise

Jeder mit einer 2xx-Antwort an einen Endpunkt zugestellte Alarm kostet 2 Credits. Die Credits werden unmittelbar vor dem ersten Versuch reserviert und erstattet, wenn die Zustellung fehlschlägt, abgebrochen oder der Endpunkt gelöscht wird. Testereignisse sind kostenlos. Reicht das Guthaben nicht aus, wird der Alarm übersprungen und nichts berechnet.

POST /v1/webhooks

Registriert einen HTTPS-Endpunkt. Die URL muss auf eine öffentliche Adresse auflösen. Lassen Sie events weg oder übergeben Sie ["*"], um jeden Ereignistyp zu empfangen. Das Signaturgeheimnis wird nur in dieser Antwort zurückgegeben.

Beispielanfrage

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"]
  }'

Beispielantwort

{
  "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_..."
}

Antwortfelder

Feld Typ
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

Listet Ihre Endpunkte mit Status, abonnierten Ereignissen, Fehleranzahl und den letzten vier Zeichen des Geheimnisses auf, zusammen mit den verfügbaren Ereignistypen und der Zustellungsrichtlinie.

Antwortfelder

Feld Typ
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

Beispielantwort

{
  "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

Pausiert oder aktiviert einen Endpunkt, ändert seine Ereignisse oder bearbeitet seine Beschreibung. Beim Aktivieren eines Endpunkts wird seine Fehleranzahl zurückgesetzt.

{ "enabled": true, "events": ["*"] }

Antwortfelder

Feld Typ
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

Beispielantwort

{
  "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

Löscht einen Endpunkt. Ausstehende Zustellungen werden abgebrochen und reservierte Credits erstattet.

Antwortfelder

Feld Typ
id string
deleted boolean

Beispielantwort

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

Sendet ein kostenloses Ereignis webhook.test und gibt das Ergebnis zurück. Testereignisse werden nicht wiederholt und zählen nicht für die automatische Pausierung.

Antwortfelder

Feld Typ
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

Beispielantwort

{
  "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

Ersetzt das Signaturgeheimnis eines Endpunkts, auch eines pausierten. Das neue Geheimnis wird nur in dieser Antwort zurückgegeben. In den nächsten 24 Stunden wird jede Zustellung mit dem neuen und dem vorherigen Geheimnis signiert. Die Rotation ist kostenlos.

Beispielanfrage

curl -X POST "https://domscan.net/v1/webhooks/whe_3f1c0a9b8e7d6c5b4a39281706f5e4d3/rotate-secret" \
  -H "X-API-Key: $DOMSCAN_API_KEY"

Beispielantwort

{
  "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
}

Antwortfelder

Feld Typ
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

Abfrageparameter

ParameterTypBeschreibung
limit integer Anzahl der zurückzugebenden Zustellungen, von 1 bis 100. Standard: 50.

Listet aktuelle Zustellungen mit Status, Versuchen, HTTP-Antwort, berechneten Credits und Erstattungen auf. Zustellungsprotokolle werden 30 Tage lang aufbewahrt.

Antwortfelder

Feld Typ
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

Beispielantwort

{
  "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"
    }
  ]
}

Anfrageformat

Jeder Alarm ist eine POST-Anfrage mit JSON-Body. Das Feld id bleibt für ein Ereignis gleich und wird in X-DomScan-Event-Id wiederholt, sodass Sie bereits verarbeitete Wiederholungen ignorieren können.

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"
  }
}

Signaturen prüfen

Berechnen Sie mit dem Geheimnis Ihres Endpunkts einen HMAC-SHA256 aus dem Wert von X-DomScan-Timestamp, einem Punkt und dem unveränderten Anfrage-Body. Vergleichen Sie das Ergebnis in konstanter Zeit mit X-DomScan-Signature und weisen Sie Anfragen zurück, deren Zeitstempel älter als 5 Minuten ist.

Das folgende Beispiel prüft jede Signatur im Header und funktioniert daher auch während einer Rotation des Geheimnisses weiter.

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);
  });
}

Signaturgeheimnis rotieren

Während der 24-stündigen Übergangsfrist nach einer Rotation enthält X-DomScan-Signature zwei durch ein Komma getrennte Signaturen, das neue Geheimnis zuerst, wie unten gezeigt. Akzeptieren Sie eine Anfrage, wenn ein Eintrag zu einem Geheimnis passt, dem Sie vertrauen, setzen Sie das neue Geheimnis ein und vertrauen Sie dann dem alten nicht mehr. Wenn Sie während der Übergangsfrist erneut rotieren, wird das ältere vorherige Geheimnis sofort außer Kraft gesetzt.

X-DomScan-Signature: sha256=<new>,sha256=<previous>

Wiederholungen und automatische Pausierung

Geben Sie innerhalb von 8 Sekunden einen beliebigen 2xx-Status zurück, um einen Alarm zu bestätigen. Weiterleitungen, andere Statuscodes und Zeitüberschreitungen werden mit exponentiellem Backoff wiederholt (1, 4, 16, 64 und 256 Minuten), insgesamt bis zu 6 Versuche. Nach 15 aufeinanderfolgenden fehlgeschlagenen Versuchen wird der Endpunkt pausiert; aktivieren Sie ihn per PATCH oder in den Monitor-Einstellungen wieder.

Wird ein Endpunkt nach wiederholten Fehlern pausiert, erhält der Inhaber des Endpunkts eine E-Mail mit dem Host des Endpunkts, dem letzten Fehler und einem Link zu den Monitor-Einstellungen. Beheben Sie das Problem am Endpunkt und aktivieren Sie ihn dann wieder in den Monitor-Einstellungen oder mit PATCH und enabled auf true. Beim Aktivieren wird der Fehlerzähler auf null zurückgesetzt.

Alarm-Abonnements der Beobachtungsliste

Abonnieren Sie für ein beobachtetes Element die gewünschten Alarme. Jedes Abonnement beobachtet einen Hostnamen, eine TLD oder eine Markendomain, und Sie wählen, welche Ereignisse Sie erhalten. Die Ereignisse gehen an Ihre signierten Webhook-Endpunkte und an Ihre Alarme in der App.

TypEreignisseWann es ausgelöst wird
sslssl.expiring ssl.expired ssl.changedssl.expiring, wenn das von einem Hostnamen ausgelieferte Zertifikat innerhalb von ssl_expiring_days abläuft (30, 14, 7 oder 1, Standard 14), einmal pro Zertifikat und Schwellenwert. ssl.expired einmal pro abgelaufenem Zertifikat. ssl.changed, wenn bei zwei aufeinanderfolgenden Prüfungen ein neuer Zertifikat-Fingerprint gesehen wird; die Payload gibt an, ob sich der Aussteller geändert hat.
priceprice.droppedWenn der Registrierungs- oder Verlängerungspreis einer TLD, bei einem Registrar oder beim günstigsten, seit dem letzten Alarm um mindestens drop_percent vom höchsten Preis fällt oder target_price oder weniger erreicht. Die Preise stammen aus dem täglichen Preis-Snapshot, und jeder Snapshot wird einmal ausgewertet.
dnsdns.changedWenn ein beobachteter Eintragstyp (A, AAAA, MX, NS, TXT oder CNAME) eines beliebigen Hostnamens bei zwei aufeinanderfolgenden bestätigten Abfragen dieselbe neue Antwort liefert.
typosquattyposquat.detectedWenn eine ähnliche Domain zur Markendomain neu registriert wird, bestätigt durch eine maßgebliche Registrierungsabfrage. Der erste vollständige Durchlauf über die ähnlichen Domains legt die Ausgangsbasis fest und löst keinen Alarm aus.

Nur eindeutige Belege lösen ein Ereignis aus. Ein fehlgeschlagener TLS-Handshake, eine DNS-Abfrage, die fehlschlägt oder in ein Timeout läuft, ein fehlender Preis und eine blockierte oder ratenbegrenzte Abfrage gelten als unbekannt: Sie ändern nichts und lösen nie einen Alarm oder eine Abbuchung aus. Die erste bestätigte Prüfung eines Abonnements legt dessen Ausgangsbasis fest.

Die Prüfungen laufen automatisch: Zertifikate alle 12 Stunden, DNS-Einträge stündlich (mit einer Bestätigungsprüfung 15 Minuten nach der ersten Erkennung einer Änderung), Preise alle 2 Stunden gegen den täglichen Snapshot und ähnliche Domains in Batches zu 30 mit einem vollständigen Durchlauf pro Tag. Nach einer unbekannten Prüfung erfolgt der nächste Versuch früher.

Das Anlegen von Abonnements und das Ausführen von Prüfungen ist kostenlos. Jeder an einen Webhook-Endpunkt zugestellte Alarm mit 2xx-Antwort kostet 2 Credits, wie jeder andere Monitoring-Alarm. Fehlgeschlagene Zustellungen werden erstattet, und ein Konto kann bis zu 100 Abonnements haben, davon 20 für ähnliche Domains.

POST /v1/watchlist/alerts

Legt ein Abonnement an. type bestimmt, welche Felder gelten: domain für ssl, dns und typosquat; tld, registrar, price_type, drop_percent und target_price für price. Felder, die nicht zum Typ passen, werden abgelehnt.

Anfragetext

ParameterTypBeschreibung
typestringssl, price, dns oder typosquat. Erforderlich.
domainstringZu beobachtender Hostname für ssl und dns oder die Markendomain für typosquat.
tldstringZu beobachtende TLD für price, zum Beispiel com.
registrarstringRegistrar-ID für price. Weglassen, um den günstigsten Registrar zu beobachten.
eventsstring[]Zu empfangende Ereignisse. Standardmäßig alle Ereignisse des Typs.
ssl_expiring_daysintegerTage vor Ablauf für ssl.expiring: 30, 14, 7 oder 1. Standard 14.
price_typestringregistration (Standard) oder renewal.
drop_percentnumberAlarm bei einem Rückgang um mindestens diesen Prozentsatz, 1 bis 95.
target_pricenumberAlarm, wenn der Preis in USD diesen Betrag oder weniger erreicht. Ein Preis-Abonnement benötigt drop_percent, target_price oder beides.
record_typesstring[]Zu beobachtende Eintragstypen für dns. Standardmäßig A, AAAA, MX, NS, TXT und CNAME.

Beispielanfrage

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
  }'

Beispielantwort

{
  "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"
  }
}

Antwortfelder

Feld Typ
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

Listet Ihre Abonnements mit den neuesten bestätigten Belegen und dem Prüfstatus, den von jedem Typ unterstützten Ereignissen, dem Prüfplan und dem Alarmpreis auf.

Antwortfelder

Feld Typ
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

Beispielantwort

{
  "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

Ruft ein Abonnement mit den neuesten bestätigten Belegen und seinen 20 jüngsten Ereignissen ab.

Antwortfelder

Feld Typ
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

Beispielantwort

{
  "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

Pausiert oder setzt ein Abonnement mit enabled fort oder ändert dessen events, ssl_expiring_days, drop_percent, target_price oder record_types. Ein neuer Zielpreis löst erst bei einer späteren Preisbewegung einen Alarm aus.

{ "enabled": false }

Antwortfelder

Feld Typ
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

Beispielantwort

{
  "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

Löscht ein Abonnement. Noch nicht gesendete Ereignisse werden verworfen und nie berechnet.

Antwortfelder

Feld Typ
id string
deleted boolean

Beispielantwort

{
  "id": "example-id",
  "deleted": true
}

Beispiel für ein dns.changed-Ereignis

{
  "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"
  }
}