מפתחים

Webhooks

קבל אירועי חתימה בזמן אמת באמצעות HTTP עם משלוחים חתומים על ידי HMAC, ניסיונות חוזרים אוטומטיים ורשת ביטחון חוזרת מהמסוף. חתימת בקשה

HMAC

SHA-256

Per-webhook סוד, נשלח כX-Endorsed-Signature

10s

זמן קצוב למשלוח

החזר 2xx בתוך החלון או שהניסיון נכשל

5×

מנסה שוב לאחר הניסיון הראשון

60s, 5m, 15m, 1h, ואז 6h

Replay

ממסוף המפתחים

בדוק כל ניסיון והפעל מחדש אירועים בודדים

מה אתה יכול לעשות עם אירועי webhook

כל מעבר משמעותי במחזור החיים פולט אירוע מוקלד. השתמש בהם כדי לעדכן את הרשומות שלך ללא סקר.

✅

הפעל פעולות במורד הזרם

כאשר מעטפה חתומה במלואה, עדכן את ה-CRM שלך, שחרר משאב שהוקצה, או שלח אישור בתוך המוצר שלך - הכל מבלי לבצע סקר API.

🔄

סנכרון סטטוס מסמך

שמור את מסד הנתונים שלך מסונכרן עם מחזור חיי החתימה: נשלח, נפתח, נחתם, נדחה, פג תוקפו, בטל. אירוע אחד לכל מעבר, אין צורך בלולאת סקרים.

📋

רישום ביקורת ותאימות

הזינו webhook אירועים לחנות הביקורת שלכם. מזהי מתאם מקשרים כל אירוע בחזרה לבקשת ה-API המקורית למעקב מלא.

🔁

הפעל מחדש משלוחים שנכשלו

אירועים שמתישים את סולם הניסיון החוזר נוחתים בתור של אותיות מתות שתוכלו לבדוק בקונסולת המפתחים ולהפעיל מחדש בכוונה. הפניה לאירוע

Webhook

רשם webhook, בחר אילו אירועים אתה רוצה, ו- EndorsedSign מספק מטען JSON עם ''event'', ''tenantId'', ''timestamp'' ו-''data''. שמות האירועים תואמים למחרוזות שאתה שולח בשיחת היצירה webhook.

סוג אירוע כאשר הוא יורה שדות ''נתונים'' מפתח
document.createdאתה מעלה מסמך דרך APIdocumentId, 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 לפני הפעלת מטפל כלשהו.

typescript
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. 1

    צור את נקודת הקצה באפליקציה שלך

    הוסף מסלול שמקבל בקשות POST ומחזיר HTTP 200 תוך 10 שניות. כל תגובה של 2xx נחשבת כמסירה מוצלחת.

  2. 2

    רשום את נקודת הקצה בהגדרות הדייר שלך

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

  3. 3

    אמת את החתימה בכל בקשה

    קרא את `X-Endorsed-Signature`. חשב מחדש את HMAC-SHA256 מעל `{timestamp}.{rawBody}` וזמן קבוע להשוות עם `v1` (ראה את דוגמת הקוד למעלה). דחה כותרת חסרה, ערך hex רע, חותמת זמן מחוץ ל-5 דקות או אי התאמה של HMAC. ''X-Webhook-Signature'' הוא כינוי שהוצא משימוש בחלק ממסירות הבדיקה - אל תתייחס אליו כאל החוזה החי.

  4. 4

    החזר 2xx במהירות, עבד אסינכרון

    אשר מסירה עם 200 תוך 10 שניות והעמיד את גוף האירוע בתור לעיבוד אסינכרון. קונסולת המפתחים מציגה כל ניסיון (כותרות, גוף, סטטוס, תזמון) ומאפשרת לך להפעיל מחדש כל מסירה - אין צורך להפעיל מחדש את זרימת חתימת המקור רק כדי לבדוק את המטפל שלך.

שאלות נפוצות

מטען אמיתי של webhook — המסמך הושלם

כאשר כל הצדדים חתמו, EndorsedSign מפרסם את המטען הזה לנקודת הקצה הרשומה שלך. אמת את חתימת ה-HMAC, הכנס לתור ואשר באמצעות 200.

 היסטוריית אירועי מסירה עם ערכי מחזור חיים של מסמכים
היסטוריית אירועי מסירה - אירועי מחזור חיים חתומים עם חותמות זמן ותוצאות סטטוס לאימות תפעולי.

חבר את webhook הראשון שלך

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