Webhook: olaylar anında adresinize
Webhook ile PazarOMatik'te bir olay olduğu anda (yeni sipariş, stok değişimi, yeni müşteri sorusu...) verdiğiniz HTTPS adrese bir POST isteği gelir. Sürekli sorgulamaya (polling) gerek kalmaz.
← Geliştirici rehberi 📖 API referansı
Kurulum
- Programda Ayarlar > Bulut > 🔑 API ve webhook'lar > 📡 Webhook'lar > + Webhook ekle.
- Adresinizi (yalnız
https://, internetten erişilebilen) ve almak istediğiniz olayları seçin. En çok 5 adres eklenebilir. - Gösterilen gizli anahtarı (
whsec_...) alıcınıza kaydedin; imzayı bununla doğrularsınız. Anahtarı daha sonra 🔐 Gizli anahtar ile görebilir ya da yenileyebilirsiniz. - ▶ Test gönder ile
pingolayı gönderin; sonuç (HTTP kodu, süre) hemen görünür. 📜 Gönderim geçmişi son 7 günün teslimatlarını gösterir.
Olaylar bulut eşitlemesi sırasında üretilir: program açıkken birkaç saniye ile bir dakika içinde gelir. Program kapalıyken olan değişiklikler (ör. sunucu eşitlemesinin çektiği siparişler) program açılıp eşitlendiğinde gönderilir.
Olaylar
| Olay | Ne zaman | data |
|---|---|---|
order.created |
Yeni pazaryeri / e-ticaret siparişi geldi | Sipariş (GET /v2/orders/{id} biçimi) |
order.updated |
Durum, kargo kodu / firması / takip adresi, fatura bağlantısı, stok düşümü, etiket basımı değişti | Sipariş + changes |
product.updated |
Ürün adı, stok kodu, barkod, fiyat, KDV, aktiflik, kategori / marka değişti | Ürün + changes |
stock.changed |
Ürünün stoğu değişti (satış, giriş, sayım, transfer...) | {product_id, sku, barcode, name, stock} |
listing.updated |
Pazaryeri ilanının fiyatı, stoğu, durumu ya da eşleştiği ürün değişti | İlan + changes |
question.created |
Yeni müşteri sorusu | Soru |
claim.created |
Yeni iade talebi | İade |
document.created |
Yeni teklif / sipariş / fatura / irsaliye | Belge (kalemleriyle) |
party.created |
Yeni cari açıldı | Cari |
request.completed |
API / panelden gönderilen istek programda işlendi | {request_id, kind, entity, op, action, source, ok, status, message, ref, target} |
ping |
Programdan "Test gönder" | {message, webhook_id} ve gövdede "test": true |
changes değişen alanları verir: {"status": {"from": "processing", "to": "shipped"}}.
İstek
POST /pazaromatik-webhook HTTP/1.1
Content-Type: application/json
User-Agent: PazarOMatik-Webhook/1.0
X-PZM-Event: order.updated
X-PZM-Delivery: 5f0c2a9e-6c1b-4f7e-9d3a-2b8e7c1d4a90
X-PZM-Timestamp: 1760521964
X-PZM-Signature: sha256=8d6f...c41a
{"id": "5f0c2a9e-6c1b-4f7e-9d3a-2b8e7c1d4a90", "event": "order.updated", "created_at": "2026-10-15T12:52:44+03:00",
"firm": "ABC123", "data": {"id": 21055, "channel": "trendyol", "number": "7781234567", "status": "shipped",
"cargo": {"tracking_number": "YK123", "carrier": "Yurtiçi Kargo"}, "changes": {"status": {"from": "processing", "to": "shipped"}}}}
İmzayı doğrulayın
İmza: HMAC-SHA256(gizli_anahtar, X-PZM-Timestamp + "." + ham_gövde) (onaltılık), başında sha256=. Ham gövdeyi (JSON'a çevirmeden önceki baytları) kullanın; zaman damgası 5 dakikadan eskiyse reddedin (tekrar saldırısına karşı).
PHP
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_PZM_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_PZM_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, getenv('PZM_WEBHOOK_SECRET'));
if (!hash_equals($expected, $sig) || abs(time() - (int)$ts) > 300) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
// işi kuyruğa atın, hemen 200 dönün
http_response_code(200);
Node.js (Express)
const crypto = require('crypto');
app.post('/pazaromatik-webhook', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-PZM-Timestamp'), sig = req.get('X-PZM-Signature') || '';
const expected = 'sha256=' + crypto.createHmac('sha256', process.env.PZM_WEBHOOK_SECRET)
.update(ts + '.' + req.body).digest('hex');
const ok = sig.length === expected.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!ok || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(401);
const event = JSON.parse(req.body);
res.sendStatus(200); // işi sonra yapın
});
Python (Flask)
import hashlib, hmac, os, time
from flask import Flask, request
@app.post("/pazaromatik-webhook")
def hook():
ts, sig = request.headers.get("X-PZM-Timestamp", ""), request.headers.get("X-PZM-Signature", "")
expected = "sha256=" + hmac.new(os.environ["PZM_WEBHOOK_SECRET"].encode(), ts.encode() + b"." + request.get_data(),
hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig) or abs(time.time() - int(ts or 0)) > 300:
return "", 401
event = request.get_json()
return "", 200
Kurallar
- 5 saniye içinde 2xx dönün. İşi senkron yapmayın: doğrulayın → kuyruğa atın → 200 dönün.
- Yeniden deneme: 2xx dışında her yanıt (ya da zaman aşımı) 1 dk, 5 dk, 15 dk, 1 sa, 3 sa, 6 sa ve 12 sa sonra yeniden denenir; 8 denemeden sonra bırakılır. Gönderimler 7 gün geçmişte görünür.
- En az bir kez teslim: Aynı olay nadiren iki kez gelebilir.
X-PZM-Delivery(gövdedekiid) değerini kaydedip tekrarını atlayın. - Sıra garanti değildir: Aynı siparişin iki
order.updated'ı ters sırada gelebilir; hangisinin yeni olduğunacreated_at'e bakarak karar verin ya da güncel hâliGET /v2/orders/{id}ile okuyun. - Yönlendirme (3xx) izlenmez; yerel ağ / özel IP adreslerine gönderim yapılmaz.
- Test olaylarında gövdede
"test": truebulunur; gerçek olaylarda bu alan hiç yoktur.