واجهة GetFacade البرمجية للوكلاء

تصميم الواجهات عبر MCP وHTTP. كل تصميم يُعَدّ للبلد الذي يقوم فيه المبنى: المواد القابلة للتطبيق هناك، والمنتجات التي تبيعها الشركات المصنّعة هناك فعلاً، وبنية الطبقات التقنية خلف السطح. يعرضه الريندر على صورة المنزل، ويحسبه تقدير التكلفة بنداً بنداً، ويوثّقه ألبوم PDF للفريق الذي سينفّذه. كل مسار أدناه هو نقطة نهاية قائمة في GetFacade، ذاتها التي تستدعيها تطبيقات iOS وAndroid والويب. مفتاح الوكيل يضيّق فقط من يحق له الاستدعاء، ويقيس الإنفاق، ويتوقف عند سقفه.

العنوان الأساسي
https://api.getfacade.ai/api/v1
المصادقة
Bearer <agent key>
الحزمة
@getfacade/mcp
بيئة التشغيل
Node.js 20+
النقل
stdio (MCP), HTTPS (REST)
المواصفة
OpenAPI 3.1, v1.0.0

بداية سريعة

  1. أصدر مفتاحًا

    app.getfacade.aiالحسابالإعداداتAPIإنشاء مفتاح

    تظهر القيمة مرة واحدة ولا يمكن استرجاعها، بل استبدالها فقط. يُحدَّد سقف الإنفاق عند الإصدار ويُطبَّق في كل استدعاء مدفوع.

    إصدار مفتاح وكيل
  2. سجّل خادم MCP

    مدخل واحد في إعدادات العميل، ثم إعادة تشغيل العميل. يحفظه Claude Desktop في claude_desktop_config.json، وكل عميل MCP آخر يقبل الحقول الثلاثة نفسها.

    claude_desktop_config.json
    {
      "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
  3. أو استدعِ واجهة HTTP مباشرة

    يعمل المفتاح نفسه كرمز Bearer. الطلبات والردود مستندات JSON:API، وفيها id حقل من المستوى الأعلى ولا يقع أبدًا داخل attributes.

    shell
    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 بحالة ولا بقواعد خاصة به: كل أداة هي استدعاء واحد أو أكثر لنقاط النهاية المذكورة بجوارها، وكل رسالة ينقلها الوكيل تكتبها الواجهة البرمجية.

  • create_building
    create_building(name, goals?, construction_region?)
      -> { building_id, name }

    ينشئ مبنى. الاسم فريد داخل الحساب وبحد أقصى 50 حرفًا؛ ويُرفض التكرار برمز 422.

    يستدعيPOST /projects

  • upload_photo
    upload_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}/validation

  • start_designغير متزامنة
    start_design(building_id, view_id, prompt?, style_ids?, colors?,
                 brand_selections?, render_effort?, seed?)
      -> { design_id, job_id, status, seed }

    يصمّم الواجهة على زاوية مختارة ويعرضها على الصورة: مواد قابلة للتطبيق في بلد المبنى، ومنتجات تُباع هناك فعلاً، وبنية الطبقات خلف السطح. ينشئ تصميماً، ويضع العمل في الطابور، ويعيد معرّف المهمة. البذرة اختيارية: عند إغفالها يولّدها الخادم ويعيدها.

    يستدعيPOST /projects/{project}/concepts → POST /concepts/{concept}/angles/{conceptAngle}/renders

  • refine_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_job
    get_job(job_id, kind: "render" | "album" | "estimate" = "render")
      -> { status, expected_seconds?, result_url?, error?, error_code? }

    يقرأ حالة تصيير أو تقدير أو ألبوم واحد.

    يستدعيGET /renders/{render} · GET /estimates/{estimate}

  • list_jobs
    list_jobs(kind?, limit? = 20)
      -> [{ job_id, kind, status, building_id, created_at }]

    أحدث المهام على مستوى الحساب، غير المكتملة أولًا.

    يستدعيGET /history

  • list_designs
    list_designs(building_id)
      -> [{ design_id, note, has_main_render, main_render_id,
           main_render_url, renders }]

    تصاميم المبنى مع تصييراتها. من هنا تأتي معرّفات التصيير اللازمة للتقدير والألبوم.

    يستدعيGET /projects/{project}/concepts

  • order_estimateغير متزامنة
    order_estimate(design_id, render_ids, currency?,
                   measurement_system?, special_requirements?)
      -> { job_id, status }

    يسعّر التصميم بنداً بنداً، مواد وأجور عمل، بأسعار المواد المحدّدة في بلد المبنى. العملة ونظام القياس يتبعان ذلك البلد افتراضياً.

    يستدعيPOST /projects/{project}/concepts/{concept}/estimates

  • order_albumغير متزامنة
    order_album(design_id, render_ids, language?, include_blueprints?,
                include_estimate?, requirements?)
      -> { job_id, status }

    يوثّق التصميم للفريق الذي سينفّذه: المواد، وبنية طبقات الواجهة، وملاحظات السلامة، والمعايير التي تستند إليها. يتطلب ريندراً رئيسياً مكتملاً.

    يستدعيPOST /concepts/{concept}/album/generate

  • upscale_renderغير متزامنة
    upscale_render(render_id)
      -> { job_id, status }

    يكبّر لقطة مكتملة. يكلّف رصيدًا ويعمل بشكل غير متزامن.

    يستدعيPOST /renders/{render}/upscale

  • get_estimate
    get_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_line
    add_estimate_line(estimate_id, section, name, quantity,
                      unit_price, unit?, category?)
      -> { line_id }

    يضيف سطرًا إلى التقدير. تأتي الوحدات من نظام القياس الخاص بالتقدير نفسه.

    يستدعيPOST /estimates/{estimate}/items

  • update_estimate_line
    update_estimate_line(estimate_id, line_id, name?, quantity?,
                         unit_price?, unit?, category?, section?)
      -> { line_id }

    يعدّل سطرًا في التقدير. تتغيّر الحقول المرسلة فقط، والمجاميع يعيد حسابها الخادم.

    يستدعيPATCH /estimates/{estimate}/items/{item}

  • delete_estimate_line
    delete_estimate_line(estimate_id, line_id)
      -> { deleted }

    يحذف سطرًا من التقدير.

    يستدعيDELETE /estimates/{estimate}/items/{item}

  • delete_render
    delete_render(render_id)
      -> { deleted }

    يحذف لقطة واحدة. حذف اللقطة الرئيسية يعيد تصميمها إلى المسودة.

    يستدعيDELETE /renders/{render}

  • delete_design
    delete_design(building_id, design_id)
      -> { deleted }

    يحذف تصميمًا مع اللقطات التي تحته.

    يستدعيDELETE /projects/{project}/concepts/{concept}

  • delete_building
    delete_building(building_id)
      -> { deleted }

    يحذف مبنى بكل ما فيه. الرصيد المنفَق لا يُستردّ.

    يستدعيDELETE /projects/{project}

  • list_token_packages
    list_token_packages()
      -> [{ package, tokens, price, currency }]

    الباقات التي يمكن لهذا الحساب شراؤها، بأسعارها وعدد أرصدتها.

    يستدعيGET /tokens/packages

  • buy_tokensغير متزامنة
    buy_tokens(package)
      -> { status, transaction_id, tokens, checkout_url?, detail }

    يشتري باقة واحدة لمحفظة هذا المفتاح. يتطلّب مفتاحًا صادرًا بصلاحية الشراء، ولا يتجاوز أبدًا ما لا يزال مسموحًا للمفتاح بإنفاقه.

    يستدعيPOST /tokens/purchase

  • get_balance
    get_balance()
      -> { balance, scope: "api", spend_cap, spent, remaining, is_admissible }

    محفظة الوكيل، وسقف هذا المفتاح، وما إذا كان الاستدعاء المدفوع التالي سيُقبل.

    يستدعيGET /tokens/balance

  • report_problem
    report_problem(message, category?,
                   context?: { tool, endpoint, status_code, job_id,
                               expected, actual })
      -> { reference, message }

    يُبلغ عن خلل في هذه الواجهة البرمجية: حقل موصوف هنا لكنه لا يصل، رفض لا تُفهم منه الخطوة التالية، نتيجة لا تطابق ما طُلب. مجاني ويُقبل على محفظة فارغة، ويعود بمرجع لا برد.

    يستدعيPOST /feedback

المصادقة والمفاتيح

  • ينتقل المفتاح كرمز Bearer في ترويسة Authorization. يقرأه خادم MCP من GETFACADE_API_KEY ولا يرسل سواه.
  • تظهر القيمة مرة واحدة عند الإصدار، ولا يُخزَّن منها سوى البصمة. التدوير يعني إصدار مفتاح جديد وإبطال القديم.
  • لكل مفتاح سقف إنفاق يُطبَّق على الخادم قبل أن يصل الاستدعاء إلى وحدة التحكم. بلوغ السقف يوقف ذلك المفتاح، لا الحساب.
  • المفاتيح لا تدير المفاتيح: هذا إجراء بشري، وتلك النقاط تردّ 403 على مفتاح الوكيل.
  • الإبطال يسري فورًا. الاستدعاءات بمفتاح مُبطَل تردّ 401.

العمل غير المتزامن والاستعلام

  • تعيد start_design وorder_estimate وorder_album معرّف مهمة ثم تنتهي. يستغرق التصيير دقائق: استعلم عن GET /renders/{render} أو GET /estimates/{estimate} حتى تصبح الحالة نهائية.
  • يُعلَن انتهاء فحص الصورة عبر مقبس ويب لا يملكه الوكيل. استعلم عن GET /angles/{angle}/validation واقرأ validation.is_in_progress؛ ولا تستنتج النهائية بنفسك من نص الحالة.
  • الريندر المكتمل والألبوم المكتمل موجودان على عناوين عامة دائمة: بلا توقيع وبلا انتهاء صلاحية. يمكن تسليم الرابط إلى شخص مباشرةً، وهذا هو الجواب على «أرِني النتيجة». ولأنه غير موقّع فهو لا يستأذن أحداً: يظل يعمل لدى كل من يصله، ولا يمكن سحبه لاحقاً.
  • GET /renders/{render}/download شيء آخر: رابط موقّع تنتهي صلاحيته خلال دقائق ويحمل اسم ملف. وظيفته حفظ الملف، لا مشاركته.

حدود المعدل لكل مفتاح

لمفتاح الوكيل حصص خاصة به، منفصلة عن الجلسات البشرية للحساب نفسه، حتى لا يلتهم وكيل عالق في حلقة حصة الشخص الجالس أمام الشاشة. الرفض رخيص: يُتخذ في الطبقة الوسيطة قبل أي عمل على قاعدة البيانات.

النطاقفي الدقيقةفي الساعة
القراءات والكتابات المعتادة1202000
استعلامات الحالة والفحص1202000
طلبات التصيير والتقدير والألبوم10200

خاصية عدم التكرار

النداء المدفوع يُنشئ مهمة، والرسوم تتبع المهمة. تسمية النداء هي ما يجعل إعادته تُرجع المهمة نفسها بدل إنشاء مهمة ثانية.

  • ترويسة Idempotency-Key مطلوبة في كل نداء مدفوع يُجرى بمفتاح API: بدء تصميم أو تحسينه، تكبير صورة، طلب تقدير تكلفة أو ألبوم، إعادة توليد تقدير. بدونها يردّ النداء بـ 422 IDEMPOTENCY_KEY_REQUIRED ولا يدخل شيء إلى الطابور.
  • أي قيمة بطول 8 إلى 191 حرفًا، واحدة لكل طلب، والمعتاد هو UUID. الطلب الجديد يأخذ قيمة جديدة: نداءان متطابقان بقيمتين هما تصميمان.
  • إعادة النداء بالقيمة نفسها والجسم نفسه تُرجع الحالة والجسم الأصليين، مع Idempotent-Replay: true في الاستجابة. لا يدخل شيء إلى الطابور ولا يُحتسب أي مبلغ مرتين.
  • القيمة نفسها بجسم مختلف تردّ بـ 422 IDEMPOTENCY_KEY_REUSED. والإعادة التي تصل بينما النداء الأول ما زال يعمل تردّ بـ 409 IDEMPOTENCY_IN_PROGRESS: انتظر ثم أرسل النداء نفسه مرة أخرى.
  • أي استجابة 4xx تحرّر القيمة، فيمكن إرسالها من جديد بعد معالجة السبب. تُحفظ القيم 24 ساعة، لكل حساب.
  • @getfacade/mcp ينشئ القيمة ويعيد النداء بها من تلقاء نفسه، فلا شيء يُمرَّر في نداء الأداة.

الأخطاء

تصل الإخفاقات كمستندات أخطاء بصيغة JSON:API. ردود التحقق في Laravel ليست بهذه الصيغة وتحمل نصها في الحقل message.

الحالةالرمزالمعنىقابل للإعادة
401المفتاح مفقود أو مُبطَل أو منتهي الصلاحية.لا
402AGENT_CREDITS_EXHAUSTEDلم يعد في الحساب رصيد في نطاق api.لا
402AGENT_KEY_CAP_REACHEDاستنفد هذا المفتاح سقفه. أصدر مفتاحًا آخر أو ارفع السقف.لا
403نقطة النهاية هذه غير متاحة لمفاتيح واجهة البرمجة. تشمل واجهة الوكلاء المباني والصور والتصاميم وصور العرض والتقديرات والألبومات ومحفظة الواجهة. أما إعدادات الحساب وتسجيل الدخول والدفع فيغيّرها شخص مسجَّل الدخول في التطبيق.لا
403AGENT_PURCHASE_NOT_ALLOWEDأُصدر هذا المفتاح دون صلاحية شراء الرصيد.لا
403AGENT_PURCHASE_EXCEEDS_CAPهذه العملية ستتجاوز سقف إنفاق المفتاح.لا
409IDEMPOTENCY_IN_PROGRESSلم يستجب بعد أول نداء يحمل Idempotency-Key هذا. انتظر ثم أرسل النداء نفسه مرة أخرى.نعم
422فُهم الطلب ورُفض: اسم مبنى مكرر، أو صورة مرفوضة، أو ألبوم طُلب قبل اكتمال التصيير الرئيسي.لا
422IDEMPOTENCY_KEY_REQUIREDنداء مدفوع بمفتاح API بلا ترويسة Idempotency-Key. لم يدخل شيء إلى الطابور؛ أعد إرساله مع الترويسة.لا
422IDEMPOTENCY_KEY_REUSEDاستُخدم Idempotency-Key هذا في طلب آخر. استخدم قيمة جديدة لطلب جديد.لا
429نفدت الحصة الخاصة بهذا المفتاح. تمهّل، ولا تُعد المحاولة في حلقة ضيقة.نعم

النص المقروء تكتبه الواجهة البرمجية بلغة المُستدعي. اعرض errors[].detail كما هو بدل صياغة رسالة خاصة بك.

الدفع والقبول

  • تُخصم المكالمات المدفوعة من أرصدة نطاق api، ولا ينظر القبول إلا إلى هذا الرصيد: كل مفتاح يدفع بالأرصدة.
  • يملأ اشتراك Pro Plan النشط محفظة api حتى 1000 رصيد مرة واحدة في كل دورة فوترة. وبعد ذلك تُشترى الأرصدة.
  • لا يعبّئ المفتاح محفظته إلا إذا صدر بصلاحية الشراء، وبما لا يتجاوز ما لا يزال مسموحًا له بإنفاقه، فالشراء لا يرفع سقف الإنفاق أبدًا.
  • نطاق 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 كمنظور له، وابدأ تصميمًا بجدران رمادية دافئة وإطارات بيضاء. اطلب التقدير والألبوم للنتيجة.
جلسة MCP
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)

مصادر