Webhooks
קבל אירועי חתימה בזמן אמת באמצעות HTTP עם משלוחים חתומים על ידי HMAC, ניסיונות חוזרים אוטומטיים ורשת ביטחון חוזרת מהמסוף. חתימת בקשה
SHA-256
Per-webhook סוד, נשלח כX-Endorsed-Signature
זמן קצוב למשלוח
החזר 2xx בתוך החלון או שהניסיון נכשל
מנסה שוב לאחר הניסיון הראשון
60s, 5m, 15m, 1h, ואז 6h
ממסוף המפתחים
בדוק כל ניסיון והפעל מחדש אירועים בודדים
מה אתה יכול לעשות עם אירועי webhook
כל מעבר משמעותי במחזור החיים פולט אירוע מוקלד. השתמש בהם כדי לעדכן את הרשומות שלך ללא סקר.
הפעל פעולות במורד הזרם
כאשר מעטפה חתומה במלואה, עדכן את ה-CRM שלך, שחרר משאב שהוקצה, או שלח אישור בתוך המוצר שלך - הכל מבלי לבצע סקר API.
סנכרון סטטוס מסמך
שמור את מסד הנתונים שלך מסונכרן עם מחזור חיי החתימה: נשלח, נפתח, נחתם, נדחה, פג תוקפו, בטל. אירוע אחד לכל מעבר, אין צורך בלולאת סקרים.
רישום ביקורת ותאימות
הזינו webhook אירועים לחנות הביקורת שלכם. מזהי מתאם מקשרים כל אירוע בחזרה לבקשת ה-API המקורית למעקב מלא.
הפעל מחדש משלוחים שנכשלו
אירועים שמתישים את סולם הניסיון החוזר נוחתים בתור של אותיות מתות שתוכלו לבדוק בקונסולת המפתחים ולהפעיל מחדש בכוונה. הפניה לאירוע
Webhook
רשם webhook, בחר אילו אירועים אתה רוצה, ו- EndorsedSign מספק מטען JSON עם ''event'', ''tenantId'', ''timestamp'' ו-''data''. שמות האירועים תואמים למחרוזות שאתה שולח בשיחת היצירה webhook.
| סוג אירוע | כאשר הוא יורה | שדות ''נתונים'' מפתח |
|---|---|---|
| document.created | אתה מעלה מסמך דרך API | documentId, customerId, externalDocumentId |
| document.sent | קישור החתימה נשלח לנמען הראשון | documentId, customerId, ערוץ |
| document.viewed | חתם פותח את קישור החתימה | מזהה מסמך, חותם דוא"ל, נצפה ב |
| document.signed | חתם בודד משלים את הצעד שלו | DocumentId, signerEmail, signedAt |
| document.completed | כל הצדדים חתמו | DocumentId, completedAt, downloadUrl |
| document.declined | חותם מסרב במפורש | DocumentId, SignerEmail, סיבה |
| document.expired | המסמך מגיע לתאריך התפוגה שלו ללא חתימה | documentId, expiredAt |
| signing.started | אסימון סשן חתימה מומש | documentId, sessionId, signerEmail |
| signing.completed | סיום סשן החתימה (נחתם או נדחה) | documentId, sessionId, תוצאה |
| customer.created /.updated /.deleted | אתה משנה רשומת לקוח | מזהה לקוח, מזהה לקוח חיצוני |
| template.created /.updated | אתה משנה תבנית | templateId, שם |
הרשימה המלאה חיה ב-backend `WEBHOOK_EVENTS`. הוסף או צמצם מנויים לכל webhook - צינור המסירה מוציא שיחת HTTP אחת לכל נקודת קצה רשומה.
אימות חתימות webhook (Node.js)
כל משלוח כולל כותרת `X-Endorsed-Signature`: `t={unix_seconds},v1={hex}`. `v1` הוא HMAC-SHA256 של `{timestamp}.{rawBody}` באמצעות הסוד שהוחזר כאשר ה- webhook נוצר. דחה חותמות זמן בחוץ ±5 דקות. ''X-Webhook-Signature'' עדיין עשוי להופיע במשלוחי בדיקות של פורטל מפתחים ככינוי שהוצא משימוש בגוף בלבד - אמת את ''X-Endorsed-Signature''. תנאים מוקדמים: סוד ה-webhook שלך ב-env var, מסלול אקספרס ששומר על הגוף הגולמי. פלט צפוי: מטענים לא מזוהים או מבולבלים נדחים עם 401 לפני הפעלת מטפל כלשהו.
import crypto from 'node:crypto';
import express from 'express';
const WEBHOOK_SECRET = process.env.ENDORSED_WEBHOOK_SECRET!;
const TOLERANCE_SECONDS = 5 * 60;
export function verifyWebhookSignature(
rawBody: string,
header: string | undefined,
nowSeconds = Math.floor(Date.now() / 1000),
): boolean {
if (!header) return false;
let timestamp: number | null = null;
let v1 = '';
for (const part of header.split(',')) {
const eq = part.indexOf('=');
if (eq === -1) continue;
const key = part.slice(0, eq).trim();
const value = part.slice(eq + 1).trim();
if (key === 't' && /^\d+$/.test(value)) timestamp = Number.parseInt(value, 10);
if (key === 'v1' && /^[a-f0-9]{64}$/i.test(value)) v1 = value.toLowerCase();
}
if (timestamp === null || !v1) return false;
if (Math.abs(nowSeconds - timestamp) > TOLERANCE_SECONDS) return false;
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(timestamp + '.' + rawBody)
.digest('hex');
const a = Buffer.from(expected, 'hex');
const b = Buffer.from(v1, 'hex');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
app.post(
'/webhooks/endorsed',
express.json({ verify: (req, _res, buf) => { (req as any).rawBody = buf.toString('utf8'); } }),
(req, res) => {
const sig = req.header('X-Endorsed-Signature');
if (!verifyWebhookSignature((req as any).rawBody, sig)) {
return res.status(401).send('Invalid signature');
}
res.sendStatus(200);
},
);החזר 2xx תוך 30 שניות או שהמסירה מסומנת ככשלה. ניסיונות שנכשלו נסה שוב עם הסולם שלמעלה וניתן להפעיל מחדש ממסוף המפתחים.
איך להגדיר נקודת קצה webhook
- 1
צור את נקודת הקצה באפליקציה שלך
הוסף מסלול שמקבל בקשות POST ומחזיר HTTP 200 תוך 10 שניות. כל תגובה של 2xx נחשבת כמסירה מוצלחת.
- 2
רשום את נקודת הקצה בהגדרות הדייר שלך
עבור אל Admin → הגדרות → Webhooks. הזן את כתובת האתר של נקודת הקצה שלך ובחר את סוגי האירועים הרצויים. סוד חתימה נוצר לכל נקודת קצה.
- 3
אמת את החתימה בכל בקשה
קרא את `X-Endorsed-Signature`. חשב מחדש את HMAC-SHA256 מעל `{timestamp}.{rawBody}` וזמן קבוע להשוות עם `v1` (ראה את דוגמת הקוד למעלה). דחה כותרת חסרה, ערך hex רע, חותמת זמן מחוץ ל-5 דקות או אי התאמה של HMAC. ''X-Webhook-Signature'' הוא כינוי שהוצא משימוש בחלק ממסירות הבדיקה - אל תתייחס אליו כאל החוזה החי.
- 4
החזר 2xx במהירות, עבד אסינכרון
אשר מסירה עם 200 תוך 10 שניות והעמיד את גוף האירוע בתור לעיבוד אסינכרון. קונסולת המפתחים מציגה כל ניסיון (כותרות, גוף, סטטוס, תזמון) ומאפשרת לך להפעיל מחדש כל מסירה - אין צורך להפעיל מחדש את זרימת חתימת המקור רק כדי לבדוק את המטפל שלך.
שאלות נפוצות
מטען אמיתי של webhook — המסמך הושלם
כאשר כל הצדדים חתמו, EndorsedSign מפרסם את המטען הזה לנקודת הקצה הרשומה שלך. אמת את חתימת ה-HMAC, הכנס לתור ואשר באמצעות 200.

חבר את webhook הראשון שלך
תבע ארגז חול, רשום את נקודת הקצה ב-Admin → Developer → Webhooks, ובדוק או הפעל מחדש כל מסירה ממסוף המפתחים.