דלגו לתוכן

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

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

תקלות בטפסים — אבחון לפי תסמין

עודכן 30.08.2026

התסמינים בקליטת טפסים מטעים: קוד הסטטוס כמעט אף פעם לא מספר את הסיפור. 200 יכול להיות כישלון שקט, ו‑400 הוא הסטטוס של כמעט כל תקלה — ההבחנה היא בגוף התשובה.

התחילו מהטבלה, ורדו לפירוט של התסמין שלכם.

התסמין (גוף התשובה) הסטטוס הסיבה השכיחה הבדיקה
<שם הדגל> is Disabled 400 דגל ה‑Config כבוי, חסר, או שהודלק הדגל השני
missing "phone" 400 phone לא נשלח, או נשלח עם קידומת
missing "PhoneNumber" or "Email" 400 ValidatePhoneOrEmail דלוק והקלט לא תקין
User function not found 400 שם נקודת קצה שלא קיים — למשל השם הישן web2lead
{"code":103,"message":"Class X does not exist."} 400 ערך table שאינו שם מחלקה קיים
{"code":111,"message":"schema mismatch …"} 400 Pointer באורך ≠ 10 ב‑account_*, בוליאני כמספר, תאריך לא מרופד, שדה File
200 ושדה Pointer ריק 200 ב‑table_*: אורך ≠ 10 או אובייקט Pointer — נזרק בשקט; בשתי הקבוצות: SaleStatusId
200 ושדה רגיל לא נשמר 200 שם השדה לא קיים בסכימה — נזרק בשקט
איש קשר הוכפל בכל פנייה 200 account_PhoneNumber במקום phone; טלפון שמור בפורמט לא נסרק; אימייל באותיות אחרות
איש קשר קיים לא התעדכן 200 התנהגות מתוכננת
404 Not Found 404 הכתובת מתחת ל‑/parse/
code 119 400 ניסיון כתיבה ישירה ל‑REST במקום דרך נקודת הקצה
הדפדפן חוסם — CORS כמעט תמיד סימפטום של משהו אחר

הסיבה בכ‑9 מתוך 10 מקרים: דגל ה‑Config. לא הקוד, לא ההרשאות, לא ה‑Application Id.

הבדיקה מתפצלת לשלוש שאלות, בסדר הזה:

א. איזה דגל? הם נפרדים לגמרי:

נקודת הקצה הדגל ההודעה (בסטטוס 400)
web2table AcceptWebToTable AcceptWebToTable is Disabled
web2case AcceptWebToCaseLeads AcceptWebToCaseLeads is Disabled
getlead AcceptWebLeads AcceptWebLeads is Disabled — אך בפועל תקבלו User function not found

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

ב. הערך בצורה הנכונה? חייב להיות אובייקט עם המפתח הפנימי:

JSON
// ✔
{ "Name": "AcceptWebToTable", "Value": { "AcceptWebToTable": true } }
// ✘ — ייקרא ככבוי
{ "Name": "AcceptWebToTable", "Value": true }

ג. כמה שורות יש? אם יש יותר מאחת עם אותו Name, הקוד לוקח query.first() ללא מיון — והשורה שנוצרה ראשונה מנצחת תמיד. כלומר שורה ישנה עם false תשתק בוודאות שורה חדשה עם true. מחקו כפילויות לפני שממשיכים לאבחן.


שם נקודת קצה שלא קיים בשרת. שלושה מקרים:

  1. web2lead — נתקלתם בשם הזה במדריך ישן? הפונקציה הרשומה בשרת ללכידת ליד היא getlead. החליפו את השם — ראו getlead.
  2. web2sale / web2contact — מעולם לא היו נקודות קצה. השתמשו ב‑web2table עם ה‑table המתאים.
  3. שגיאת כתיב בשם. שימו לב: אותיות גדולות/קטנות אינן משנות (web2Table ו‑getLead עובדים), אבל כל שאר השם כן.

web2case כן קיימת — היא נשלטת בדגל AcceptWebToCaseLeads ומחזירה caseId במקום Id.


מופיע רק ב‑web2table, בסטטוס 400. הקוד שנפרס דורש phone בפועל, גם כשנשלחו email ו‑idnum.

JSON
// ✘ יחזיר 400 {"error":"missing \"phone\""}
{ "table": "Sales", "email": "israel@example.co.il", "account_Name": "ישראל" }
// ✔
{ "table": "Sales", "phone": "0501234567", "email": "israel@example.co.il" }

שתי סיבות אפשריות:

  1. phone לא נשלח בכלל — לרוב כי הטופס אוסף רק אימייל. הפתרון היחיד: להפוך את שדה הטלפון לחובה בטופס.
  2. phone נשלח עם קידומתaccount_phone או account_PhoneNumber. מפתחות האיתור הם בלי קידומת.

missing "table" in request body הוא אותו סטטוס עם סיבה אחרת: חסר שם המחלקה.

שתי תקלות table נוספות שנראות דומה אבל מחזירות משהו אחר לגמרי:

JSON
// שם מחלקה שאינו קיים
{ "table": "NoSuchTable", "phone": "0501234567" }
// 400 {"code":103,"message":"Class NoSuchTable does not exist."}
// התווית בעברית במקום שם המחלקה
{ "table": "מכירות", "phone": "0501234567" }
// 400 {"code":100,"message":"XMLHttpRequest failed: \"Request path contains unescaped characters\""}

ולידציה של תוכן — פעילה רק כש‑ValidatePhoneOrEmail: true יושב בתוך ה‑Value של שורת הדגל (למשל {"AcceptWebToTable": true, "ValidatePhoneOrEmail": true}) — שורת Config נפרדת בשם ValidatePhoneOrEmail לא עושה כלום. ראו Config. הגבולות, אחד־אחד:

השדה הכלל דוגמאות
טלפון מסירים תווים שאינם ספרות, ואז נדרשות 7–14 ספרות 6 ספרות נדחות · 7 עוברות · 14 עוברות · 15 נדחות · 050-123-4567 ו‑+972 50-123-4567 עוברים
אימייל 6–80 תווים, מכיל @ וגם . a@b.c (5) נדחה · a@b.co (6) עובר · 80 תווים עוברים · 81 נדחים · aaaa@bbbb (בלי נקודה) ו‑aaaabbbb.com (בלי @) נדחים

השרת דוחה כשגם הטלפון וגם האימייל אינם תקינים. תקין אחד מהם — הבקשה עוברת (טלפון "abcdefgh" + אימייל תקין → 200).

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


JSON
{ "code": 111, "message": "schema mismatch for Accounts.LeadSourceId; expected Pointer<LeadSource> but got String" }

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

  1. Pointer באורך שאינו 10 תווים בשדה account_* — מזהה שנחתך בהעתקה, רווח מוביל, או ערך תצוגה שנשלח במקום המזהה. (בשדה table_* אותו ערך נזרק בשקט — ראו הסעיף הבא.)
  2. בוליאני כמספר1 / 0 במקום true / false (expected Boolean but got Number). וגם account_IsAccount כמחרוזת.
  3. תאריך לא מרופד"2026-9-1" במקום "2026-09-01" (expected Date but got String).
  4. שדה File / PrivateFile — אינו נתמך כלל בזרימה הזו. עם אובייקט {"__type":"File",…} השגיאה היא {"code":1}.
  5. טיפוס שהשרת לא ממיר — למשל אובייקט מקונן בשדה מחרוזת או מספר.
JavaScript
// בדיקת שפיות לפני שליחה — חוסכת בקשה שנכשלת (ואיש קשר יתום)
const isId = (v) => typeof v === 'string' && v.length === 10;
if (data.account_LeadSourceId && !isId(data.account_LeadSourceId)) delete data.account_LeadSourceId;
if (typeof data.table_IsWeb !== 'undefined') data.table_IsWeb = data.table_IsWeb === true || data.table_IsWeb === 'true';

הבקשה הצליחה, הרשומה נוצרה, השדה ריק. הסיבה תלויה בקבוצת השדה:

בשדה account_* — סיבה אחת: המזהה תקין באורכו אבל אינו קיים בטבלת ה‑lookup (מפה סטטית שנבנתה לפני שנה, וערך שנמחק מאז). במקרה כזה הערך אף נשמר כ‑Pointer שמצביע לשום מקום — השדה “ריק” רק בתצוגה. אמתו מול הטבלה עצמה — ראו מיפוי שדות.

בשדה table_* — שלוש סיבות, כולן שקטות:

  1. אורך שאינו 10 תווים — בניגוד ל‑account_*, כאן זה לא 400 אלא 200 והשדה פשוט לא נכתב.
  2. אובייקט Pointer של Parse ({"__type":"Pointer",…}) — נזרק בשקט. שלחו מזהה חשוף.
  3. table_SaleStatusId ב‑Sales — נזרק תמיד, גם כמזהה חשוף תקין. הדרך היחידה: DefaultValues.Table בשורת ה‑Config.

200 ושדה שנשלח פשוט לא נשמר

Section titled “200 ושדה שנשלח פשוט לא נשמר”

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

הסיבות, בסדר שכיחות:

  1. שגיאת כתיב או אותיות גדולות/קטנותPhonenumber במקום PhoneNumber, city במקום City.
  2. שם השדה בעברית — התוויות בעברית יושבות בטבלת מערכת נפרדת ואינן שמות השדות. אין שדה בשם “טלפון”.
  3. דיאלקט שגוי — שם שטוח ב‑web2table, או account_ ב‑getlead.
  4. השדה באמת לא קיים אצל הלקוח הזה — קיים אצל לקוח אחר, או נמחק.

הבדיקה:

Bash
# /parse/schemas דורש Master Key — לא API Key ולא sessionToken. צד שרת בלבד.
curl -sS "https://api.mbapps.co.il/parse/schemas/Accounts" \
-H "X-Parse-Application-Id: $APP_ID" -H "X-Parse-Master-Key: $MASTER_KEY" \
| python -c "import sys,json;print('\n'.join(sorted(json.load(sys.stdin)['fields'])))"
JavaScript
// /parse/schemas דורש Master Key — לא API Key ולא sessionToken. צד שרת בלבד.
const res = await fetch("https://api.mbapps.co.il/parse/schemas/Accounts", {
headers: {
'X-Parse-Application-Id': APP_ID,
'X-Parse-Master-Key': MASTER_KEY,
},
});
const schema = await res.json();
console.log(Object.keys(schema.fields).sort().join('\n'));
Python
# /parse/schemas דורש Master Key — לא API Key ולא sessionToken. צד שרת בלבד.
import requests
res = requests.get(
"https://api.mbapps.co.il/parse/schemas/Accounts",
headers={
"X-Parse-Application-Id": APP_ID,
"X-Parse-Master-Key": MASTER_KEY,
},
)
print("\n".join(sorted(res.json()["fields"])))
PHP
<?php
// /parse/schemas דורש Master Key — לא API Key ולא sessionToken. צד שרת בלבד.
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.mbapps.co.il/parse/schemas/Accounts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-Parse-Application-Id: {$APP_ID}",
"X-Parse-Master-Key: {$MASTER_KEY}",
],
]);
$response = curl_exec($ch);
curl_close($ch);
$fields = array_keys(json_decode($response, true)["fields"]);
sort($fields);
echo implode("\n", $fields);

אם אין לכם Master Key — אותה שליפה זמינה דרך כלי ה‑MCP Get-Schema עם {"className":"Accounts"}.


הלקוח מדווח: “כל פעם שמישהו ממלא, נוצר איש קשר חדש”.

ב‑web2table — כמעט תמיד account_PhoneNumber (או account_Phone / account_Email) במקום המפתחות הלא מקודמים phone / email. הערך המקודם נשמר בשדה, אבל לא מזין את שאילתת זיהוי הכפילויות — ולכן המערכת “לא מוצאת” את איש הקשר בכל פעם.

JavaScript
// ✘
{ table: 'Sales', account_PhoneNumber: '0501234567' }
// ✔
{ table: 'Sales', phone: '0501234567' }

ואל תשלחו את שניהם — phone יחד עם account_PhoneNumber הוא כפילות מיותרת.

account_PhoneNumber אכן נשמר ב‑Accounts.PhoneNumber (ואף דורס את הערך שהגיע מ‑phone), אבל לא מאתר. הווריאנט account_phone באותיות קטנות נזרק לגמרי — הוא כלל אינו שדה בסכימה.

שתי סיבות נוספות, כשהמפתחות נכונים והלקוח עדיין מוכפל — שתיהן בצד הנתונים הקיימים:

  • הטלפון שמור בפורמט שאינו נסרק. השרת משווה רק מול חמישה פורמטים שמורים (0501234567, 972501234567, +972501234567, 050-1234567, +972-50-1234567). איש קשר שיובא כ‑050-123-4567 או 050 1234567 לא יאותר לעולם — גם מקלט זהה. הבדיקה: שלפו את ה‑PhoneNumber השמור ב‑REST והשוו לרשימה. התיקון: נרמול הטבלה.
  • האימייל שמור באותיות אחרות. ההשוואה רגישה לאותיות: Dana@Example.co.il לא מתאים ל‑dana@example.co.il. התיקון: lowercase בשני הצדדים.

ראו זיהוי כפילויות.

ב‑getlead — זו התנהגות מתוכננת: הפונקציה תמיד יוצרת שורה חדשה, וכפילות מסומנת בסטטוס “ליד כפול” במקום להיחסם. אם הלקוח ציפה למיזוג — ההסבר בעמוד זיהוי כפילויות.


“מילאתי את הטופס עם כתובת חדשה, והכתובת הישנה נשארה.”

זו התנהגות מתוכננת. ב‑web2table, שדות account_* מוחלים רק כשנוצר איש קשר חדש. איש קשר קיים מקושר לשורה החדשה — ולא מעודכן.

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


סיבה אחת בלבד: הכתובת תחת /parse/. Cloud Functions לא יושבות שם:

✘ https://api.mbapps.co.il/parse/functions/{appId}/web2table → 404 Not Found
✔ https://api.mbapps.co.il/functions/{appId}/web2table

JSON
{ "code": 119, "error": "This action is not allowed without a valid CAPTCHA" }

זה לא קורה בנקודות הקצה של הטפסים — זה קורה כשמנסים לכתוב ישירות ל‑/parse/classes/<Table> עם Application Id בלבד.

התיקון: לעבור ל‑web2table. לא לפתוח CLP — שער ה‑CAPTCHA יושב לפני בדיקת ההרשאות (גם עם create: {"*": true} התשובה נשארת 119), ופתיחתן לא תעזור אבל כן תגדיל חשיפה. הפירוט: מודל האבטחה.

code 119 מופיע גם בקריאה ובעדכון, עם הודעות אחרות:

JSON
// GET /parse/classes/Sales עם App-Id בלבד
{ "code": 119, "error": "Permission denied for action find on class Sales." }
// PUT /parse/classes/Sales/<objectId> עם App-Id בלבד
{ "code": 119, "error": "Permission denied for action update on class Sales." }

CORS פתוח לנקודות הקצה האלה כברירת מחדל: preflight מחזיר 200 עם Access-Control-Allow-Origin שמהדהד את ה‑Origin, ו‑Allow-Methods: GET,PUT,POST,DELETE,OPTIONS.

מה שנראה כמו CORS מה זה בעצם
נחסם בעמוד HTTPS הקוד קורא ל‑http:// במקום https:// — זו חסימת mixed content, לא CORS
עובד ב‑curl ולא בדפדפן תוסף חוסם, או iframe מוגבל (הטמעות במערכות בנייה)
“נכשל” בלי פרטים בקונסול לרוב 400 עם גוף שגיאה — פתחו את לשונית Network וקראו את הגוף

הבדיקה: הריצו את אותה בקשה ב‑curl. אם היא מחזירה 400 או 404 — הבעיה שם, לא ב‑CORS.


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

  1. הגוף, לא הסטטוס. קראו את מחרוזת ה‑error בתשובה — הכול חוזר כ‑400.
  2. דגל. האם הדגל הנכון דלוק, בצורה הנכונה, בשורה אחת (והיא הישנה ביותר)? (Config)
  3. סכימה. האם כל שם שדה קיים בסכימה של הלקוח הזה, ובדיאלקט הנכון? (מיפוי שדות)
  4. פורמט. Pointer כמזהה חשוף בן 10 בדיוק (לא אובייקט), תאריך ISO שטוח מרופד, בוליאנים אמיתיים (לא 1/0), ערכים ריקים מושמטים.
  5. CORS — אחרון, ורק אחרי ש‑curl הוכיח שהבקשה עצמה מצליחה.

אם עברתם את ארבעת השלבים ועדיין תקוע:

  • הזמן המדויק של הקריאה, כולל אזור זמן
  • ה‑Application Id
  • נקודת הקצה המדויקת
  • גוף הבקשה המלא, בלי סודות
  • קוד הסטטוס וגוף התשובה המלא

support@mybusiness-crm.com