API agent GetFacade

Conception de façade via MCP et HTTP. Chaque conception est élaborée pour le pays où se trouve le bâtiment : les matériaux qui y sont applicables, les produits que les fabricants y vendent réellement, et la composition technique derrière la surface. Un rendu la montre sur la photo de la maison, le devis la chiffre ligne par ligne, et l'album PDF la documente pour l'entreprise qui la réalise. Chaque chemin ci-dessous est un point d'entrée GetFacade existant, celui-là même qu'appellent les applications iOS, Android et web. Une clé agent restreint qui peut l'appeler, mesure ce qu'elle dépense et s'arrête à son plafond.

URL de base
https://api.getfacade.ai/api/v1
Authentification
Bearer <agent key>
Paquet
@getfacade/mcp
Environnement d'exécution
Node.js 20+
Transport
stdio (MCP), HTTPS (REST)
Spécification
OpenAPI 3.1, v1.0.0

Démarrage rapide

  1. Créer une clé

    app.getfacade.aiCompteParamètresAPICréer une clé

    La valeur s'affiche une seule fois et ne peut être récupérée, seulement remplacée. Le plafond de dépense se fixe à la création et s'applique à chaque appel payant.

    Créer une clé agent
  2. Déclarer le serveur MCP

    Une entrée dans la configuration du client, puis redémarrage du client. Claude Desktop la garde dans claude_desktop_config.json ; tout autre client MCP accepte les trois mêmes champs.

    claude_desktop_config.json
    {
      "mcpServers": {
        "getfacade": {
          "command": "npx",
          "args": ["-y", "@getfacade/mcp"],
          "env": { "GETFACADE_API_KEY": "your-key" }
        }
      }
    }
    Variables d'environnement
    VariableObligatoireValeur par défaut
    GETFACADE_API_KEYOui
    GETFACADE_API_BASE_URLNonhttps://api.getfacade.ai/api/v1
  3. Ou appeler l'API HTTP directement

    La même clé sert de jeton Bearer. Requêtes et réponses sont des documents JSON:API, où id est un champ de premier niveau et ne se trouve jamais dans 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"}}}'

Outils

Vingt-et-un outils. Le serveur MCP ne conserve aucun état ni règle propre : chaque outil est un ou plusieurs appels aux points de terminaison indiqués à côté, et chaque message que l'agent répète est écrit par l'API.

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

    Crée un bâtiment. Le nom est unique dans le compte et fait 50 caractères au plus ; un doublon est refusé avec un 422.

    AppellePOST /projects

  • upload_photo
    upload_photo(building_id, file_path, wait_for_validation? = true)
      -> { view_id, validation: { status, reason? } }

    Enregistre une vue, téléverse les octets vers une URL présignée, les confirme et interroge le statut jusqu'à ce que la photo soit acceptée ou refusée. Largeur, hauteur et md5 sont calculés localement ; le rapport d'aspect est déduit par le serveur.

    AppellePOST /projects/{project}/angles → PUT (presigned) → POST /angles/{angle}/confirm → GET /angles/{angle}/validation

  • start_designasynchrone
    start_design(building_id, view_id, prompt?, style_ids?, colors?,
                 brand_selections?, render_effort?, seed?)
      -> { design_id, job_id, status, seed }

    Conçoit la façade sur une vue choisie et la montre sur la photo : matériaux applicables dans le pays du bâtiment, produits qui y sont réellement vendus et composition derrière la surface. Crée une conception, met le travail en file d'attente et renvoie l'identifiant de tâche. La graine est facultative : si elle est omise, le serveur en génère une et la renvoie.

    AppellePOST /projects/{project}/concepts → POST /concepts/{concept}/angles/{conceptAngle}/renders

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

    Révise en mots une conception terminée. L'instruction s'applique à la conception terminée, donc tout ce qu'elle ne mentionne pas est conservé. Réviser une vue principale crée une nouvelle conception, la précédente n'est donc jamais écrasée.

    AppelleGET /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? }

    Lit l'état d'un rendu, d'une estimation ou d'un album.

    AppelleGET /renders/{render} · GET /estimates/{estimate}

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

    Tâches récentes du compte, les inachevées d'abord.

    AppelleGET /history

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

    Designs d'un bâtiment avec leurs rendus. C'est de là que viennent les identifiants de rendu pour une estimation ou un album.

    AppelleGET /projects/{project}/concepts

  • order_estimateasynchrone
    order_estimate(design_id, render_ids, currency?,
                   measurement_system?, special_requirements?)
      -> { job_id, status }

    Chiffre la conception ligne par ligne, en matériaux et en main-d'œuvre, au prix des matériaux indiqués dans le pays du bâtiment. La devise et le système de mesure suivent par défaut ce pays.

    AppellePOST /projects/{project}/concepts/{concept}/estimates

  • order_albumasynchrone
    order_album(design_id, render_ids, language?, include_blueprints?,
                include_estimate?, requirements?)
      -> { job_id, status }

    Documente la conception pour l'entreprise qui la réalise : les matériaux, la composition de la façade, les consignes de sécurité et les normes qui les fondent. Exige un rendu principal terminé.

    AppellePOST /concepts/{concept}/album/generate

  • upscale_renderasynchrone
    upscale_render(render_id)
      -> { job_id, status }

    Agrandit un rendu terminé. Coûte des crédits et s'exécute de façon asynchrone.

    AppellePOST /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 }] }

    Le devis lui-même : totaux, hypothèses retenues et chaque ligne avec quantité, unité et prix. get_job indique l'état d'un devis, jamais son contenu.

    AppelleGET /estimates/{estimate}

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

    Ajoute une ligne au devis. Les unités viennent du système de mesure du devis lui-même.

    AppellePOST /estimates/{estimate}/items

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

    Modifie une ligne du devis. Seuls les champs transmis changent ; le serveur recalcule les totaux.

    AppellePATCH /estimates/{estimate}/items/{item}

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

    Supprime une ligne du devis.

    AppelleDELETE /estimates/{estimate}/items/{item}

  • delete_render
    delete_render(render_id)
      -> { deleted }

    Supprime un rendu. Supprimer le rendu principal ramène son design à l'état de brouillon.

    AppelleDELETE /renders/{render}

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

    Supprime un design et les rendus qu'il contient.

    AppelleDELETE /projects/{project}/concepts/{concept}

  • delete_building
    delete_building(building_id)
      -> { deleted }

    Supprime un bâtiment avec tout son contenu. Les crédits déjà dépensés ne sont pas remboursés.

    AppelleDELETE /projects/{project}

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

    Les packs que ce compte peut acheter, avec leur prix et leur nombre de crédits.

    AppelleGET /tokens/packages

  • buy_tokensasynchrone
    buy_tokens(package)
      -> { status, transaction_id, tokens, checkout_url?, detail }

    Achète un pack pour le portefeuille de cette clé. Exige une clé créée avec l'achat autorisé et ne dépasse jamais ce que la clé peut encore dépenser.

    AppellePOST /tokens/purchase

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

    Portefeuille agent, plafond de cette clé et indication que le prochain appel payant sera admis.

    AppelleGET /tokens/balance

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

    Signale un défaut de cette API : un champ décrit ici qui n'arrive jamais, un refus dont la formulation n'ouvre aucune suite, un résultat qui ne correspond pas à la demande. Gratuit et accepté avec un solde vide ; ce qui revient est une référence, pas une réponse.

    AppellePOST /feedback

Authentification et clés

  • La clé voyage comme jeton Bearer dans l'en-tête Authorization. Le serveur MCP la lit dans GETFACADE_API_KEY et n'envoie rien d'autre.
  • La valeur s'affiche une fois, à la création, et seul son hachage est conservé. La rotation consiste à créer une clé et à révoquer l'ancienne.
  • Chaque clé porte un plafond de dépense, appliqué côté serveur avant que l'appel n'atteigne un contrôleur. Un plafond atteint arrête cette clé, pas le compte.
  • Les clés ne gèrent pas les clés : c'est une action humaine, et ces points de terminaison répondent 403 à une clé agent.
  • La révocation prend effet immédiatement. Les appels avec une clé révoquée répondent 401.

Travail asynchrone et interrogation

  • start_design, order_estimate et order_album renvoient un identifiant de tâche et s'arrêtent là. Un rendu prend des minutes : interrogez GET /renders/{render} ou GET /estimates/{estimate} jusqu'à un état terminal.
  • La fin de la validation de la photo est annoncée par un websocket dont l'agent ne dispose pas. Interrogez GET /angles/{angle}/validation et lisez validation.is_in_progress ; ne déduisez pas vous-même la finalité de la chaîne de statut.
  • Un rendu terminé et un album terminé résident à des URL publiques permanentes : sans signature, sans expiration. Le lien peut être remis directement à une personne, en réponse à « montre-moi le résultat ». N'étant pas signé, il ne demande la permission à personne : il continue de fonctionner pour quiconque le reçoit et ne peut pas être révoqué.
  • GET /renders/{render}/download est autre chose : une URL signée qui expire en quelques minutes et porte un nom de fichier. Elle sert à enregistrer le fichier, pas à le partager.

Limites de débit par clé

Une clé agent dispose de ses propres compteurs, séparés des sessions humaines du même compte, afin qu'un agent en boucle ne consomme pas le quota de la personne devant l'écran. Le refus coûte peu : il est décidé dans le middleware, avant tout travail en base.

PortéePar minutePar heure
Lectures et écritures ordinaires1202000
Interrogation des statuts et de la validation1202000
Commandes de rendu, d'estimation et d'album10200

Idempotence

Un appel payant crée une tâche, et la facturation suit la tâche. C'est le fait de nommer l'appel qui permet à un renvoi de retourner la même tâche au lieu d'en créer une seconde.

  • Idempotency-Key est obligatoire sur tout appel payant effectué avec une clé API : lancer ou retoucher un design, agrandir un rendu, commander un devis ou un album, régénérer un devis. Sans lui, l'appel répond 422 IDEMPOTENCY_KEY_REQUIRED et rien n'est mis en file.
  • Toute valeur de 8 à 191 caractères, une par commande ; un UUID est le choix habituel. Une nouvelle commande prend une nouvelle valeur : deux appels identiques sous deux valeurs sont deux designs.
  • Renvoyer un appel avec la même valeur et le même corps retourne le statut et le corps d'origine, avec Idempotent-Replay: true dans la réponse. Rien n'est mis en file et rien n'est facturé deux fois.
  • La même valeur avec un corps différent répond 422 IDEMPOTENCY_KEY_REUSED. Un renvoi qui arrive pendant que le premier appel tourne encore répond 409 IDEMPOTENCY_IN_PROGRESS : attendez, puis renvoyez le même appel.
  • Toute réponse 4xx libère la valeur, qui peut donc être renvoyée une fois la cause corrigée. Les valeurs sont mémorisées 24 heures, par compte.
  • @getfacade/mcp génère la valeur et renvoie l'appel sous celle-ci de lui-même : il n'y a rien à passer dans l'appel d'outil.

Erreurs

Les échecs arrivent sous forme de documents d'erreur JSON:API. Les réponses de validation Laravel n'ont pas cette forme et portent leur texte dans message.

StatutCodeSignificationRéessayable
401La clé est absente, révoquée ou expirée.Non
402AGENT_CREDITS_EXHAUSTEDLe compte n'a plus de crédits de portée api.Non
402AGENT_KEY_CAP_REACHEDCette clé a dépensé son plafond. Créez une autre clé ou relevez le plafond.Non
403Ce point de terminaison n'est pas accessible avec une clé API. L'API pour agents couvre les bâtiments, les photos, les designs, les rendus, les devis, les albums et le portefeuille API. Les paramètres de compte, de connexion et de paiement sont modifiés par une personne connectée dans l'application.Non
403AGENT_PURCHASE_NOT_ALLOWEDCette clé a été créée sans le droit d'acheter des crédits.Non
403AGENT_PURCHASE_EXCEEDS_CAPL'achat ferait dépasser à la clé son plafond de dépense.Non
409IDEMPOTENCY_IN_PROGRESSLe premier appel portant cet Idempotency-Key n'a pas encore répondu. Attendez et renvoyez le même appel.Oui
422La requête a été comprise et refusée : nom de bâtiment en double, photo rejetée, album commandé avant la fin du rendu principal.Non
422IDEMPOTENCY_KEY_REQUIREDUn appel payant avec une clé API et sans en-tête Idempotency-Key. Rien n'a été mis en file ; renvoyez-le avec l'en-tête.Non
422IDEMPOTENCY_KEY_REUSEDCet Idempotency-Key a servi pour une autre requête. Utilisez une nouvelle valeur pour une nouvelle commande.Non
429Le compteur propre à cette clé est épuisé. Ralentissez, ne réessayez pas en boucle serrée.Oui

Le texte lisible est écrit par l'API, dans la langue de l'appelant. Affichez errors[].detail tel quel plutôt que de composer votre propre message.

Facturation et admission

  • Les appels payants puisent dans les crédits de portée api, et l'admission ne regarde que ce solde : chaque clé paie en crédits.
  • Un Pro Plan actif porte le portefeuille api à 1 000 crédits une fois par période de facturation. Au-delà, les crédits s'achètent.
  • Une clé ne recharge son portefeuille que si elle a été créée avec l'achat autorisé, et seulement à hauteur de ce qu'elle peut encore dépenser : un achat ne relève donc jamais le plafond.
  • La portée api est un portefeuille distinct. Les crédits de l'application, tranche gratuite comprise, ne sont jamais dépensés par une clé.
  • La dépense est comptée par clé, ce qui rend visible la consommation de chaque assistant.
  • Le contrôle préalable est GET /tokens/balance, champ data.attributes.agent.is_admissible. Le bloc n'apparaît que pour les clés agent, et l'indicateur reflète exactement le middleware d'admission. Lisez-le au lieu de comparer vous-même le solde et le plafond.
  • L'admission est tranchée avant toute mise en file, donc un appel refusé ne dépense rien.

Jetons de couleur et de marque

start_design accepte deux listes indépendantes de dix entrées au plus. L'ordre porte le rôle 60/30/10 : la première entrée est la couleur dominante des murs.

colors

JetonSignification
palette:1Une harmonie GetFacade, par identifiant.
#8A8F7DUne couleur libre, six chiffres hexadécimaux.
paint:412Une teinte de fabricant, dans la forme à deux segments conservée pour compatibilité.

brand_selections

JetonSignification
siding:brand:12N'importe quel produit de ce fabricant dans cette catégorie.
siding:line:40@double-4-dutchlapUne gamme, sur une géométrie.
siding:product:88@double-4-dutchlapUn produit, entièrement précisé.
paint:brand:3N'importe quelle teinte de cette marque de peinture.
paint:product:412Une teinte de peinture.

La grammaire est category:level:id[@value][.value]. La partie après @ porte des slugs de valeurs de géométrie, uniques dans leur catégorie : l'axe auquel ils appartiennent se retrouve par recherche au lieu d'être écrit dans le jeton. Un jeton inconnu est refusé avec un 422, jamais ignoré en silence.

Session de bout en bout

Un bâtiment, une photo, un design, puis les deux documents. L'instruction qui produit tout cela :

Crée un bâtiment nommé Maple Street 14, téléverse ./front.jpg comme vue et lance un design avec des murs gris chaud et des encadrements blancs. Commande l'estimation et l'album pour le résultat.
Session 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)

Ressources