Il motore di home staging virtuale che sta dietro all'app web è ora disponibile come API HTTP. Invii la foto di una stanza, indichi un tipo di ambiente e uno stile di arredamento, e l'immagine arredata torna nella stessa risposta. Costa $0.15 a immagine, non c'è abbonamento, né minimo, né fattura mensile, e la documentazione di riferimento è su stagify.ai/developers.html.
Questo articolo è ciò che una pagina di riferimento non può essere: perché l'API ha la forma che ha, e la manciata di cose su cui inciamperai il primo pomeriggio.
Tutta l'API è un solo endpoint
C'è esattamente una chiamata che costa denaro.
curl https://stagify.ai/api/v1/renders \
-H "Authorization: Bearer $STAGIFY_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-F "image=@living-room.jpg" \
-F "roomType=Living room" \
-F "furnitureStyle=modern" \
-F "labelVirtuallyStaged=true"
Questa è l'integrazione. La risposta porta l'immagine arredata come data URL, insieme a uno stato e a un id di richiesta. Tutto il resto dell'API è gratuito e in sola lettura: GET /api/v1/options ti dà i valori ammessi per ogni enum, GET /api/v1/me ti dice se la tua chiave funziona, GET /api/v1/credits riporta il saldo e GET /api/v1/renders/{id} recupera un singolo render.
Le richieste sono multipart/form-data, perché stai caricando una fotografia e il base64 in un corpo JSON ti costerebbe un terzo di byte in più per nulla. Le immagini sono JPEG, PNG o WebP fino a 25 MB, e ciò che viene controllato è il tipo MIME, non l'estensione del file.
Perché non c'è una coda di lavori
Il design ovvio per un'API di immagini lenta è accettare la richiesta, restituire un id di job e far interrogare il risultato al client. Deliberatamente non l'abbiamo fatto, e la ragione merita di essere detta, perché da fuori sembra una scorciatoia e non lo è.
Questa applicazione non ha alcuna coda di lavori. Aggiungerne una solo per l'API significherebbe introdurre una coda i cui job vivono in un unico processo, su un host che si riavvia a ogni deploy. Quando succede a metà di un render, il credito del cliente è già speso e non resta alcun socket per dirgli qualcosa. Quel fallimento è strettamente peggiore di una connessione caduta, perché una connessione caduta si può ritentare con la stessa chiave di idempotenza e non costa nulla.
Quindi un render tiene aperta la connessione finché non finisce, e ci vuole da qualche secondo a un paio di minuti. Imposta il read timeout del tuo client a 300 secondi. Il valore predefinito nella maggior parte delle librerie HTTP è 30 o 60, e un client che si arrende a 30 secondi sembrerà un'API che fallisce di continuo, mentre in silenzio spende crediti per render che non raccoglie mai.
status: "succeeded", e GET /api/v1/renders/{id} esiste già. Se un giorno aggiungeremo una coda, arriverà come un nuovo valore di status sullo stesso endpoint, non come una nuova API. Tratta qualsiasi stato diverso da succeeded come «vai a interrogare la GET» e il tuo client è già pronto per il futuro.
Lo stesso ragionamento limita variations a 1. Una richiesta è un credito è un'immagine è un rimborso, senza aritmetica di distribuzione parziale in nessun punto dei soldi. Se vuoi tre versioni di una stanza, lancia tre richieste in parallelo: ottieni così un parallelismo migliore di quello che il fan-out ti ha mai dato.
Crediti prepagati, e perché sono una misura di sicurezza
Compri i crediti in anticipo. Ogni render riuscito ne spende uno, e un render fallito viene rimborsato automaticamente, quindi non paghi mai una foto che non hai ricevuto. I pacchetti partono da 20 crediti per $3, e il prezzo per immagine scende man mano che crescono, fino a $0.12 a immagine sul pacchetto da 500 crediti. La tabella aggiornata è sulla pagina di documentazione dell'API, generata dagli stessi dati su cui addebita il webhook di pagamento, quindi non può divergere da ciò che ti viene effettivamente fatturato.
La fatturazione a consumo sarebbe stata più facile da costruire. Il prepagato è meglio per te su un punto specifico: una chiave rubata può costarti al massimo il saldo che le resta. Non c'è fattura a fine mese, non ci sono eccedenze, e non esiste lo scenario in cui una chiave trapelata diventa un conto a quattro cifre prima che qualcuno se ne accorga. Lo stop netto a zero è l'obiettivo e non un limite, ed è anche il motivo per cui ogni risposta porta un header X-Stagify-Credits-Remaining: puoi vedere il muro avvicinarsi senza interrogarlo.
Le chiavi sono pensate solo per l'uso da server a server. L'API non invia header CORS, quindi il JavaScript del browser non può chiamarla, e questo è deliberato, non un'omissione che intendiamo correggere. Una chiave raggiungibile da un browser è una chiave trapelata. Mostriamo una chiave nuova esattamente una volta, ne conserviamo solo un hash e la revochiamo all'istante dalla dashboard delle chiavi API.
Quattro cose su cui inciamperai
Ogni API ha comportamenti perfettamente ragionevoli una volta spiegati e sconcertanti prima. Ecco i nostri, detti chiaramente invece che lasciati in una tabella di parametri.
roomTypedistingue maiuscole e spazi, e un valore sbagliato non viene rifiutato. Viene scritto nel prompt come testo libero, quindiLiving Roomnon èLiving room. Otterrai un render, solo non quello che volevi, e lo avrai pagato. L'insieme ammesso èBedroom,Living room,Dining room,Kitchen,Office,Bathroom,OutdoorseDorm. Prendilo daGET /api/v1/optionsinvece di ridigitarlo nel tuo menu a tendina.- Un
furnitureStylenon riconosciuto diventa silenziosamentestandard. Stessa classe di problema, sintomo più silenzioso: un refuso nel nome di uno stile non dà errore, ti restituisce semplicemente l'aspetto predefinito su ogni immagine del lotto. removeFurnitureaccettatrueoppureon, e nient'altro. Non1, nonyes. Entrambi vengono letti come false, e ottieni una foto arredata con il vecchio divano ancora dentro. Il suo compagnokeepFurnitureaccetta testo libero che indica cosa lasciare al suo posto, fino a 500 caratteri, e viene letto solo quandoremoveFurnitureè effettivamente impostato.- Invia una
Idempotency-Keya ogni richiesta. Ometterla è consentito e significa nessuna protezione dai replay, che è il comportamento predefinito onesto; non la deriveremo dalla tua foto, perché allora due render genuinamente distinti della stessa stanza si scontrerebbero e al secondo chiamante verrebbe consegnata l'immagine del primo. Riprova con lo stesso valore e una richiesta completata viene riprodotta dallo storage conX-Stagify-Replayed: truee senza un secondo addebito. Riusane una con parametri diversi e ottieni422 IDEMPOTENCY_KEY_REUSED, cioè l'API che ti dice che il tuo generatore di chiavi ha un bug.
Oltre a questi, i parametri che vale la pena conoscere rispecchiano l'app web: additionalPrompt per indicazioni in testo libero, e fino a cinque foto di riferimento furnitureImage a cui il modello può ispirarsi.
L'etichetta di divulgazione non si può disattivare
La maggior parte delle regole delle MLS, e le linee guida NAR che le sostengono, richiedono che una foto di annuncio arredata digitalmente dichiari di esserlo; da gennaio 2026 l'AB 723 della California lo impone per legge. Ne abbiamo scritto la versione stato per stato in modo esteso.
labelVirtuallyStaged incide la dicitura nei pixel invece di allegarla come metadato, perché i metadati vengono rimossi da praticamente ogni strumento a valle attraverso cui passa un'immagine diretta a un portale. Il suo aspetto lo controlli tu: stampStyle sceglie tra dark, light, minimal e banner, stampScale la dimensiona tra 0.7 e 1.6, e stampLang la rende in una qualsiasi di undici lingue.
Ciò che non controlli è la modalità di fallimento. Se l'etichetta è richiesta e non può essere applicata, l'immagine viene trattenuta invece che consegnata senza etichetta. La chiamata risponde 500 DISCLOSURE_STAMP_FAILED e il tuo credito viene rimborsato. Non c'è alcun flag per disattivarlo, né un valore predefinito per chiave che lo spenga in sordina. L'alternativa è consegnare una foto arredata senza etichetta a un cliente che ha chiesto esplicitamente di etichettarla: è l'unico bug di questo sistema capace di mettere qualcuno davanti a un regolatore.
Gli errori, e l'unica regola che li riguarda
Ogni fallimento risponde con un corpo JSON che porta sia una stringa error sia un code. Ramifica sul codice, mai sul messaggio. I messaggi vengono riscritti; i codici no.
Quelli che incontrerai davvero in produzione sono 402 INSUFFICIENT_CREDITS (ricarica; il corpo porta il saldo residuo), 409 CONCURRENCY_LIMIT (troppi render in corso su una stessa chiave; il margine predefinito è di tre alla volta, quindi aspetta un secondo e riprova), 409 REQUEST_IN_FLIGHT (hai ritentato una chiave di idempotenza ancora in esecuzione, quindi aspetta invece di insistere), 429 RATE_LIMITED e 422 NO_IMAGE_GENERATED, che significa che il modello non ha restituito nulla e viene rimborsato automaticamente. Il limite sui render è attualmente di 60 per chiave ogni cinque minuti; se ti serve di più, o una fattura invece di una carta, scrivici.
Nota il motivo ricorrente in tutto questo: tutto ciò che fallisce dopo un addebito viene rimborsato. Quell'invariante è la ragione per cui l'API è sincrona e la ragione per cui variations è limitato a uno, ed è la cosa per cui rinunceremmo a delle funzionalità.
A chi serve, e a chi no
L'API esiste per i casi in cui lo staging è un passaggio nella pipeline di qualcun altro e non qualcosa che una persona si siede a fare:
- Portali di annunci e fornitori IDX che arredano in fase di ingestione, così che la foto di una stanza vuota di un agente arrivi già arredata alla griglia dei risultati.
- Strumenti di consegna dei fotografi. Se hai già uno script che rinomina, ridimensiona e carica un servizio, lo staging diventa un passaggio in più al suo interno invece che una serata in un'app web.
- Prodotti PropTech che vogliono lo staging come funzionalità senza costruire l'impianto del modello, l'apposizione della dicitura e la gestione degli errori che ci stanno dietro.
- Lavori in blocco di qualsiasi dimensione, perché il prezzo è a immagine e il minimo è $3.
Non è affatto pensata per chi arreda una sola casa. Se sei tu, l'app web fa più dell'API, dato che Masking Studio e l'AI Designer non hanno un equivalente nell'API, ed è gratuita, senza filigrana. Pagare $0.15 per fare in codice ciò che puoi fare gratis in un browser sarebbe una scelta strana, e preferiamo dirtelo piuttosto che venderti un pacchetto di crediti.
Per iniziare
Crea una chiave nella pagina delle chiavi API, compra il pacchetto più piccolo e spendi un credito su una foto di cui conosci già il risultato. Poi leggi per bene la documentazione prima di scrivere il ciclo in blocco, in particolare la tabella dell'idempotenza. Venti crediti sono $3, e bastano ampiamente per scoprire se questo si incastra nella tua pipeline.
Fonti e note
- Documentazione dell'API Stagify. Il riferimento autorevole per endpoint, parametri, codici di errore e prezzi correnti dei pacchetti di crediti. Dove questo articolo e quella pagina non concordano, ha ragione quella pagina: la sua tabella prezzi è generata dagli stessi dati su cui addebita il webhook di pagamento, mentre questo è un testo scritto in un giorno preciso.
- Dashboard chiavi API e crediti. Crea e revoca chiavi, compra pacchetti e leggi il saldo. Solo da desktop.
- I limiti di frequenza, il margine di concorrenza per chiave e i prezzi dei pacchetti citati qui sono i valori predefiniti al momento della stesura e sono soggetti a modifica. Limiti più alti e fatturazione su fattura sono disponibili su richiesta a team@stagify.ai.
- L'AB 723 della California e le regole di divulgazione delle MLS citate sopra sono trattate con le fonti in Bisogna dichiarare l'home staging virtuale? invece di essere ripetute qui.