Nasıl çalışır
- Bir adres eklersin: senin denetimindeki bir
https://adresi. - Bir olay olur; örneğin listeye yeni giren bir domain alarm kurallarından birine uyar.
- JSON gövdeli ve imza başlıklı bir
POSTgöndeririz; genellikle bir dakika içinde. - Adresin herhangi bir
2xxkoduyla cevap verir. Başka bir cevap ya da 8 saniye içinde cevap gelmemesi başarısızlık sayılır ve teslimat yeniden denenir.
Webhook Pro'ya dahildir. En çok 3 adresin olabilir.
Kurulum
Adresi hesabındaki API sayfasından ya da API ile ekle:
curl -X POST "https://hunter.domains/api/v1/webhooks" \
-H "Authorization: Bearer hd_…" -H "Content-Type: application/json" \
-d '{"url": "https://hooks.example.com/hunter", "events": ["alert.matched", "domain.available"]}'
Cevapta imza anahtarı (whsec_…) bulunur. Bir kez gösterilir; diğer gizli anahtarlarının yanında sakla. Sonra hesap sayfasında "Dene" düğmesine bas ya da POST /webhooks/{id}/test ucunu çağır; adresine bir ping olayı gelir.
Adres, herkese açık bir sunucu adında (IP adresi olmaz, adreste kullanıcı adı ya da şifre olmaz), 443 ya da 1023'ten büyük bir kapıda, https:// ile başlamalıdır. Yönlendirmeler izlenmez.
alert.matched almak için en az bir etkin alarm kuralın da olmalı.
Olaylar
type | Ne zaman gider |
|---|---|
alert.matched | Listeye yeni giren bir domain alarm kurallarından birine uydu. Kuralın e-posta sıklığından bağımsız, anında gider. |
domain.available | Takip ettiğin ya da bir kuralına uyan domain boşa düştü ve kimse almadı. |
domain.ending_soon | Takipteki ya da kurala uymuş bir domainin artırması bitmek üzere. Bildirim ayarlarında seçtiğin hatırlatma saatlerinde gider. |
check.completed | İstediğin domain kontrolü bitti: status, done ya da failed olur. |
ping | “Dene” düğmesine bastığında ya da deneme ucunu çağırdığında giden deneme olayı. |
Gövde
Her olay aynı zarfı taşır: olaya özgü bir id, olayın türü (type), zamanı ve verisi (data).
{
"id": "evt_01k6x2f0q8m3r7t9v4b5n6c8dz",
"type": "alert.matched",
"created_at": "2026-10-06T16:44:02Z",
"data": {
"alert": {
"id": 12,
"name": "Health, DR 30+"
},
"domain": {
"domain": "example.org",
"tld": "org",
"status": "listed",
"score": 78,
"verdict": "ok",
"flags": [],
"topic": "Home",
"language": "en",
"title": "Seasonal planting guides for small gardens",
"metrics": {
"domain_rating": 46,
"referring_domains": 412,
"archive_years": 17,
"archive_first_year": 2006,
"archive_last_year": 2025,
"trust_flow": 28,
"citation_flow": 31
},
"listing": {
"source": "godaddy",
"type": "bid",
"price_usd": 25,
"bids": 3,
"ends_at": "2026-10-09T17:30:00Z",
"url": "https://auctions.godaddy.com/trpItemListing.aspx?domain=example.org"
},
"found_at": "2026-10-06T16:42:10Z",
"open": true,
"detail": "full",
"report_url": "https://hunter.domains/domain/example.org"
}
}
}
domain nesnesi API'deki ile aynıdır. Tam rapor gerekiyorsa GET /domains/{domain} ucunu çağır.
Boşa düşüp alınmayan domain:
{
"id": "evt_01k6x2f0q8m3r7t9v4b5n6c8dz",
"type": "domain.available",
"created_at": "2026-10-06T16:44:02Z",
"data": {
"domain": {
"domain": "example.org",
"tld": "org",
"status": "available",
"score": 78,
"verdict": "ok",
"flags": [],
"topic": "Home",
"language": "en",
"title": "Seasonal planting guides for small gardens",
"metrics": {
"domain_rating": 46,
"referring_domains": 412,
"archive_years": 17,
"archive_first_year": 2006,
"archive_last_year": 2025,
"trust_flow": 28,
"citation_flow": 31
},
"listing": {
"source": "godaddy",
"type": "bid",
"price_usd": 25,
"bids": 3,
"ends_at": "2026-10-09T17:30:00Z",
"url": "https://auctions.godaddy.com/trpItemListing.aspx?domain=example.org"
},
"found_at": "2026-10-06T16:42:10Z",
"open": true,
"detail": "full",
"report_url": "https://hunter.domains/domain/example.org"
},
"registration": {
"availability": "available",
"checked_at": "2026-10-06T16:40:00Z",
"available_since": "2026-10-06T16:40:00Z",
"register_url": "https://www.spaceship.com/domain-search/?query=example.org",
"registrar": null,
"registered_at": null,
"expires_at": null,
"caught_after_drop": false
}
}
}
Biten kontrol özetle gelir; raporun kendisi GET /checks/{id} ucundadır:
{
"id": "evt_01k6x2f0q8m3r7t9v4b5n6c8dz",
"type": "check.completed",
"created_at": "2026-10-06T16:44:02Z",
"data": {
"check": {
"id": "01k6x2f0q8m3r7t9v4b5n6c8dz",
"domain": "example.org",
"status": "done",
"created_at": "2026-10-06T17:02:11Z",
"finished_at": "2026-10-06T17:03:24Z",
"score": 78,
"verdict": "ok",
"report_url": "https://hunter.domains/domain-checker/report/01k6x2f0q8m3r7t9v4b5n6c8dz"
}
}
}
Her istek şu başlıkları da taşır:
| Başlık | Değer |
|---|---|
Hunter-Event |
Olayın türü, ör. alert.matched. |
Hunter-Delivery |
Olayın kimliği. Yeniden denemede aynı kimlik gider. |
Hunter-Signature |
t=<unix zamanı>,v1=<imza>. |
User-Agent |
hunter.domains-webhooks/1. |
İmzayı doğrulama
Adresini öğrenen herkes oraya istek atabilir; bu yüzden isteğe güvenmeden önce imzayı denetle.
İmza, <t>.<ham gövde> dizgesinin, anahtar olarak imza anahtarınla hesaplanmış HMAC-SHA256 değeridir ve onaltılık yazılır. Doğrulamak için:
Hunter-Signaturebaşlığındantvev1değerlerini oku.t, bir nokta ve isteğin ham gövdesinden (JSON'a çevrilmeden önceki, geldiği haliyle) oluşan dizgenin HMAC-SHA256 değerini hesapla.- Sonucu
v1ile sabit zamanlı bir karşılaştırmayla kıyasla. tbeş dakikadan eskiyse isteği reddet; böylece ele geçirilmiş bir istek yeniden gönderilemez.
Node.js:
import crypto from 'node:crypto';
export function verify(rawBody, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const expected = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) <= toleranceSeconds;
const given = Buffer.from(parts.v1 ?? '');
return fresh && given.length === expected.length && crypto.timingSafeEqual(given, Buffer.from(expected));
}
Python:
import hashlib, hmac, time
def verify(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
signed = parts.get("t", "").encode() + b"." + raw_body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
fresh = abs(time.time() - int(parts.get("t", 0))) <= tolerance
return fresh and hmac.compare_digest(expected, parts.get("v1", ""))
PHP:
function verify(string $rawBody, string $header, string $secret, int $tolerance = 300): bool
{
parse_str(str_replace(',', '&', $header), $parts);
$expected = hash_hmac('sha256', ($parts['t'] ?? '').'.'.$rawBody, $secret);
return abs(time() - (int) ($parts['t'] ?? 0)) <= $tolerance
&& hash_equals($expected, (string) ($parts['v1'] ?? ''));
}
Yeniden deneme ve hatalar
- Bir teslimat en çok 6 kez denenir: hemen, ardından yaklaşık 1 dakika, 5 dakika, 30 dakika, 2 saat ve 6 saat sonra.
- Hızlıca
2xxdön, ağır işi sonra yap. 8 saniyeden uzun süren istek, kodun sonradan bitirse bile başarısız sayılır. - Aynı olay birden fazla kez gelebilir; örneğin
2xxcevabın yolda kaybolduysa. Tekrarları ayıklamak için olayıniddeğerini kullan. - Olaylar sırasız gelebilir. Geliş sırasına değil,
created_atdeğerine bak. - Art arda 15 teslimat bütün denemelerine rağmen başarısız olursa adresi kapatır ve sana e-posta göndeririz. Hesap sayfasından ya da
PATCH /webhooks/{id}ucuna{"active": true}göndererek yeniden açarsın. - Bir adresin son 50 teslimatı, durumu ve cevap koduyla, hesap sayfasında ve
GET /webhooks/{id}/deliveriesucundadır. 14 gün saklanır.
Olayları başka araçlara aktarma
- n8n, Make, Zapier, Pipedream: araçta bir webhook tetikleyicisi oluştur, verdiği adresi webhook adresin olarak yapıştır ve akışın gerisini orada kur: Slack mesajı, tabloya satır, görev.
- Doğrudan Slack ve Discord: bu servislerin gelen webhook'ları kendi gövde biçimini bekler, bizim JSON'umuzu reddeder. Araya yukarıdaki araçlardan birini ya da birkaç satır kendi kodunu koy.
- Kendi sunucun: imzayı doğrula,
200dön, sonra olayı bir kuyruktan işle.
Sık sorulan sorular
Expired domain bildirimlerini webhook ile alabilir miyim?
Evet. İstediğin filtrelerle (niş, dil, Domain Rating, fiyat, uzantı) bir alarm kuralı oluştur ve bir webhook adresi ekle. Kurala uyan her yeni domain, alert.matched olayı olarak adresine gönderilir.
Webhook ne kadar hızlı?
Genellikle olaydan sonraki bir dakika içinde. Domain, günlük tarama sırasında incelemesi biter bitmez alarm kurallarıyla karşılaştırılır.
Webhook ücretsiz planda var mı?
Hayır. Webhook ve alarm kuralları Pro'ya dahildir. Ücretsiz planda bunun yerine API'yi aralıklı sorgulayabilirsin.
Sunucum kapalıysa ne olur?
Teslimat yaklaşık dokuz saat boyunca yeniden denenir. Sunucun bu sürede geri gelirse hiçbir şey kaybolmaz. Sonrasında teslimat başarısız olarak işaretlenir; kaçırdıklarını yine de GET /alerts/matches ucundan okuyabilirsin.
Adresim neden kapatıldı?
Art arda 15 teslimat bütün denemelerine rağmen başarısız oldu. Teslimat listesindeki cevap kodlarına bak, adresi düzelt ve yeniden aç.
Güncellendi: 6 Ekim 2026