Разработчици → Webhooks

Webhooks

NameOcean изпраща подписано JSON събитие до Вашата HTTPS крайна точка, когато нещо се случи във Вашия акаунт, така че кодът Ви да реагира, вместо периодично да проверява.

Добавяне на крайна точка

В Табло → Webhooks, чрез API или като помолите Вашия AI през MCP (create_webhook). Изберете типове събития, групи като dns.* или всички събития. Отговорът съдържа тайния ключ за подписване (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"]}'

URL адресът трябва да е https на публичен сървър. Отговорете с какъвто и да е 2xx код до 10 секунди; извършвайте бавната обработка след отговора.

Какво получавате

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

Идентификаторът на събитието остава същият, когато доставката се опитва повторно или се изпраща отново: използвайте го, за да пропускате вече обработени събития. Събитията може да пристигат в разменен ред.

Проверка на подписа

t е Unix времето на заявката, а v1 е шестнадесетичният HMAC-SHA256 на t, точка и необработеното тяло, с ключ Вашата тайна. Изчислявайте го върху необработените байтове, преди да парсвате JSON, сравнявайте за постоянно време и отхвърляйте времеви печати, по-стари от пет минути.

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

Повторни опити и изключване

Доставка, която не получи отговор, изтече по време или получи 5xx, 408 или 429, се опитва повторно след 1m, 5m, 30m, 2h, 5h, 10h, 10h: 8 опита в рамките на около един ден. Всеки друг 4xx код води до незабавен неуспех. След 5 последователни окончателно неуспешни доставки крайната точка се изключва и получавате имейл; включете я отново от таблото или с PATCH active: true. Всяка доставка, с код на състоянието и началото на Вашия отговор, е показана в таблото и на GET /api/v1/webhooks/{id}/deliveries, където можете да я изпратите отново.

Събития

domain.registeredВъв Вашия акаунт беше регистриран домейн.
domain.renewedДатата на изтичане на домейн беше преместена напред (подновяване).
domain.expiringДомейн изтича след 30, 7 или 1 ден.
domain.expiredДомейн е изтекъл вчера.
domain.nameservers.updatedСървърите за имена (nameservers) на домейн бяха променени.
domain.transfer.startedВ регистъра беше заявен входящ или изходящ трансфер.
domain.transfer.completedТрансфер беше завършен.
domain.transfer.failedТрансфер беше отхвърлен или отменен.
dns.zone.createdБеше създадена DNS зона.
dns.zone.deletedБеше изтрита DNS зона.
dns.record.createdБеше добавен DNS запис.
dns.record.updatedБеше променен DNS запис.
dns.record.deletedБеше изтрит DNS запис.
ssl.issuedБеше издаден сертификат за първи път.
ssl.renewedБеше подновен сертификат.
ssl.expiringСертификат изтича след 7 дни и все още не е подновен.
email.mailbox.createdКъм един от Вашите пощенски домейни беше добавена пощенска кутия.
email.mailbox.deletedПощенска кутия и пощата в нея бяха изтрити.
email.forwarding.enabledПренасочването на имейли беше включено за домейн.
email.forwarding.disabledПренасочването на имейли беше изключено за домейн от Вас или защото домейнът вече не отговаря на условията (причината е посочена в събитието).
webhook.testИзпраща се, когато натиснете „Изпращане на тест“; игнорира филтъра за събития на крайната точка.

data съдържа домейна или зоната и обекта: записа (с previous при промени), датата на изтичане, DNS сървърите (с previous). Точните полета на всеки обект са същите като в REST API.

Входящите имейли също могат да се изпращат към URL: задайте го за всеки адрес в Пренасочване на имейли. Тези заявки използват същите заглавки и подпис, с X-NameOcean-Event: email.received.

Полезно е да знаете

  • NameOcean изпраща само към публични адреси, проверявани отново при всяка доставка, и никога не следва пренасочвания.
  • Сменете тайния ключ от таблото, ако изтече; събитията веднага започват да се подписват с новия.
  • Изпращане на тест незабавно изпраща събитие webhook.test, независимо от филтъра за събития на крайната точка.