GetFacade エージェント API

MCP と HTTP による外装設計です。設計はどれも建物のある国に合わせて練られます。その国で使える材料、メーカーがそこで実際に販売している製品、そして表面の裏にある技術的な層構成です。レンダーはそれを住宅の写真の上に示し、見積書は明細ごとに金額を出し、PDF アルバムは施工する職方向けに内容を記録します。以下の各パスは既存の GetFacade エンドポイントであり、iOS・Android・Web の各アプリが呼ぶものと同じです。エージェントキーは呼び出せる相手を絞り、支出を計測し、上限で停止します。

ベース 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 サーバーを登録する

    クライアント設定に 1 項目追加し、クライアントを再起動します。Claude Desktop は claude_desktop_config.json に保持します。他の MCP クライアントも同じ 3 つのフィールドを受け取ります。

    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 を直接呼ぶ

    同じキーがベアラートークンとして使えます。リクエストとレスポンスは 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"}}}'

ツール

ツールは 21 個です。MCP サーバーは状態も独自の規則も持ちません。各ツールは横に示したエンドポイントへの 1 回以上の呼び出しであり、エージェントが伝えるメッセージはすべて 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 }

    選んだ視点で外装を設計し、写真の上に示します。建物のある国で使える材料、そこで実際に販売されている製品、表面の裏にある層構成を踏まえます。デザインを作成して作業をキューに入れ、ジョブ ID を返します。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? }

    1 件のレンダー、見積り、アルバムの状態を読みます。

    呼び出し先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 }]

    建物のデザインとそのレンダー。見積りやアルバムに渡すレンダー ID はここから得ます。

    呼び出し先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 }

    見積もりに 1 行追加します。単位は見積もり自身の単位系から取られます。

    呼び出し先POST /estimates/{estimate}/items

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

    見積もりの 1 行を変更します。渡した項目だけが変わり、合計はサーバーが計算し直します。

    呼び出し先PATCH /estimates/{estimate}/items/{item}

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

    見積もりから 1 行を削除します。

    呼び出し先DELETE /estimates/{estimate}/items/{item}

  • delete_render
    delete_render(render_id)
      -> { deleted }

    レンダーを 1 つ削除します。メインレンダーを削除すると、そのデザインは下書きに戻ります。

    呼び出し先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 }

    このキーのウォレットにパックを 1 つ購入します。購入を許可して発行されたキーが必要で、そのキーがまだ使える範囲を超えることはありません。

    呼び出し先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

認証とキー

  • キーは Authorization ヘッダーのベアラートークンとして送られます。MCP サーバーは GETFACADE_API_KEY から読み取り、それ以外は送りません。
  • 値は発行時に一度だけ表示され、保存されるのはハッシュだけです。ローテーションとは新しいキーを発行し、古いキーを失効させることです。
  • 各キーには支出上限があり、呼び出しがコントローラーに届く前にサーバー側で適用されます。上限に達して止まるのはそのキーであり、アカウントではありません。
  • キーはキーを管理しません。これは人間の操作であり、該当エンドポイントはエージェントキーに 403 を返します。
  • 失効は即時に効きます。失効したキーでの呼び出しは 401 を返します。

非同期処理とポーリング

  • start_designorder_estimateorder_album はジョブ ID を返して終了します。レンダーには数分かかります。状態が終端になるまで GET /renders/{render} または GET /estimates/{estimate} を問い合わせてください。
  • 写真検証の完了はエージェントが持たない WebSocket で通知されます。GET /angles/{angle}/validation を問い合わせ、validation.is_in_progress を読んでください。状態文字列から終端かどうかを自分で判断しないでください。
  • 完成したレンダーとアルバムは、恒久的な公開 URL に置かれます。署名も有効期限もありません。このリンクはそのまま人に渡せます。「結果を見せて」への答えがこれです。署名がないため誰の許可も求めず、受け取った人は誰でも開けますし、あとから取り消すこともできません。
  • GET /renders/{render}/download は別物です。数分で失効し、ファイル名を伴う署名付き URL で、共有用ではなくファイルを保存するためのものです。

キーごとのレート制限

エージェントキーには、同じアカウントの人間のセッションとは別の枠があります。ループに陥ったエージェントが、画面の前にいる人の枠を食い尽くさないためです。拒否は安価で、データベース処理の前にミドルウェアで決まります。

対象毎分毎時
読み取りと通常の書き込み1202000
状態と検証のポーリング1202000
レンダー・見積り・アルバムの発注10200

冪等性

有料の呼び出しはジョブを作り、課金はそのジョブに従います。呼び出しに名前を付けることで、再送しても二つ目が作られず同じジョブが返ります。

  • API キーで行う有料の呼び出しには Idempotency-Key が必須です。デザインの開始と修正、レンダーの拡大、見積もりやアルバムの注文、見積もりの再生成が対象です。ヘッダーがない場合は 422 IDEMPOTENCY_KEY_REQUIRED を返し、キューには何も入りません。
  • 値は 8〜191 文字であれば自由で、注文ごとに 1 つ。通常は UUID を使います。新しい注文には新しい値を使ってください。異なる 2 つの値による同一の呼び出しは、2 つのデザインです。
  • 同じ値と同じボディで呼び出しを繰り返すと、元のステータスとボディがそのまま返り、応答に 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_REQUIREDAPI キーによる有料の呼び出しに Idempotency-Key ヘッダーがありません。キューには何も入っていないので、ヘッダーを付けて再送してください。いいえ
422IDEMPOTENCY_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 は独立した 2 つのリストを受け取り、それぞれ最大 10 件です。並び順が 60/30/10 の役割を担い、最初の要素が壁の主色です。

colors

トークン意味
palette:1GetFacade が用意した配色を ID で指定します。
#8A8F7D任意の色を 16 進 6 桁で指定します。
paint:412メーカーの色見本。互換性のために残された 2 セグメント形式です。

brand_selections

トークン意味
siding:brand:12そのカテゴリーにおける、そのメーカーの任意の製品。
siding:line:40@double-4-dutchlap1 つのシリーズを、1 つの形状で。
siding:product:88@double-4-dutchlap完全に指定された 1 製品。
paint:brand:3その塗料ブランドの任意の色。
paint:product:412塗料の色見本 1 点。

文法は category:level:id[@value][.value] です。@ 以降は形状の値スラッグで、カテゴリー内で一意のため、どの軸に属するかはトークンに書かず参照で解決します。未知のトークンは 422 で拒否され、黙って無視されることはありません。

一連のセッション

建物 1 件、写真 1 枚、デザイン 1 件、そして 2 つの文書。これを生む指示は次のとおりです。

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)

関連資料