Ontwikkelaars → Webhooks

Webhooks

NameOcean stuurt een ondertekend JSON-event naar uw HTTPS-endpoint wanneer er iets gebeurt in uw account, zodat uw code kan reageren in plaats van te pollen.

Endpoint toevoegen

Via Dashboard → Webhooks, met de API, of door het uw AI te vragen via MCP (create_webhook). Kies eventtypes, groepen zoals dns.*, of alle events. Het antwoord bevat het ondertekeningsgeheim (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"]}'

De URL moet https zijn op een openbare server. Antwoord binnen 10 seconden met een willekeurige 2xx; voer trage taken uit na het antwoorden.

Wat u ontvangt

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

Het event-id blijft hetzelfde wanneer een aflevering opnieuw wordt geprobeerd of opnieuw wordt verzonden: gebruik het om events over te slaan die u al hebt verwerkt. Events kunnen in een andere volgorde binnenkomen.

De handtekening verifiëren

t is de Unix-tijd van het verzoek, v1 de hexadecimale HMAC-SHA256 van t, een punt en de onbewerkte body, met uw geheime sleutel als sleutel. Bereken deze over de onbewerkte bytes, vóórdat u de JSON parseert, vergelijk in constante tijd en weiger tijdstempels die ouder zijn dan vijf minuten.

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

Nieuwe pogingen en uitschakelen

Een aflevering die geen antwoord, een time-out, een 5xx, 408 of 429 krijgt, wordt opnieuw geprobeerd na 1m, 5m, 30m, 2h, 5h, 10h, 10h: 8 pogingen verspreid over ongeveer een dag. Elke andere 4xx mislukt meteen. Nadat 5 afleveringen op rij definitief zijn mislukt, wordt het endpoint uitgeschakeld en ontvangt u een e-mail; schakel het weer in via het dashboard of met PATCH active: true. Elke aflevering, met de statuscode en het begin van uw antwoord, wordt weergegeven in het dashboard en op GET /api/v1/webhooks/{id}/deliveries, waar u er een opnieuw kunt verzenden.

Events

domain.registeredEr is een domein geregistreerd in uw account.
domain.renewedDe vervaldatum van een domein is verschoven (verlenging).
domain.expiringEen domein verloopt over 30, 7 of 1 dag(en).
domain.expiredEen domein is gisteren verlopen.
domain.nameservers.updatedDe nameservers van een domein zijn gewijzigd.
domain.transfer.startedEr is een inkomende of uitgaande verhuizing aangevraagd bij de registry.
domain.transfer.completedEen verhuizing is voltooid.
domain.transfer.failedEen verhuizing is afgewezen of geannuleerd.
dns.zone.createdEr is een DNS-zone aangemaakt.
dns.zone.deletedEr is een DNS-zone verwijderd.
dns.record.createdEr is een DNS-record toegevoegd.
dns.record.updatedEr is een DNS-record gewijzigd.
dns.record.deletedEr is een DNS-record verwijderd.
ssl.issuedEr is voor het eerst een certificaat uitgegeven.
ssl.renewedEr is een certificaat verlengd.
ssl.expiringEen certificaat verloopt over 7 dagen en is nog niet verlengd.
email.mailbox.createdEr is een mailbox toegevoegd aan een van uw maildomeinen.
email.mailbox.deletedEen mailbox en de bijbehorende e-mail zijn verwijderd.
email.forwarding.enabledE-mail doorsturen is ingeschakeld voor een domein.
email.forwarding.disabledE-mail doorsturen is uitgeschakeld voor een domein, door u of omdat het domein niet langer in aanmerking kwam (de reden staat in de gebeurtenis).
webhook.testWordt verzonden wanneer u op Test verzenden klikt; negeert het gebeurtenisfilter van het endpoint.

data bevat het domein of de zone en het object: het record (met previous bij updates), de vervaldatum, de nameservers (met previous). De exacte velden van elk object zijn die van de REST API.

Inkomende e-mail kan ook naar een URL worden gepost: stel dit per adres in via E-mail doorsturen. Die posts gebruiken dezelfde headers en handtekening, met X-NameOcean-Event: email.received.

Goed om te weten

  • NameOcean post alleen naar openbare adressen, wat bij elke aflevering opnieuw wordt gecontroleerd, en volgt nooit redirects.
  • Vernieuw het geheim in het dashboard als het uitlekt; events worden direct met het nieuwe ondertekend.
  • Test verzenden post direct een webhook.test-event, ongeacht het eventfilter van het endpoint.