GetFacades agent-API

Facadeprojektering via MCP og HTTP. Hvert design udarbejdes til det land, bygningen står i: materialer, der kan bruges der, produkter, som producenterne faktisk sælger der, og den tekniske opbygning bag overfladen. En render viser det på fotoet af huset, prisoverslaget sætter pris på det linje for linje, og PDF-albummet dokumenterer det for det sjak, der bygger. Hver sti nedenfor er et eksisterende GetFacade-endpoint, det samme som iOS-, Android- og webappen kalder. En agentnøgle begrænser blot, hvem der må kalde det, måler forbruget og stopper ved sit loft.

Basis-URL
https://api.getfacade.ai/api/v1
Godkendelse
Bearer <agent key>
Pakke
@getfacade/mcp
Kørselsmiljø
Node.js 20+
Transport
stdio (MCP), HTTPS (REST)
Specifikation
OpenAPI 3.1, v1.0.0

Hurtig start

  1. Opret en nøgle

    app.getfacade.aiKontoIndstillingerAPIOpret nøgle

    Værdien vises én gang og kan ikke gendannes, kun erstattes. Forbrugsloftet sættes ved oprettelsen og gælder ved hvert betalt kald.

    Opret en agentnøgle
  2. Registrér MCP-serveren

    Én post i klientens konfiguration og derefter genstart af klienten. Claude Desktop gemmer den i claude_desktop_config.json; enhver anden MCP-klient tager de samme tre felter.

    claude_desktop_config.json
    {
      "mcpServers": {
        "getfacade": {
          "command": "npx",
          "args": ["-y", "@getfacade/mcp"],
          "env": { "GETFACADE_API_KEY": "your-key" }
        }
      }
    }
    Miljøvariabler
    VariabelPåkrævetStandardværdi
    GETFACADE_API_KEYJa
    GETFACADE_API_BASE_URLNejhttps://api.getfacade.ai/api/v1
  3. Eller kald HTTP-API'et direkte

    Samme nøgle fungerer som bearer-token. Forespørgsler og svar er JSON:API-dokumenter, hvor id er et felt på øverste niveau og aldrig ligger inde i 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"}}}'

Værktøjer

Enogtyve værktøjer. MCP-serveren holder ingen tilstand og ingen egne regler: hvert værktøj er et eller flere kald til de endpoints, der står ved siden af, og hver besked, agenten gengiver, er skrevet af API'et.

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

    Opretter en bygning. Navnet er unikt inden for kontoen og højst 50 tegn; en dublet afvises med 422.

    KalderPOST /projects

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

    Registrerer en visning, uploader bytes til en forhåndssigneret URL, bekræfter dem og spørger, indtil fotoet godkendes eller afvises. Bredde, højde og md5 beregnes lokalt; billedforholdet udleder serveren.

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

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

    Projekterer facaden på en valgt visning og viser den på fotoet: materialer, der kan bruges i bygningens land, produkter, der faktisk sælges der, og opbygningen bag overfladen. Opretter et design, sætter arbejdet i kø og returnerer job-id. Seed er valgfrit: udelades det, genererer serveren et og returnerer det.

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

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

    Retter et færdigt design med ord. Instruktionen anvendes på det færdige design, så alt, den ikke nævner, bevares. At rette en hovedvisning opretter et nyt design, så det tidligere aldrig overskrives.

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

    Læser tilstanden for én rendering, ét overslag eller ét album.

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

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

    Seneste job på tværs af kontoen, ufærdige først.

    KalderGET /history

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

    Bygningens designs med deres renderinger. Herfra kommer render-id'erne til overslag og album.

    KalderGET /projects/{project}/concepts

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

    Sætter pris på designet linje for linje, i materialer og arbejdsløn, til det de angivne materialer koster i bygningens land. Valuta og målesystem følger som standard det land.

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

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

    Dokumenterer designet for det sjak, der bygger: materialerne, facadens opbygning, sikkerhedsnoter og de normer, de hviler på. Kræver en færdig hovedrender.

    KalderPOST /concepts/{concept}/album/generate

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

    Forstørrer en færdig rendering. Koster tokens og kører asynkront.

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

    Selve overslaget: totaler, forudsætningerne bag dem og hver linje med mængde, enhed og pris. get_job melder et overslags status, aldrig dets indhold.

    KalderGET /estimates/{estimate}

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

    Tilføjer en linje til overslaget. Enhederne kommer fra dets eget målesystem.

    KalderPOST /estimates/{estimate}/items

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

    Ændrer en linje i overslaget. Kun de sendte felter ændres; serveren regner totalerne om.

    KalderPATCH /estimates/{estimate}/items/{item}

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

    Fjerner en linje fra overslaget.

    KalderDELETE /estimates/{estimate}/items/{item}

  • delete_render
    delete_render(render_id)
      -> { deleted }

    Sletter en rendering. Slettes hovedrenderingen, går designet tilbage til kladde.

    KalderDELETE /renders/{render}

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

    Sletter et design med de renderinger, der hører til.

    KalderDELETE /projects/{project}/concepts/{concept}

  • delete_building
    delete_building(building_id)
      -> { deleted }

    Sletter en bygning med alt indhold. Allerede brugte tokens refunderes ikke.

    KalderDELETE /projects/{project}

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

    De pakker, kontoen kan købe, med pris og antal tokens.

    KalderGET /tokens/packages

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

    Køber en pakke til denne nøgles tegnebog. Kræver en nøgle udstedt med køb slået til og går aldrig ud over det, nøglen stadig må bruge.

    KalderPOST /tokens/purchase

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

    Agentpungen, denne nøgles loft og om næste betalte kald bliver lukket igennem.

    KalderGET /tokens/balance

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

    Rapporterer en fejl i dette API: et felt der er beskrevet her, men aldrig kommer, et afslag hvis ordlyd ikke viser en vej videre, et resultat der ikke svarer til det, der blev bedt om. Gratis og accepteres med tom pengepung; tilbage kommer en reference, ikke et svar.

    KalderPOST /feedback

Godkendelse og nøgler

  • Nøglen sendes som bearer-token i Authorization-headeren. MCP-serveren læser den fra GETFACADE_API_KEY og sender ikke andet.
  • Værdien vises én gang, ved oprettelsen, og kun dens hash gemmes. Rotation betyder at oprette en ny nøgle og tilbagekalde den gamle.
  • Hver nøgle bærer et forbrugsloft, der håndhæves på serveren, før kaldet når en controller. Et nået loft standser den nøgle, ikke kontoen.
  • Nøgler administrerer ikke nøgler: det er en menneskelig handling, og de endpoints svarer 403 på en agentnøgle.
  • Tilbagekaldelse virker med det samme. Kald med en tilbagekaldt nøgle svarer 401.

Asynkront arbejde og polling

  • start_design, order_estimate og order_album returnerer et job-id og er dermed færdige. En rendering tager minutter: poll GET /renders/{render} eller GET /estimates/{estimate}, indtil tilstanden er endelig.
  • At fotokontrollen er færdig, meldes over en websocket, agenten ikke har. Poll GET /angles/{angle}/validation og læs validation.is_in_progress; udled ikke selv sluttilstanden af statusteksten.
  • En færdig render og et færdigt album ligger på permanente offentlige URL'er: uden signatur og uden udløb. Linket kan gives direkte til en person som svar på “vis mig resultatet”. Da det ikke er signeret, spørger det ingen om lov: det bliver ved med at virke for enhver, der modtager det, og kan ikke trækkes tilbage.
  • GET /renders/{render}/download er noget andet: en signeret URL, der udløber i løbet af minutter og bærer et filnavn. Den er til at gemme filen, ikke til at dele den.

Hastighedsgrænser pr. nøgle

En agentnøgle har sine egne kvoter, adskilt fra de menneskelige sessioner på samme konto, så en agent i løkke ikke æder kvoten for personen foran skærmen. Afvisningen er billig: den træffes i mellemlaget, før alt databasearbejde.

OmrådePr. minutPr. time
Læsninger og almindelige skrivninger1202000
Status- og kontrolpolling1202000
Bestilling af rendering, overslag og album10200

Idempotens

Et betalt kald opretter et job, og betalingen følger jobbet. At give kaldet et navn er det, der lader en gentagelse returnere det samme job i stedet for at oprette et nummer to.

  • Idempotency-Key er påkrævet ved ethvert betalt kald med en API-nøgle: start eller finpudsning af et design, forstørrelse af et render, bestilling af et overslag eller et album, ny beregning af et overslag. Uden den svarer kaldet 422 IDEMPOTENCY_KEY_REQUIRED, og intet sættes i kø.
  • Enhver værdi på 8 til 191 tegn, én pr. bestilling; typisk en UUID. En ny bestilling får en ny værdi: to ens kald under to værdier er to designs.
  • Gentager du et kald med samme værdi og samme body, får du den oprindelige status og body tilbage, med Idempotent-Replay: true i svaret. Intet sættes i kø, og intet betales to gange.
  • Samme værdi med en anden body svarer 422 IDEMPOTENCY_KEY_REUSED. En gentagelse, der ankommer mens det første kald stadig kører, svarer 409 IDEMPOTENCY_IN_PROGRESS: vent, og send det samme kald igen.
  • Ethvert 4xx-svar frigiver værdien, så den samme kan sendes igen, når årsagen er rettet. Værdier huskes i 24 timer, pr. konto.
  • @getfacade/mcp danner værdien og gentager kaldet under den af sig selv, så der er intet at sende med i et værktøjskald.

Fejl

Fejl kommer som JSON:API-fejldokumenter. Laravels valideringssvar har ikke JSON:API-form og bærer teksten i message.

StatusKodeBetydningKan gentages
401Nøglen mangler, er tilbagekaldt eller udløbet.Nej
402AGENT_CREDITS_EXHAUSTEDKontoen har ikke flere kreditter i api-omfanget.Nej
402AGENT_KEY_CAP_REACHEDDenne nøgle har brugt sit loft. Opret en anden nøgle, eller hæv loftet.Nej
403Dette endpoint er ikke tilgængeligt for API-nøgler. Agent-API'et dækker bygninger, fotos, designs, renderinger, overslag, albums og API-tegnebogen. Indstillinger for konto, login og betaling ændres af en person, der er logget ind i appen.Nej
403AGENT_PURCHASE_NOT_ALLOWEDDenne nøgle blev udstedt uden ret til at købe tokens.Nej
403AGENT_PURCHASE_EXCEEDS_CAPKøbet ville føre nøglen forbi dens forbrugsloft.Nej
409IDEMPOTENCY_IN_PROGRESSDet første kald med denne Idempotency-Key har ikke svaret endnu. Vent, og send det samme kald igen.Ja
422Forespørgslen blev forstået og afvist: dubleret bygningsnavn, afvist foto, album bestilt før hovedrenderingen var færdig.Nej
422IDEMPOTENCY_KEY_REQUIREDEt betalt kald med API-nøgle uden Idempotency-Key-header. Intet blev sat i kø; send det igen med headeren.Nej
422IDEMPOTENCY_KEY_REUSEDDenne Idempotency-Key er brugt til en anden anmodning. Brug en ny værdi til en ny bestilling.Nej
429Nøglens egen kvote er brugt op. Vent lidt, gentag ikke i tæt løkke.Ja

Den læsbare tekst skrives af API'et, på kalderens sprog. Vis errors[].detail, som den står, i stedet for at formulere din egen besked.

Betaling og adgang

  • Betalte kald trækker på api-scope-kreditter, og adgangen ser kun på den saldo: hver nøgle betaler i kreditter.
  • Et aktivt Pro Plan fylder api-tegnebogen op til 1.000 kreditter en gang pr. faktureringsperiode. Derudover købes kreditter.
  • En nøgle fylder kun sin egen tegnebog op, hvis den blev udstedt med køb slået til, og højst med det, den stadig må bruge, så et køb hæver aldrig forbrugsloftet.
  • api-området er en selvstændig pung. Appens kreditter, gratisniveauet inklusive, bruges aldrig af en nøgle.
  • Forbruget tælles pr. nøgle, så hver assistents forbrug ses for sig.
  • Forhåndstjekket er GET /tokens/balance, feltet data.attributes.agent.is_admissible. Blokken findes kun for agentnøgler, og flaget spejler adgangsmellemlaget nøjagtigt. Læs det i stedet for selv at sammenligne saldo og loft.
  • Adgangen afgøres, før arbejde sættes i kø, så et afvist kald koster ingenting.

Farve- og mærketokens

start_design tager to uafhængige lister med højst ti poster hver. Rækkefølgen bærer rollen 60/30/10: første post er den dominerende vægfarve.

colors

TokenBetydning
palette:1Et kurateret GetFacade-skema, efter id.
#8A8F7DEn fri farve, seks hexadecimale tegn.
paint:412En producentkulør, i den todelte form der beholdes af hensyn til kompatibilitet.

brand_selections

TokenBetydning
siding:brand:12Ethvert produkt fra den producent i den kategori.
siding:line:40@double-4-dutchlapÉn serie, på én geometri.
siding:product:88@double-4-dutchlapÉt produkt, fuldt bestemt.
paint:brand:3Enhver kulør fra det malingsmærke.
paint:product:412Én malingskulør.

Grammatikken er category:level:id[@value][.value]. Delen efter @ bærer slugs for geometriværdier, unikke inden for deres kategori, så aksen, de hører til, slås op i stedet for at blive skrevet i tokenet. Et ukendt token afvises med 422 og forbigås aldrig i stilhed.

Fuld session

Én bygning, ét foto, ét design og så de to dokumenter. Instruktionen, der giver det:

Opret en bygning ved navn Maple Street 14, upload ./front.jpg som dens visning, og start et design med varmgrå vægge og hvide lister. Bestil overslaget og albummet for resultatet.
MCP-session
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)

Ressourcer