דלגו לתוכן

או התחילו מנקודה בטוחה: אינדקס הכלים המלא · מפת הטבלאות המרכזיות

מערכת חדשה — 14 יום חינם

web2table — יצירת רשומה מקושרת

עודכן 30.08.2026
POST https://api.mbapps.co.il/functions/{appId}/web2table

יוצר שורה בכל טבלת יעד (Sales, Cases, Orders, טבלה מותאמת) וגם איש קשר ב‑Accounts, אם הוא עדיין לא קיים. איש קשר קיים נמצא ומקושר, לא משוכפל.

JSON
{
"table": "Sales",
"phone": "0501234567",
"email": "israel@example.co.il",
"account_Name": "ישראל ישראלי",
"account_City": "תל אביב",
"table_Name": "פנייה מדף נחיתה",
"table_Total": 1500,
"table_Comment": "הגיע מדף הנחיתה"
}

חובה: table (שם המחלקה המדויק) וגם phone. בלי phone התשובה היא 400 {"error":"missing \"phone\""}.

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

הקבוצה קידומת דוגמאות מה השרת עושה
מפתחות איתור אין phone, phone2, email, email2, idnum, table מזינים את זיהוי הכפילויות. באיש קשר חדש: phonePhoneNumber, emailEmail, idnumCompanyId
שדות Accounts account_ account_Name, account_F_name, account_City, account_CompanyId מוחלים רק כשנוצר איש קשר חדש
שדות טבלת היעד table_ table_Name, table_Total, table_Comment מוחלים על השורה החדשה, אחרי אימות מול הסכימה
תוספות ברמה העליונה אין Name, CampaignName, PageName, isExistsAccountCheck ראו “שדות שנקבעים אוטומטית”

חמישה מפתחות מזינים את זיהוי הכפילויות, וכולם בלי קידומת. שניים מהם — phone2 ו‑email2 — מפתחות משניים שקל לפספס, והם בדיוק מה שמונע כפילות אצל לקוח שיש לו שני מספרים או שתי כתובות:

המפתח מה הוא עושה בחיפוש מה הוא ממלא באיש קשר חדש
phone חובה. נסרק בחמישה פורמטים שמורים בלבד (הרשימה) Accounts.PhoneNumber
phone2 מפתח משני — נסרק גם הוא כלום — ראו למטה
email השוואת שוויון, ב‑OR מול הטלפון Accounts.Email
email2 מפתח משני כלום — ראו למטה
idnum ח.פ. / ת.ז. — השוואה מדויקת, בלי נרמול Accounts.CompanyId

שדות שנקבעים אוטומטית בשורה החדשה

Section titled “שדות שנקבעים אוטומטית בשורה החדשה”
השדה הערך
AccountId Pointer לאיש הקשר שנמצא או נוצר
IsFirst true לאיש קשר חדש; false רק כשאיש הקשר היה קיים וגם נשלח isExistsAccountCheck: true
Name ה‑Name מהבקשה; אחרת "פניה ראשונה" (חדש) או "פניה חוזרת" (חוזר + isExistsAccountCheck)
CampaignName / PageName הערך מהבקשה; אחרת "MainLandingPage"
PhoneNumber, Email מועתקים מאיש הקשר
AccountNotExist trueתמיד, ראו למטה

אותה שאילתה רב‑פורמטית של getlead — כל וריאציות הטלפון, ב‑OR עם האימייל — ובנוסף CompanyId (מ‑idnum) והמפתחות המשניים phone2 / email2. הפירוט המלא: זיהוי כפילויות — מה קורה בשרת.

סטטוס הגוף
200 { "success": true, "accountId": "<objectId>", "Id": "<objectId של שורת היעד>" }
400 missing "phone" · missing "table" in request body · missing "PhoneNumber" or "Email" (ולידציה) · AcceptWebToTable is Disabled
400 {"code":103,"message":"Class X does not exist."} — שם מחלקה שאינו קיים
400 {"code":111,"message":"schema mismatch for …"} — טיפוס שגוי: Pointer באורך לא נכון, תאריך לא מרופד ("2026-6-1"), מחרוזת ב‑account_IsAccount, מספר בשדה בוליאני, מחרוזת URL בשדה File. שורת היעד לא נוצרת; מה קורה לאיש הקשר תלוי בקבוצת השדה (ראו למטה)
400 {"code":1} — אובייקט File של Parse בגוף. חוזר אחרי ~4 שניות, ובצד השרת נוצרו איש קשר ו‑5 שורות יעד כפולות
400 {} (גוף ריק) — table או phone שאינם מחרוזת (למשל מספר)
500 תקלת שרת
JavaScript
const APP_ID = 'הדביקו-כאן';
const COURSE_MAP = {
'קורס יסודות CRM': 'aB3dEf9HiJ',
'סדנת אוטומציות': 'kLm4NoP7Qr',
};
async function submitRegistration(f) {
const data = {
table: 'CourseRegistrations', // שם המחלקה המדויק
phone: f.phone, // חובה, בלי קידומת
email: f.email,
idnum: f.idNumber, // → Accounts.CompanyId על איש קשר חדש
account_F_name: f.firstName,
account_L_name: f.lastName,
account_City: f.city,
table_CourseId: COURSE_MAP[f.course], // objectId חשוף
table_StartDate: f.startDate, // ISO שטוח: "2026-09-01"
table_Comment: f.notes,
PageName: 'course-landing-2026',
isExistsAccountCheck: true, // כדי ש-IsFirst יהיה אמין
};
Object.keys(data).forEach((k) => { if (data[k] == null || data[k] === '') delete data[k]; });
const res = await fetch(`https://api.mbapps.co.il/functions/${APP_ID}/web2table`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Parse-Application-Id': APP_ID },
body: JSON.stringify(data),
});
const body = await res.json().catch(() => ({}));
if (!res.ok) {
// כל שגיאה עסקית חוזרת כ-400 — ההבחנה היא לפי הגוף
const e = body.error || body.message || '';
if (/Disabled/.test(e)) throw new Error('AcceptWebToTable כבוי במערכת');
if (/missing/.test(e)) throw new Error('חסר טלפון או שם טבלה');
throw new Error('שגיאת שרת: ' + e);
}
return body; // { success, accountId, Id }
}

לקוח (ולא ליד) + בחירה מרובה

Section titled “לקוח (ולא ליד) + בחירה מרובה”
JavaScript
const data = {
table: 'Orders',
phone: '0501234567',
account_Name: 'חברת דוגמה בע"מ',
account_IsAccount: true, // בוליאני אמיתי! → נוצר כלקוח, לא כליד
account_CompanyId: '514999999',
table_Total: '2400',
table_array_tags_Pointer_Tags: ['GGZUYqBjqT', 'io3Z6YsMcG'],
};

שדות בחירה מרובה (array_*_Pointer_*) מקבלים מערך של objectId חשופים, עם הקידומת המתאימה לקבוצה.

הפעלה — דגל נפרד משל עצמו

Section titled “הפעלה — דגל נפרד משל עצמו”
שדה ערך
Name AcceptWebToTable
Value { "AcceptWebToTable": true }
המפתח מה הוא עושה
AcceptWebToTable המתג עצמו
ValidatePhoneOrEmail אכיפה בצד השרת: 400 missing "PhoneNumber" or "Email" כשגם הטלפון (מסירים תווים שאינם ספרות, ואז 7–14 ספרות) וגם האימייל (6–80 תווים, מכיל @ ו‑.) אינם תקינים
DefaultValues.Account ערכי ברירת מחדל לאיש הקשר שנוצר
DefaultValues.Table ערכי ברירת מחדל לשורה שנוצרת בטבלת היעד — למשל סטטוס פתיחה או דגל “הגיע מהאתר”, בלי לחשוף מזהים בקוד הדף
JSON
{
"Name": "AcceptWebToTable",
"Value": {
"AcceptWebToTable": true,
"ValidatePhoneOrEmail": true,
"DefaultValues": {
"Account": { "LeadSourceId": "yOTdl4L99Q" },
"Table": { "SaleStatusId": "zrP1MSVBoq", "IsWeb": "true" }
}
}
}

שני כללים על DefaultValues:

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

מודל האבטחה — שלוש עובדות שקובעות ארכיטקטורה

Section titled “מודל האבטחה — שלוש עובדות שקובעות ארכיטקטורה”
  1. כתיבה אנונימית ישירה ל‑REST חסומה ב‑CAPTCHA — פתיחת CLP לא עוזרת. POST /parse/classes/<Table> עם Application Id בלבד נדחה עם code 119, גם אחרי הגדרת create: {"*": true}. שער ה‑CAPTCHA יושב לפני בדיקת ההרשאות.
  2. web2table רץ בהרשאות מוגברות ועוקף CLP. גם כשה‑CLP של טבלת היעד סגור לחלוטין ({} לכל פעולה) הפונקציה יוצרת שורה ומחזירה 200. המסקנה המעשית: השאירו את ההרשאות של טבלת היעד סגורות. פתיחתן היא חשיפה נטו בלי שום תועלת.
  3. web2table הוא create‑only. אין לו סמנטיקת עדכון: שליחת objectId או table_objectId לא פונה לשורה קיימת — מזהה חדש חוזר בתשובה וכל קריאה מוסיפה שורה.

מה עושים כשצריך בכל זאת “עדכון מקישור ציבורי”

Section titled “מה עושים כשצריך בכל זאת “עדכון מקישור ציבורי””

התבנית: טבלת קליטה + טריגר השלכה. הדף הציבורי יוצר שורה בטבלת ביניים ייעודית, וטריגר data‑change על אותה טבלה משליך את הערכים על אובייקט העסק האמיתי (update-object עם connection: "source.<שדה Pointer>"). כך טבלת העסק נשארת סגורה לכתיבה אנונימית.

שלוש השלכות שכדאי לתעד מראש כדי שמישהו לא “יתקן” אותן שנה אחר כך:

  • הקישור חייב לשאת phone (שדה חובה), כלומר מספר טלפון של לקוח נוסע ב‑URL ונוחת בלוגים של שרתים. זו החלטת פרטיות שצריך להעלות מול הלקוח, לא להסתיר — החלופה היא טוקן אטום לכל רשומה שנפתר בצד שרת.
  • אינטראקציה דו‑שלבית (דירוג עכשיו, הערה כעבור רגע) מייצרת שתי שורות קליטה לתגובה אחת. זו התנהגות נכונה: טבלת הקליטה היא היומן הגולמי, ואובייקט העסק מחזיק את התשובה הסופית.
  • טריגר שמגיב לקריאה הראשונה ירוץ לפני שהנתונים של השנייה קיימים. אל תרכיבו גוף הודעה או משימה משדה שמגיע בקריאה המאוחרת — הפנו את הקורא לרשומה.

הפירוט המלא של שלוש העובדות ושל תבנית טבלת הקליטה: מודל האבטחה של כתיבה אנונימית.

  • table הוא שם המחלקה המדויק (לא התווית בעברית — היא מחזירה code 100, לא missing "table")
  • phone נשלח, בלי קידומת
  • נשלפו סכימות Accounts וגם טבלת היעד, וכל שדה אומת
  • Pointer כמחרוזת של 10 תווים בדיוק (אורך אחר → 400 code 111; אם השגיאה ב‑table_* נשאר איש קשר יתום)
  • תאריכים כ‑ISO מרופד (2026-06-01); לא מרופד → 400 code 111, ו‑dd/mm/yyyy נקרא כחודש/יום
  • אין שדה File בגוף — 400 ובכל זאת נוצרות רשומות (עד 5 כפולות)
  • account_IsAccount — אם נדרש, נשלח כבוליאני ולא כמחרוזת (מחרוזת → 400 לכל הבקשה)
  • SaleStatusId נקבע דרך DefaultValues.Table ולא דרך table_SaleStatusId
  • isExistsAccountCheck: true אם IsFirst משמעותי לדיווח — ו‑AccountNotExist לא משמש לשום הבחנה
  • AcceptWebToTable דלוק — שורה אחת בלבד
  • טיפול השגיאות בקוד מסתעף על גוף התשובה ולא על 403/422
  • ה‑CLP של טבלת היעד נשאר סגור
  • הבנתם ותיעדתם שכל קריאה מוסיפה שורה