Движок виртуального хоум-стейджинга, на котором работает веб-приложение, теперь доступен как 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, а вместе с ним статус и идентификатор запроса. Всё остальное в API бесплатно и работает только на чтение: GET /api/v1/options выдаёт допустимые значения каждого перечисления, GET /api/v1/me сообщает, работает ли ваш ключ, GET /api/v1/credits показывает баланс, а GET /api/v1/renders/{id} находит один конкретный рендер.
Запросы идут как multipart/form-data, потому что вы загружаете фотографию, а base64 в теле JSON обошёлся бы вам на треть большим числом байтов просто так. Изображения — JPEG, PNG или WebP до 25 МБ, и проверяется MIME-тип, а не расширение файла.
Почему здесь нет очереди задач
Очевидный дизайн для медленного API изображений — принять запрос, вернуть идентификатор задачи и заставить клиента опрашивать результат. Мы намеренно так не сделали, и причину стоит назвать, потому что снаружи это выглядит как срезанный угол, а это не так.
В этом приложении вообще нет очереди задач. Добавить её ради одного лишь API означало бы завести очередь, задачи которой живут в единственном процессе, на хосте, перезапускающемся при каждом деплое. Когда это случается посреди рендера, кредит клиента уже потрачен, а сокета, чтобы хоть что-то ему сообщить, уже нет. Такой отказ строго хуже оборванного соединения, потому что оборванное соединение можно повторить с тем же ключом идемпотентности, и это не стоит ничего.
Поэтому рендер держит соединение, пока не закончит, а это занимает от нескольких секунд до пары минут. Выставьте read timeout вашего клиента на 300 секунд. По умолчанию в большинстве HTTP-библиотек стоит 30 или 60, и клиент, сдающийся на тридцатой секунде, будет выглядеть как постоянно падающий API, тихо тратя кредиты на рендеры, которые он никогда не заберёт.
status: "succeeded", а GET /api/v1/renders/{id} уже существует. Если мы когда-нибудь добавим очередь, она придёт новым значением status на том же эндпоинте, а не новым API. Считайте любой статус, кроме succeeded, командой «иди опрашивай GET» — и ваш клиент уже готов к будущему.
По той же логике variations ограничен единицей. Один запрос — это один кредит, одно изображение и один возврат, без всякой арифметики частичного размножения в денежной части. Если вам нужны три варианта комнаты, отправьте три параллельных запроса: так параллелизма получится больше, чем когда-либо давал fan-out.
Предоплаченные кредиты и почему это мера безопасности
Кредиты вы покупаете заранее. Каждый успешный рендер тратит один, а неудавшийся рендер возвращается автоматически, так что вы никогда не платите за фото, которое не получили. Пакеты начинаются с 20 кредитов за $3, и цена за снимок падает по мере их роста — до $0.12 за снимок в пакете на 500 кредитов. Актуальная таблица есть на странице документации API, она строится из тех же данных, по которым списывает платёжный вебхук, поэтому она не может разойтись с тем, что с вас реально берут.
Оплату по факту потребления было бы проще построить. Предоплата лучше для вас в одном конкретном смысле: украденный ключ может стоить вам самое большее того остатка, что на нём есть. Нет счёта в конце месяца, нет перерасхода и нет сценария, при котором утёкший ключ превращается в четырёхзначный счёт раньше, чем кто-нибудь это заметит. Жёсткая остановка на нуле — это цель, а не ограничение, и потому же каждый ответ несёт заголовок 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 сообщит вам, что в вашем генераторе ключей ошибка.
Помимо этого, параметры, которые стоит знать, повторяют веб-приложение: additionalPrompt для указаний свободным текстом и до пяти референсных фотографий furnitureImage, на которые модель будет ориентироваться.
Отметку о виртуальной обстановке нельзя отключить
Большинство правил MLS и стоящие за ними рекомендации NAR требуют, чтобы обставленная фотография объявления сообщала об этом; с января 2026 года калифорнийский AB 723 требует этого по закону. Мы написали подробный разбор этого по штатам.
labelVirtuallyStaged впечатывает отметку в пиксели, а не прикладывает её метаданными, потому что метаданные вырезает едва ли не каждый инструмент, через который изображение проходит по пути на портал. Внешний вид вы контролируете: stampStyle выбирает между dark, light, minimal и banner, stampScale задаёт размер в диапазоне от 0.7 до 1.6, а stampLang выводит её на одном из одиннадцати языков.
Чего вы не контролируете, так это поведение при сбое. Если отметка запрошена и не может быть нанесена, изображение удерживается, а не выдаётся без отметки. Вызов отвечает 500 DISCLOSURE_STAMP_FAILED, а ваш кредит возвращается. Нет флага, который это отключает, и нет настройки по умолчанию для ключа, которая тихо это выключит. Альтернатива — отдать неотмеченное обставленное фото клиенту, который прямо просил его отметить, а это единственная ошибка в этой системе, способная поставить кого-то перед регулятором.
Ошибки и единственное правило о них
Каждый сбой отвечает телом JSON, несущим и строку error, и code. Ветвитесь по коду, никогда по сообщению. Сообщения переписывают; коды — нет.
На практике в продакшене вам встретятся 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, и этого более чем достаточно, чтобы выяснить, подходит ли это вашему конвейеру.
Источники и примечания
- Документация API Stagify. Авторитетный справочник по эндпоинтам, параметрам, кодам ошибок и текущим ценам пакетов кредитов. Там, где эта статья и та страница расходятся, права страница: её таблица цен строится из тех же данных, по которым списывает платёжный вебхук, а здесь — проза, написанная в конкретный день.
- Панель ключей API и кредитов. Создание и отзыв ключей, покупка пакетов и просмотр баланса. Только на десктопе.
- Приведённые здесь лимиты частоты, допустимая одновременность на ключ и цены пакетов — значения по умолчанию на момент написания, и они могут измениться. Повышенные лимиты и оплата по счёту доступны по запросу на team@stagify.ai.
- Калифорнийский AB 723 и упомянутые выше правила раскрытия MLS разобраны со ссылками в материале Нужно ли раскрывать виртуальный хоум-стейджинг?, а не повторяются здесь.