İçeriğe geç

Webhook

Aralıklı sorgulamayı bırak. İstediğin şey olduğunda adresine imzalı bir POST göndeririz: alarm kuralına uyan yeni domain, takip ettiğin domainin düşmesi, biten kontrol.

Nasıl çalışır

  1. Bir adres eklersin: senin denetimindeki bir https:// adresi.
  2. Bir olay olur; örneğin listeye yeni giren bir domain alarm kurallarından birine uyar.
  3. JSON gövdeli ve imza başlıklı bir POST göndeririz; genellikle bir dakika içinde.
  4. Adresin herhangi bir 2xx koduyla 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

typeNe zaman gider
alert.matchedListeye yeni giren bir domain alarm kurallarından birine uydu. Kuralın e-posta sıklığından bağımsız, anında gider.
domain.availableTakip ettiğin ya da bir kuralına uyan domain boşa düştü ve kimse almadı.
domain.ending_soonTakipteki 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:

  1. Hunter-Signature başlığından t ve v1 değerlerini oku.
  2. t, bir nokta ve isteğin ham gövdesinden (JSON'a çevrilmeden önceki, geldiği haliyle) oluşan dizgenin HMAC-SHA256 değerini hesapla.
  3. Sonucu v1 ile sabit zamanlı bir karşılaştırmayla kıyasla.
  4. t beş 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 2xx dö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 2xx cevabın yolda kaybolduysa. Tekrarları ayıklamak için olayın id değerini kullan.
  • Olaylar sırasız gelebilir. Geliş sırasına değil, created_at değ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}/deliveries ucundadı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, 200 dö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

Bir sonraki iyi domaini kaçırma.

Kuralını kur, gerisini bize bırak. Uyan domain bulunduğu an haberin olur.

Ücretsiz başla