API הסוכנים של GetFacade
תכנון חזיתות דרך MCP ו-HTTP. כל תכנון נבנה עבור המדינה שבה עומד המבנה: חומרים שישימים שם, מוצרים שהיצרנים באמת מוכרים שם, ושכבות המבנה הטכניות מאחורי פני השטח. הרינדור מציג אותו על תצלום הבית, האומדן מתמחר אותו שורה אחר שורה, ואלבום ה-PDF מתעד אותו עבור הצוות שיבצע. כל נתיב למטה הוא נקודת קצה קיימת של GetFacade, אותה אחת שאפליקציות iOS, אנדרואיד והדפדפן קוראות לה. מפתח סוכן רק מצמצם מי רשאי לקרוא לה, מודד את ההוצאה ונעצר בתקרה שלו.
- כתובת בסיס
- https://api.getfacade.ai/api/v1
- אימות
- Bearer <agent key>
- חבילה
- @getfacade/mcp
- סביבת הרצה
- Node.js 20+
- תעבורה
- stdio (MCP), HTTPS (REST)
- מפרט
- OpenAPI 3.1, v1.0.0
התחלה מהירה
הנפיקו מפתח
app.getfacade.aiחשבוןהגדרותAPIיצירת מפתח
הערך מוצג פעם אחת ואי אפשר לשחזר אותו, רק להחליף. תקרת ההוצאה נקבעת בהנפקה ונאכפת בכל קריאה בתשלום.
הנפקת מפתח סוכןרשמו את שרת ה-MCP
רשומה אחת בתצורת הלקוח, ואז הפעלה מחדש של הלקוח. Claude Desktop שומר אותה ב-claude_desktop_config.json; כל לקוח MCP אחר מקבל את אותם שלושה שדות.
{ "mcpServers": { "getfacade": { "command": "npx", "args": ["-y", "@getfacade/mcp"], "env": { "GETFACADE_API_KEY": "your-key" } } } }משתני סביבה משתנה נדרש ברירת מחדל GETFACADE_API_KEYכן —GETFACADE_API_BASE_URLלא https://api.getfacade.ai/api/v1או קראו ישירות ל-API
אותו מפתח משמש כאסימון Bearer. הבקשות והתשובות הן מסמכי JSON:API, שבהם id הוא שדה ברמה העליונה ולעולם אינו יושב בתוך attributes.
curl -X POST https://api.getfacade.ai/api/v1/projects \ -H "Authorization: Bearer $GETFACADE_API_KEY" \ -H "Content-Type: application/json" \ -d '{"data":{"type":"project","attributes":{"name":"Maple Street 14"}}}'
כלים
עשרים ואחד כלים. שרת ה-MCP אינו שומר מצב ואין לו כללים משלו: כל כלי הוא קריאה אחת או יותר לנקודות הקצה המצוינות לצידו, וכל הודעה שהסוכן מוסר נכתבת על ידי ה-API.
create_buildingcreate_building(name, goals?, construction_region?) -> { building_id, name }יוצר מבנה. השם ייחודי בתוך החשבון ואורכו עד 50 תווים; כפילות נדחית עם 422.
קורא ל
POST /projectsupload_photoupload_photo(building_id, file_path, wait_for_validation? = true) -> { view_id, validation: { status, reason? } }רושם תצוגה, מעלה את הבתים לכתובת חתומה מראש, מאשר אותם ומתשאל עד שהתצלום מתקבל או נדחה. רוחב, גובה ו-md5 מחושבים מקומית; את יחס הממדים גוזר השרת.
קורא ל
POST /projects/{project}/angles → PUT (presigned) → POST /angles/{angle}/confirm → GET /angles/{angle}/validationstart_designאסינכרוניstart_design(building_id, view_id, prompt?, style_ids?, colors?, brand_selections?, render_effort?, seed?) -> { design_id, job_id, status, seed }מתכנן את החזית בזווית שנבחרה ומציג אותה על התצלום: חומרים ישימים במדינת המבנה, מוצרים שנמכרים שם באמת, ושכבות המבנה שמאחורי פני השטח. יוצר תכנון, מכניס את העבודה לתור ומחזיר מזהה משימה. ה-seed אופציונלי: אם לא נמסר, השרת מייצר אותו ומחזיר אותו.
קורא ל
POST /projects/{project}/concepts → POST /concepts/{concept}/angles/{conceptAngle}/rendersrefine_designאסינכרוניrefine_design(render_id | design_id + building_id, instruction, style_ids?, colors?, brand_selections?, render_effort?, seed?) -> { design_id, job_id, status, parent_render_id, seed }מתקן במילים תכנון מוגמר. ההוראה חלה על התכנון המוגמר, ולכן כל מה שלא הוזכר בה נשמר. תיקון של הזווית הראשית יוצר תכנון חדש, כך שהקודם לעולם אינו נדרס.
קורא ל
GET /renders/{render} → POST /concepts/{concept}/angles/{conceptAngle}/renders (mode: refine)get_jobget_job(job_id, kind: "render" | "album" | "estimate" = "render") -> { status, expected_seconds?, result_url?, error?, error_code? }קורא את מצבם של רינדור, אומדן או אלבום בודדים.
קורא ל
GET /renders/{render} · GET /estimates/{estimate}list_jobslist_jobs(kind?, limit? = 20) -> [{ job_id, kind, status, building_id, created_at }]המשימות האחרונות בחשבון, הלא גמורות בראש.
קורא ל
GET /historylist_designslist_designs(building_id) -> [{ design_id, note, has_main_render, main_render_id, main_render_url, renders }]העיצובים של מבנה יחד עם הרינדורים שלהם. מכאן מגיעים מזהי הרינדור לאומדן ולאלבום.
קורא ל
GET /projects/{project}/conceptsorder_estimateאסינכרוניorder_estimate(design_id, render_ids, currency?, measurement_system?, special_requirements?) -> { job_id, status }מתמחר את התכנון שורה אחר שורה, בחומרים ובעבודה, במחירים שיש לחומרים שצוינו במדינת המבנה. המטבע ושיטת המידה נגזרים כברירת מחדל מאותה מדינה.
קורא ל
POST /projects/{project}/concepts/{concept}/estimatesorder_albumאסינכרוניorder_album(design_id, render_ids, language?, include_blueprints?, include_estimate?, requirements?) -> { job_id, status }מתעד את התכנון עבור הצוות שיבצע: החומרים, שכבות החזית, הערות בטיחות והתקנים שעליהם הן נשענות. דורש רינדור ראשי מוגמר.
קורא ל
POST /concepts/{concept}/album/generateupscale_renderאסינכרוניupscale_render(render_id) -> { job_id, status }מגדיל רינדור שהושלם. עולה קרדיטים ורץ באופן אסינכרוני.
קורא ל
POST /renders/{render}/upscaleget_estimateget_estimate(estimate_id) -> { status, currency, facade_area, materials_total, labor_total, grand_total, notes, lines: [{ line_id, section, name, quantity, unit, unit_price, line_total }] }האומדן עצמו: הסכומים, ההנחות שמאחוריהם וכל שורה עם כמות, יחידה ומחיר. get_job מדווח על מצב האומדן, לעולם לא על תוכנו.
קורא ל
GET /estimates/{estimate}add_estimate_lineadd_estimate_line(estimate_id, section, name, quantity, unit_price, unit?, category?) -> { line_id }מוסיף שורה לאומדן. היחידות מגיעות משיטת המידות של האומדן עצמו.
קורא ל
POST /estimates/{estimate}/itemsupdate_estimate_lineupdate_estimate_line(estimate_id, line_id, name?, quantity?, unit_price?, unit?, category?, section?) -> { line_id }משנה שורה באומדן. רק השדות שנשלחו משתנים, והסכומים מחושבים מחדש בשרת.
קורא ל
PATCH /estimates/{estimate}/items/{item}delete_estimate_linedelete_estimate_line(estimate_id, line_id) -> { deleted }מסיר שורה מהאומדן.
קורא ל
DELETE /estimates/{estimate}/items/{item}delete_renderdelete_render(render_id) -> { deleted }מוחק רינדור. מחיקת הרינדור הראשי מחזירה את העיצוב שלו לטיוטה.
קורא ל
DELETE /renders/{render}delete_designdelete_design(building_id, design_id) -> { deleted }מוחק עיצוב יחד עם הרינדורים שתחתיו.
קורא ל
DELETE /projects/{project}/concepts/{concept}delete_buildingdelete_building(building_id) -> { deleted }מוחק מבנה על כל תכולתו. קרדיטים שכבר הוצאו אינם מוחזרים.
קורא ל
DELETE /projects/{project}list_token_packageslist_token_packages() -> [{ package, tokens, price, currency }]החבילות שהחשבון יכול לקנות, עם המחיר ומספר הקרדיטים.
קורא ל
GET /tokens/packagesbuy_tokensאסינכרוניbuy_tokens(package) -> { status, transaction_id, tokens, checkout_url?, detail }קונה חבילה אחת לארנק של המפתח הזה. דורש מפתח שהונפק עם הרשאת רכישה, ולעולם לא חורג ממה שעוד מותר למפתח להוציא.
קורא ל
POST /tokens/purchaseget_balanceget_balance() -> { balance, scope: "api", spend_cap, spent, remaining, is_admissible }ארנק הסוכן, תקרת המפתח הזה, והאם הקריאה הבאה בתשלום תתקבל.
קורא ל
GET /tokens/balancereport_problemreport_problem(message, category?, context?: { tool, endpoint, status_code, job_id, expected, actual }) -> { reference, message }מדווח על תקלה ב-API הזה: שדה שמתואר כאן ואינו מגיע, סירוב שמנוסחו לא נובע צעד הבא, תוצאה שאינה תואמת את מה שהתבקש. חינם ומתקבל גם בארנק ריק; חוזר מספר סימוכין, לא תשובה.
קורא ל
POST /feedback
אימות ומפתחות
- המפתח נשלח כאסימון Bearer בכותרת
Authorization. שרת ה-MCP קורא אותו מ-GETFACADE_API_KEYואינו שולח דבר מלבדו. - הערך מוצג פעם אחת, בהנפקה, ונשמר ממנו רק גיבוב. סבב מפתחות פירושו הנפקת מפתח חדש וביטול הישן.
- לכל מפתח יש תקרת הוצאה, הנאכפת בשרת לפני שהקריאה מגיעה לבקר. הגעה לתקרה עוצרת את המפתח הזה, לא את החשבון.
- מפתחות אינם מנהלים מפתחות: זו פעולה אנושית, ונקודות הקצה האלה משיבות 403 למפתח סוכן.
- ביטול נכנס לתוקף מיד. קריאות במפתח מבוטל מקבלות 401.
עבודה אסינכרונית ותשאול
start_design,order_estimateו-order_albumמחזירים מזהה משימה ומסתיימים. רינדור אורך דקות: תשאלו אתGET /renders/{render}אוGET /estimates/{estimate}עד שהמצב סופי.- סיום בדיקת התצלום מוכרז בערוץ websocket שאין לסוכן. תשאלו את
GET /angles/{angle}/validationוקראו אתvalidation.is_in_progress; אל תסיקו בעצמכם סופיות ממחרוזת המצב. - רינדור מוגמר ואלבום מוגמר נמצאים בכתובות ציבוריות קבועות: בלי חתימה ובלי תפוגה. אפשר למסור את הקישור לאדם ישירות, וזו התשובה ל«תראה לי את התוצאה». מכיוון שאינו חתום הוא אינו מבקש רשות מאיש: הוא ממשיך לעבוד אצל כל מי שמקבל אותו, ואי אפשר לבטל אותו.
GET /renders/{render}/downloadהוא דבר אחר: כתובת חתומה שפגה בתוך דקות ונושאת שם קובץ. היא נועדה לשמירת הקובץ, לא לשיתופו.
מגבלות קצב לכל מפתח
למפתח סוכן יש מכסות משלו, נפרדות מהפעילות האנושית באותו חשבון, כדי שסוכן שנתקע בלולאה לא יכלה את המכסה של מי שיושב מול המסך. הסירוב זול: הוא מתקבל בשכבת הביניים, לפני כל עבודה מול מסד הנתונים.
| תחום | לדקה | לשעה |
|---|---|---|
| קריאות וכתיבות רגילות | 120 | 2000 |
| תשאול מצב ובדיקה | 120 | 2000 |
| הזמנות רינדור, אומדן ואלבום | 10 | 200 |
אידמפוטנטיות
קריאה בתשלום יוצרת משימה, והחיוב הולך אחרי המשימה. מתן שם לקריאה הוא מה שמאפשר לחזרה עליה להחזיר את אותה משימה במקום ליצור שנייה.
-
Idempotency-Keyנדרשת בכל קריאה בתשלום שנעשית עם מפתח API: התחלת עיצוב או שיפורו, הגדלת רינדור, הזמנת אומדן או אלבום, יצירת אומדן מחדש. בלעדיה הקריאה משיבה 422IDEMPOTENCY_KEY_REQUIREDודבר לא נכנס לתור. - כל ערך באורך 8 עד 191 תווים, אחד לכל הזמנה; בדרך כלל UUID. הזמנה חדשה מקבלת ערך חדש: שתי קריאות זהות תחת שני ערכים הן שני עיצובים.
- חזרה על קריאה עם אותו ערך ואותו גוף מחזירה את הסטטוס והגוף המקוריים, עם
Idempotent-Replay: trueבתשובה. דבר לא נכנס לתור ודבר לא מחויב פעמיים. - אותו ערך עם גוף שונה משיב 422
IDEMPOTENCY_KEY_REUSED. חזרה שמגיעה בזמן שהקריאה הראשונה עדיין רצה משיבה 409IDEMPOTENCY_IN_PROGRESS: המתינו ושלחו את אותה קריאה שוב. - כל 4xx משחרר את הערך, כך שאפשר לשלוח אותו שוב אחרי שהסיבה תוקנה. הערכים נשמרים 24 שעות, לכל חשבון.
-
@getfacade/mcpמייצר את הערך וחוזר על הקריאה איתו בעצמו, כך שאין מה להעביר בקריאה לכלי.
שגיאות
כשלים מגיעים כמסמכי שגיאה של JSON:API. תשובות האימות של Laravel אינן בתבנית הזאת ונושאות את הטקסט בשדה message.
| סטטוס | קוד | משמעות | ניתן לנסות שוב |
|---|---|---|---|
401 | — | המפתח חסר, בוטל או פג. | לא |
402 | AGENT_CREDITS_EXHAUSTED | בחשבון לא נותרו קרדיטים בהיקף api. | לא |
402 | AGENT_KEY_CAP_REACHED | המפתח הזה מיצה את התקרה שלו. הנפיקו מפתח אחר או העלו את התקרה. | לא |
403 | — | נקודת קצה זו אינה זמינה למפתחות API. ממשק הסוכנים מכסה מבנים, תמונות, עיצובים, רינדורים, אומדנים, אלבומים וארנק ה-API. הגדרות החשבון, ההתחברות והתשלום משנה אדם שמחובר באפליקציה. | לא |
403 | AGENT_PURCHASE_NOT_ALLOWED | המפתח הזה הונפק בלי הרשאה לקנות קרדיטים. | לא |
403 | AGENT_PURCHASE_EXCEEDS_CAP | הרכישה תוציא את המפתח מעבר לתקרת ההוצאה שלו. | לא |
409 | IDEMPOTENCY_IN_PROGRESS | הקריאה הראשונה עם Idempotency-Key זה עדיין לא השיבה. המתינו ושלחו את אותה קריאה שוב. | כן |
422 | — | הבקשה הובנה ונדחתה: שם מבנה כפול, תצלום שנדחה, אלבום שהוזמן לפני שהרינדור הראשי הסתיים. | לא |
422 | IDEMPOTENCY_KEY_REQUIRED | קריאה בתשלום עם מפתח API ללא כותרת Idempotency-Key. דבר לא נכנס לתור; שלחו אותה שוב עם הכותרת. | לא |
422 | IDEMPOTENCY_KEY_REUSED | Idempotency-Key זה שימש לבקשה אחרת. השתמשו בערך חדש עבור הזמנה חדשה. | לא |
429 | — | המכסה של המפתח הזה אזלה. המתינו, אל תנסו שוב בלולאה צפופה. | כן |
את הטקסט הקריא כותב ה-API, בשפת הקורא. הציגו את errors[].detail כפי שהוא במקום לנסח הודעה משלכם.
חיוב וקבלה
- קריאות בתשלום נמשכות מקרדיטים של היקף
api, והכניסה בוחנת רק את היתרה הזו: כל מפתח משלם בקרדיטים. - Pro Plan פעיל ממלא את ארנק ה-api עד 1,000 קרדיטים פעם בכל תקופת חיוב. מעבר לכך קונים קרדיטים.
- מפתח ממלא את הארנק שלו רק אם הונפק עם הרשאת רכישה, ולכל היותר בגובה מה שעוד מותר לו להוציא, ולכן רכישה לעולם אינה מעלה את תקרת ההוצאה.
- תחום
apiהוא ארנק נפרד. את הקרדיטים של האפליקציה, לרבות השכבה החינמית, מפתח לעולם אינו מוציא. - ההוצאה נספרת לכל מפתח בנפרד, כך שהצריכה של כל עוזר נראית לחוד.
- בדיקה מקדימה היא
GET /tokens/balance, השדהdata.attributes.agent.is_admissible. הבלוק מופיע רק במפתחות סוכן, והדגל משקף במדויק את שכבת הקבלה. קראו אותו במקום להשוות בעצמכם יתרה מול תקרה. - הקבלה נקבעת לפני שעבודה נכנסת לתור, ולכן קריאה שנדחתה אינה עולה דבר.
אסימוני צבע ומותג
start_design מקבל שתי רשימות בלתי תלויות, עד עשרה פריטים בכל אחת. הסדר נושא את תפקיד 60/30/10: הפריט הראשון הוא צבע הקירות הדומיננטי.
colors
| אסימון | משמעות |
|---|---|
palette:1 | מערך צבעים מוכן של GetFacade, לפי מזהה. |
#8A8F7D | צבע חופשי, שש ספרות הקסדצימליות. |
paint:412 | גוון של יצרן, בתבנית בת שני מקטעים שנשמרה לצורכי תאימות. |
brand_selections
| אסימון | משמעות |
|---|---|
siding:brand:12 | כל מוצר של אותו יצרן בקטגוריה הזאת. |
siding:line:40@double-4-dutchlap | קו מוצרים אחד, בגיאומטריה אחת. |
siding:product:88@double-4-dutchlap | מוצר אחד, מוגדר במלואו. |
paint:brand:3 | כל גוון של מותג הצבע הזה. |
paint:product:412 | גוון צבע יחיד. |
הדקדוק הוא category:level:id[@value][.value]. החלק שאחרי @ נושא מזהי ערכי גיאומטריה, ייחודיים בתוך הקטגוריה שלהם, ולכן הציר שאליו הם שייכים נמצא בחיפוש ולא נכתב באסימון. אסימון לא מוכר נדחה עם 422 ולעולם אינו מנוטרל בשקט.
מפגש מקצה לקצה
מבנה אחד, תצלום אחד, עיצוב אחד ואז שני המסמכים. ההנחיה שמייצרת את זה:
צור מבנה בשם Maple Street 14, העלה את ./front.jpg כתצוגה שלו, והתחל עיצוב עם קירות אפורים חמים ומסגרות לבנות. הזמן את האומדן והאלבום עבור התוצאה.
create_building(name: "Maple Street 14")
-> { building_id: "0f8c…" }
upload_photo(building_id: "0f8c…", file_path: "./front.jpg")
-> { view_id: "41ab…", validation: { status: "approved" } }
start_design(building_id: "0f8c…", view_id: "41ab…",
colors: ["#8A8F7D", "#F2F0EB"],
brand_selections: ["siding:line:40@double-4-dutchlap"])
-> { design_id: "7d21…", job_id: "b933…", status: "queued" }
get_job(job_id: "b933…")
-> { status: "completed", result_url: "https://…" }
refine_design(render_id: "b933…",
instruction: "put a canopy over the front door")
-> { design_id: "9e44…", job_id: "c07f…", status: "queued" }
order_estimate(design_id: "9e44…", render_ids: ["c07f…"])
order_album(design_id: "9e44…", render_ids: ["c07f…"], include_estimate: true)