Агентний API GetFacade

Проєктування фасаду через MCP і HTTP. Кожен дизайн опрацьовується під країну, де стоїть будинок: матеріали, застосовні там, продукти виробників, які там справді продаються, і технічний пиріг оздоблення за поверхнею. Рендер показує це на фотографії будинку, кошторис рахує порядково, а PDF-альбом документує для бригади, яка будуватиме. Кожен шлях нижче це наявний ендпоінт GetFacade, той самий, що викликають застосунки iOS, Android і веб. Агентний ключ лише звужує коло тих, хто може його викликати, рахує витрати і зупиняється на своїй стелі.

Базовий URL
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-API напряму

    Той самий ключ працює як токен 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-сервер не зберігає стану й не має власних правил: кожен інструмент це один або кілька викликів перелічених поруч ендпоінтів, а будь-яке повідомлення, яке повторює агент, написане API.

  • 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? } }

    Реєструє ракурс, завантажує байти за підписаним URL, підтверджує їх і опитує, доки фотографію не буде прийнято або відхилено. Ширину, висоту та 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 }

    Проєктує фасад на обраному ракурсі й показує його на фотографії: матеріали, застосовні в країні об'єкта, продукти, які там дійсно продаються, і пиріг оздоблення за поверхнею. Створює дизайн, ставить роботу в чергу й повертає ідентифікатор завдання. 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 }

    Повідомляє про несправність цього API: поле, описане тут і відсутнє у відповіді, відмову, з формулювання якої не випливає наступний крок, результат, що не відповідає запиту. Безкоштовно і приймається за порожнього гаманця; у відповідь приходить номер звернення, а не відповідь.

    Викликає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 це інше: підписаний URL, який спливає за хвилини й несе ім'я файлу. Він потрібен, щоб зберегти файл, а не щоб поділитися ним.

Обмеження частоти на ключ

Агентний ключ має власні кошики лімітів, окремі від людських сесій того самого акаунта, тож зациклений агент не з'їсть ліміт людини за екраном. Відмова дешева: її ухвалює middleware, до будь-якої роботи з базою.

ОбластьЗа хвилинуЗа годину
Читання та звичайний запис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 не мають форми JSON:API і несуть текст у полі message.

СтатусКодЗначенняПовтор
401Ключ відсутній, відкликаний або прострочений.Ні
402AGENT_CREDITS_EXHAUSTEDНа акаунті не лишилося кредитів скоупу api.Ні
402AGENT_KEY_CAP_REACHEDКлюч витратив свій ліміт. Випустіть інший ключ або підніміть ліміт.Ні
403Цей ендпоінт недоступний за API-ключем. Агентний API охоплює об'єкти, фотографії, дизайни, рендери, кошториси, альбоми та гаманець API. Налаштування облікового запису, входу та оплати змінює людина, яка увійшла в застосунок.Ні
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Власний кошик лімітів цього ключа вичерпано. Зробіть паузу, не повторюйте в щільному циклі.Так

Людиночитний текст пише API, мовою того, хто викликає. Показуйте errors[].detail як є, не складаючи власного повідомлення.

Оплата та допуск

  • Платні виклики йдуть із кредитів скоупу api, і допуск дивиться лише на цей баланс: кожен ключ платить кредитами.
  • Активний Pro Plan раз на білінговий період доводить гаманець api до 1000 кредитів. Далі кредити купуються.
  • Ключ поповнює свій гаманець, лише якщо його випущено з дозволом на покупку, і не більше, ніж йому ще можна витратити, тож покупка ніколи не піднімає стелю витрат.
  • Область api це окремий гаманець. Кредити застосунку, включно з безкоштовним рівнем, ключем не витрачаються ніколи.
  • Витрата рахується за кожним ключем, тож споживання кожного асистента видно окремо.
  • Передпольотна перевірка це GET /tokens/balance, поле data.attributes.agent.is_admissible. Блок присутній лише в агентних ключів, а прапорець точно повторює middleware допуску. Читайте його замість порівняння балансу з лімітом.
  • Допуск вирішується до постановки роботи в чергу, тому відхилений виклик нічого не витрачає.

Колірні та брендові токени

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 і ніколи не ігнорується мовчки.

Наскрізна сесія

Один об'єкт, одна фотографія, один дизайн і потім два документи. Запит, що це породжує:

Створи об'єкт «Кленова 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)

Матеріали