Desarrolladores → Webhooks
NameOcean envía un evento JSON firmado a su endpoint HTTPS cuando ocurre algo en su cuenta, para que su código pueda reaccionar en lugar de consultar periódicamente.
En Panel → Webhooks, con la API, o pidiéndoselo a su IA a través de MCP (create_webhook). Elija tipos de eventos, grupos como dns.*, o todos los eventos. La respuesta incluye el secreto de firma (whsec_…).
$ 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"]}'
La URL debe ser https en un servidor público. Responda con cualquier 2xx en un plazo de 10 segundos; realice las tareas lentas después de responder.
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"}
}
}
El id del evento se mantiene igual cuando una entrega se reintenta o se reenvía: úselo para omitir los eventos que ya haya procesado. Los eventos pueden llegar desordenados.
t es la hora Unix de la solicitud y v1 es el HMAC-SHA256 en hexadecimal de t, un punto y el cuerpo sin procesar, firmado con su clave secreta. Calcúlelo sobre los bytes sin procesar, antes de analizar el JSON, compárelo en tiempo constante y rechace las marcas de tiempo con más de cinco minutos de antigüedad.
t=1794300000,v1=hex(HMAC_SHA256(secret, "1794300000." + raw_body))
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", ""))
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);
}
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))
}
Una entrega que no recibe respuesta, agota el tiempo de espera o recibe un 5xx, 408 o 429 se reintenta tras 1m, 5m, 30m, 2h, 5h, 10h, 10h: 8 intentos a lo largo de aproximadamente un día. Cualquier otro 4xx falla de inmediato. Cuando 5 entregas consecutivas fallan definitivamente, el endpoint se desactiva y usted recibe un correo electrónico; vuelva a activarlo en el panel o con PATCH active: true. Cada entrega, con el código de estado y el inicio de su respuesta, aparece en el panel y en GET /api/v1/webhooks/{id}/deliveries, donde puede reenviarla.
| domain.registered | Se registró un dominio en su cuenta. |
| domain.renewed | La fecha de vencimiento de un dominio se ha ampliado (renovación). |
| domain.expiring | Un dominio vence en 30, 7 o 1 días. |
| domain.expired | Un dominio venció ayer. |
| domain.nameservers.updated | Los servidores de nombres de un dominio han cambiado. |
| domain.transfer.started | Se ha solicitado una transferencia entrante o saliente en el registro. |
| domain.transfer.completed | Una transferencia ha finalizado. |
| domain.transfer.failed | Una transferencia ha sido rechazada o cancelada. |
| dns.zone.created | Se ha creado una zona DNS. |
| dns.zone.deleted | Se ha eliminado una zona DNS. |
| dns.record.created | Se ha añadido un registro DNS. |
| dns.record.updated | Se ha modificado un registro DNS. |
| dns.record.deleted | Se ha eliminado un registro DNS. |
| ssl.issued | Se ha emitido un certificado por primera vez. |
| ssl.renewed | Se ha renovado un certificado. |
| ssl.expiring | Un certificado vence en 7 días y aún no se ha renovado. |
| email.mailbox.created | Se añadió un buzón a uno de sus dominios de correo. |
| email.mailbox.deleted | Se eliminaron un buzón y su correo. |
| email.forwarding.enabled | Se activó el reenvío de correo para un dominio. |
| email.forwarding.disabled | Se desactivó el reenvío de correo para un dominio, por usted o porque el dominio dejó de cumplir los requisitos (el motivo figura en el evento). |
| webhook.test | Se envía cuando pulsa Enviar prueba; ignora el filtro de eventos del endpoint. |
data contiene el dominio o la zona y el objeto: el registro (con previous en las actualizaciones), la fecha de caducidad, los servidores de nombres (con previous). Los campos exactos de cada objeto son los de la API REST.
El correo entrante también puede enviarse a una URL: configúrelo para cada dirección en Reenvío de correo. Estos envíos usan los mismos encabezados y la misma firma, con X-NameOcean-Event: email.received.