Webhook یعنی وقتی رویدادی در سرویس خارجی رخ می‌دهد (پرداخت تأیید شد، سفارش آماده شد)، آن سرویس یک درخواست HTTP — معمولاً POST — به URL شما می‌فرستد. Polling برعکس است: شما هر چند ثانیه یا دقیقه API می‌زنید و می‌پرسید «آیا چیزی عوض شده؟». در اتوماسیون داده، webhook برای رویدادهای لحظه‌ای و polling برای sync دوره‌ای bulk منطقی‌تر است. مبنای API در راهنمای دریافت داده از API.

خلاصه
  • Webhook = push رویداد؛ polling = pull دوره‌ای.
  • endpoint شما باید سریع ۲xx بدهد؛ پردازش سنگین async.
  • امضا (HMAC) و idempotency برای تحویل تکراری.

تفاوت عملی

Webhook در برابر polling
معیارWebhookPolling
تأخیرثانیه‌ها پس از رویدادتا یک interval کامل (مثلاً ۵ دقیقه)
بار روی شمافقط وقتی رویداد هستمداوم حتی اگر تغییری نباشد
بار روی ارائه‌دهندهpush کنترل‌شدههر مشتری هر N ثانیه می‌زند
پیچیدگیendpoint عمومی، TLS، امضاcron + client ساده‌تر
با scrapeمکمل (اعلان سفارش)هم‌راستا با job شبانه scrape

مثال: پرداخت → سفارش در Django

Payment provider→POST webhook→ Django view→validate signature→update order
نمونه نمایشی — جریان تأیید پرداخت

ارائه‌دهنده پرداخت بعد از موفقیت، JSON شامل order_id و event_id می‌فرستد. view شما امضا را با secret مشترک چک می‌کند، رویداد را idempotent پردازش می‌کند (اگر event_id قبلاً دیده شده → ۲۰۰ بدون کار دوباره)، وضعیت سفارش را به «پرداخت‌شده» به‌روز می‌کند.

امنیت و امضا

secret در env نگه دارید؛ header امضا (مثلاً X-Signature) را با HMAC payload محاسبه و مقایسه کنید. timestamp در payload برای جلوگیری از replay قدیمی. IP allowlist در صورت مستند بودن.

Retry و تحویل تکراری

اگر endpoint شما ۵xx یا timeout بدهد، ارائه‌دهنده معمولاً همان رویداد را دوباره می‌فرستد. بنابراین handler باید idempotent باشد: کلید یکتا event_id در DB؛ duplicate → ۲۰۰ OK.

HTTP response و timeout

ارائه‌دهنده انتظار پاسخ سریع دارد (اغلب چند ثانیه). کار سنگین (ایمیل، scrape follow-up) را در queue بگذارید و بلافاصله ۲۰۰ برگردانید. اگر sync پردازش کنید و ۳۰ ثانیه طول بکشد، retryهای پشت‌سرهم و duplicate زیاد می‌شود.

python">
# ایدهٔ idempotency — شبه‌کد
def payment_webhook(request):
    verify_hmac(request.body, request.headers["X-Signature"])
    payload = json.loads(request.body)
    if WebhookEvent.objects.filter(event_id=payload["event_id"]).exists():
        return HttpResponse(status=200)
    WebhookEvent.objects.create(event_id=payload["event_id"], raw=payload)
    enqueue_process_payment(payload["order_id"])
    return HttpResponse(status=200)

Webhook در برابر زمان‌بندی scrape

Webhook برای «الان یک سفارش جدید آمد» عالی است. برای «هر شب همه قیمت‌های ۵۰ هزار محصول» هنوز cron یا Celery لازم است. بعضی پروژه‌ها hybrid دارند: webhook برای trigger فوری + job شبانه برای تکمیل dataset.

نکته

در محیط توسعه از tunnel (مثلاً ngrok) برای تست webhook استفاده کنید؛ URL ثابت production را در پنل ارائه‌دهنده ثبت کنید.

در عمل چه انتخابی کنیم؟

رویداد لحظه‌ای با قرارداد push از سرویس → webhook با امضا و idempotency. فقط sync دوره‌ای bulk بدون push رسمی → polling یا scrape زمان‌بندی‌شده. پیاده‌سازی endpoint: توسعه API. خطا و retry سمت ingest: مدیریت خطا.