Webhook
YHA Abone · Çıkışlar'da webhook türünde bir çıkış açın. Yeni haber, düzeltme ve iptalde adresinize POST gelir.
- Adres yalnızca
https; bağlantı noktası 443 ya da 1024–65535. Özel ve yerel ağ adresleri reddedilir. - Zaman aşımı 10 saniye; yönlendirme izlenmez (3xx hata sayılır).
User-Agent: YHA-Webhook/1,Content-Type: application/json.- Varsayılan yük tam içeriktir; profilde "ince" seçilirse yalnızca kimlik ve adres gelir, içeriği API'den alırsınız.
Gövde
{ "surum": 1, "olay_turu": "haber.duzeltme", "zaman": "2026-10-07T11:19:02Z", "deneme": false, "veri": { "olay_id": "…" } }olay_turu: haber.yeni, haber.duzeltme, haber.iptal, varlik.yeni, varlik.iptal, varlik.guncelleme, sinama.ping. veri bir DisOlay'dır. Gövde 256 KB'ı aşarsa govde boşaltılır ve govde_kesildi: true gelir.
Yanıtınız
| Yanıt | Biz ne yaparız |
|---|---|
| 2xx | Teslim edildi |
| 5xx, 408, 429, 401, 403, 404, 3xx, bağlantı hatası | Yeniden deneriz: 30 sn, 1 dk, 2 dk, 5 dk, sonra 15 dakikada bir (yaklaşık 24 saat); 429'da Retry-After'a uyarız |
| 400, 413, 422 | Bu içerik için vazgeçeriz |
| 410 | Çıkışı duraklatırız ve size bildiririz |
Art arda hatalar sürerse çıkış "arızalı" görünür, Teknik Destek uyarılır ve her 15 dakikada yalnızca bir deneme yapılır; ilk başarıda biriken içerik sırayla gider. Sıra garantisi yoktur (flaş öne geçer): eski düzeltmeyi surum_no ile yok sayın.
İmza (Standard Webhooks)
webhook-id: <teslim kimliği> (yeniden denemelerde aynı)
webhook-timestamp: 1791371942 (Unix saniye)
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=İmzalanan metin <webhook-id>.<webhook-timestamp>.<ham gövde>; anahtar sırrın whsec_ önekinden sonraki base64 çözülmüş baytları; HMAC-SHA256, base64. Zaman damgasını ±5 dakikada kabul edin, sabit zamanlı karşılaştırın ve webhook-id'yi çift işlememek için saklayın. Sır döndürüldüğünde eski sır 24 saat daha geçerlidir ve başlık iki imza taşır (v1,<yeni> v1,<eski>); birinin tutması yeter.
import base64, hmac, hashlib, time
def imza_gecerli(sir: str, b: dict, govde: bytes) -> bool:
anahtar = base64.b64decode(sir.removeprefix("whsec_"))
wid, zaman = b["webhook-id"], b["webhook-timestamp"]
if abs(time.time() - int(zaman)) > 300: return False
beklenen = base64.b64encode(hmac.new(anahtar, f"{wid}.{zaman}.".encode() + govde, hashlib.sha256).digest()).decode()
return any(hmac.compare_digest(p[3:], beklenen) for p in b["webhook-signature"].split() if p.startswith("v1,"))// JavaScript (Node): govde ham Buffer olmalı
import { createHmac, timingSafeEqual } from 'node:crypto';
export function imzaGecerli(sir, b, govde) {
const anahtar = Buffer.from(sir.replace(/^whsec_/, ''), 'base64');
const zaman = b['webhook-timestamp'];
if (Math.abs(Date.now() / 1000 - Number(zaman)) > 300) return false;
const beklenen = createHmac('sha256', anahtar).update(`${b['webhook-id']}.${zaman}.`).update(govde).digest('base64');
return b['webhook-signature'].split(' ').some((p) => p.startsWith('v1,') && p.length - 3 === beklenen.length
&& timingSafeEqual(Buffer.from(p.slice(3)), Buffer.from(beklenen)));
}using System.Security.Cryptography; using System.Text;
static bool ImzaGecerli(string sir, string id, string zaman, byte[] govde, string imzaBasligi) {
if (Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - long.Parse(zaman)) > 300) return false;
using var hmac = new HMACSHA256(Convert.FromBase64String(sir["whsec_".Length..]));
var imzalanan = Encoding.UTF8.GetBytes($"{id}.{zaman}.").Concat(govde).ToArray();
var beklenen = Encoding.ASCII.GetBytes(Convert.ToBase64String(hmac.ComputeHash(imzalanan)));
return imzaBasligi.Split(' ').Where(p => p.StartsWith("v1,"))
.Any(p => CryptographicOperations.FixedTimeEquals(Encoding.ASCII.GetBytes(p[3..]), beklenen));
}Ham gövdeyi JSON'a çevirmeden önce imzayı doğrulayın (yeniden biçimlendirilmiş gövdenin imzası tutmaz). Tam örnekler ornekler/ klasöründedir.
Sınama
Çıkış ekranındaki "Bağlantıyı sına" sinama.ping gönderir ve yanıt kodunuzu gösterir; "Deneme gönder" son uygun içeriği deneme: true ile yollar.
Yazar Haber Ajansı Webhook Rehberi: Haberleri Yayınlandığı Anda Alın
Yazar Haber Ajansı webhook servisi, yeni bir haber servis edildiğinde, düzeltildiğinde veya iptal edildiğinde sizin belirlediğiniz https adresine imzalı bir POST isteği gönderir. Böylece sisteminiz "yeni haber var mı?" diye sürekli sormak zorunda kalmaz; haber hazır olduğu anda size gelir.
Webhook, YHA geliştirici belgeleri içindeki entegrasyon yöntemlerinden biridir. Varsayılan olarak tam içeriği taşır; isterseniz yalnızca kimlik ve adres taşıyan "ince" yükü seçip haberin ayrıntısını Yazar Haber Ajansı API ile alırsınız.
Push ve pull: webhook neden daha hızlı?
Haber almanın iki temel yolu vardır. Pull (çekme) modelinde sisteminiz belirli aralıklarla API'ye veya RSS beslemesine istek atar. Push (itme) modelinde ise ajans, bir olay gerçekleştiğinde size haber verir. Webhook bir push yöntemidir.
| Kriter | Pull (API akışı / RSS) | Push (Webhook) |
|---|---|---|
| Gecikme | Sorgulama aralığı kadar | Saniyeler |
| Gereksiz istek | Çok (çoğu sorguda yeni haber yoktur) | Yok, yalnızca olay olduğunda |
| Kurulum | Basit, yalnızca istemci | Herkese açık bir HTTPS adresi gerekir |
| Kesinti durumunda | Bir sonraki sorguda imleçten telafi edilir | Ajans yaklaşık 24 saat yeniden dener |
| En uygun kullanım | Basit siteler | Son dakika ağırlıklı siteler, uygulamalar |
Kendi tarafınızda herkese açık bir adres açamıyorsanız aynı hızı anlık akışla (SSE) da alabilirsiniz: bu kez bağlantıyı siz açarsınız ve olaylar birkaç saniye içinde gelir.
Webhook kurulumu: adım adım
- Alıcı adresi hazırlayın. Sunucunuzda
POSTisteklerini kabul eden bir adres oluşturun (ör.https://siteniz.com/yha-webhook). Adres yalnızcahttpsolabilir; bağlantı noktası 443 ya da 1024–65535 aralığında olmalıdır. Özel ve yerel ağ adresleri reddedilir. - Çıkışı açın. YHA Abone · Çıkışlar ekranında
webhooktüründe bir çıkış açın ve adresi girin. Çıkışın imza sırrıwhsec_önekiyle başlar. - Sırrı güvenle saklayın. Sırrı sunucunuzda ortam değişkeni olarak tanımlayın; kod deposuna veya paylaşılan belgelere yazmayın.
- İmza doğrulamayı ekleyin. Aşağıdaki örneklerden kendi dilinize uygun olanı kullanarak her isteğin gerçekten YHA'dan geldiğini doğrulayın.
- Sınayın. Çıkış ekranındaki "Bağlantıyı sına"
sinama.pinggönderir ve yanıt kodunuzu gösterir; "Deneme gönder" son uygun içeriğideneme: trueile yollar; "Alıcıyı denetle" alıcınızın imzayı gerçekten doğrulayıp doğrulamadığını ölçer (aşağıda).
Güvenlik duvarınız gelen istekleri süzüyorsa ajansın çıkış adreslerine izin verin; adresler canlıya geçişte yayımlanır ve değişiklik 30 gün önceden duyurulur.
Olay türleri
Her bildirimin gövdesinde bir olay_turu bulunur:
olay_turu |
Ne zaman gönderilir | Sizin yapmanız gereken |
|---|---|---|
haber.yeni |
Haber ilk kez servis edildiğinde | Haberi içe aktarın ya da editör kuyruğuna ekleyin |
haber.duzeltme |
Haberin yeni sürümü servis edildiğinde | surum_no büyükse mevcut yazıyı güncelleyin |
haber.iptal |
Haber iptal edildiğinde | Yayından kaldırın |
varlik.yeni, varlik.iptal, varlik.guncelleme |
Tek başına servis edilen fotoğraf ya da video yeni geldiğinde, iptal edildiğinde ya da bilgisi değiştiğinde | Medya kütüphanenizi güncelleyin |
sinama.ping |
"Bağlantıyı sına" düğmesinde | 2xx dönün |
İptal olayını mutlaka işleyin. Ajans bir haberi iptal ettiğinde sizin sitenizde yayında kalması yanlış bilginin yayılmasına ve hukuki risklere yol açabilir; abonelik koşulları da iptal edilen içeriğin yayından kaldırılmasını ister. Yeni olay türleri geriye uyumlu eklemedir: tanımadığınız olay_turu'nu 2xx ile kabul edip yok sayın.
Gövde
İstek POST yöntemiyle, Content-Type: application/json ve User-Agent: YHA-Webhook/1 başlıklarıyla gelir:
{
"surum": 1,
"olay_turu": "haber.duzeltme",
"zaman": "2026-10-07T11:19:02Z",
"deneme": false,
"veri": { "olay_id": "…", "olay": "duzeltme", "icerik": "haber", "haber": { "no": "H-001230", "surum_no": 2, "…": "…" }, "varlik": null }
}
veri, API'deki akışla aynı olay nesnesidir (DisOlay): içinde haberin başlığı, spotu, gövdesi, kategorisi, embargo bilgisi, kullanım notu ve medya bilgisi bulunur. Gövde 256 KB'ı aşarsa govde boşaltılır ve govde_kesildi: true gelir; bu durumda tam metni API'den alın. Profilde "ince" yük seçilirse veri yalnızca olay_id, olay, icerik, id, no, surum_no ve adres taşır.
İmza doğrulama (Standard Webhooks)
Webhook adresiniz internete açık olduğundan herkes oraya sahte bir istek gönderebilir. YHA her isteği Standard Webhooks biçiminde imzalar ve üç başlık gönderir:
webhook-id: <teslim kimliği> (yeniden denemelerde aynı)
webhook-timestamp: 1791371942 (Unix saniye)
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=
İmzalanan metin <webhook-id>.<webhook-timestamp>.<ham gövde>'dir. Anahtar, sırrın whsec_ önekinden sonraki kısmının base64 çözülmüş baytlarıdır; imza HMAC-SHA256 ile hesaplanır ve base64 olarak v1, önekiyle yazılır.
Önemli kurallar:
- İmzayı ham gövde üzerinden hesaplayın; JSON'u çözüp yeniden yazmak imzayı bozar.
- Karşılaştırmayı sabit zamanlı fonksiyonla yapın (
hash_equals,timingSafeEqual,compare_digest). webhook-timestampşimdiye göre ±5 dakika dışındaysa reddedin (tekrar oynatma saldırısı).- Sır döndürüldüğünde eski sır 24 saat daha geçerlidir ve başlık iki imza taşır (
v1,<yeni> v1,<eski>); birinin tutması yeterlidir. - İmza tutmazsa 401 dönün ve hiçbir iş yapmayın.
PHP
<?php
$sir = getenv('YHA_WEBHOOK_SIRRI'); // whsec_...
$govde = file_get_contents('php://input'); // ham gövde
$wid = $_SERVER['HTTP_WEBHOOK_ID'] ?? '';
$zaman = $_SERVER['HTTP_WEBHOOK_TIMESTAMP'] ?? '';
$imzalar = $_SERVER['HTTP_WEBHOOK_SIGNATURE'] ?? '';
if (!ctype_digit($zaman) || abs(time() - (int) $zaman) > 300) {
http_response_code(401); exit;
}
$anahtar = base64_decode(preg_replace('/^whsec_/', '', $sir), true);
$beklenen = base64_encode(hash_hmac('sha256', "{$wid}.{$zaman}.{$govde}", $anahtar, true));
$gecerli = false;
foreach (explode(' ', $imzalar) as $p) {
if (str_starts_with($p, 'v1,') && hash_equals($beklenen, substr($p, 3))) { $gecerli = true; }
}
if (!$gecerli) { http_response_code(401); exit; }
kuyruga_ekle($wid, json_decode($govde, true)); // webhook-id ile tekrarı ayıklayın
http_response_code(200);
JavaScript (Node)
// govde ham Buffer olmalı (ör. express.raw({ type: 'application/json' }))
import { createHmac, timingSafeEqual } from 'node:crypto';
export function imzaGecerli(sir, b, govde) {
const anahtar = Buffer.from(sir.replace(/^whsec_/, ''), 'base64');
const zaman = b['webhook-timestamp'];
if (Math.abs(Date.now() / 1000 - Number(zaman)) > 300) return false;
const beklenen = createHmac('sha256', anahtar).update(`${b['webhook-id']}.${zaman}.`).update(govde).digest('base64');
return b['webhook-signature'].split(' ').some((p) => p.startsWith('v1,') && p.length - 3 === beklenen.length
&& timingSafeEqual(Buffer.from(p.slice(3)), Buffer.from(beklenen)));
}
Python
import base64, hmac, hashlib, time
def imza_gecerli(sir: str, b: dict, govde: bytes) -> bool:
anahtar = base64.b64decode(sir.removeprefix("whsec_"))
wid, zaman = b["webhook-id"], b["webhook-timestamp"]
if abs(time.time() - int(zaman)) > 300:
return False
beklenen = base64.b64encode(
hmac.new(anahtar, f"{wid}.{zaman}.".encode() + govde, hashlib.sha256).digest()).decode()
return any(hmac.compare_digest(p[3:], beklenen)
for p in b["webhook-signature"].split() if p.startswith("v1,"))
Dört dilde (Python, JavaScript, PHP, C#) çalışır alıcılar entegrasyon kitinde bulunur.
Hızlı 2xx yanıt ve kuyruk
Ajans yanıt için 10 saniye bekler ve yönlendirmeleri izlemez (3xx hata sayılır). Alıcınızın tek görevi isteği doğrulamak, kaydetmek ve hemen 2xx dönmektir. Haberi API'den çekmek, görselleri indirmek, yazıyı oluşturmak gibi uzun işleri aynı istek içinde yapmayın.
Önerilen akış ("dürt ve çek"):
- Gövdeyi ham bayt olarak okuyun, imzayı ve zaman damgasını doğrulayın.
- Olayı veritabanına veya bir kuyruğa yazın.
- 2xx dönün.
- Arka planda çalışan işçi olayları işlesin; ince yükte ya da kesilmiş gövdede içeriği akıştan çeksin.
Aynı olay iki kez gelirse
Yeniden denemeler nedeniyle aynı bildirim birden fazla kez gelebilir. webhook-id'yi en az 24 saat saklayın; yeniden gelirse 2xx dönün ama işlemeyin. Ayrıca haberleri kendi kimlikleriyle eşleştirin; böylece haber.yeni iki kez gelse bile tek yazı oluşur.
Sıra garantisi yoktur (flaş öne geçebilir): eski bir düzeltme yeni sürümden sonra gelirse surum_no ile yok sayın.
Yanıtınız ve yeniden deneme
| Yanıtınız | Ajans ne yapar |
|---|---|
| 2xx | Teslim edildi |
| 5xx, 408, 429, 401, 403, 404, 3xx, bağlantı hatası | Yeniden dener: 30 sn, 1 dk, 2 dk, 5 dk, sonra 15 dakikada bir (yaklaşık 24 saat); 429'da Retry-After'a uyar |
| 400, 413, 422 | Bu içerik için vazgeçer |
| 410 | Çıkışı duraklatır ve size bildirir |
Art arda hatalar sürerse çıkış "arızalı" görünür, Teknik Destek uyarılır ve her 15 dakikada yalnızca bir deneme yapılır; ilk başarıda biriken içerik sırayla gider. Uzun bir kesintiden sonra eksik kalan olayları API'deki akıştan saklanan imleçle tamamlayabilirsiniz. Ajans tarafındaki kesintileri YHA servis durumu sayfasından takip edebilirsiniz.
Alıcı denetimi
En sık entegrasyon hatası imzanın doğrulanmamasıdır. Webhook çıkışının ayrıntısındaki "Alıcıyı denetle" düğmesi alıcınıza dört sınama isteği gönderir (olay_turu: "sinama.denetim", deneme: true):
| No | İstek | Beklenen |
|---|---|---|
| 1 | Doğru imza | 2xx |
| 2 | Bozuk imza | 400, 401 ya da 403 |
| 3 | Doğru imza, 10 dakika eski zaman damgası | 400, 401 ya da 403 |
| 4 | Aynı webhook-id, doğru imza |
2xx (sessizce kabul) |
Profil başına saatte en çok 6 denetim yapılabilir. Ayrıntılar: Alıcı denetimi.
Güvenlik kontrol listesi
- Adres yalnızca HTTPS üzerinden çalışmalı.
- İmza sırrını kodun içine değil, ortam değişkenine veya gizli anahtar kasasına koyun.
- İmza ve zaman damgası doğrulaması olmadan hiçbir olayı işlemeyin.
- Adresi tahmin edilemez yapmak ek bir katmandır ama imzanın yerini tutmaz.
- Gövdedeki metni sitenize basmadan önce HTML açısından temizleyin (XSS'e karşı).
- Sırrı döndürürken geçiş süresinde iki imzayı da kabul eden kodu kullanın.
Örnek akış: son dakika haberi sitenize nasıl ulaşır?
Ajans editörü haberi onaylar ve servis eder. Birkaç saniye içinde YHA, sizin adresinize haber.yeni olayını gönderir. Alıcınız imzayı doğrular, olayı kuyruğa yazar ve 2xx döner. Arka plandaki işçi olaydaki haberi alır, gerekiyorsa medyayı API'den indirir ve sitenizde taslak ya da doğrudan yayında bir yazı oluşturur. Embargo bilgisi varsa yazıyı embargo saatine zamanlar. Dakikalar sonra ajans haberi düzelttiğinde haber.duzeltme gelir ve aynı yazı surum_no karşılaştırmasıyla güncellenir.
İzleme ve loglama
Webhook entegrasyonu sessizce bozulabilir: bir sertifikanın süresi dolar, bir güvenlik kuralı değişir ya da sunucu taşınır. Bunu erken fark etmek için:
- Gelen her olay için zaman,
olay_turu,webhook-idve döndürdüğünüz durum kodunu kaydedin. - Kuyrukta bekleyen olay sayısını izleyin; sayı sürekli artıyorsa işçiniz yetişemiyor demektir.
- Başarısız imza doğrulamalarını ayrıca sayın; ani artış yanlış yapılandırmaya veya kötü niyetli denemelere işaret eder.
- YHA Abone'deki çıkış durumunu ve teslim listesini düzenli kontrol edin.
Sık karşılaşılan hatalar ve çözümleri
| Belirti | Olası neden | Çözüm |
|---|---|---|
| Her istek 401 dönüyor | İmza yeniden biçimlendirilmiş gövde üzerinden hesaplanıyor ya da sır base64 çözülmüyor | Ham gövdeyi kullanın; whsec_ önekini atıp sırrı base64 çözün |
| İmza bazen tutuyor, bazen tutmuyor | Sunucu saati kaymış ya da döndürmede tek imza denetleniyor | NTP ile saati eşitleyin; başlıktaki tüm v1, imzalarını deneyin |
| Aynı haber birden çok kez oluşuyor | 10 saniyede yanıt verilmedi, yeniden denendi | Önce 2xx dönün, işi kuyruğa bırakın; webhook-id'yi saklayın |
| Hiç bildirim gelmiyor | Güvenlik duvarı, CDN veya WAF isteği engelliyor; adres yönlendiriyor | Çıkış adreslerine izin verin, yönlendirmesiz son adresi girin |
| Gövde eksik | İnce yük seçili ya da govde_kesildi: true |
İçeriği API'den alın |
| Çıkış duraklatılmış | Alıcı 410 döndü ya da uzun süre hata verdi | Sorunu giderin, çıkışı yeniden etkinleştirin |
WordPress sitelerinde webhook
WordPress sitesi için alıcıyı sıfırdan yazmanız gerekmez. Ajansın WordPress eklentisi "Anlık" kipte çalışırken ajans sitenizin POST /wp-json/yha-haber/v1/bildirim yolunu imzalı bir istekle dürter ve eklenti hemen akıştan çeker. Bunun için paketinizde webhook kanalı açık olmalı ve güvenlik eklentiniz bu yolu engellememelidir. Ayrıntılar: YHA WordPress eklentisi.
Push ve pull modelinin farkını genel hatlarıyla webhook nedir? rehberinde anlattık.
Sıkça Sorulan Sorular
Yazar Haber Ajansı webhook'u nasıl etkinleştirilir?
Paketinizde webhook kanalı açık olmalıdır (otomatik çıkışlar pakete sözleşmeyle eklenir). Ardından YHA Abone · Çıkışlar'da webhook türünde çıkış açar, adresinizi girer ve imza sırrını sunucunuza eklersiniz. "Bağlantıyı sına" ile alıcınızın çalıştığını doğrulayın.
Webhook mı, RSS mi kullanmalıyım?
Saniyeler önemliyse webhook ya da anlık akış; basit bir kurulum istiyorsanız RSS. İkisini birlikte kullanmak da mümkündür.
Localhost'ta webhook test edebilir miyim?
Hayır; ajans yalnızca genel internet adreslerine ve https adreslerine bağlanır. Geliştirme sırasında yerel sunucuyu geçici olarak internete açan bir tünel aracı kullanabilir ya da deneme ortamındaki anlık akışla çalışabilirsiniz.
Aynı haber sitemde iki kez yayınlandı, neden?
Büyük olasılıkla alıcınız 10 saniye içinde yanıt vermedi ve bildirim yeniden gönderildi. Hızlı 2xx yanıtı ve webhook-id kontrolü bu sorunu çözer.
Webhook isteklerinin sırası garanti mi?
Hayır. Flaş haberler öne geçebilir; eski düzeltmeyi surum_no ile yok sayın.