GetFacade 智能体 API
通过 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
快速开始
签发密钥
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或直接调用 HTTP 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? } }登记视角,将字节上传至预签名 URL,确认后轮询,直到照片被接受或拒绝。宽、高与 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 }在选定的视角上设计外立面,并呈现在照片上:建筑所在国家可用的材料、当地确实有售的产品,以及表面之后的构造层次。创建一个设计,把工作排入队列,并返回任务 id。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 }]某建筑的设计及其渲染。估算和图册所需的渲染 ID 由此获得。
调用
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返回任务 ID 后即结束。渲染需要数分钟:轮询GET /renders/{render}或GET /estimates/{estimate},直到状态为终态。- 照片校验完成通过智能体所没有的 WebSocket 通知。请轮询
GET /angles/{angle}/validation并读取validation.is_in_progress;不要自行从状态字符串判断是否为终态。 - 完成的渲染和图册位于永久的公开地址:没有签名,也没有有效期。这个链接可以直接交给他人,正是对「把结果给我看」的回答。因为没有签名,它不会向任何人索取许可:拿到的人都能打开,事后也无法收回。
GET /renders/{render}/download是另一回事:一个几分钟内过期、带文件名的签名 URL,用于保存文件,而不是用于分享。
按密钥计的频率限制
智能体密钥拥有独立配额,与同一账户的人工会话分开,这样陷入循环的智能体不会吃掉屏幕前那个人的额度。拒绝的代价很低:它在中间件中判定,先于任何数据库操作。
| 范围 | 每分钟 | 每小时 |
|---|---|---|
| 读取与常规写入 | 120 | 2000 |
| 状态与校验轮询 | 120 | 2000 |
| 渲染、估算与图册的下单 | 10 | 200 |
幂等性
付费调用会创建一个任务,费用跟着任务走。给调用起个名字,重发时才会返回同一个任务,而不是再建一个。
- 用 API 键发出的每一次付费调用都必须带
Idempotency-Key:开始或修改设计、放大渲染图、订购预算或相册、重新生成预算。缺少该头时,调用返回 422IDEMPOTENCY_KEY_REQUIRED,不会有任何任务入队。 - 值为 8 到 191 个字符,每笔订单一个,通常用 UUID。新的订单换用新的值:两个值下的两次相同调用就是两个设计。
- 用相同的值和相同的请求体重复调用,会原样返回最初的状态码和响应体,并在响应中带上
Idempotent-Replay: true。不会入队,也不会重复计费。 - 相同的值配上不同的请求体,返回 422
IDEMPOTENCY_KEY_REUSED。在第一次调用尚未完成时到达的重发,返回 409IDEMPOTENCY_IN_PROGRESS:稍候,再发送同一次调用。 - 任何 4xx 都会释放该值,原因修复后可以用同一个值重发。值按账户保存 24 小时。
@getfacade/mcp会自行生成该值并用它重发,因此工具调用中无需传任何东西。
错误
失败以 JSON:API 错误文档返回。Laravel 的校验响应不是 JSON:API 结构,其文本位于 message 字段。
| 状态码 | 代码 | 含义 | 可否重试 |
|---|---|---|---|
401 | — | 密钥缺失、已吊销或已过期。 | 否 |
402 | AGENT_CREDITS_EXHAUSTED | 账户已没有 api 范围的额度。 | 否 |
402 | AGENT_KEY_CAP_REACHED | 该密钥已用尽上限。请签发新密钥或提高上限。 | 否 |
403 | — | 此端点不对 API 密钥开放。代理 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 | 按 ID 指定 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]。@ 之后是造型取值的 slug,在其品类内唯一,因此所属的轴通过查询确定,而不写进令牌。未知令牌以 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)