סקירה כללית
ה-Webhooks של דרימפו מאפשרים ליישום שלך לקבל התראות בזמן אמת כאשר מידע משתנה בארגון הניהול שלך. במקום לבצע Polling מול ה-API, אתה מספק כתובת URL, ואנחנו שולחים בקשת HTTP POST לכתובת זו בכל פעם שמתרחש אירוע רלוונטי.
למה אפשר להירשם #
| ישות | אירועים מופעלים |
|---|---|
| קריאת שירות (Service Call) | נוצרה, עודכנה |
| ביקורת מתוזמנת (Scheduled Review) | נוצרה, עודכנה, נמחקה |
| משימת ארגון (Organization Task) | נוצרה, עודכנה |
| חשבונית מס (Tax Invoice) | נוצרה, זוכתה |
| הוצאה (Expense) | נוצרה, זוכתה |
איך זה עובד #
- אתה רושם כתובת URL ל-Webhook ובוחר אילו סוגי ישויות תרצה לקבל.
- אתה יוצר Secret Token (שמור אותו — לא נציג אותו שוב).
- כאשר אירוע מתרחש בארגון שלך, דרימפו שולחת בקשת
POSTלכתובת שלך עם Payload בפורמט JSON. - השרת שלך מאמת את כותרת
X-Webhook-Secretומעבד את האירוע.
דרישות מנקודת הקצה שלך #
- כתובת HTTPS ציבורית וזמינה
- מחזירה HTTP 2xx בתוך זמן סביר
- מסוגלת לטפל במשלוחים כפולים (Idempotent)
- מאמתת את כותרת
X-Webhook-Secretבכל בקשה
התחלה מהירה
הפעל את ה-Webhook הראשון שלך תוך 5 דקות.
שלב 1 — הכן נקודת קצה ציבורית #
נקודת הקצה שלך חייבת להיות:
- כתובת HTTPS ציבורית (לדוגמה:
https://your-app.com/darimpo-webhooks) - לקבל
POSTעם גוף JSON - להחזיר
200 OKבמהירות האפשרית
שלב 2 — רשום את ה-Webhook במערכת דרימפו #
רישום וניהול Webhooks מתבצע כולו מתוך מערכת דרימפו, לא באמצעות קריאות API.
- היכנס למערכת דרימפו בכתובת
manager.darimpo.comעם שם המשתמש והסיסמה שלך. - בתפריט העליון, עבור ל-הגדרות ← Webhooks.
- לחץ על הוסף Webhook והזן:
- URL — כתובת נקודת הקצה שלך
- שם — שם תיאורי להצגה
- סוגי ישויות — בחר אילו אירועים תרצה לקבל (קריאות שירות, חשבוניות וכו')
- שמור. המערכת תיצור Webhook פעיל ותציג את ה-Secret Token.
שלב 3 — שמור את ה-Secret Token #
לאחר שמירת ה-Webhook, המערכת מציגה את ה-secretToken:
secretToken מוצג רק פעם אחת, ביצירה. שמור אותו במקום מאובטח — הוא לא יוצג שוב.ה-Token הזה הוא מה שישלח בכל בקשה שדרימפו תפנה לשרת שלך, ובאמצעותו השרת שלך יאמת שהבקשה אכן הגיעה מדרימפו.
שלב 4 — טפל באירועים נכנסים #
דרימפו תשלח בקשות POST בצורה הבאה:
// Headers Content-Type: application/json X-Webhook-Secret: 123456 // Body { "event": "created", "entityType": "tax_invoice", "entityId": 1599173, "webhookId": 1, "timestamp": 1777174160730, "data": { "id": 1599173, "lastUpdated": 1777174160461, "apartmentId": 741, "payment": 1, "type": 0, "transactionType": 1 } }
השרת שלך צריך:
- לאמת שה-
X-Webhook-Secretתואם לטוקן ששמרת. - להחזיר
200 OKמיד. - לעבד את האירוע באופן אסינכרוני.
שלב 5 — בדוק את זה #
הפעל את האירוע מממשק המשתמש של דרימפו (לדוגמה, צור חשבונית מס). נקודת הקצה שלך אמורה לקבל את ההתראה תוך שניות.
אימות ואבטחה
כל בקשת Webhook מדרימפו כוללת כותרת עם Secret Token. עליך לאמת אותה לפני עיבוד ה-Payload.
ה-Secret Token #
ה-secretToken שהוצג ביצירת ה-Webhook הוא מפתח משותף בין השרת שלך לדרימפו.
הוא משמש לאימות שכל בקשה נכנסת הגיעה באמת מדרימפו ולא מגורם חיצוני.
חשוב:
- ה-Token מוצג רק ביצירת ה-Webhook ולא ניתן להציגו שוב במערכת.
- אחסן את ה-Token במנהל Secrets או במשתני סביבה — לעולם לא בקוד.
אם איבדת את ה-Token, תצטרך ליצור Webhook חדש, או לבצע רוטציה דרך ממשק הניהול.
הכותרת X-Webhook-Secret #
כאשר דרימפו שולחת Webhook, בקשת ה-HTTP כוללת:
X-Webhook-Secret: wh_sk_9c2b4a7e8f1d...
הערך תואם ל-secretToken שנוצר ברישום ה-Webhook.
מה השרת שלך צריך לעשות #
בכל בקשה נכנסת:
- קרא את הכותרת
X-Webhook-Secret. - השווה אותה ל-Token ששמרת עבור Webhook זה.
- אם הערכים לא תואמים או שהכותרת חסרה — החזר
401 Unauthorizedואל תמשיך לעבד. - לשם אבטחה מוגברת, השתמש בהשוואה בזמן קבוע (Timing-safe comparison) כדי למנוע התקפות תזמון.
שיטות עבודה מומלצות באבטחה #
- תמיד הגש את נקודת הקצה שלך מעל HTTPS
- שמור Secrets במנהל Secrets או במשתני סביבה, לעולם לא בקוד
- השתמש בהשוואה בזמן קבוע
- דחה בקשות ללא הכותרת עם
401 - אל תרשום ערכי Secret בלוגים
- אל תקבל Webhooks מעל HTTP רגיל (לא מוצפן)
ניהול Webhooks
רישום, עדכון ומחיקה של Webhooks מתבצעים כולם מתוך מערכת דרימפו, לא באמצעות קריאות API.
רישום Webhook חדש #
- היכנס למערכת דרימפו בכתובת
manager.darimpo.com. - בתפריט העליון, עבור ל-הגדרות ← Webhooks.
- לחץ על הוסף Webhook והזן URL, שם וסוגי ישויות.
- שמור. המערכת תציג את ה-Secret Token — שמור אותו מיד, הוא לא יוצג שוב.
למדריך המלא #
ניהול מפורט של Webhooks — כולל עריכה, השבתה, מחיקה, רוטציית Secret, וניטור משלוחים — מכוסה במדריך הניהול הנפרד.
לפרטים טכניים על מבנה הבקשות שתקבל, עבור ל-מבנה ה-Payload.
סוגי אירועים
משלוח Webhook מורכב משני מזהים: entityType — איזה סוג של אובייקט השתנה, ו-event — מה קרה לו.
סוגי ישויות #
בעת רישום Webhook, העבר את מזהי הישויות כמספרים שלמים במערך entityTypes.
| ID | entityType (ב-Payload) | תיאור |
|---|---|---|
1 | service_call | קריאת שירות / תחזוקה |
2 | schedual_review | ביקורת תקופתית מתוזמנת |
3 | organization_task | משימה בבעלות ארגון הניהול |
4 | tax_invoice | חשבונית מס / קבלה |
5 | expense | הוצאה של הבניין |
[1, 4] מספק קריאות שירות וחשבוניות מס.אירועים #
השדה event ב-Payload יהיה אחד מאלה:
| ערך | משמעות |
|---|---|
created | הישות זה עתה נוצרה |
updated | ישות קיימת שונתה |
deleted | הישות נמחקה |
אירועים שנשלחים לכל ישות #
לא כל ישות פולטת כל אירוע. הטבלה הבאה מראה מה תקבל בפועל:
| ישות | created | updated | deleted |
|---|---|---|---|
service_call | ✅ | ✅ | — |
schedual_review | ✅ | ✅ | ✅ |
organization_task | ✅ | ✅ | — |
tax_invoice | ✅ | — | ✅ |
expense | ✅ | — | ✅ |
מקרה מיוחד: מחיקת הוצאה
כאשר הוצאה נמחקת, דרימפו עשויה לשלוח שני אירועים:
deleted— ההוצאה המקוריתcreated— הוצאת זיכוי (Reversal)
זה משקף את אופן מעקב המחיקות בחשבונאות. טפל בשני האירועים בשילוב שלך.
מקרה מיוחד: זיכויי חשבונית מס
כאשר חשבונית מס מבוטלת עם הודעת זיכוי, אתה מקבל אירוע created לחשבונית חדשה שבה:
creditTypeמוגדרparentIdמפנה לחשבונית המקורית
מבנה ה-Payload
כל משלוחי ה-Webhook חולקים את אותו מעטפת. רק data משתנה לפי סוג הישות.
מעטפת #
{ "event": "created", "entityType": "tax_invoice", "entityId": 1599173, "webhookId": 1, "timestamp": 1777174160730, "data": { ... } }
| שדה | סוג | תיאור |
|---|---|---|
event | string | created | updated | deleted |
entityType | string | לדוגמה service_call, tax_invoice |
entityId | long | מזהה הישות המושפעת |
webhookId | long | מזהה ה-Webhook שקיבל משלוח זה |
timestamp | long | זמן משלוח (Epoch milliseconds) |
data | object | שדות ספציפיים לישות (ראה למטה) |
שדות בסיס לכל הישויות #
כל הישויות כוללות את שדות הבסיס הללו:
| שדה | סוג | תיאור |
|---|---|---|
id | long | מפתח ראשי |
lastUpdated | long | זמן עדכון אחרון (Epoch ms) |
סוגי שדות לפי סיומת
| סיומת | סוג | הערות |
|---|---|---|
Id | long | מזהה מספרי |
Date, timestamp | long | Epoch milliseconds (UTC) |
payment, amount, fee | float | ערכי מטבע, 2 מקומות עשרוניים |
service_call #
{ "id": 472871, "lastUpdated": 1777173826103, "status": 0, "reportedDate": 1777173825995, "resolvedDate": 0, "buildingFacilityId": 836, "buildingFacilityName": "אחר", "isPublic": true, "isEmergency": false, "descriptionDone": "", "description": "תקלת בדיקה", "buildingId": 401, "dueDateReminder": 0, "areaId": 34760, "fullAddress": "ליגד סנטר 2, קומה 1", "area": { "id": 34760, "name": "1", "lastUpdated": 0 }, "serviceCallAvgUrgency": { "urgency": 0, "usersCount": 1 } }
שדות
| שדה | סוג | תיאור |
|---|---|---|
status | int | סטטוס הקריאה (ראה טבלה למטה) |
reportedDate | long | תאריך הדיווח (Epoch ms) |
resolvedDate | long | תאריך הפתרון (Epoch ms). 0 = לא נפתר |
buildingFacilityId | long | מזהה המתקן בבניין |
buildingFacilityName | string | שם המתקן |
isPublic | boolean | האם הקריאה ציבורית (גלויה לדיירים) |
isEmergency | boolean | האם הקריאה דחופה |
description | string | תיאור הבעיה |
descriptionDone | string | תיאור הטיפול שבוצע |
buildingId | long | מזהה הבניין |
dueDateReminder | long | יעד לטיפול (Epoch ms) |
areaId | long | מזהה האזור |
fullAddress | string | כתובת מלאה לתצוגה |
area | object | אובייקט האזור — ראה מבנה למטה |
serviceCallAvgUrgency | object | דחיפות ממוצעת — ראה מבנה למטה |
area (אובייקט)
| שדה | סוג | תיאור |
|---|---|---|
id | long | מזהה האזור |
name | string | שם האזור |
lastUpdated | long | זמן עדכון אחרון (Epoch ms) |
serviceCallAvgUrgency (אובייקט)
הדחיפות מחושבת כממוצע על בסיס הצבעות של משתמשים שצפו בקריאה.
| שדה | סוג | תיאור |
|---|---|---|
urgency | int | דחיפות ממוצעת (ראה טבלה למטה) |
usersCount | int | מספר המשתמשים שדירגו |
status
| ערך | משמעות |
|---|---|
0 | התקבלה |
1 | בטיפול |
2 | טופל |
urgency (בתוך serviceCallAvgUrgency)
| ערך | משמעות |
|---|---|
0 | לא חשוב |
1 | חשוב |
2 | חשוב מאוד |
3 | דחוף |
4 | מסוכן |
schedual_review #
{ "id": 29526, "lastUpdated": 1777174075835, "isPartialExecution": false, "lastReviewDate": 0, "reviewDaysFrequancy": 7, "name": "ביקורת תקופתית", "checklist": "{\"lastId\":0, \"selectedIds\":[], \"items\":[]}", "description": "ביקורת עבור webhooks", "buildingId": 401, "dueDateReminder": 1776157200000, "areaId": 0 }
שדות
| שדה | סוג | תיאור |
|---|---|---|
isPartialExecution | boolean | האם הביצוע חלקי |
lastReviewDate | long | תאריך הביקורת האחרונה (Epoch ms). 0 = אין |
reviewDaysFrequancy | int | תדירות הביקורת בימים |
name | string | שם הביקורת |
checklist | string | מחרוזת JSON של פריטי הצ'קליסט |
description | string | תיאור הביקורת |
buildingId | long | מזהה הבניין |
dueDateReminder | long | יעד לטיפול (Epoch ms) |
areaId | long | מזהה האזור. 0 = ללא אזור |
checklist הוא מחרוזת המכילה JSON, ולא אובייקט JSON ישיר. עליך לבצע JSON.parse על תוכן השדה כדי לקרוא את הצ'קליסט.ל-schedual_review אין שדות Enum ייחודיים.
organization_task #
{ "id": 45122, "lastUpdated": 1777173940716, "status": 1, "type": 2, "urgency": 0, "reportedDate": 1777173940700, "isEmergency": false, "description": "משימה ארגונית", "buildingId": 2142, "dueDateReminder": 1777194000000, "areaId": 0 }
שדות
| שדה | סוג | תיאור |
|---|---|---|
status | int | סטטוס המשימה (ראה טבלה למטה) |
type | int | סוג המשימה (ראה טבלה למטה) |
urgency | int | דחיפות (ראה טבלה למטה) |
reportedDate | long | תאריך הדיווח (Epoch ms) |
isEmergency | boolean | האם המשימה דחופה |
description | string | תיאור המשימה |
buildingId | long | מזהה הבניין |
dueDateReminder | long | יעד לטיפול (Epoch ms) |
areaId | long | מזהה האזור. 0 = ללא אזור |
status
| ערך | משמעות |
|---|---|
1 | התקבלה |
2 | בטיפול |
3 | טופל |
urgency
| ערך | משמעות |
|---|---|
1 | לא חשוב |
2 | חשוב |
3 | חשוב מאוד |
4 | דחוף |
5 | מסוכן |
type (סוג משימה)
| ערך | משמעות |
|---|---|
1 | הצעת מחיר |
2 | תשלום ועד בית |
3 | צור קשר |
4 | חירום |
5 | אחר |
tax_invoice #
{ "id": 1599173, "lastUpdated": 1777174160461, "apartmentId": 741, "apartmentAddress": "ליגד סנטר 2, דירה 2", "buildingTaxPricingModelName": "ועד בית - 2026", "months": [ { "month": 3, "payment": 1, "id": 2131254, "lastUpdated": 0 } ], "creditTaxInvoiceId": 0, "payment": 1, "type": 0, "transactionType": 1, "actualPayDate": 1777174157491, "repaymentDate": 1777181357491, "deletedId": 0, "parentId": 0, "isDeposit": false, "notes": "", "description": "ועד בית ליגד סנטר 2 דירה 2" }
שדות
| שדה | סוג | תיאור |
|---|---|---|
apartmentId | long | מזהה הדירה |
apartmentAddress | string | כתובת הדירה לתצוגה |
buildingTaxPricingModelName | string | שם מודל החיוב של הבניין |
months | array | רשימת חודשי החיוב — ראה מבנה למטה |
creditTaxInvoiceId | long | מזהה חשבונית הזיכוי הקשורה. 0 = אין |
payment | float | סכום החשבונית הכולל |
type | int | אמצעי תשלום (ראה טבלה למטה) |
transactionType | int | סוג עסקה (ראה טבלה למטה) |
actualPayDate | long | תאריך התשלום בפועל (Epoch ms) |
repaymentDate | long | תאריך תשלום מתוכנן (Epoch ms) |
deletedId | int | 1 = מזוכה, 0 = לא מזוכה |
parentId | long | מזהה החשבונית ההורה. 0 = אין הורה |
isDeposit | boolean | true = הפקדה |
notes | string | הערות חופשיות |
description | string | תיאור החשבונית |
months[] (פריט בודד)
| שדה | סוג | תיאור |
|---|---|---|
month | int | חודש (1-12) |
payment | float | סכום לחודש |
id | long | מזהה רשומת החודש |
lastUpdated | long | זמן עדכון אחרון (Epoch ms) |
type (אמצעי תשלום)
| ערך | משמעות |
|---|---|
0 | מזומן |
1 | צ'ק |
2 | כרטיס אשראי |
3 | העברה בנקאית חיצונית |
4 | הוראת קבע חיצונית |
5 | ביט |
6 | אשראי חיצוני |
7 | Apple Pay |
8 | Google Pay |
9 | העברה בנקאית |
10 | הוראת קבע |
transactionType
| ערך | משמעות |
|---|---|
0 | רגיל |
1 | זיכוי / החזר |
expense #
{ "id": 168024, "lastUpdated": 1777174252079, "taskId": 0, "taskType": 0, "payment": 100, "description": "הוצאה עבור webhooks", "actualPayDate": 1777323600000, "repaymentDate": 1777323600000, "buildingId": 401, "deletedId": 0, "parentId": 0, "paymentType": 0, "transactionType": 1, "type": 2, "isPaid": true, "fullAddress": "ליגד סנטר 2, קומה 2" }
שדות
| שדה | סוג | תיאור |
|---|---|---|
taskId | long | מזהה המשימה הקשורה. 0 = ללא |
taskType | int | סוג המשימה הקשורה |
payment | float | סכום ההוצאה |
description | string | תיאור ההוצאה |
actualPayDate | long | תאריך התשלום בפועל (Epoch ms) |
repaymentDate | long | תאריך תשלום מתוכנן (Epoch ms) |
buildingId | long | מזהה הבניין |
deletedId | int | 1 = מזוכה, 0 = לא מזוכה |
parentId | long | מזהה ההוצאה ההורה. 0 = אין הורה |
paymentType | int | אמצעי תשלום (ראה טבלה למטה) |
transactionType | int | סוג עסקה (ראה טבלה למטה) |
type | int | סוג ההוצאה (ראה טבלה למטה) |
isPaid | boolean | האם ההוצאה שולמה |
fullAddress | string | כתובת מלאה לתצוגה |
paymentType (אמצעי תשלום)
זהה ל-type של חשבונית מס:
| ערך | משמעות |
|---|---|
0 | מזומן |
1 | צ'ק |
2 | כרטיס אשראי |
3 | העברה בנקאית חיצונית |
4 | הוראת קבע חיצונית |
5 | ביט |
6 | אשראי חיצוני |
7 | Apple Pay |
8 | Google Pay |
9 | העברה בנקאית |
10 | הוראת קבע |
type (סוג הוצאה)
| ערך | משמעות |
|---|---|
0 | תחזוקה |
1 | משרד |
2 | מכירות |
3 | כללי |
transactionType
| ערך | משמעות |
|---|---|
0 | רגיל |
1 | זיכוי / החזר |
הערות חשובות #
- שדות לא מסומנים אינם נכללים ב-Payloads — רק השדות המתועדים לעיל.
- שדות חדשים עשויים להתווסף בעתיד. ה-Parser שלך צריך להתעלם משדות לא ידועים.
- תאריך
0משמעו "לא מוגדר". - ערכי Enum עשויים להתפתח — התייחס לערכים לא ידועים כ-"לא ידוע" במקום להיכשל.
שיטות עבודה מומלצות
המלצות לבניית אינטגרציית Webhooks אמינה ומאובטחת.
הגב מהר #
החזר 200 OK במהירות האפשרית — רצוי בפחות מ-3 שניות. בצע את העבודה האמיתית ב-Background Job, Queue או Worker.
// טוב: מגיב מיד, מעבד באופן אסינכרוני app.post('/darimpo-webhooks', (req, res) => { res.status(200).send('OK'); queue.push(req.body); });
היה Idempotent #
דרימפו עשויה למסור את אותו אירוע יותר מפעם אחת (ניסיונות רשת חוזרים, השרת שלך החזיר 5xx וכו').
השתמש ב-entityId + event + timestamp כמפתח לזיהוי כפילויות:
const key = `${body.entityId}:${body.event}:${body.timestamp}`; if (await alreadyProcessed(key)) return; // דלג על כפילות await markProcessed(key); await doTheWork(body);
מאגרי Idempotency נפוצים: Redis SETNX, אינדקס ייחודי בבסיס נתונים, טבלת Idempotency-key.
טפל בניסיונות חוזרים בחן #
| תגובה | התנהגות דרימפו |
|---|---|
| 2xx | המשלוח מוצלח |
| 4xx | כישלון קבוע, בדרך כלל לא ננסה שוב |
| 5xx / Timeout | ננסה שוב |
ודא שנקודת הקצה שלך זמינה. אם היא לא פעילה למשך זמן ממושך, אירועים עלולים ללכת לאיבוד.
אמת את ה-Secret בכל בקשה #
לעולם אל תדלג על אימות חתימה — גם בפיתוח. ראה אימות ואבטחה.
הסדר לא מובטח #
אירועים עשויים להגיע לא לפי סדר. עצב Handlers שישתמשו ב-timestamp או במצב הישות (לא בסדר המשלוח) כמקור האמת.
updated לפני created, התייחס לזה כלוגיקת "Upsert" — הוסף אם לא קיים.הירשם בצמצום #
הירשם רק לסוגי הישויות שאתה באמת משתמש בהם. זה מפחית עומס בשני הצדדים ומפשט Debugging. תמיד ניתן לעדכן את רשימת המנויים שלך מאוחר יותר דרך ממשק הניהול.
התעלם משדות לא ידועים #
דרימפו עשויה להוסיף שדות חדשים ל-Payloads ללא הודעה. Parsers שנכשלים על שדות לא ידועים יישברו.
JSON.parse(body)— טוב- אימות סכמה קפדני שדוחה שדות נוספים — רע
רשום הכל בלוגים (בזהירות) #
רשום בלוגים עבור כל משלוח:
webhookIdentityIdeventtimestamp- סטטוס HTTP שהחזרת
X-Webhook-Secret או את ה-Payload המלא אם הוא מכיל נתוני לקוח רגישים.בדיקות #
- פיתוח מקומי: השתמש ב-ngrok או Cloudflare Tunnel כדי לחשוף את השרת המקומי שלך.
- בדיקה: webhook.site נותן לך כתובת חד-פעמית שמציגה את כל הבקשות הנכנסות. מצוין לגילוי.
- Staging: רשום Webhook נפרד שמצביע לסביבת ה-Staging שלך. לעולם אל תבדוק מול פרודקשן.
קצב ונפח #
עדכון יחיד בממשק המשתמש של דרימפו יכול לפלוט מספר אירועי Webhook (לדוגמה, יצירת חשבוניות בכמות גדולה שולחת אירוע לכל חשבונית). גודל את ה-Workers בהתאם.
צ'קליסט לפני עלייה לאוויר #
- נקודת קצה HTTPS פרוסה
- Secret מאוחסן במשתני סביבה / מנהל Secrets (לא בקוד)
- השוואת Secret בזמן קבוע
- מפתח Idempotency על כל אירוע
- מחזיר
200בפחות מ-3 שניות - מטפל ב-
created,updated, ו-deleted(היכן שרלוונטי) - ניטור / התראות על משלוחים שנכשלו
- נוהל עבודה לרוטציית Secret
צריך עזרה? #
פנה לתמיכת דרימפו עם:
- ה-
idשל ה-Webhook שלך - ה-
timestampשל המשלוח החסר/כושל - קוד סטטוס HTTP שהשרת שלך החזיר