网页应用背后的软装引擎现已作为 HTTP API 开放。你上传一张房间照片,指定房间类型和家具风格,做好虚拟软装的图片会在同一个响应里返回。每张图 $0.15,没有订阅、没有起订量、也没有月度账单,参考文档在 stagify.ai/developers.html。
这篇文章写的是参考文档做不到的那部分:这个 API 为什么是现在这个样子,以及第一个下午就会绊住你的那几件事。
整个 API 只有一个端点
真正收费的调用只有一个。
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"
集成工作到此为止。响应以 data URL 的形式携带软装后的图片,另外还有一个状态和一个请求 id。API 里其余的一切都是免费且只读的:GET /api/v1/options 返回每个枚举的可用取值,GET /api/v1/me 告诉你密钥是否有效,GET /api/v1/credits 报告余额,GET /api/v1/renders/{id} 用来回查某一次渲染。
请求采用 multipart/form-data,因为你上传的是照片,而在 JSON 正文里用 base64 会白白多出三分之一的字节。图片支持 JPEG、PNG 或 WebP,最大 25 MB,校验的是 MIME 类型,而不是文件扩展名。
为什么没有任务队列
对于一个慢速图像 API,显而易见的设计是:接收请求,返回一个任务 id,让客户端轮询结果。我们刻意没有这么做,理由值得说清楚,因为从外面看这像是走捷径,其实不是。
这个应用根本没有任务队列。仅仅为了 API 而加一个,就意味着引入一个任务只存在于单个进程里的队列,而这个进程所在的主机每次部署都会重启。如果重启发生在渲染中途,客户的点数已经扣掉了,却连一个还能通知他们的连接都不剩。这种失败严格地比断线更糟,因为断掉的连接可以用同一个幂等键重试,而且不花钱。
所以一次渲染会一直占着连接直到完成,耗时从几秒到几分钟不等。请把客户端的读取超时设为 300 秒。大多数 HTTP 库的默认值是 30 或 60 秒,而一个在 30 秒就放弃的客户端,会让这个 API 看起来一直在失败,同时还在悄悄为它永远取不回来的渲染花掉点数。
status: "succeeded",GET /api/v1/renders/{id} 也已经存在。如果我们将来真的加上队列,它会以同一个端点上一个新的 status 取值出现,而不是一个新的 API。把 succeeded 以外的任何状态都当作“去轮询那个 GET”,你的客户端就已经面向未来了。
同样的道理把 variations 的上限定在 1。一个请求就是一个点数、一张图片、一次退款,钱这一侧不存在任何按比例扇出的算术。如果你想看一个房间的三种效果,就并发发三个请求:这样得到的并行度比原来的扇出更好。
预付点数,以及它为什么是一项安全特性
你先购买点数。每次成功渲染扣掉一个,失败的渲染会自动退还,所以你永远不会为没收到的照片付钱。点数包从 20 个点数 $3 起,包越大每张图越便宜,500 点数包低至每张图 $0.12。实时价格表在 API 文档页上,它由支付 webhook 扣费时所用的同一份数据渲染而来,所以不可能和你实际被扣的金额产生偏差。
按量计费本来更好做。预付在一个很具体的方面对你更有利:被盗的密钥最多只能花掉它上面剩下的余额。月底没有账单,没有超额费用,也不存在密钥泄露后在任何人察觉之前变成四位数账单的情形。归零时的硬性停止是重点,而不是一种局限,这也是为什么每个响应都带有 X-Stagify-Credits-Remaining 响应头:你不用轮询就能看着余额见底。
密钥只适用于服务器到服务器的调用。这个 API 不发送任何 CORS 响应头,所以浏览器里的 JavaScript 调不了它,这是刻意为之,而不是我们打算修的疏漏。浏览器能够到的密钥就是已经泄露的密钥。新密钥只显示一次,我们只保存它的哈希值,并且可以在 API 密钥面板里当场吊销。
会绊住你的四件事
每个 API 都有一些行为,解释过之后完全合理,解释之前让人摸不着头脑。下面是我们的,直说,而不是丢在一张参数表里。
roomType区分大小写和空格,而且错误的取值不会被拒绝。它会作为自由文本写进提示词,所以Living Room不等于Living room。你会拿到一张渲染图,只是不是你想要的那张,而且钱已经付了。可用取值是Bedroom、Living room、Dining room、Kitchen、Office、Bathroom、Outdoors和Dorm。请从GET /api/v1/options取用,而不要手动抄进自己的下拉菜单。- 无法识别的
furnitureStyle会静默地变成standard。同一类问题,症状更安静:风格名称打错不会报错,只会让这一批里的每张图都用上默认风格。 removeFurniture只接受true或on,别的都不行。不是1,也不是yes。这两个都会被读成 false,于是你拿到的软装照片里旧沙发还在。与它配套的keepFurniture用自由文本说明要原样保留什么,最多 500 个字符,并且只有在确实设置了removeFurniture时才会被读取。- 每个请求都带上
Idempotency-Key。不带是允许的,代表没有重放保护,这是诚实的默认行为;我们不会从你的照片推导一个出来,因为那样一来,同一个房间两次真正独立的渲染就会撞在一起,第二个调用者会拿到第一个的图片。用同一个值重试时,已完成的请求会从存储中重放,带上X-Stagify-Replayed: true,并且不会二次扣费。如果用不同的参数复用同一个值,你会得到422 IDEMPOTENCY_KEY_REUSED,这是 API 在告诉你:你的密钥生成器有 bug。
除此之外,值得了解的参数和网页应用里的一致:additionalPrompt 用于自由文本的额外指示,以及最多五张 furnitureImage 参考照片,供模型比对。
披露标注无法关闭
大多数 MLS 规则,以及其背后的 NAR 指引,都要求经过软装处理的房源照片注明它做过处理;自 2026 年 1 月起,加利福尼亚州的 AB 723 更是以成文法作出了这一要求。我们已经就此写过一篇逐州梳理的长文。
labelVirtuallyStaged 会把披露信息直接烧进像素,而不是作为元数据附上,因为图片在送到门户网站的路上,几乎每一个下游工具都会把元数据剥掉。外观由你控制:stampStyle 可在 dark、light、minimal 和 banner 之间选择,stampScale 在 0.7 到 1.6 之间调整大小,stampLang 可以用十一种语言中的任意一种来呈现它。
你控制不了的是失败时的行为。如果请求了标注却无法应用,图片会被扣下,而不是不带标注地交付出去。该调用会返回 500 DISCLOSURE_STAMP_FAILED,并退还你的点数。没有开关能关掉这一点,也没有哪个按密钥设置的默认值能悄悄把它关上。另一种做法是把一张没有标注的软装照片交给一个明确要求加标注的客户,而这正是这套系统里唯一一个可能把人送到监管机构面前的 bug。
错误,以及关于错误的那一条规则
每一次失败都会返回一个 JSON 正文,其中同时带有 error 字符串和 code。请按 code 分支,永远不要按 message。消息会被改写,代码不会。
你在生产环境里真正会遇到的是 402 INSUFFICIENT_CREDITS(去充值;正文中带有剩余余额)、409 CONCURRENCY_LIMIT(同一个密钥上同时进行的渲染太多;默认额度是三个并发,所以退避一秒再重试)、409 REQUEST_IN_FLIGHT(你重试了一个仍在运行的幂等键,所以请等待,而不要升级处理)、429 RATE_LIMITED,以及 422 NO_IMAGE_GENERATED,它表示模型什么都没返回,会自动退款。渲染的速率限制目前是每个密钥每五分钟 60 次;如果你需要更高的额度,或者需要发票而不是刷卡,请给我们发邮件。
注意这些情况共同的模式:任何在扣费之后失败的请求都会退款。这条不变量正是这个 API 采用同步设计的原因,也是 variations 上限为一的原因,而且它是我们宁可牺牲功能也要守住的东西。
这是给谁用的,又不是给谁用的
这个 API 的存在,是为了那些软装只是别人流程中的一个步骤、而不是某个人坐下来专门去做的场景:
- 房源平台和 IDX 服务商在数据接入时就完成软装,这样经纪人拍的空房照片在进入搜索列表之前就已经布置好了。
- 摄影师的交付工具链。如果你已经有一个脚本负责重命名、缩放并上传一次拍摄的成果,那么软装只是其中多出来的一步,而不是在网页应用里耗掉一个晚上。
- PropTech 产品,它们想把软装作为一项功能提供,却不想自己搭建背后的模型管道、披露标注和失败处理。
- 任何规模的批量处理,因为价格是按张算的,门槛只有 $3。
它绝对不适合只给一套房子做软装的人。如果你是这种情况,网页应用能做的比 API 更多,因为 Masking Studio 和 AI Designer 在 API 里没有对应功能,而且它免费、无水印。为了在代码里完成浏览器中免费就能做的事而付 $0.15,是个奇怪的选择,我们宁愿直说,也不想卖你一个点数包。
开始使用
在 API 密钥页面创建一个密钥,买最小的那个点数包,然后用一张你早已知道该是什么效果的照片花掉一个点数。接着,在写批处理循环之前认真读一遍参考文档,特别是幂等性那张表。二十个点数是 $3,足够你弄清楚这套东西是否适合你的流程。
来源与说明
- Stagify API 文档。端点、参数、错误码和当前点数包定价的权威参考。如果本文与该页面不一致,以该页面为准:它的价格表由支付 webhook 扣费时所用的同一份数据生成,而这篇只是某一天写下的文字。
- API 密钥与点数面板。创建和吊销密钥、购买点数包、查看余额。仅支持桌面端。
- 此处引用的速率限制、每个密钥的并发额度和点数包价格是撰文时的默认值,可能会变更。更高的限额和以发票结算的方式可来信 team@stagify.ai 申请。
- 上文提到的加利福尼亚州 AB 723 和 MLS 披露规则,在 虚拟软装必须披露吗?一文中有带出处的说明,这里不再重复。