Geliştiriciler → Webhooks

Webhook'lar

Hesabınızda bir şey olduğunda NameOcean, HTTPS uç noktanıza imzalı bir JSON olayı gönderir; böylece kodunuz sürekli sorgulama yapmak yerine doğrudan tepki verebilir.

Uç nokta ekleyin

Panel → Webhook'lar bölümünden, API ile veya yapay zekânızdan MCP üzerinden (create_webhook) isteyerek. Olay türlerini, dns.* gibi grupları ya da tüm olayları seçin. Yanıt, imzalama anahtarını (whsec_…) içerir.

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, herkese açık bir sunucuda https olmalıdır. 10 saniye içinde herhangi bir 2xx yanıtı verin; uzun süren işleri yanıt verdikten sonra yapın.

Ne alırsınız

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

Bir gönderim yeniden denendiğinde veya tekrar gönderildiğinde olay kimliği aynı kalır: daha önce işlediğiniz olayları atlamak için bunu kullanın. Olaylar sırasız gelebilir.

İmzayı doğrulayın

t, isteğin Unix zamanıdır; v1 ise t, bir nokta ve ham gövdenin, gizli anahtarınızla anahtarlanmış onaltılık HMAC-SHA256 değeridir. Bunu JSON'u ayrıştırmadan önce ham baytlar üzerinden hesaplayın, karşılaştırmayı sabit zamanda yapın ve beş dakikadan eski zaman damgalarını reddedin.

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

Yeniden denemeler ve devre dışı bırakma

Yanıt alınamayan, zaman aşımına uğrayan, 5xx, 408 veya 429 dönen bir gönderim 1m, 5m, 30m, 2h, 5h, 10h, 10h sonra yeniden denenir: yaklaşık bir gün içinde 8 deneme. Diğer tüm 4xx yanıtları anında başarısız sayılır. Art arda 5 gönderim kalıcı olarak başarısız olursa uç nokta devre dışı bırakılır ve size e-posta gönderilir; uç noktayı panelden veya PATCH active: true ile yeniden etkinleştirebilirsiniz. Her gönderim, durum kodu ve yanıtınızın başlangıcıyla birlikte panelde ve GET /api/v1/webhooks/{id}/deliveries adresinde listelenir; buradan bir gönderimi yeniden gönderebilirsiniz.

Olaylar

domain.registeredHesabınızda bir alan adı kaydedildi.
domain.renewedBir alan adının bitiş tarihi ileri alındı (yenileme).
domain.expiringBir alan adının süresi 30, 7 veya 1 gün içinde doluyor.
domain.expiredBir alan adının süresi dün doldu.
domain.nameservers.updatedBir alan adının ad sunucuları değişti.
domain.transfer.startedKayıt kuruluşunda gelen veya giden bir transfer talep edildi.
domain.transfer.completedBir transfer tamamlandı.
domain.transfer.failedBir transfer reddedildi veya iptal edildi.
dns.zone.createdBir DNS bölgesi oluşturuldu.
dns.zone.deletedBir DNS bölgesi silindi.
dns.record.createdBir DNS kaydı eklendi.
dns.record.updatedBir DNS kaydı değişti.
dns.record.deletedBir DNS kaydı silindi.
ssl.issuedBir sertifika ilk kez verildi.
ssl.renewedBir sertifika yenilendi.
ssl.expiringBir sertifikanın süresi 7 gün içinde doluyor ve henüz yenilenmedi.
email.mailbox.createdE-posta alan adlarınızdan birine bir posta kutusu eklendi.
email.mailbox.deletedBir posta kutusu ve içindeki e-postalar silindi.
email.forwarding.enabledBir alan adı için e-posta yönlendirme açıldı.
email.forwarding.disabledBir alan adı için e-posta yönlendirme, sizin tarafınızdan veya alan adı artık koşulları karşılamadığı için kapatıldı (neden, olay ayrıntılarında yer alır).
webhook.testTest gönder düğmesine bastığınızda gönderilir; uç noktanın olay filtresini dikkate almaz.

data, alan adını veya bölgeyi ve nesneyi içerir: kayıt (güncellemelerde previous ile birlikte), son kullanma tarihi, ad sunucuları (previous ile birlikte). Her nesnenin alanları REST API'dekilerle birebir aynıdır.

Gelen e-postalar da bir URL'ye gönderilebilir: bunu E-posta Yönlendirme bölümünden adres bazında ayarlayın. Bu gönderimler aynı başlıkları ve imzayı kullanır; X-NameOcean-Event: email.received olur.

Bilmeniz gerekenler

  • NameOcean yalnızca herkese açık adreslere gönderim yapar, bunu her gönderimde yeniden kontrol eder ve yönlendirmeleri asla takip etmez.
  • Anahtar sızarsa panelden yenileyin; olaylar hemen yeni anahtarla imzalanır.
  • Test gönder, uç noktanın olay filtresinden bağımsız olarak hemen bir webhook.test olayı gönderir.