סכימות — לקרוא לפני שכותבים
זו הקריאה הראשונה של כל אינטגרציה. לא ה‑CRUD, לא ההתחברות — הסכימה.
הסיבה מבנית: כל לקוח הוא אפליקציה נפרדת שהתחילה מאותו בסיס מוצר ואז הותאמה. שדות נוספו, שדות הוסרו, שדות באותו שם קיבלו טיפוס אחר. סכימה שהעתקתם מלקוח אחד תשקר לכם אצל השני.
מה חוזר
Section titled “מה חוזר”curl -sS "https://api.mbapps.co.il/parse/schemas/Accounts" \ -H "X-Parse-Application-Id: $APP_ID" \ -H "X-Parse-API-Key: $API_KEY"const res = await fetch('https://api.mbapps.co.il/parse/schemas/Accounts', { headers: { 'X-Parse-Application-Id': APP_ID, 'X-Parse-API-Key': API_KEY, },});import requests
res = requests.get( "https://api.mbapps.co.il/parse/schemas/Accounts", headers={ "X-Parse-Application-Id": APP_ID, "X-Parse-API-Key": API_KEY, }, timeout=30,)<?php$ch = curl_init('https://api.mbapps.co.il/parse/schemas/Accounts');curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'X-Parse-Application-Id: ' . $appId, 'X-Parse-API-Key: ' . $apiKey, ],]);$response = curl_exec($ch);curl_close($ch);{ "className": "Accounts", "fields": { "objectId": { "type": "String" }, "createdAt": { "type": "Date" }, "updatedAt": { "type": "Date" }, "ACL": { "type": "ACL" }, "createdBy": { "type": "Pointer", "targetClass": "_User" }, "updatedBy": { "type": "Pointer", "targetClass": "_User" }, "Name": { "type": "String" }, "PhoneNumber": { "type": "String" }, "Email": { "type": "String" }, "IsAccount": { "type": "Boolean" }, "StatusId": { "type": "Pointer", "targetClass": "AccountStatuses" }, "LeadStatusId": { "type": "Pointer", "targetClass": "LeadStatuses" }, "LeadSourceId": { "type": "Pointer", "targetClass": "LeadSource" }, "Comment": { "type": "HTML/XML" }, "array_languages_Pointer_Languages": { "type": "Array" } }, "classLevelPermissions": { "find": { "role:Sales": true }, "get": {}, "create": {} }, "triggers": [], "timeline": { "displayFields": { "Name": "AccountName" }, "index": { "objectId": "AccountId" } }}(הדוגמה מקוצרת ומייצגת — Accounts במערכת חדשה מחזירה 40 שדות, וכל לקוח מוסיף משלו.)
| מפתח | מה הוא אומר |
|---|---|
className |
שם הטבלה — הערך שתשלחו בנתיב |
fields |
מפה של שם שדה → הגדרה |
fields.<X>.type |
הטיפוס. מכתיב את פורמט החוט — ראו סוגי נתונים |
fields.<X>.targetClass |
ל‑Pointer ו‑Relation בלבד: לאיזו טבלה השדה מצביע |
fields.<X>.dictionary |
התווית בעברית של השדה — מוחזרת רק ב‑Get-Schema של שכבת ה‑MCP. ב‑REST המפתח הזה אינו חוזר לעולם, גם כשהתווית קיימת (start-a-02). ראו למטה |
classLevelPermissions |
הרשאות הטבלה. מפה ריקה = אף אחד לא רואה כלום |
triggers |
מערך הגדרות האוטומציה של הטבלה — ראו למטה |
timeline |
הגדרות ציר הזמן. מופיע רק בטבלאות שהרישום שלהן דלוק — 11 טבלאות מהקופסה (Accounts, Contacts, Sales, PriceQuotes, Cases, Tasks, Activities, Notes, Conversations, Emails, SMS) |
בלי שם טבלה בנתיב (GET /parse/schemas) חוזרת רשימת כל המחלקות. במערכת חדשה זו תשובה של 111 מחלקות, ובסביבה מותאמת כמעט 200 — שאלו טבלה ספציפית כשאתם יודעים מה אתם מחפשים. שתי הצורות דורשות Master Key או API Key; עם X-Parse-Application-Id בלבד חוזר 403 {"error":"unauthorized: master key is required"}.
targetClass — המפתח לכל Pointer
Section titled “targetClass — המפתח לכל Pointer”בלי targetClass אי אפשר לכתוב Pointer תקין: פורמט החוט דורש את className.
// מהסכימה"LeadSourceId": { "type": "Pointer", "targetClass": "LeadSource" }
// ולכן הכתיבה ב-REST היא{ "LeadSourceId": { "__type": "Pointer", "className": "LeadSource", "objectId": "vOZLqOWnQf" } }הצעד הבא אחרי קריאת הסכימה הוא בדרך כלל שליפת טבלאות ה‑lookup ובניית מיפוי תווית → objectId:
curl -sS -G "https://api.mbapps.co.il/parse/classes/LeadSource" \ -H "X-Parse-Application-Id: $APP_ID" -H "X-Parse-API-Key: $API_KEY" \ --data-urlencode 'keys=Name' --data-urlencode 'limit=200'const params = new URLSearchParams({ keys: 'Name', limit: '200' });const res = await fetch(`https://api.mbapps.co.il/parse/classes/LeadSource?${params}`, { headers: { 'X-Parse-Application-Id': APP_ID, 'X-Parse-API-Key': API_KEY, },});import requests
res = requests.get( "https://api.mbapps.co.il/parse/classes/LeadSource", headers={ "X-Parse-Application-Id": APP_ID, "X-Parse-API-Key": API_KEY, }, params={"keys": "Name", "limit": 200}, timeout=30,)<?php$params = http_build_query(['keys' => 'Name', 'limit' => 200]);$ch = curl_init("https://api.mbapps.co.il/parse/classes/LeadSource?$params");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'X-Parse-Application-Id: ' . $appId, 'X-Parse-API-Key: ' . $apiKey, ],]);$response = curl_exec($ch);curl_close($ch);dictionary — לבנות ממשק בעברית בלי לתרגם ידנית
Section titled “dictionary — לבנות ממשק בעברית בלי לתרגם ידנית”התווית העברית נשמרת בטבלת המערכת _Dictionary (tblName, field, value). ההשלכה המעשית נחמדה: אפשר לייצר טופס בעברית ישירות מהסכימה, בלי לקודד תרגומים ובלי לצאת מסנכרון כשהלקוח משנה תווית — אבל צריך לדעת מאיזו שכבה לקרוא אותה:
| השכבה | איפה התווית |
|---|---|
MCP — Get-Schema |
inline בתוך הגדרת השדה: "JoinDate": { "type": "Date", "dictionary": "תאריך הצטרפות" } |
REST — GET /parse/schemas/<Table> |
אינה חוזרת. גם כששורת _Dictionary קיימת, REST מחזיר "JoinDate": { "type": "Date" } בלבד |
// טופס בעברית מתוך REST: סכימה + _Dictionaryconst [schemaRes, dictRes] = await Promise.all([ fetch('https://api.mbapps.co.il/parse/schemas/Accounts', { headers: H }), fetch('https://api.mbapps.co.il/parse/classes/_Dictionary?limit=1000&where=' + encodeURIComponent(JSON.stringify({ tblName: 'Accounts' })), { headers: H }),]);const { fields } = await schemaRes.json();const labels = Object.fromEntries((await dictRes.json()).results.map(r => [r.field, r.value]));
const SYSTEM = new Set(['objectId', 'createdAt', 'updatedAt', 'ACL', 'createdBy', 'updatedBy']);
const formFields = Object.entries(fields) .filter(([name]) => !SYSTEM.has(name)) .map(([name, def]) => ({ name, label: labels[name] ?? name, // תווית עברית, ואם אין — שם השדה type: def.type, target: def.targetClass ?? null, // צריך שליפת lookup }));triggers — למה כתיבה “עושה דברים מוזרים”
Section titled “triggers — למה כתיבה “עושה דברים מוזרים””במוצר הזה תשובת הסכימה הפרטנית נושאת גם מערך triggers: הגדרות האוטומציה נשמרות יחד עם הסכימה של הטבלה.
זו נקודת האבחון הראשונה כשכתיבה תמימה מייצרת התנהגות לא צפויה — עדכון סטטוס ששולח מייל, יצירת רשומה שיוצרת שלוש רשומות נוספות, שדה שמשנה את עצמו מיד אחרי הכתיבה.
שינוי סכימה — לא דרך REST גולמי
Section titled “שינוי סכימה — לא דרך REST גולמי”וטבלה שנוצרה ב‑REST גולמי נולדת חסרת הרשאות. ה‑CLP שלה ריק לחלוטין ({"find":{},"get":{},"create":{},"update":{},"delete":{}}), ולכן “השדות מופיעים ריקים” ו“המשתמש לא רואה כלום” — התקלה הנפוצה ביותר אחרי הקמה. טבלה שנוצרה ב‑Create-Table מקבלת את ברירת המחדל שלמעלה — וגם אותה צריך לפתוח לתפקידים הרלוונטיים, מיד אחרי היצירה.
מה לא חוזר בסכימה
Section titled “מה לא חוזר בסכימה”| מה | איפה כן |
|---|---|
| אילו שדות מאונדקסים לחיפוש טקסט | אין נקודת קצה. הבדיקה היחידה: $text שמחזיר 500 IndexNotFound = אין אינדקס |
| ערכי טבלאות ה‑lookup | שליפה רגילה מהטבלה עצמה |
| מבנה עמודים וטפסים | שכבת ה‑site, לא Parse — כלי העמודים בלבד |
_Role ו‑_Session |
Get-Schema של MCP מחזיר עליהן {}; ב‑REST עם Master Key הן חוזרות מלאות |
(הרשאות הטבלה כן חוזרות — במפתח classLevelPermissions.)
הצעד הראשון בכל אינטגרציה — סקריפט
Section titled “הצעד הראשון בכל אינטגרציה — סקריפט”#!/usr/bin/env python3"""describe_table.py <TableName> — מה יש בטבלה הזו, בעברית ובאנגלית."""import os, sys, requests
APP_ID = os.environ["MB_APP_ID"]API_KEY = os.environ["MB_API_KEY"]TABLE = sys.argv[1]
r = requests.get( f"https://api.mbapps.co.il/parse/schemas/{TABLE}", headers={"X-Parse-Application-Id": APP_ID, "X-Parse-API-Key": API_KEY}, timeout=30,)r.raise_for_status()schema = r.json()
SYSTEM = {"objectId", "createdAt", "updatedAt", "ACL", "createdBy", "updatedBy"}fields = schema["fields"]print(f'{schema["className"]} — {len(fields)} שדות\n')
for name, d in sorted(fields.items()): if name in SYSTEM: continue kind = d["type"] if d.get("targetClass"): kind += " -> " + d["targetClass"] print(f' {name:<38} {kind:<30} {d.get("dictionary", "")}')
print(f'\ntriggers: {len(schema.get("triggers", []))}')המשך מכאן
Section titled “המשך מכאן”- סוגי נתונים — מהטיפוס שקראתם אל פורמט הכתיבה
- מפת הטבלאות — מה לחפש בכל טבלה
- עבודה עם רשומות — הכתיבה עצמה
- יומנים וראיות — מה עשה הטריגר שראיתם בסכימה
- שגיאות ופתרון תקלות — “200 אבל השדה ריק”