Développeurs → Webhooks

Webhooks

NameOcean envoie un événement JSON signé à votre endpoint HTTPS lorsqu'il se passe quelque chose sur votre compte, afin que votre code puisse réagir au lieu d'interroger l'API en boucle.

Ajouter un endpoint

Dans Tableau de bord → Webhooks, avec l'API, ou en le demandant à votre IA via MCP (create_webhook). Choisissez des types d'événements, des groupes comme dns.*, ou tous les événements. La réponse contient le secret de signature (whsec_…).

curl
$ curl -X POST https://nameocean.net/api/v1/webhooks \
    -H "Authorization: Bearer $NAMEOCEAN_API_KEY" -H "Content-Type: application/json" \
    -d '{"url": "https://example.com/hooks/nameocean", "events": ["dns.*", "ssl.issued", "domain.expiring"]}'

L'URL doit être en https sur un serveur public. Répondez avec un code 2xx dans un délai de 10 secondes ; effectuez les traitements longs après avoir répondu.

Ce que vous recevez

POST https://example.com/hooks/nameocean
Content-Type: application/json
X-NameOcean-Event: dns.record.created
X-NameOcean-Delivery: whd_7c1e0f9a2b3d4e5f6a7b8c9d
X-NameOcean-Signature: t=1794300000,v1=5f2b…

{
  "id": "evt_3a9f1c2e4b5d6a7c8e9f0a1b",
  "type": "dns.record.created",
  "created": "2026-11-10T09:20:00+00:00",
  "data": {
    "zone": "example.com",
    "record": {"id": 4211, "type": "A", "hostname": "www", "ip": "203.0.113.10", "ttl": "1h"}
  }
}

L'identifiant de l'événement reste le même lorsqu'une livraison est retentée ou renvoyée : utilisez-le pour ignorer les événements déjà traités. Les événements peuvent arriver dans le désordre.

Vérifier la signature

t est l'horodatage Unix de la requête, v1 le HMAC-SHA256 en hexadécimal de t, d'un point et du corps brut, calculé avec votre secret comme clé. Calculez-le sur les octets bruts, avant d'analyser le JSON, effectuez la comparaison en temps constant et refusez les horodatages de plus de cinq minutes.

X-NameOcean-Signature
t=1794300000,v1=hex(HMAC_SHA256(secret, "1794300000." + raw_body))
Python
import hashlib, hmac, time

def verify(secret: str, header: str, body: bytes, tolerance: int = 300) -> bool:
    fields = dict(part.split("=", 1) for part in header.split(","))
    ts = int(fields["t"])
    if abs(time.time() - ts) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, fields.get("v1", ""))
Node.js
import crypto from "node:crypto";

export function verify(secret, header, rawBody, tolerance = 300) {
  const fields = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
  const ts = Number(fields.t);
  if (Math.abs(Date.now() / 1000 - ts) > tolerance) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${ts}.`).update(rawBody).digest("hex");
  const got = Buffer.from(fields.v1 || "", "hex");
  return got.length === 32 && crypto.timingSafeEqual(Buffer.from(expected, "hex"), got);
}
Go
func Verify(secret, header string, body []byte) bool {
	var ts int64
	var v1 string
	for _, part := range strings.Split(header, ",") {
		k, v, _ := strings.Cut(part, "=")
		switch k {
		case "t":
			ts, _ = strconv.ParseInt(v, 10, 64)
		case "v1":
			v1 = v
		}
	}
	if d := time.Now().Unix() - ts; d > 300 || d < -300 {
		return false
	}
	mac := hmac.New(sha256.New, []byte(secret))
	fmt.Fprintf(mac, "%d.", ts)
	mac.Write(body)
	return hmac.Equal([]byte(hex.EncodeToString(mac.Sum(nil))), []byte(v1))
}

Nouvelles tentatives et désactivation

Une livraison sans réponse, qui expire ou qui reçoit un 5xx, 408 ou 429 est retentée après 1m, 5m, 30m, 2h, 5h, 10h, 10h : 8 tentatives sur environ une journée. Tout autre code 4xx échoue immédiatement. Après 5 livraisons consécutives en échec définitif, l'endpoint est désactivé et vous recevez un e-mail ; réactivez-le dans le tableau de bord ou avec PATCH active: true. Chaque livraison, avec le code de statut et le début de votre réponse, est listée dans le tableau de bord et sur GET /api/v1/webhooks/{id}/deliveries, où vous pouvez en renvoyer une.

Événements

domain.registeredUn domaine a été enregistré dans votre compte.
domain.renewedLa date d'expiration d'un domaine a été repoussée (renouvellement).
domain.expiringUn domaine expire dans 30, 7 ou 1 jours.
domain.expiredUn domaine a expiré hier.
domain.nameservers.updatedLes serveurs de noms d'un domaine ont changé.
domain.transfer.startedUn transfert entrant ou sortant a été demandé auprès du registre.
domain.transfer.completedUn transfert est terminé.
domain.transfer.failedUn transfert a été refusé ou annulé.
dns.zone.createdUne zone DNS a été créée.
dns.zone.deletedUne zone DNS a été supprimée.
dns.record.createdUn enregistrement DNS a été ajouté.
dns.record.updatedUn enregistrement DNS a été modifié.
dns.record.deletedUn enregistrement DNS a été supprimé.
ssl.issuedUn certificat a été émis pour la première fois.
ssl.renewedUn certificat a été renouvelé.
ssl.expiringUn certificat expire dans 7 jours et n'a pas encore été renouvelé.
email.mailbox.createdUne boîte mail a été ajoutée à l'un de vos domaines de messagerie.
email.mailbox.deletedUne boîte mail et ses e-mails ont été supprimés.
email.forwarding.enabledLe transfert d'e-mails a été activé pour un domaine.
email.forwarding.disabledLe transfert d'e-mails a été désactivé pour un domaine, par vous ou parce que le domaine ne remplissait plus les conditions (le motif figure dans l'événement).
webhook.testEnvoyé lorsque vous cliquez sur Envoyer un test ; ignore le filtre d'événements du point de terminaison.

data contient le domaine ou la zone et l'objet : l'enregistrement (avec previous lors des mises à jour), la date d'expiration, les serveurs de noms (avec previous). Les champs exacts de chaque objet sont ceux de l'API REST.

Les e-mails entrants peuvent aussi être envoyés vers une URL : configurez-la pour chaque adresse dans Redirection d'e-mails. Ces envois utilisent les mêmes en-têtes et la même signature, avec X-NameOcean-Event: email.received.

Bon à savoir

  • NameOcean n'envoie qu'à des adresses publiques, vérifiées à nouveau à chaque livraison, et ne suit jamais les redirections.
  • Renouvelez le secret dans le tableau de bord s'il a fuité ; les événements sont immédiatement signés avec le nouveau.
  • Envoyer un test envoie immédiatement un événement webhook.test, quel que soit le filtre d'événements de l'endpoint.