मुख्य सामग्री पर जाएं

वेबहुक

वेबहुक एक चर्च को तीसरी पार्टी के उपकरणों को वास्तविक समय की सूचनाओं को धकेलने देते हैं — स्वचालन प्लेटफॉर्म (Zapier, Make, n8n), CRMs, लेखांकन प्रणालियां, या कोई भी जो HTTP POST को स्वीकार करता है। जब B1 में कोई व्यक्ति, समूह या परिवार बदलता है, तो B1 हस्ताक्षरित JSON पेलोड को उस घटना के लिए सदस्य प्रत्येक URL को भेजता है।

शुरुआत से पहले

  • एक चर्च प्रशासक जो चर्च सेटिंग्स संपादित करें अनुमति के साथ वेबहुक को पंजीकृत और प्रबंधित करता है
  • आपका प्राप्त समापन बिंदु HTTPS पर एक सार्वजनिक पते पर पहुंचने योग्य होना चाहिए
  • हस्ताक्षरण गोपनीयता को सुरक्षित रूप से संग्रहीत करने का एक तरीका है — यह केवल एक बार दिखाया जाता है

अवलोकन

वेबहुक केवल आउटबाउंड हैं: B1 आपके समापन बिंदु को कॉल करता है, आप B1 को कॉल नहीं करते हैं। प्रत्येक वेबहुक एक प्रति-चर्च सदस्यता है जिसमें एक गंतव्य URL, एक हस्ताक्षरण गोपनीयता और सदस्य घटनाओं की एक सूची शामिल है।

वितरण एक टिकाऊ आउटबॉक्स का उपयोग करता है: जब कोई सदस्य घटना होती है, तो B1 एक वितरण पंक्ति रिकॉर्ड करता है और एक पृष्ठभूमि कार्यकर्ता इसे लगभग एक मिनट के भीतर POST करता है। विफल डिलीवरी घातांकीय बैकऑफ के साथ पुनः प्रयास किए जाते हैं। कुछ भी नहीं खोता है यदि एक वितरण धीमी है या आपका समापन बिंदु संक्षेप में बंद है।

एक वेबहुक पंजीकृत करना

B1Admin में

सेटिंग्स → डेवलपर → वेबहुक → नई वेबहुक पर जाएं। एक नाम, पेलोड URL दर्ज करें, और सदस्य करने के लिए घटनाएं चुनें। सहेजने पर, हस्ताक्षरण गोपनीयता तुरंत प्रदर्शित होता है — इसे तुरंत कॉपी करें और इसे अपने एकीकरण के साथ संग्रहीत करें। यह फिर कभी दिखाई नहीं देता है (आप बाद में इसे घुमा सकते हैं, लेकिन आप मूल को पुनः प्राप्त नहीं कर सकते)।

API के माध्यम से

सभी समापन बिंदु सदस्यता मॉड्यूल आधार पथ /membership/webhooks के तहत हैं और एक चर्च प्रशासक से JWT की आवश्यकता है जिसके पास Settings / Edit अनुमति है, या settings:write दायरे के साथ टकसाल API कुंजी। एक ही मार्ग दोनों को स्वीकार करता है। यह वह है जो Zapier और Make को चर्च की ओर से वेबहुक पंजीकृत करने देता है जब कोई Zap या परिदृश्य चालू हो जाता है।

POST /membership/webhooks
Authorization: Bearer <jwt>
Content-Type: application/json

{
"name": "Zapier — new members",
"url": "https://hooks.zapier.com/hooks/catch/123/abc",
"events": ["person.created", "person.updated", "group.member.added"]
}

सृजन प्रतिक्रिया — और केवल सृजन प्रतिक्रिया — secret शामिल करता है:

{
"id": "a1b2c3d4e5f",
"name": "Zapier — new members",
"url": "https://hooks.zapier.com/hooks/catch/123/abc",
"events": ["person.created", "person.updated", "group.member.added"],
"active": true,
"secret": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822c"
}
विधि और पथउद्देश्य
GET /membership/webhooksचर्च की वेबहुक को सूची में सूचीबद्ध करें (गोपनीयता छोड़ी गई)
GET /membership/webhooks/eventsमान्य ईवेंट नामों की सूची
GET /membership/webhooks/:idएक वेबहुक को लोड करें
POST /membership/webhooksबनाएं (कोई id नहीं) या अद्यतन करें (साथ में id)
POST /membership/webhooks/:id/regenerate-secretहस्ताक्षरण गोपनीयता को घुमाएं; नई मान को एक बार सौ करें
DELETE /membership/webhooks/:idएक वेबहुक हटाएं
GET /membership/webhooks/:id/deliveriesएक वेबहुक के लिए हालिया वितरण प्रयास
GET /membership/webhooks/deliveries/:deliveryIdएक वितरण के लिए पूर्ण पेलोड और प्रतिक्रिया
POST /membership/webhooks/deliveries/:deliveryId/redeliverएक वितरण को फिर से कतार में रखें

घटना सूची

घटना नाम पैटर्न का पालन करें {entity}.{action}GET /membership/webhooks/events से लाइव सूची प्राप्त करें।

घटनाकब फायर होता है
person.createdएक व्यक्ति जोड़ा जाता है
person.updatedएक व्यक्ति रिकॉर्ड बदल दिया जाता है
person.destroyedएक व्यक्ति हटाया जाता है
household.createdएक परिवार जोड़ा जाता है
household.updatedएक परिवार बदल दिया जाता है
household.destroyedएक परिवार हटाया जाता है
group.createdएक समूह जोड़ा जाता है
group.updatedएक समूह बदल दिया जाता है
group.destroyedएक समूह हटाया जाता है
group.member.addedएक व्यक्ति एक समूह में जोड़ा जाता है
group.member.removedएक व्यक्ति एक समूह से हटा दिया जाता है
donation.createdएक उपहार दर्ज किया जाता है — मैनुअल प्रविष्टि, ऑनलाइन, या प्रतीक्षित → पूर्ण संक्रमण
donation.updatedएक दान रिकॉर्ड संपादित किया जाता है
attendance.recordedएक यात्रा दर्ज की जाती है (मैनुअल प्रविष्टि या चेक-इन)
session.createdएक नया उपस्थिति सत्र बनाया जाता है (मैनुअल या पहली चेक-इन पर स्वचालित)
form.submission.createdएक फॉर्म जमा किया जाता है
event.createdएक कैलेंडर घटना जोड़ी जाती है
event.updatedएक कैलेंडर घटना संपादित की जाती है
event.destroyedएक कैलेंडर घटना हटाई जाती है

पेलोड प्रारूप

प्रत्येक वितरण एक HTTP POST है एक JSON बॉडी और इन शीर्षलेख के साथ:

शीर्षलेखविवरण
Content-Typeहमेशा application/json
X-B1-Eventघटना का नाम, जैसे person.created
X-B1-Delivery-Idइस वितरण प्रयास के लिए अद्वितीय id — इसे deduplicate करने के लिए उपयोग करें
X-B1-Signatureकच्चे शरीर के HMAC-SHA256 हस्ताक्षर (नीचे देखें)
X-B1-TimestampUnix epoch सेकंड जब अनुरोध भेजा गया था
User-AgentB1-Webhooks/1.0

शरीर एक छोटे लिफाफे में बदला हुआ संसाधन लपेटता है:

{
"event": "person.created",
"churchId": "AbC123XyZ90",
"occurredAt": "2026-05-17T14:32:08.114Z",
"data": {
"id": "Pq7Rs2Tu4Vw",
"churchId": "AbC123XyZ90",
"name": { "display": "Jordan Rivera", "first": "Jordan", "last": "Rivera" },
"contactInfo": { "email": "jordan@example.com" }
}
}

*.destroyed घटनाओं के लिए, data केवल हटाए गए रिकॉर्ड की id और churchId शामिल करता है।

जिन घटनाओं की पेलोड अन्य रिकॉर्डों को id द्वारा संदर्भित करते हैं, वे वितरण समय पर मानव-पठनीय नाम भी ले जाते हैं: personName और groupName समूह सदस्यता घटनाओं पर, personName उपस्थिति, दान और सूची सदस्यता घटनाओं पर, groupName session.created पर, और formName (साथ ही personName जब जमा किसी व्यक्ति से बंधा होता है) form.submission.created पर।

कनेक्टर प्रकार

डिफ़ॉल्ट वितरण प्रारूप ऊपर JSON लिफाफा है — connectorType: "standard"Slack और Discord के लिए एक ही वेबहुक इंजन इसके बजाय एक चैट-आकार का संदेश पोस्ट करता है जो उन सेवाएं सीधे स्वीकार करती हैं:

connectorTypeभेजा गया शरीरकब का उपयोग करें
"standard" (डिफ़ॉल्ट){event, churchId, occurredAt, data} लिफाफा, हस्ताक्षरितआप अपना खुद का एकीकरण लिख रहे हैं, या Zapier / Make / कस्टम सर्वर पर इंगित कर रहे हैं
"slack"{ "text": "💝 नया दान: $50.00" }आप सीधे Slack संदेश URL को कॉल कर रहे हैं
"discord"{ "content": "💝 नया दान: $50.00" }आप सीधे Discord चैनल वेबहुक को कॉल कर रहे हैं
"mailchimp"n/a — कनेक्टर Mailchimp API को स्वयं कॉल करता हैआप ऑडियंस सिंक चाहते हैं कोई URL के साथ होस्ट किए जाने के बिना

कनेक्टर प्रकार वेबहुक संपादक पर कनेक्टर प्रकार ड्रॉपडाउन में सेट किया जाता है, या POST /membership/webhooks शरीर में connectorType के माध्यम से। हस्ताक्षरित X-B1-Signature शीर्षलेख अभी भी Slack/Discord डिलीवरी के लिए भेजा जाता है (वे हानिरहित रूप से इसे अनदेखा करते हैं), इसलिए बाद में वेबहुक को standard पर स्विच करने के लिए कोई फिर से हस्ताक्षर की आवश्यकता नहीं होती है।

Slack और Discord शुद्ध शरीर को आकार देते हैं — इंजन अभी भी चर्च-आपूर्ति URL को POST करता है। mailchimp पहला कनेक्टर है जो इसके बजाय अपने HTTP विनिमय को स्वामित्व देता है: प्रति घटना यह Mailchimp API के विरुद्ध प्रमाणीकृत upsert/archive/tag अनुरोध जारी करता है (MailchimpConnector.deliver), और इसके क्रेडेंशियल ({apiKey, audienceId}) webhooks.connectorConfig में AES-एन्क्रिप्ट संग्रहीत होते हैं, API के माध्यम से केवल-लिखना। Mailchimp वेबहुक केवल व्यक्ति, समूह-सदस्य और सूची-सदस्य घटनाओं को स्वीकार करते हैं; बचत मार्ग Mailchimp के विरुद्ध कुंजी और ऑडियंस को सत्यापित करता है स्वीकार करने से पहले। वितरण पंक्तियां मानक लिफाफा संग्रहीत करते हैं, इसलिए वितरण लॉग B1 के साथ Mailchimp की प्रतिक्रिया दिखाता है। अमैप की गई स्थितियां (कोई ईमेल के साथ व्यक्ति, कोई मैपिंग के साथ घटना) पुनः प्रयास जलाने के बजाय Skipped: प्रतिक्रिया शरीर के साथ सफल हो जाते हैं।

परीक्षण डिलीवरी

हर वेबहुक संपादक में एक परीक्षा घटना भेजें बटन है — संबंधित API कॉल POST /membership/webhooks/:id/test है। परीक्षा मार्ग पहली सदस्य घटना के लिए एक सिंथेटिक पेलोड बनाता है, इसे वास्तविक हस्ताक्षरित वितरण पथ के माध्यम से सिंक्रोनस रूप से भेजता है (और Slack/Discord के लिए formatForConnector के माध्यम से), और परिणामी वितरण पंक्ति को responseStatus और responseBody सहित सौ करता है। इसका उपयोग एकीकरण को वास्तविक के लिए चालू करने से पहले कनेक्टिविटी और हस्ताक्षर हैंडलिंग की पुष्टि करने के लिए करें। mailchimp वेबहुक के लिए परीक्षा इसके बजाय Mailchimp API के विरुद्ध संग्रहीत क्रेडेंशियल को सत्यापित करता है (एक सिंथेटिक घटना चर्च की वास्तविक ऑडियंस में एक नकली सदस्य लिखता है) और कोई पंक्ति बनाए बिना एक वितरण-आकार परिणाम सौ करता है।

हस्ताक्षर सत्यापित करना

पेलोड पर भरोसा करने से पहले हमेशा X-B1-Signature सत्यापित करें। हस्ताक्षर sha256= होता है जिसके बाद कच्चे अनुरोध शरीर का hex HMAC-SHA256 होता है जो आपकी हस्ताक्षरण गोपनीयता के साथ कुंजी होता है। आपके द्वारा प्राप्त बाइट्स पर इसे गणना करें — पार्स किए गए JSON को फिर से serialize न करें।

Node.js

const crypto = require("crypto");

function isValid(rawBody, signatureHeader, secret) {
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signatureHeader || "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Python

import hashlib, hmac

def is_valid(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header or "")

PHP

function isValid(string $rawBody, string $signatureHeader, string $secret): bool {
$expected = "sha256=" . hash_hmac("sha256", $rawBody, $secret);
return hash_equals($expected, $signatureHeader ?? "");
}

कोई भी अनुरोध जिसका हस्ताक्षर मेल नहीं खाता अस्वीकार करें। वैकल्पिक रूप से भी X-B1-Timestamp पुनरावृत्ति विंडो को सीमित करने के लिए कुछ मिनटों से अधिक पुरानी अनुरोधों को अस्वीकार करें।

SDK सपोर्ट

Node.js के लिए, @churchapps/integration-sdk एक टाइप किया गया सत्यापक और Express मध्यस्थ को जहाज देता है जो कच्चे-शरीर पकड़, हस्ताक्षर चेक और लिफाफे को आपके लिए पार्स करता है:

import express from "express";
import { b1WebhookMiddleware } from "@churchapps/integration-sdk";

const app = express();
// हस्ताक्षर को अभी भी सत्यापित करने के लिए आवश्यक JSON पार्सिंग से पहले कच्चे शरीर को पकड़ें।
app.use(express.json({ verify: (req, _res, buf) => { (req as any).rawBody = buf; } }));

app.post("/webhooks/b1", b1WebhookMiddleware({ secret: process.env.B1_WEBHOOK_SECRET! }), (req, res) => {
const env = req.b1Webhook!;
switch (env.event) {
case "donation.created": console.log("new gift", env.data.amount); break;
}
res.sendStatus(200);
});

SDK भी WebhookVerifier.verify(secret, rawBody, signatureHeader) को Express-न-रनटाइम (सर्वलेस कार्य, Fastify, आदि) के लिए प्रकट करता है। npm पर पैकेज देखें।

डिलीवरी और पुनः प्रयास

आपका समापन बिंदु जितनी जल्दी संभव हो 2xx स्थिति के साथ प्रतिक्रिया करना चाहिए — आदर्श रूप से केवल काम को कतार में रखने के बाद, इसे संसाधित करने के बाद नहीं। कोई भी गैर-2xx प्रतिक्रिया, एक कनेक्शन विफलता, या 10 सेकंड से धीमी प्रतिक्रिया एक विफल वितरण के रूप में मायने रखता है।

विफल डिलीवरी घातांकीय बैकऑफ के साथ पुनः प्रयास किए जाते हैं — 16 प्रयास लगभग 5 दिनों में। अंतराल 1 मिनट से, घंटों के माध्यम से, अंतिम प्रयासों के लिए 3-दिन के अंतराल तक बढ़ता है। 16वें विफल प्रयास के बाद वितरण को exhausted के रूप में चिह्नित किया जाता है और छोड़ दिया जाता है।

वितरण कम से कम-एक बार है: एक वितरण एक से अधिक बार आ सकता है (उदाहरण के लिए, यदि आपका समापन बिंदु सफल होता है लेकिन प्रतिक्रिया खो जाती है)। deduplicate करने के लिए X-B1-Delivery-Id शीर्षलेख का उपयोग करें — प्रत्येक id को केवल एक बार संसाधित करें और दोहराव को no-ops मानें।

ऑटो-अक्षमता

यदि एक वेबहुक तीन क्रमागत थकी हुई डिलीवरी का उत्पादन करता है, तो B1 इसे स्वचालित रूप से अक्षम करता है। कारण को ठीक करें (आमतौर पर एक रद्द कुंजी), इसे फिर से सक्षम करें और परीक्षण भेजें के साथ पुष्टि करें।

निरीक्षण और फिर से भेजना

B1Admin में वेबहुक संपादक एक हाल की डिलीवरी टेबल दिखाता है — घटना, स्थिति, प्रयास गणना, प्रतिक्रिया कोड और टाইमस्टैम्प। एक पंक्ति चुनने से भेजा गया पूर्ण पेलोड और प्राप्त प्रतिक्रिया का पता चलता है।

किसी भी पिछली डिलीवरी को फिर से भेजने के लिए फिर से भेजें का उपयोग करें इसकी मूल पेलोड के साथ — अपने समापन बिंदु में कोई बग को ठीक करने के बाद उपयोगी, या आपका समापन बिंदु जबकि बंद था को याद की गई घटनाओं को backfill करने के लिए।

URL आवश्यकताएं

क्योंकि वेबहुक URL चर्च-आपूर्ति होते हैं, B1 सर्वर-साइड अनुरोध जालसाजी के विरुद्ध रक्षक को लागू करता है। एक वेबहुक URL को अस्वीकार कर दिया जाता है — पंजीकरण पर और हर वितरण से पहले फिर से जांच की जाती है — यदि यह:

  • https नहीं का उपयोग करता है
  • localhost, .local / .internal होस्टनाम पर इंगित करता है, या
  • एक निजी, loopback, link-local या cloud-metadata IP पते को हल करता है

आपका समापन बिंदु एक सार्वजनिक रूप से पहुंचने योग्य HTTPS सेवा होना चाहिए।