GetFacade Agenten-API
Fassadenentwurf über MCP und HTTP. Jeder Entwurf wird für das Land ausgearbeitet, in dem das Gebäude steht: Materialien, die dort anwendbar sind, Herstellerprodukte, die dort tatsächlich verkauft werden, und der technische Aufbau hinter der Oberfläche. Ein Render zeigt ihn auf dem Foto des Hauses, die Kostenschätzung beziffert ihn Position für Position, und das PDF-Album dokumentiert ihn für den Betrieb, der ihn ausführt. Jeder Pfad unten ist ein bestehender GetFacade-Endpunkt, derselbe, den die iOS-, Android- und Web-App aufrufen. Ein Agentenschlüssel schränkt nur ein, wer ihn aufrufen darf, misst die Ausgaben und stoppt beim Limit.
- Basis-URL
- https://api.getfacade.ai/api/v1
- Authentifizierung
- Bearer <agent key>
- Paket
- @getfacade/mcp
- Laufzeitumgebung
- Node.js 20+
- Transport
- stdio (MCP), HTTPS (REST)
- Spezifikation
- OpenAPI 3.1, v1.0.0
Schnellstart
Schlüssel erstellen
app.getfacade.aiKontoEinstellungenAPISchlüssel erstellen
Der Wert wird einmal angezeigt und lässt sich nicht wiederherstellen, nur ersetzen. Das Ausgabenlimit wird bei der Erstellung gesetzt und bei jedem kostenpflichtigen Aufruf geprüft.
Agentenschlüssel erstellenMCP-Server eintragen
Ein Eintrag in der Client-Konfiguration, dann den Client neu starten. Claude Desktop hält ihn in claude_desktop_config.json; jeder andere MCP-Client nimmt dieselben drei Felder.
{ "mcpServers": { "getfacade": { "command": "npx", "args": ["-y", "@getfacade/mcp"], "env": { "GETFACADE_API_KEY": "your-key" } } } }Umgebungsvariablen Variable Erforderlich Standardwert GETFACADE_API_KEYJa —GETFACADE_API_BASE_URLNein https://api.getfacade.ai/api/v1Oder die HTTP-API direkt aufrufen
Derselbe Schlüssel dient als Bearer-Token. Anfragen und Antworten sind JSON:API-Dokumente, in denen id ein Feld der obersten Ebene ist und nie in attributes steht.
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"}}}'
Werkzeuge
Einundzwanzig Werkzeuge. Der MCP-Server hält keinen Zustand und keine eigenen Regeln: Jedes Werkzeug ist ein Aufruf oder eine Folge von Aufrufen der daneben genannten Endpunkte, und jede Meldung, die der Agent weitergibt, stammt von der API.
create_buildingcreate_building(name, goals?, construction_region?) -> { building_id, name }Legt ein Gebäude an. Der Name ist innerhalb des Kontos eindeutig und höchstens 50 Zeichen lang; ein Duplikat wird mit 422 abgelehnt.
Ruft auf
POST /projectsupload_photoupload_photo(building_id, file_path, wait_for_validation? = true) -> { view_id, validation: { status, reason? } }Registriert eine Ansicht, lädt die Bytes an eine vorsignierte URL, bestätigt sie und fragt ab, bis das Foto angenommen oder abgelehnt ist. Breite, Höhe und md5 werden lokal berechnet; das Seitenverhältnis leitet der Server ab.
Ruft auf
POST /projects/{project}/angles → PUT (presigned) → POST /angles/{angle}/confirm → GET /angles/{angle}/validationstart_designasynchronstart_design(building_id, view_id, prompt?, style_ids?, colors?, brand_selections?, render_effort?, seed?) -> { design_id, job_id, status, seed }Entwirft die Fassade auf einer gewählten Ansicht und zeigt sie auf dem Foto: Materialien, die im Land des Gebäudes anwendbar sind, Produkte, die dort tatsächlich verkauft werden, und der Aufbau hinter der Oberfläche. Legt einen Entwurf an, stellt die Arbeit in die Warteschlange und liefert die Auftrags-ID. Der Seed ist optional: Fehlt er, erzeugt ihn der Server und gibt ihn zurück.
Ruft auf
POST /projects/{project}/concepts → POST /concepts/{concept}/angles/{conceptAngle}/rendersrefine_designasynchronrefine_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 }Überarbeitet einen fertigen Entwurf in Worten. Die Anweisung wird auf den fertigen Entwurf angewendet, alles Nichtgenannte bleibt erhalten. Die Überarbeitung einer Hauptansicht erzeugt einen neuen Entwurf, der frühere wird also nie überschrieben.
Ruft auf
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? }Liest den Stand eines Renderings, einer Kostenschätzung oder eines Albums.
Ruft auf
GET /renders/{render} · GET /estimates/{estimate}list_jobslist_jobs(kind?, limit? = 20) -> [{ job_id, kind, status, building_id, created_at }]Aktuelle Aufträge des Kontos, unfertige zuerst.
Ruft auf
GET /historylist_designslist_designs(building_id) -> [{ design_id, note, has_main_render, main_render_id, main_render_url, renders }]Entwürfe eines Gebäudes samt ihren Renderings. Von hier stammen die Rendering-Kennungen für Kostenschätzung und Album.
Ruft auf
GET /projects/{project}/conceptsorder_estimateasynchronorder_estimate(design_id, render_ids, currency?, measurement_system?, special_requirements?) -> { job_id, status }Beziffert den Entwurf Position für Position, in Material und Arbeitszeit, zu den Preisen der angegebenen Materialien im Land des Gebäudes. Währung und Maßsystem richten sich standardmäßig nach diesem Land.
Ruft auf
POST /projects/{project}/concepts/{concept}/estimatesorder_albumasynchronorder_album(design_id, render_ids, language?, include_blueprints?, include_estimate?, requirements?) -> { job_id, status }Dokumentiert den Entwurf für den ausführenden Betrieb: die Materialien, den Aufbau der Fassade, Sicherheitshinweise und die zugrunde liegenden Normen. Setzt einen fertigen Hauptrender voraus.
Ruft auf
POST /concepts/{concept}/album/generateupscale_renderasynchronupscale_render(render_id) -> { job_id, status }Vergrößert ein fertiges Rendering. Kostet Token und läuft asynchron.
Ruft auf
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 }] }Die Kalkulation selbst: Summen, die Annahmen dahinter und jede Position mit Menge, Einheit und Preis. get_job meldet den Status einer Kalkulation, nie ihren Inhalt.
Ruft auf
GET /estimates/{estimate}add_estimate_lineadd_estimate_line(estimate_id, section, name, quantity, unit_price, unit?, category?) -> { line_id }Fügt der Kalkulation eine Position hinzu. Die Einheiten stammen aus deren eigenem Maßsystem.
Ruft auf
POST /estimates/{estimate}/itemsupdate_estimate_lineupdate_estimate_line(estimate_id, line_id, name?, quantity?, unit_price?, unit?, category?, section?) -> { line_id }Ändert eine Position der Kalkulation. Nur übergebene Felder werden berührt, die Summen rechnet der Server neu.
Ruft auf
PATCH /estimates/{estimate}/items/{item}delete_estimate_linedelete_estimate_line(estimate_id, line_id) -> { deleted }Entfernt eine Position aus der Kalkulation.
Ruft auf
DELETE /estimates/{estimate}/items/{item}delete_renderdelete_render(render_id) -> { deleted }Löscht ein Rendering. Wird das Haupt-Rendering gelöscht, kehrt sein Entwurf in den Entwurfsstatus zurück.
Ruft auf
DELETE /renders/{render}delete_designdelete_design(building_id, design_id) -> { deleted }Löscht einen Entwurf samt seiner Renderings.
Ruft auf
DELETE /projects/{project}/concepts/{concept}delete_buildingdelete_building(building_id) -> { deleted }Löscht ein Gebäude mit allem darin. Bereits verbrauchte Token werden nicht erstattet.
Ruft auf
DELETE /projects/{project}list_token_packageslist_token_packages() -> [{ package, tokens, price, currency }]Die für dieses Konto kaufbaren Pakete, mit Preis und Tokenzahl.
Ruft auf
GET /tokens/packagesbuy_tokensasynchronbuy_tokens(package) -> { status, transaction_id, tokens, checkout_url?, detail }Kauft ein Paket für das Guthaben dieses Schlüssels. Setzt einen Schlüssel mit Kaufberechtigung voraus und geht nie über das hinaus, was er noch ausgeben darf.
Ruft auf
POST /tokens/purchaseget_balanceget_balance() -> { balance, scope: "api", spend_cap, spent, remaining, is_admissible }Agenten-Guthaben, das Limit dieses Schlüssels und ob der nächste kostenpflichtige Aufruf zugelassen wird.
Ruft auf
GET /tokens/balancereport_problemreport_problem(message, category?, context?: { tool, endpoint, status_code, job_id, expected, actual }) -> { reference, message }Meldet einen Fehler dieser API: ein hier beschriebenes Feld, das nie ankommt, eine Ablehnung, aus deren Wortlaut kein nächster Schritt folgt, ein Ergebnis, das nicht zum Auftrag passt. Kostenlos und auch bei leerem Guthaben angenommen; zurück kommt eine Referenz, keine Antwort.
Ruft auf
POST /feedback
Authentifizierung und Schlüssel
- Der Schlüssel reist als Bearer-Token im
Authorization-Header. Der MCP-Server liest ihn ausGETFACADE_API_KEYund sendet sonst nichts. - Der Wert wird einmal bei der Erstellung angezeigt, gespeichert wird nur sein Hash. Rotation heißt: neuen Schlüssel erstellen, alten widerrufen.
- Jeder Schlüssel trägt ein Ausgabenlimit, das serverseitig geprüft wird, bevor ein Aufruf einen Controller erreicht. Ein erreichtes Limit stoppt diesen Schlüssel, nicht das Konto.
- Schlüssel verwalten keine Schlüssel: Das ist eine menschliche Handlung, und die Endpunkte antworten einem Agentenschlüssel mit 403.
- Ein Widerruf wirkt sofort. Aufrufe mit einem widerrufenen Schlüssel antworten mit 401.
Asynchrone Arbeit und Statusabfrage
start_design,order_estimateundorder_albumliefern eine Auftragskennung und sind damit fertig. Renderings dauern Minuten:GET /renders/{render}oderGET /estimates/{estimate}abfragen, bis der Zustand endgültig ist.- Das Ende der Fotoprüfung meldet ein Websocket, den ein Agent nicht hat.
GET /angles/{angle}/validationabfragen undvalidation.is_in_progresslesen; leiten Sie die Endgültigkeit nicht selbst aus dem Statustext ab. - Ein fertiger Render und ein fertiges Album liegen unter dauerhaften öffentlichen URLs: ohne Signatur, ohne Ablauf. Der Link lässt sich einer Person direkt geben, als Antwort auf „zeig mir das Ergebnis“. Da er nicht signiert ist, fragt er niemanden um Erlaubnis: Er funktioniert für jeden, der ihn erhält, und lässt sich nicht zurückziehen.
GET /renders/{render}/downloadist etwas anderes: eine signierte URL, die nach Minuten abläuft und einen Dateinamen trägt. Sie dient zum Speichern der Datei, nicht zum Teilen.
Ratenlimits je Schlüssel
Ein Agentenschlüssel hat eigene Kontingente, getrennt von den menschlichen Sitzungen desselben Kontos, damit ein Agent in einer Schleife nicht das Kontingent der Person am Bildschirm aufbraucht. Die Ablehnung ist billig: Sie fällt in der Middleware, vor jeder Datenbankarbeit.
| Bereich | Pro Minute | Pro Stunde |
|---|---|---|
| Lesen und gewöhnliches Schreiben | 120 | 2000 |
| Status- und Prüfungsabfragen | 120 | 2000 |
| Bestellung von Rendering, Kostenschätzung und Album | 10 | 200 |
Idempotenz
Ein kostenpflichtiger Aufruf erzeugt einen Auftrag, und die Abrechnung folgt dem Auftrag. Erst der Name des Aufrufs macht es möglich, dass eine Wiederholung denselben Auftrag zurückgibt, statt einen zweiten zu erzeugen.
Idempotency-Keyist bei jedem kostenpflichtigen Aufruf mit einem API-Schlüssel erforderlich: Design starten oder überarbeiten, Render vergrößern, Kostenschätzung oder Album bestellen, Kostenschätzung neu erzeugen. Ohne ihn antwortet der Aufruf mit 422IDEMPOTENCY_KEY_REQUIRED, und nichts wird eingereiht.- Beliebiger Wert mit 8 bis 191 Zeichen, einer pro Auftrag; üblich ist eine UUID. Ein neuer Auftrag bekommt einen neuen Wert: zwei identische Aufrufe unter zwei Werten sind zwei Designs.
- Ein wiederholter Aufruf mit demselben Wert und demselben Body liefert Status und Body des Originals zurück, mit
Idempotent-Replay: truein der Antwort. Nichts wird eingereiht und nichts doppelt berechnet. - Derselbe Wert mit einem anderen Body antwortet mit 422
IDEMPOTENCY_KEY_REUSED. Eine Wiederholung, die eintrifft, während der erste Aufruf noch läuft, antwortet mit 409IDEMPOTENCY_IN_PROGRESS: warten und denselben Aufruf erneut senden. - Jede 4xx-Antwort gibt den Wert frei, er kann also erneut gesendet werden, sobald die Ursache behoben ist. Werte werden 24 Stunden lang je Konto gemerkt.
@getfacade/mcperzeugt den Wert selbst und wiederholt den Aufruf darunter, im Tool-Aufruf ist also nichts zu übergeben.
Fehler
Fehlschläge kommen als JSON:API-Fehlerdokumente. Laravel-Validierungsantworten haben nicht die JSON:API-Form und tragen ihren Text in message.
| Status | Code | Bedeutung | Wiederholbar |
|---|---|---|---|
401 | — | Der Schlüssel fehlt, ist widerrufen oder abgelaufen. | Nein |
402 | AGENT_CREDITS_EXHAUSTED | Das Konto hat kein Guthaben im api-Scope mehr. | Nein |
402 | AGENT_KEY_CAP_REACHED | Dieser Schlüssel hat sein Limit ausgeschöpft. Neuen Schlüssel erstellen oder Limit anheben. | Nein |
403 | — | Dieser Endpunkt steht API-Schlüsseln nicht zur Verfügung. Die Agenten-API umfasst Gebäude, Fotos, Entwürfe, Renderings, Kostenschätzungen, Alben und die API-Guthabenkasse. Konto-, Anmelde- und Zahlungseinstellungen ändert eine Person, die in der App angemeldet ist. | Nein |
403 | AGENT_PURCHASE_NOT_ALLOWED | Dieser Schlüssel wurde ohne Kaufberechtigung ausgestellt. | Nein |
403 | AGENT_PURCHASE_EXCEEDS_CAP | Der Kauf würde den Schlüssel über sein Ausgabenlimit bringen. | Nein |
409 | IDEMPOTENCY_IN_PROGRESS | Der erste Aufruf mit diesem Idempotency-Key hat noch nicht geantwortet. Warten Sie und senden Sie denselben Aufruf erneut. | Ja |
422 | — | Die Anfrage wurde verstanden und abgelehnt: doppelter Gebäudename, abgelehntes Foto, Album vor dem Ende des Hauptrenderings bestellt. | Nein |
422 | IDEMPOTENCY_KEY_REQUIRED | Ein kostenpflichtiger Aufruf mit API-Schlüssel ohne Idempotency-Key-Header. Nichts wurde eingereiht; senden Sie ihn erneut, diesmal mit Header. | Nein |
422 | IDEMPOTENCY_KEY_REUSED | Dieser Idempotency-Key wurde für eine andere Anfrage verwendet. Nehmen Sie für einen neuen Auftrag einen neuen Wert. | Nein |
429 | — | Das eigene Kontingent dieses Schlüssels ist erschöpft. Warten Sie, wiederholen Sie nicht in enger Schleife. | Ja |
Den lesbaren Text schreibt die API, in der Sprache des Aufrufers. Zeigen Sie errors[].detail unverändert an, statt eine eigene Meldung zu formulieren.
Abrechnung und Zulassung
- Bezahlte Aufrufe zehren am Guthaben des
api-Scopes, und die Zulassung sieht allein auf diesen Stand: jeder Schlüssel zahlt in Guthaben. - Ein aktiver Pro Plan füllt das
api-Guthaben einmal pro Abrechnungszeitraum auf 1.000 Credits auf. Darüber hinaus wird Guthaben gekauft. - Ein Schlüssel füllt sein Guthaben nur auf, wenn er mit Kaufberechtigung ausgestellt wurde, und höchstens um das, was er noch ausgeben darf. Ein Kauf hebt das Ausgabenlimit also nie an.
- Der
api-Scope ist eine eigene Geldbörse. Die Credits der App, das Gratiskontingent eingeschlossen, gibt ein Schlüssel nie aus. - Die Ausgaben werden je Schlüssel gezählt, der Verbrauch jedes Assistenten ist also einzeln sichtbar.
- Die Vorabprüfung ist
GET /tokens/balance, Felddata.attributes.agent.is_admissible. Der Block erscheint nur bei Agentenschlüsseln, und das Flag spiegelt die Zulassungs-Middleware exakt. Lesen Sie es, statt Guthaben und Limit selbst zu vergleichen. - Die Zulassung wird entschieden, bevor Arbeit in die Warteschlange geht; ein abgelehnter Aufruf kostet daher nichts.
Farb- und Markentoken
start_design nimmt zwei unabhängige Listen mit höchstens zehn Einträgen. Die Reihenfolge trägt die 60/30/10-Rolle: Der erste Eintrag ist die dominierende Wandfarbe.
colors
| Token | Bedeutung |
|---|---|
palette:1 | Ein kuratiertes GetFacade-Schema, per Kennung. |
#8A8F7D | Eine freie Farbe, sechs Hexadezimalstellen. |
paint:412 | Ein Herstellerfarbton in der zweiteiligen Form, die aus Kompatibilitätsgründen bleibt. |
brand_selections
| Token | Bedeutung |
|---|---|
siding:brand:12 | Jedes Produkt dieses Herstellers in dieser Kategorie. |
siding:line:40@double-4-dutchlap | Eine Linie, auf einer Geometrie. |
siding:product:88@double-4-dutchlap | Ein Produkt, vollständig bestimmt. |
paint:brand:3 | Jede Farbe dieser Farbenmarke. |
paint:product:412 | Ein einzelner Farbton. |
Die Grammatik lautet category:level:id[@value][.value]. Der Teil nach dem @ trägt Geometrie-Wertslugs, die innerhalb ihrer Kategorie eindeutig sind, sodass die zugehörige Achse nachgeschlagen und nicht ausgeschrieben wird. Ein unbekanntes Token wird mit 422 abgelehnt und nie stillschweigend übergangen.
Durchgehende Sitzung
Ein Gebäude, ein Foto, ein Entwurf, dann die beiden Dokumente. Die Anweisung, die das erzeugt:
Lege ein Gebäude namens Ahornstraße 14 an, lade ./front.jpg als Ansicht hoch und starte einen Entwurf mit warmgrauen Wänden und weißen Zierleisten. Bestelle Kostenschätzung und Album zum Ergebnis.
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)