---
title: "Webhook: Expired Domain Bildirimleri Kendi Adresine"
description: "Bir domain alarm kuralına uyduğu, boşa düştüğü ya da kontrol bittiği an adresine imzalı bir POST gelir. Gövde, imza doğrulama, yeniden deneme kuralları ve…"
url: https://hunter.domains/tr/docs/webhooks
language: tr
---

# 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](https://hunter.domains/tr/account/api) 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](https://hunter.domains/tr/docs/api#alarm-kurallari) 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](https://hunter.domains/tr/docs/api#domain-nesnesi) 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](https://hunter.domains/tr/docs/api) 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

## Anahtarını al, ilk isteği at

Ücretsiz hesapla API anahtarı oluşturabilir, MCP sunucusunu asistanına bağlayabilirsin. Kart gerekmez.

[Ücretsiz hesap aç](https://hunter.domains/tr/register)

## Bir sonraki iyi domaini kaçırma.

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

[Ücretsiz başla](https://hunter.domains/tr/register)
