דוגמאות קוד
הצורה זהה בכל שפה: POST של JSON עם שתי כותרות. משתנים רק לקוח ה‑HTTP וההמרה לפורמט השליחה (serialization). שמות השדות, הקידומות, טיפוסי הערכים ובדיקות התקינות אינם תלויי שפה.
הקטלוג
Section titled “הקטלוג”| הדוגמה | השכבה | האימות | איפה הקוד רץ |
|---|---|---|---|
| שרת ביניים לטופס | /functions/{appId}/getlead |
Application Id בלבד | דפדפן וגם שרת שלכם |
| סנכרון יוצא עם עימוד | /parse/classes/… |
API Key | צד שרת בלבד |
| הרשמה לקורס | /functions/{appId}/web2table |
Application Id בלבד | דפדפן, או שרת ביניים |
| מצא‑או‑צור | /parse/classes/… · /parse/batch |
API Key | צד שרת בלבד |
| חיבור לקוח MCP | https://mcp.mbapps.co.il/ |
API Key או OAuth 2.1 | לקוח ה‑MCP שלכם |
מוסכמת הטאבים
Section titled “מוסכמת הטאבים”כל בלוק קוד מופיע בחמש שפות קבועות, בטאבים עם מפתח סנכרון משותף: PHP · Python · Node.js · C# · JavaScript (דפדפן). בוחרים שפה פעם אחת, והבחירה חלה על כל הבלוקים בעמוד ועל עמודי הדוגמאות האחרים.
הכללים שכל דוגמה מקיימת
Section titled “הכללים שכל דוגמה מקיימת”- הקוד רץ במלואו. אין
// ...באמצע ואין “השלימו כאן”. - טיפול שגיאות אמיתי. ארבע קטגוריות נפרדות: שגיאת נתונים (בשכבת הטפסים
400עםerrorשל שדה חסר או לא תקין; ב‑REST400עםcode), דגל כבוי במערכת (400עם… is Disabled), 5xx, ושגיאת רשת או timeout. - בלי סודות בדפדפן. ה‑Application Id מותר בקוד לקוח, הוא מזהה ציבורי. API Key ו‑Master Key ממשתנה סביבה או ממנהל סודות, בצד שרת בלבד. ראו אימות והרשאות.
- ערכי דמה מסומנים. כל מזהה כאן הוא ערך המצאה בפורמט הנכון (10 תווים). ראו טבלת ערכי הדמה.
limitמפורש תמיד. ברירות המחדל שונות בין השכבות (100 ב‑REST, 5 ב‑MCP), ותשובה קטומה נראית כמו טבלה קטנה. ראו מגבלות.- ערכים ריקים מוסרים מהגוף. מחרוזת ריקה היא ערך ריק ולא היעדר ערך, והיא מתנהגת אחרת בשאילתות.
- timeout על כל קריאה יוצאת.
ערכי הדמה שחוזרים בכל הדוגמאות
Section titled “ערכי הדמה שחוזרים בכל הדוגמאות”| הערך בדוגמה | מה הוא | מאיפה לוקחים את שלכם |
|---|---|---|
הדביקו-כאן / APP_ID |
Application Id | Databases ← המערכת שלכם ← Settings. סביבות וגישה |
MB_API_KEY (משתנה סביבה) |
API Key | אותו מסך, טבלת API Keys ← Add Key ← Save. אימות |
xK9mP2qRsT |
objectId של רשומה — בדיוק 10 תווים |
חוזר מהיצירה, או משאילתה |
vOZLqOWnQf, aB3dEf9HiJ |
ערך Pointer (שורה בטבלת lookup) | שליפה חד‑פעמית מטבלת ה‑lookup |
0501234567 · israel@example.co.il |
פרטי איש קשר לדוגמה | — |
Accounts · Sales · CourseRegistrations |
שמות מחלקות | שלפו סכימה — שמות הטבלאות משתנים בין מערכות |
הצורה, בשלוש שכבות
Section titled “הצורה, בשלוש שכבות”1 · getlead — לכידת ליד
Section titled “1 · getlead — לכידת ליד”<?phpconst APP_ID = 'הדביקו-כאן';
function submitLead(array $form): array{ $data = array_filter([ 'Name' => $form['fullName'] ?? null, 'PhoneNumber' => $form['phone'] ?? null, 'Email' => $form['email'] ?? null, ], static fn ($v) => $v !== null && $v !== '');
if (empty($data['PhoneNumber']) && empty($data['Email'])) { return ['ok' => false, 'error' => 'נדרש טלפון או אימייל']; }
$ch = curl_init('https://api.mbapps.co.il/functions/' . APP_ID . '/getlead'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'X-Parse-Application-Id: ' . APP_ID, ], CURLOPT_POSTFIELDS => json_encode($data, JSON_UNESCAPED_UNICODE), ]);
$body = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch);
if ($body === false) return ['ok' => false, 'error' => 'שגיאת רשת']; $json = json_decode($body, true) ?: []; if ($status === 400) { // כל שגיאה עסקית חוזרת כ-400 — מסתעפים על הגוף $err = $json['error'] ?? ''; if (str_contains($err, 'Disabled')) return ['ok' => false, 'error' => 'AcceptWebLeads כבוי במערכת']; if (str_contains($err, 'missing')) return ['ok' => false, 'error' => 'טלפון או אימייל לא תקינים']; return ['ok' => false, 'error' => "שגיאת שרת (400: $err)"]; // למשל "User function not found" } if ($status !== 200) return ['ok' => false, 'error' => "שגיאת שרת ($status)"];
// תשובת ההצלחה עטופה: { "result": { "success": true, "leadId": "..." } } return ['ok' => true, 'leadId' => $json['result']['leadId'] ?? ''];}import requests
APP_ID = "הדביקו-כאן"ENDPOINT = f"https://api.mbapps.co.il/functions/{APP_ID}/getlead"HEADERS = {"Content-Type": "application/json", "X-Parse-Application-Id": APP_ID}
def submit_lead(form: dict) -> dict: data = { "Name": form.get("full_name"), "PhoneNumber": form.get("phone"), "Email": form.get("email"), } data = {k: v for k, v in data.items() if v}
if not data.get("PhoneNumber") and not data.get("Email"): return {"ok": False, "error": "נדרש טלפון או אימייל"}
try: r = requests.post(ENDPOINT, json=data, headers=HEADERS, timeout=10) except requests.RequestException as exc: return {"ok": False, "error": f"שגיאת רשת: {exc}"}
body = r.json() if r.headers.get("content-type", "").startswith("application/json") else {} # תשובת ההצלחה עטופה: { "result": { "success": true, "leadId": "..." } } result = body.get("result", {}) if r.status_code == 200 and result.get("success"): return {"ok": True, "leadId": result["leadId"]} if r.status_code == 400: # כל שגיאה עסקית חוזרת כ-400 — מסתעפים על הגוף err = body.get("error", "") if "Disabled" in err: return {"ok": False, "error": "AcceptWebLeads כבוי במערכת"} if "missing" in err: return {"ok": False, "error": "טלפון או אימייל לא תקינים"} return {"ok": False, "error": f"שגיאת שרת (400: {err})"} # למשל "User function not found" return {"ok": False, "error": "שגיאת שרת", "raw": r.text}const APP_ID = process.env.MB_APP_ID; // מזהה ציבורי, אבל נוח לנהל בקונפיגconst ENDPOINT = `https://api.mbapps.co.il/functions/${APP_ID}/getlead`;
export async function submitLead({ fullName, phone, email }) { const data = Object.fromEntries( Object.entries({ Name: fullName, PhoneNumber: phone, Email: email }) .filter(([, v]) => v), );
if (!data.PhoneNumber && !data.Email) { return { ok: false, error: 'נדרש טלפון או אימייל' }; }
try { const res = await fetch(ENDPOINT, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Parse-Application-Id': APP_ID }, body: JSON.stringify(data), signal: AbortSignal.timeout(10_000), });
const body = await res.json().catch(() => ({})); // תשובת ההצלחה עטופה: { result: { success: true, leadId: "..." } } if (res.ok) return { ok: true, leadId: body.result?.leadId }; if (res.status === 400) { // כל שגיאה עסקית חוזרת כ-400 — מסתעפים על הגוף const err = String(body.error ?? ''); if (err.includes('Disabled')) return { ok: false, error: 'AcceptWebLeads כבוי במערכת' }; if (err.includes('missing')) return { ok: false, error: 'טלפון או אימייל לא תקינים' }; return { ok: false, error: `שגיאת שרת (400: ${err})` }; // למשל "User function not found" } return { ok: false, error: `שגיאת שרת (${res.status})` }; } catch { return { ok: false, error: 'שגיאת רשת או timeout' }; }}using System.Net.Http.Json;using System.Text.Json;
public sealed class GetLeadClient(HttpClient http, string appId){ private readonly string _endpoint = $"https://api.mbapps.co.il/functions/{appId}/getlead";
public async Task<(bool Ok, string? LeadId, string? Error)> SubmitAsync( string? fullName, string? phone, string? email, CancellationToken ct = default) { var data = new Dictionary<string, object?> { ["Name"] = fullName, ["PhoneNumber"] = phone, ["Email"] = email, }; foreach (var k in data.Where(kv => kv.Value is null or "").Select(kv => kv.Key).ToList()) data.Remove(k);
if (!data.ContainsKey("PhoneNumber") && !data.ContainsKey("Email")) return (false, null, "נדרש טלפון או אימייל");
using var req = new HttpRequestMessage(HttpMethod.Post, _endpoint) { Content = JsonContent.Create(data), }; req.Headers.Add("X-Parse-Application-Id", appId);
try { using var res = await http.SendAsync(req, ct); var body = await res.Content.ReadFromJsonAsync<JsonElement>(cancellationToken: ct); if (res.IsSuccessStatusCode) // תשובת ההצלחה עטופה ב-result return (true, body.GetProperty("result").GetProperty("leadId").GetString(), null); if ((int)res.StatusCode == 400) // כל שגיאה עסקית חוזרת כ-400 — מסתעפים על הגוף { var err = body.TryGetProperty("error", out var e) ? e.GetString() ?? "" : ""; if (err.Contains("Disabled")) return (false, null, "AcceptWebLeads כבוי במערכת"); if (err.Contains("missing")) return (false, null, "טלפון או אימייל לא תקינים"); return (false, null, $"שגיאת שרת (400: {err})"); // למשל "User function not found" } return (false, null, $"שגיאת שרת ({(int)res.StatusCode})"); } catch (Exception ex) when (ex is HttpRequestException or TaskCanceledException) { return (false, null, "שגיאת רשת או timeout"); } }}// ישירות מדף נחיתה — בלי שרת ביניים ובלי סודותconst APP_ID = 'הדביקו-כאן'; // מזהה ציבורי, מותר בדפדפן
async function submitLead({ fullName, phone, email }) { const data = { Name: fullName, PhoneNumber: phone, Email: email }; Object.keys(data).forEach((k) => { if (!data[k]) delete data[k]; });
if (!data.PhoneNumber && !data.Email) throw new Error('נדרש טלפון או אימייל');
const res = await fetch(`https://api.mbapps.co.il/functions/${APP_ID}/getlead`, { 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) return body.result?.leadId; // התשובה עטופה ב-result if (res.status === 400) { // כל שגיאה עסקית חוזרת כ-400 — מסתעפים על הגוף if (String(body.error).includes('Disabled')) throw new Error('קליטת פניות מהאתר כבויה'); if (String(body.error).includes('missing')) throw new Error('טלפון או אימייל לא תקינים'); throw new Error('שגיאת שרת'); // למשל "User function not found" } throw new Error('שגיאת שרת');}המשך: שרת ביניים לטופס · getlead.
2 · web2table — רשומה מקושרת
Section titled “2 · web2table — רשומה מקושרת”שלוש קבוצות שמות: מפתחות איתור בלי קידומת, שדות איש קשר ב‑account_, שדות טבלת היעד ב‑table_.
<?phpfunction submitSale(array $form): array{ $data = array_filter([ 'table' => 'Sales', // שם המחלקה המדויק — חובה 'phone' => $form['phone'] ?? null, // חובה, בלי קידומת 'email' => $form['email'] ?? null,
'account_Name' => $form['full_name'] ?? null, 'account_City' => $form['city'] ?? null,
'table_Name' => 'פנייה מדף נחיתה', // שדות Sales בתבנית vanilla: Name, Total, Comment… 'table_Total' => $form['amount'] ?? null, 'isExistsAccountCheck' => 'true', // בוליאני כמחרוזת ], static fn ($v) => $v !== null && $v !== '');
if (empty($data['phone'])) { return ['ok' => false, 'error' => 'נדרש טלפון']; }
$ch = curl_init('https://api.mbapps.co.il/functions/' . APP_ID . '/web2table'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'X-Parse-Application-Id: ' . APP_ID], CURLOPT_POSTFIELDS => json_encode($data, JSON_UNESCAPED_UNICODE), ]); $body = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch);
return $status === 200 ? ['ok' => true] + json_decode($body, true) // { success, accountId, Id } : ['ok' => false, 'status' => $status, 'raw' => $body];}def submit_sale(form: dict) -> dict: data = { "table": "Sales", # שם המחלקה המדויק — חובה "phone": form.get("phone"), # חובה, בלי קידומת "email": form.get("email"),
"account_Name": form.get("full_name"), "account_City": form.get("city"),
"table_Name": "פנייה מדף נחיתה", # שדות Sales בתבנית vanilla: Name, Total, Comment… "table_Total": form.get("amount"), "isExistsAccountCheck": "true", # בוליאני כמחרוזת } data = {k: v for k, v in data.items() if v not in (None, "")}
if not data.get("phone"): return {"ok": False, "error": "נדרש טלפון"}
r = requests.post(f"https://api.mbapps.co.il/functions/{APP_ID}/web2table", json=data, headers=HEADERS, timeout=10) body = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}
if r.status_code == 200 and body.get("success"): return {"ok": True, "accountId": body["accountId"], "rowId": body["Id"]} return {"ok": False, "status": r.status_code, "raw": body or r.text}async function submitSale(form) { const data = { table: 'Sales', // שם המחלקה המדויק — חובה phone: form.phone, // חובה, בלי קידומת email: form.email,
account_Name: form.fullName, account_City: form.city,
table_Name: 'פנייה מדף נחיתה', // שדות Sales בתבנית vanilla: Name, Total, Comment… table_Total: form.amount, isExistsAccountCheck: 'true', // בוליאני כמחרוזת }; Object.keys(data).forEach((k) => { if (data[k] == null || data[k] === '') delete data[k]; });
if (!data.phone) return { ok: false, error: 'נדרש טלפון' };
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), signal: AbortSignal.timeout(10_000), });
if (!res.ok) return { ok: false, status: res.status, raw: await res.text() }; // 400 לכל שגיאה עסקית — הסתעפו על הגוף const body = await res.json(); // { success, accountId, Id } return { ok: true, accountId: body.accountId, rowId: body.Id };}public async Task<JsonElement> SubmitSaleAsync(SaleForm form, CancellationToken ct = default){ var data = new Dictionary<string, object?> { ["table"] = "Sales", // שם המחלקה המדויק — חובה ["phone"] = form.Phone, // חובה, בלי קידומת ["email"] = form.Email,
["account_Name"] = form.FullName, ["account_City"] = form.City,
["table_Name"] = "פנייה מדף נחיתה", // שדות Sales בתבנית vanilla: Name, Total, Comment… ["table_Total"] = form.Amount, ["isExistsAccountCheck"] = "true", // בוליאני כמחרוזת }; foreach (var k in data.Where(kv => kv.Value is null or "").Select(kv => kv.Key).ToList()) data.Remove(k);
if (!data.ContainsKey("phone")) throw new ArgumentException("phone הוא שדה חובה — בלעדיו התשובה היא 400 missing \"phone\"");
using var req = new HttpRequestMessage(HttpMethod.Post, $"https://api.mbapps.co.il/functions/{_appId}/web2table") { Content = JsonContent.Create(data), }; req.Headers.Add("X-Parse-Application-Id", _appId);
using var res = await _http.SendAsync(req, ct); res.EnsureSuccessStatusCode(); return await res.Content.ReadFromJsonAsync<JsonElement>(cancellationToken: ct);}const APP_ID = 'הדביקו-כאן';
async function submitSale(form) { const data = { table: 'Sales', phone: form.phone, // חובה, בלי קידומת email: form.email,
account_Name: form.fullName,
table_Name: 'פנייה מדף נחיתה', // שדות Sales בתבנית vanilla: Name, Total, Comment… table_Total: form.amount, isExistsAccountCheck: 'true', }; Object.keys(data).forEach((k) => { if (!data[k]) delete data[k]; });
if (!data.phone) throw new Error('נדרש טלפון');
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.status === 400) { // 400 לכל שגיאה עסקית: "missing \"phone\"" · "AcceptWebToTable is Disabled" · code 111 if (String(body.error).includes('Disabled')) throw new Error('AcceptWebToTable כבוי במערכת'); throw new Error(body.error || 'חסר טלפון או שם טבלה'); } if (!res.ok) throw new Error('שגיאת שרת'); return body; // { success, accountId, Id }}המשך: הרשמה לקורס עם web2table · web2table.
3 · REST — קריאה מאומתת
Section titled “3 · REST — קריאה מאומתת”<?phpfunction fetchRecentLeads(int $limit = 100): array{ $qs = http_build_query([ 'where' => json_encode(['IsAccount' => false], JSON_UNESCAPED_UNICODE), 'keys' => 'Name,PhoneNumber,Email,createdAt', 'order' => '-createdAt', 'limit' => $limit, // תמיד מפורש — ברירת המחדל היא 100 ]);
$ch = curl_init("https://api.mbapps.co.il/parse/classes/Accounts?$qs"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_HTTPHEADER => [ 'X-Parse-Application-Id: ' . getenv('MB_APP_ID'), 'X-Parse-API-Key: ' . getenv('MB_API_KEY'), ], ]); $body = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch);
if ($status !== 200) throw new RuntimeException("REST $status: $body"); return json_decode($body, true)['results'] ?? [];}import json, os, requests
API = "https://api.mbapps.co.il/parse"H = { "X-Parse-Application-Id": os.environ["MB_APP_ID"], "X-Parse-API-Key": os.environ["MB_API_KEY"],}
def fetch_recent_leads(limit: int = 100) -> list[dict]: params = { "where": json.dumps({"IsAccount": False}), # requests מקודד ל-URL עבורכם "keys": "Name,PhoneNumber,Email,createdAt", "order": "-createdAt", "limit": limit, # תמיד מפורש } r = requests.get(f"{API}/classes/Accounts", headers=H, params=params, timeout=30) r.raise_for_status() return r.json()["results"]const API = 'https://api.mbapps.co.il/parse';const H = { 'X-Parse-Application-Id': process.env.MB_APP_ID, 'X-Parse-API-Key': process.env.MB_API_KEY,};
export async function fetchRecentLeads(limit = 100) { const qs = new URLSearchParams({ where: JSON.stringify({ IsAccount: false }), // URLSearchParams מקודד עבורכם keys: 'Name,PhoneNumber,Email,createdAt', order: '-createdAt', limit: String(limit), // תמיד מפורש });
const res = await fetch(`${API}/classes/Accounts?${qs}`, { headers: H, signal: AbortSignal.timeout(30_000), }); if (!res.ok) throw new Error(`REST ${res.status}: ${await res.text()}`); return (await res.json()).results;}using System.Net.Http.Json;using System.Text.Json;using System.Web;
public static async Task<JsonElement> FetchRecentLeadsAsync(HttpClient http, int limit = 100){ var qs = HttpUtility.ParseQueryString(string.Empty); qs["where"] = """{"IsAccount":false}"""; // מקודד אוטומטית qs["keys"] = "Name,PhoneNumber,Email,createdAt"; qs["order"] = "-createdAt"; qs["limit"] = limit.ToString(); // תמיד מפורש
// הכותרות נקבעות פעם אחת על ה-HttpClient: // http.DefaultRequestHeaders.Add("X-Parse-Application-Id", appId); // http.DefaultRequestHeaders.Add("X-Parse-API-Key", apiKey); var url = $"https://api.mbapps.co.il/parse/classes/Accounts?{qs}"; var doc = await http.GetFromJsonAsync<JsonElement>(url); return doc.GetProperty("results");}// בדפדפן — קוראים לשרת שלכם, לא ל-api.mbapps.co.ilconst res = await fetch('/api/leads?limit=20');if (!res.ok) throw new Error('שגיאה בטעינת הלידים');const leads = await res.json();הקריאה עם X-Parse-API-Key מחזירה 200 ואת השדות שב‑keys; ברירת המחדל בלי limit היא 100 שורות. אותו מפתח תחת X-Parse-Master-Key נדחה ב‑400 code 119 Permission denied.
בלי מפתח בכלל (App‑Id בלבד) התוצאה תלויה ב‑CLP של הטבלה: הרשאות סגורות מחזירות את אותה 400 code 119, והרשאה שנפתחה לציבור מחזירה 200 עם נתונים. יש מערכות שבהן Accounts ו‑Sales מחזירות 200 בדיוק כך. אל תניחו שהיעדר מפתח חוסם; בדקו את ה‑CLP של הטבלה.
המשך: סנכרון יוצא עם עימוד · מצא‑או‑צור.
שלוש המלכודות שחוזרות בכל שפה
Section titled “שלוש המלכודות שחוזרות בכל שפה”- Pointer בשכבת הטפסים = מחרוזת objectId חשופה בת 10 תווים, לא אובייקט Parse. ב‑REST הפוך:
{"__type":"Pointer","className":…,"objectId":…}. אותו שדה, שתי צורות. ראו סוגי נתונים. - בוליאני בשכבת הטפסים: שדות
table_*מקבלים גם מחרוזת"true"/"false"וגם בוליאני אמיתי, ושניהם נשמרים כ‑Boolean.account_IsAccountמקבל רק בוליאני אמיתי; מחרוזת מפילה את כל הבקשה ב‑400 code 111. מספר בשדה בוליאני נדחה בכל מקרה. whereב‑REST = JSON שעובר URL‑encoding. השתמשו בכלי הקידוד של הספרייה (params=,URLSearchParams,--data-urlencode). שרשור ידני נכשל בשתי צורות: רווח גולמי ב‑URL →400 Bad Requestבדף HTML מהשער, לא JSON; JSON שבור, למשל מפתח בלי מרכאות →500{"code":1,"message":"Internal server error."}, שגיאת קלט בלבוש תקלת שרת.
שפות אחרות
Section titled “שפות אחרות”תרגמו מהדוגמה הקרובה ביותר: Go ו‑Rust מ‑Node.js, Ruby ו‑Kotlin מ‑Python, Java מ‑C#. הכותרות זהות (Content-Type: application/json ו‑X-Parse-Application-Id, ובשכבת ה‑REST גם כותרת ההרשאה), ושלוש המלכודות חוצות שפה.