Liste de surveillance des domaines

Surveillez les domaines pour les changements d'expiration et de disponibilité. Recevez des alertes lorsque les domaines enregistrés deviennent disponibles.

Surveiller

Connectez-vous avec Google pour accéder à votre liste de surveillance de domaine personnalisée avec alertes e-mail, webhooks et bien plus.

Recevez des notifications par e-mail, Telegram, Slack, Discord ou Webhook.

GET /v1/watchlist

Obtenez tous les domaines de votre liste de surveillance.

Paginé : envoyez limit (de 1 à 100) et renvoyez next_cursor comme cursor. Les réponses incluent has_more et next_cursor. Sans limit, la liste complète est renvoyée. Voir la pagination.

Exemple de réponse

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

Champs de réponse

Champ Type
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

Ajoutez un domaine à votre liste de surveillance.

Corps de la requête

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

Champs de réponse

Champ Type
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

Exemple de réponse

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

Retirer de la liste de surveillance

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

Champs de réponse

Champ Type
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

Exemple de réponse

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

Expire bientôt

Paginé : envoyez limit (de 1 à 100) et renvoyez next_cursor comme cursor. Les réponses incluent has_more et next_cursor. Sans limit, la liste complète est renvoyée. Voir la pagination.

Exemple de réponse

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

Champs de réponse

Champ Type
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

Disponible

Paginé : envoyez limit (de 1 à 100) et renvoyez next_cursor comme cursor. Les réponses incluent has_more et next_cursor. Sans limit, la liste complète est renvoyée. Voir la pagination.

Exemple de réponse

{
                "available_domains": [
                {
                "domain": "startupdrop.ai",
                "status": "available",
                "last_checked": "2026-04-14T08:30:00Z",
                "check_count": 18
                }
                ],
                "total": 1,
                "message": "Ces domaines de votre liste de surveillance sont maintenant disponibles à l'enregistrement !"
                }

Champs de réponse

Champ Type
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

Webhooks d’alertes

Recevez les alertes de surveillance sous forme de requêtes POST JSON signées sur vos propres endpoints HTTPS. Gérez les endpoints avec une clé d’API, ou depuis les paramètres de Monitor une fois connecté.

Types d’événements

MonitorÉvénements
Disponibilité, expiration et statut de la liste de surveillancedomain.available domain.expiring_30 domain.expiring_14 domain.expiring_7 domain.expiring_1 domain.status_change
Surveillance des changements de domainedomain.dns_changed domain.certificate_changed domain.registration_changed domain.hosting_changed domain.technology_changed domain.email_security_changed
Surveillance de marque (nouveaux enregistrements similaires)brand.threat_detected
Abonnements d'alerte de la liste de surveillance (certificats, prix, enregistrements DNS, domaines similaires)ssl.expiring ssl.expired ssl.changed price.dropped dns.changed typosquat.detected
Tâches asynchrones (gratuit, uniquement pour les tâches créées avec notify_webhook)job.completed job.failed job.cancelled
Événement de test (gratuit)webhook.test

Lire le guide de l’API d’alertes webhook

Tarifs

Chaque alerte livrée à un endpoint avec une réponse 2xx coûte 2 crédits. Les crédits sont réservés juste avant la première tentative et remboursés si la livraison échoue, est annulée ou si l’endpoint est supprimé. Les événements de test sont gratuits. Lorsque le solde est insuffisant, l’alerte est ignorée et rien n’est facturé.

POST /v1/webhooks

Enregistre un endpoint HTTPS. L’URL doit pointer vers une adresse publique. Omettez events, ou transmettez ["*"], pour recevoir tous les types d’événements. Le secret de signature n’est renvoyé que dans cette réponse.

Exemple de requête

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

Exemple de réponse

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

Champs de réponse

Champ Type
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

Liste vos endpoints avec leur statut, les événements souscrits, le nombre d’échecs et les quatre derniers caractères du secret, ainsi que les types d’événements disponibles et la politique de livraison.

Champs de réponse

Champ Type
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

Exemple de réponse

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

Met en pause ou active un endpoint, modifie ses événements ou sa description. L’activation d’un endpoint réinitialise son nombre d’échecs.

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

Champs de réponse

Champ Type
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

Exemple de réponse

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

Supprime un endpoint. Les livraisons en attente sont annulées et les crédits réservés sont remboursés.

Champs de réponse

Champ Type
id string
deleted boolean

Exemple de réponse

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

Envoie un événement webhook.test gratuit et renvoie le résultat. Les événements de test ne sont pas réessayés et ne comptent pas pour la mise en pause automatique.

Champs de réponse

Champ Type
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

Exemple de réponse

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

Remplace le secret de signature d’un endpoint, y compris s’il est en pause. Le nouveau secret n’est renvoyé que dans cette réponse. Pendant les 24 heures suivantes, chaque livraison est signée avec le nouveau secret et avec le précédent. La rotation est gratuite.

Exemple de requête

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

Exemple de réponse

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

Champs de réponse

Champ Type
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

Paramètres de requête

ParamètreTypeDescription
limit integer Nombre de livraisons à renvoyer, de 1 à 100. Par défaut : 50.

Liste les livraisons récentes avec leur statut, leurs tentatives, la réponse HTTP, les crédits facturés et les remboursements. Les enregistrements de livraison sont conservés 30 jours.

Champs de réponse

Champ Type
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

Exemple de réponse

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

Format de la requête

Chaque alerte est une requête POST avec un corps JSON. Le champ id reste identique pour un même événement et est repris dans X-DomScan-Event-Id, ce qui vous permet d’ignorer les nouvelles tentatives déjà traitées.

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

Vérifier les signatures

Calculez un HMAC-SHA256 de la valeur de X-DomScan-Timestamp, d’un point et du corps brut de la requête, avec le secret de votre endpoint. Comparez le résultat à X-DomScan-Signature en temps constant et rejetez les requêtes dont l’horodatage date de plus de 5 minutes.

L’exemple ci-dessous vérifie chaque signature de l’en-tête, il continue donc de fonctionner pendant une rotation de secret.

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

Faire pivoter un secret de signature

Pendant la période de grâce de 24 heures qui suit une rotation, X-DomScan-Signature contient deux signatures séparées par une virgule, le nouveau secret en premier, comme illustré ci-dessous. Acceptez une requête dès qu’une entrée correspond à un secret de confiance, déployez le nouveau secret, puis cessez de faire confiance à l’ancien. Une nouvelle rotation pendant la période de grâce met aussitôt fin à l’ancien secret précédent.

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

Nouvelles tentatives et mise en pause automatique

Renvoyez un statut 2xx dans un délai de 8 secondes pour accuser réception d’une alerte. Les redirections, les autres codes de statut et les délais dépassés sont réessayés avec un backoff exponentiel (1, 4, 16, 64 et 256 minutes), jusqu’à 6 tentatives au total. Après 15 tentatives échouées consécutives, l’endpoint est mis en pause ; réactivez-le avec PATCH ou depuis les paramètres de Monitor.

Lorsqu’un endpoint est mis en pause après des échecs répétés, son propriétaire reçoit un e-mail avec l’hôte de l’endpoint, la dernière erreur et un lien vers les paramètres de Monitor. Corrigez l’endpoint, puis réactivez-le depuis les paramètres de Monitor ou avec PATCH et enabled défini sur true. La réactivation remet le compteur d’échecs à zéro.

Abonnements d'alerte de la liste de surveillance

Abonnez un élément surveillé aux alertes de votre choix. Chaque abonnement surveille un nom d'hôte, un TLD ou un domaine de marque, et vous choisissez les événements à recevoir. Les événements sont envoyés à vos endpoints de webhook signés et à vos alertes dans l'application.

TypeÉvénementsQuand il se déclenche
sslssl.expiring ssl.expired ssl.changedssl.expiring lorsque le certificat servi par un nom d'hôte expire dans les ssl_expiring_days jours (30, 14, 7 ou 1, 14 par défaut), une fois par certificat et par seuil. ssl.expired une fois par certificat expiré. ssl.changed lorsqu'une nouvelle empreinte de certificat est observée lors de deux vérifications consécutives ; le payload indique si l'émetteur a changé.
priceprice.droppedLorsque le prix d'enregistrement ou de renouvellement d'un TLD, chez un registrar donné ou chez le moins cher, baisse d'au moins drop_percent par rapport au prix le plus élevé depuis la dernière alerte, ou atteint target_price ou moins. Les prix proviennent de l'instantané quotidien des prix, et chaque instantané est évalué une seule fois.
dnsdns.changedLorsqu'un type d'enregistrement surveillé (A, AAAA, MX, NS, TXT ou CNAME) de n'importe quel nom d'hôte renvoie la même nouvelle réponse lors de deux requêtes confirmées consécutives.
typosquattyposquat.detectedLorsqu'un domaine similaire au domaine de marque est nouvellement enregistré, confirmé par une requête d'enregistrement faisant autorité. Le premier passage complet sur les domaines similaires fixe la référence et ne déclenche pas d'alerte.

Seules des preuves exactes déclenchent un événement. Un handshake TLS échoué, une requête DNS qui échoue ou expire, un prix manquant et une requête bloquée ou limitée en débit sont inconnus : ils ne changent rien et ne déclenchent jamais d'alerte ni de facturation. La première vérification confirmée d'un abonnement fixe sa référence.

Les vérifications s'exécutent automatiquement : certificats toutes les 12 heures, enregistrements DNS toutes les heures (avec une vérification de confirmation 15 minutes après la première détection d'un changement), prix toutes les 2 heures par rapport à l'instantané quotidien, et domaines similaires par lots de 30 avec un passage complet chaque jour. Après une vérification inconnue, la tentative suivante arrive plus tôt.

La création d'abonnements et l'exécution des vérifications sont gratuites. Chaque alerte livrée à un endpoint de webhook avec une réponse 2xx coûte 2 crédits, comme toute autre alerte de surveillance. Les livraisons échouées sont remboursées, et un compte peut avoir jusqu'à 100 abonnements, dont 20 pour les domaines similaires.

POST /v1/watchlist/alerts

Crée un abonnement. type détermine les champs applicables : domain pour ssl, dns et typosquat ; tld, registrar, price_type, drop_percent et target_price pour price. Les champs qui ne s'appliquent pas au type sont rejetés.

Corps de la requête

ParamètreTypeDescription
typestringssl, price, dns ou typosquat. Obligatoire.
domainstringNom d'hôte à surveiller pour ssl et dns, ou domaine de marque pour typosquat.
tldstringTLD à surveiller pour price, par exemple com.
registrarstringIdentifiant du registrar pour price. Omettez-le pour surveiller le registrar le moins cher.
eventsstring[]Événements à recevoir. Par défaut, tous les événements du type.
ssl_expiring_daysintegerNombre de jours avant l'expiration pour ssl.expiring : 30, 14, 7 ou 1. 14 par défaut.
price_typestringregistration (par défaut) ou renewal.
drop_percentnumberAlerte en cas de baisse d'au moins ce pourcentage, de 1 à 95.
target_pricenumberAlerte lorsque le prix en USD atteint ce montant ou moins. Un abonnement de prix nécessite drop_percent, target_price ou les deux.
record_typesstring[]Types d'enregistrement à surveiller pour dns. Par défaut A, AAAA, MX, NS, TXT et CNAME.

Exemple de requête

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

Exemple de réponse

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

Champs de réponse

Champ Type
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

Liste vos abonnements avec leurs dernières preuves confirmées et l'état des vérifications, les événements pris en charge par chaque type, le calendrier des vérifications et le prix de l'alerte.

Champs de réponse

Champ Type
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

Exemple de réponse

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

Récupère un abonnement avec ses dernières preuves confirmées et ses 20 événements les plus récents.

Champs de réponse

Champ Type
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

Exemple de réponse

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

Met en pause ou reprend un abonnement avec enabled, ou modifie ses events, ssl_expiring_days, drop_percent, target_price ou record_types. Un nouveau prix cible ne déclenche une alerte que lors d'un mouvement de prix ultérieur.

{ "enabled": false }

Champs de réponse

Champ Type
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

Exemple de réponse

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

Supprime un abonnement. Les événements qu'il n'a pas encore envoyés sont abandonnés et jamais facturés.

Champs de réponse

Champ Type
id string
deleted boolean

Exemple de réponse

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

Exemple d'événement 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"
  }
}