Webhooks किसी भी अपस्ट्रीम सिस्टम को एक प्रकाशक में बदल देते हैं। एक payload पर हस्ताक्षर करें, उसे POST करें, और इंजन उसे content से मैप करके पुनर्निर्माण करता है — request path में कोई key exchange नहीं, क्योंकि signature ही auth है।

एंडपॉइंट

POST https://your-host/webhooks/{integration}

{integration} एक slug है जिसे आप integration बनाते समय चुनते हैं — किसी mapper का नाम नहीं। प्रत्येक का अपना slug, अपना secret, और उसके पीछे एक mapper होता है, इसलिए एक साइट पर कई हो सकते हैं: newsroom, docs-sync, partner-feed। Slugs में lowercase अक्षर, अंक और hyphens होते हैं।

php bin/fastsite webhook:create newsroom --site=blog --mapper=autoseo

यह एक बार पूरा URL और signing secret प्रिंट करता है। आप यही काम dashboard, REST API, या create_webhook MCP tool से भी कर सकते हैं — webhooks site-scoped होते हैं, इसलिए किसी साइट का कोई भी सदस्य admin बने बिना उन्हें मैनेज कर सकता है।

Request पर हस्ताक्षर करना

कुछ भी चलने से पहले raw body को verbatim पढ़ा और verify किया जाता है। दो headers आवश्यक हैं:

  • X-Fastsite-Signature: t=<unix>,v1=<hmac_sha256("<t>.<body>", secret)> — signed string timestamp है, एक literal dot, और वे exact bytes जो आप भेजते हैं। ±300 second की window के भीतर constant time में compare किया जाता है।
  • X-Delivery-Id — प्रत्येक delivery के लिए अद्वितीय। यह replay guard है: एक repeated id को 200 के साथ accept किया जाता है और दो बार process करने की बजाय चुपचाप नज़रअंदाज़ कर दिया जाता है।

उन्हीं bytes पर हस्ताक्षर करें जो आप वास्तव में transmit करते हैं। Signing और sending के बीच JSON को re-serialise करना ही आमतौर पर signature के verify न होने का कारण बनता है।

एक व्यावहारिक उदाहरण

# body.json is the exact bytes you sign and send
SECRET="whsec_…"
BODY=$(cat body.json)
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | \
  openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')

curl -X POST https://your-host/webhooks/newsroom \
  -H "X-Fastsite-Signature: t=$TS,v1=$SIG" \
  -H "X-Delivery-Id: $(uuidgen)" \
  -H "Content-Type: application/json" \
  --data-binary @body.json

क्या वापस मिलता है

Codeअर्थ
202Accepted। रिकॉर्ड किया गया और queue में डाला गया।
200Duplicate delivery id — पहले से देखा जा चुका है, कुछ नहीं किया गया।
400X-Delivery-Id अनुपस्थित है।
401Signature अनुपस्थित या अमान्य है।
404ऐसा कोई integration नहीं, या यह disabled है।

एंडपॉइंट milliseconds में जवाब देता है क्योंकि यह केवल रिकॉर्ड करता है और enqueue करता है। Mapping, build, और publish बाद में queue पर होते हैं, retries और backoff के साथ।

Webhooks publish करते हैं; API नहीं करता

यह दोनों ingest paths के बीच एकमात्र वास्तविक अंतर है। REST या MCP से content बनाने पर वह store हो जाती है और आपके publish करने की प्रतीक्षा करती है। एक webhook delivery अपना mapper चलाती है और फिर स्वतः एक build और publish को chain करती है — एक upstream system जो कोई article push करता है, उसे live उम्मीद है, staged नहीं।

Built-in mappers

Mappers code होते हैं, configuration strings नहीं। प्रत्येक एक generic payload लेता है और उसे एक engine action में बदलता है।

MapperPayloadकरता है
autoseo{id, title, body_html, slug?, excerpt?, featured_image_url?, author?, seo_title?, seo_description?, status?, published_at?}Idempotent article ingest, id पर keyed।
create_post{title, body_html, slug?, excerpt?, status?, author?, source_ref?}एक payload को post से map करता है।
create_pageऊपर जैसा हीएक payload को page से map करता है।
import_media{url, alt?, decorative?}URL से एक file (SSRF-guarded) को library में खींचता है।
upsert_component{handle, type, source_code, css?}एक component बनाता या अपडेट करता है।

Article pipeline के लिए autoseo ही पहली पसंद है। यह payload के id पर idempotent है, इसलिए redelivering दूसरा post बनाने की बजाय मौजूदा post को अपडेट करती है। यह images को भी adopt करता है: featured image और body में हर बाहरी <img> को आपकी media library में fetch करके local references में rewrite किया जाता है, और जब source में alt text नहीं होता तो title से alt text derive किया जाता है। यदि कोई image fetch नहीं हो पाती, तो वह image drop हो जाती है और article फिर भी publish होता है — एक टूटा हुआ CDN upstream आपकी कहानी की कीमत नहीं बननी चाहिए।

Content mappers पर, status का default published है। यदि आप चाहते हैं कि redelivery duplicate बनाने की बजाय अपडेट करे, तो source_ref पास करें।

जब कुछ गलत हो जाए

हर delivery अपने headers, body और outcome के साथ रिकॉर्ड की जाती है, इसलिए failure खोने की बजाय inspect करने योग्य होती है।

php bin/fastsite webhook:list
php bin/fastsite webhook:deliveries --limit=20
php bin/fastsite webhook:replay <delivery-id>

जो payload mapper उपयोग नहीं कर सकता — एक missing id, कोई title नहीं, malformed JSON — उसे skipped mark किया जाता है और retry नहीं किया जाता, क्योंकि retry से वह ठीक नहीं होगा। कोई भी और चीज़ जो throw करती है, उसे failed mark किया जाता है और backoff के साथ retry किया जाता है। Replay एक stored delivery को उसके recorded bytes से फिर से चलाता है, इसलिए आप sender को दोबारा भेजने के लिए कहे बिना mapper या credential ठीक करके reprocess कर सकते हैं।

Secrets encrypted store होते हैं और sender को configure करने के लिए dashboard से फिर से देखे जा सकते हैं। Push होने की बजाय pull करना पसंद है? REST API और MCP server समान operations cover करते हैं।