目次(12)
今回の更新内容
- APIセクションを更新:無料API画像にはパック購入までRoomagenの透かしが入るようになり、すべてのツールがドキュメント化されました
- ツールが無視するオプションを記載した警告リストを追加しました
過去の更新(1)
- すべてのコードサンプルをRoomagenの実際のAPIに合わせて修正:roomTypeなどのcamelCaseオプション、UUIDジョブID、Idempotency-Keyヘッダー、タイムスタンプと未加工ボディから計算されるv1= Webhook署名に対応しました
- アクセス権と料金を更新:ウェイトリストの代わりに2026年8月30日以降セルフサービスキーを提供、最初のキーに1回限り50枚の無料画像、有効期限のないパック、40以上からドキュメント化された6つのツールへと改訂しました
- AB 723の「表記+元の画像へのリンク」規則、2027年1月からの賃貸広告向けカリフォルニア州AB 2025、相反するMLSのラベル規則、EU AI Act第50条を中心に開示セクションを書き直しました
- エラーコード表、レート制限、APIが対応していないことに関するセクション、ローンチ前チェックリストを追加し、裏付けのない市場規模の数値、無料再生成や開示ラベルの主張を削除しました
- ジョブの処理時間をドキュメント通りの20〜60秒に、ポーリング間隔を2〜5秒に修正し、ステージング、デイトゥダスク、間取り図を3Dにについて測定されたAPI中央値時間を記載しました
アプリにバーチャルステージングを追加するには、バックエンドから各部屋の写真を非同期ジョブとしてバーチャルステージングAPIに送信し、署名付きWebhookまたはポーリングによって結果を受け取った後、開示データとともに元の写真の横に保存します。
AIバーチャルステージング — 空室を1分以内に家具付きに
AIで空室をステージング。通常1分以内に完了します。13種類のデザインスタイルと15種類の部屋タイプで、不動産・賃貸・宿泊施設の掲載用写真を作成できます。無料クレジット6つ、クレジットカード不要。
アプリにバーチャルステージングを追加することは、要するに1つのループに集約されます。バックエンドがバーチャルステージングAPIにジョブとして部屋の写真を送信し、プロバイダーがバックグラウンドでレンダリングを行い、アプリがその結果を収集して元の写真の隣に保存し、配信先が必要とする開示とともに表示します。このチュートリアルでは、Roomagen APIを対象に、cURL、Node.js、Pythonのコードを用いてそのループを構築し、他のプロバイダーにも移行しやすい設計を保ちます。
連携の全体像
- サーバーから各写真をジョブとして送信:
Idempotency-Keyを指定してPOST /v1/jobsを実行。 - 他の処理を行う前に、返された
job_idを保存。 - 署名付きWebhookで完了したジョブを受信し、取りこぼしは
GET /v1/jobs/{id}で照合。 - 結果を自社サーバー等に再ホストし、その隣に元の写真を保持した上で、すべてのエクスポート先に開示データを引き継ぐ。
構築するもの: ステージング機能のアーキテクチャ
このチュートリアルの最後まで進めると、アプリは部屋の写真を受け取り、Roomagenのドキュメントによると通常20〜60秒後に同じ部屋の家具付きバージョンを表示できるようになります。本書に記載されているその他の内容はすべて、本番環境のトラフィック量でそのループを安定して動作させるためのものです。この同じループは、物件情報ポータル、写真納品プラットフォーム、空室を宣伝する不動産管理ソフトウェア、クライアント自身の部屋でコンセプトを提案するインテリアデザインアプリ、選択したスタイルの家具を配置した部屋を見せる家具小売業者などに対応できます。
レンダリングには数十秒かかり、HTTPリクエストを開いたまま保持するには長すぎるため、非同期設計を採用しています。ジョブを送信し、すぐにジョブIDを取得して、後から結果を収集します。ステージングは複数ステップのパイプライン(シーン分析、プロンプト生成、画像生成)を実行するため、デイトゥダスクなどのツールよりも時間がかかります。2026年10月1日までの30日間のRoomagen本番データでは、APIステージングジョブの中央値は約45秒で、デイトゥダスクや間取り図を3Dに変換する処理の約25秒と比較して長くなっています。
| ステージ | 実行場所 | 正しく設定すべきポイント |
|---|---|---|
| ジョブの送信 | バックエンド → POST /v1/jobs |
キーはサーバー側に保持、Idempotency-Key、job_idの保存 |
| レンダリング | Roomagen | 通常20〜60秒、ステージングは常に2Kでレンダリング |
| 完了の検知 | Webhook(プッシュ)+ポーリング(プル) | 署名の検証、job_idによる重複排除 |
| 保存と表示 | 自社のストレージおよびUI | 結果の再ホスト、元の写真の保持、開示 |
Roomagenは、Webアプリ内に40以上のツールを備えたAI写真編集およびバーチャルステージングプラットフォームです。APIは、1つのジョブエンドポイントの背後で、対応するすべてのツール(2026年10月時点で65種類)をドキュメント化しています。その画像ツールはGoogleのGemini画像モデルで動作し、APIにはステージングパイプライン、ジョブ処理、失敗したレンダリングの自動返金、署名付きWebhookが追加されています。
開始前の準備: キー、環境、および画像要件
キーの取得。 RoomagenのAPIは、2026年8月30日の一般公開以来、セルフサービスで提供されており、順番待ちはありません。APIクイックスタートに記載されているように、Roomagenアカウントで開発者ポータルにサインインし、メールアドレスを認証してキーを作成します。最初のキーを作成すると、アカウントごとに1回限り、50枚分の無料画像が付与されます。これは、本ガイドのすべての内容を構築してテストするのに十分な量です。アカウントがパックを購入するまで、すべてのレンダリングにはRoomagenの透かしが入るため、公開用ではなく、構築やテスト用として使用してください。
キーはrmg_live_に64文字の16進数が続く形式で、X-Api-Keyヘッダーで送信します。ポータル上では各キーは一度しか表示されません。サーバー側のシークレットストアに保管し、誰でも取り出して残高を消費できてしまうブラウザのJavaScriptやモバイルアプリ内に埋め込んで公開することは絶対に避けてください。
環境。 1つのアカウントで最大10個のアクティブなキーを保持できるため、環境ごとに1つずつ作成し、もう一方に影響を与えることなくいずれかを失効させることができます。テストモードはありません。すべてのキーが本番(live)環境用であり、アカウント内の複数のキーは1つの画像残高、1つのポータルWebhook、および1つの署名シークレットを共有します。そのため、開発用ジョブにはジョブごとの個別のwebhook_urlを指定してください。設計上、ローテーションボタンは用意されていません。新しいキーを作成してデプロイしてから、古いキーを失効させてください。
画像入力。
| 要件 | Roomagen API |
|---|---|
| 形式とサイズ | JPEG、PNG、またはWebP、最大20MB。image_urlまたはimage_base64のいずれか一方のみ |
image_url(推奨) |
公開https URL。POST処理中に取得: タイムアウト10秒、最大3回のリダイレクト、プライベートホストは拒否 |
image_base64 |
任意のデータURIプレフィックス。リクエストボディは最大30MBまで可能ですが、X-Api-Keyが存在する場合に限られます(ない場合は1MB) |
image_urlの使用をお勧めします。リクエストサイズを小さく抑えられ、base64による33%のオーバーヘッドを回避でき、POSTリクエストの処理中に取得が行われるため、署名付きURLの有効期限はそのリクエストの間だけで済むからです。フルサイズのエクスポート画像を送信し、1フレームにつき1部屋、水平に撮影され、適切な照明が当たっているものを使用してください。モデルは視認できる詳細情報しか保持できません。
コードで残高を確認する。 GET /v1/accountは、残高でまだレンダリングできる画像数であるimage_creditsを返します。今すぐ残高不足アラートを組み込んでおきましょう。残高がジョブのコストをカバーできない場合、POST /v1/jobsは402 insufficient_creditsを返し、ジョブは作成されません。
ステップ1: ステージングジョブを送信する
1回のPOSTで、ツール、画像、オプション、および任意でジョブごとのwebhook_urlを指定してジョブを作成します(指定しない場合、Roomagenはポータルに保存されたアカウントWebhookを使用するか、ポーリングを行うことになります)。
curl -X POST https://api.roomagen.com/api/v1/jobs \
-H "X-Api-Key: $ROOMAGEN_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: photo-4821-3-stage" \
-d '{
"tool": "virtual-staging",
"image_url": "https://cdn.example.com/rooms/4821-3.jpg",
"options": { "style": "scandinavian", "roomType": "living-room", "mode": "empty-room" },
"webhook_url": "https://app.example.com/hooks/roomagen"
}'
レンダリングが完了する前に、ステータス201でレスポンスが返されます。
{ "job_id": "3f1c9d4e-5b2a-4c8e-9f10-7d6a2b3c4e5f", "status": "processing", "images_charged": 1 }
Node.js 18+バックエンドからの同じ呼び出しは以下のようになります。
async function submitStagingJob(photo) {
const res = await fetch("https://api.roomagen.com/api/v1/jobs", {
method: "POST",
headers: {
"X-Api-Key": process.env.ROOMAGEN_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": `photo-${photo.id}-stage`, // 自身のレコードから導出し、ランダム値は避ける
},
body: JSON.stringify({
tool: "virtual-staging",
image_url: photo.signedUrl,
options: { style: photo.style, roomType: photo.roomType, mode: "empty-room" },
webhook_url: "https://app.example.com/hooks/roomagen",
}),
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
await db.query(
"INSERT INTO staging_jobs (photo_id, job_id, status, images_charged) VALUES ($1, $2, 'processing', $3)",
[photo.id, body.job_id, body.images_charged],
);
return body.job_id;
}
ステージングは他のツールよりも厳格です。styleは必須であり、オプションはcamelCaseで指定する必要があり、room_type、resolution、tier、customPromptを含む下記のリスト以外のキーは、invalid_requestとして拒否されます。ステージングは常に2Kでレンダリングされ、コストは画像1枚分です。
| オプション | 値 | デフォルト値 |
|---|---|---|
style(必須) |
modern、scandinavian、industrial、traditional、minimalist、bohemian、mid-century-modern、coastal、farmhouse、luxury、japandi、art-deco、mediterranean、またはモデルに選択させる場合はcustom |
なし |
roomType |
living-room、bedroom、kitchen、home-office、kids-room、terraceなど15種類 |
写真から推測 |
mode |
empty-roomは空室に家具を配置、restyleは家具付きの部屋を再コーディネート、recreateは別の部屋タイプとして再構築 |
empty-room |
furnitureMode、furniture |
ai、または"sectional sofa, floor lamp, rug"のようなリストを指定するmanual |
ai |
changeWalls、changeFloor |
trueにすると、モデルによる壁の塗り替えや床材の変更を許可 |
false |
これら3つのモードはRoomagenのWebアプリ内のステージングモードに対応しているため、コードを書く前にプロダクトチームが試してみることができます。空室向けにはバーチャルステージング、restyleには家具付きの部屋を再デザイン、recreateには部屋の用途変更が該当します。
何よりも先に永続化する。 自身のデータベースレコードに対応させてjob_idとimages_chargedを保存してください。Idempotency-Keyヘッダー(最大128文字、APIキーごとにスコープ)を使用することで、安全に再試行が可能になります。同じキーと同じリクエストボディを使用すると、追加課金されることなく元のジョブが返されます。クラッシュ後に再構築できるように、自身のレコードに基づいてキーを導出してください。そして、全く同じリクエストボディを再送してください。署名し直したimage_urlを含む、同じキーで異なるボディを送信すると、409 idempotency_conflictが返されます。
ステップ2: 完了処理 — Webhookとポーリングの比較
ジョブの完了を検知する方法は2つあり、本番環境の統合ではその両方を併用します。
| 項目 | Webhook(プッシュ) | ポーリング(プル) |
|---|---|---|
| レイテンシ | ジョブ完了後に送信され、こちらからのリクエストは不要 | 最大でポーリング間隔分。Roomagenは2〜5秒を推奨 |
| インフラ | 10秒以内に2xxを返す公開httpsエンドポイント | ワーカーまたはスケジューラー |
| 信頼性 | 少なくとも1回(at-least-once)。約36分間にわたって5回試行され、その後破棄 | ループを自身で制御可能 |
| 最適な用途 | 本番環境の大規模処理 | 開発、対話的な待機、データ照合 |
Webhookをメインとして使用し、セーフティネットとしてポーリングを使用します。 再試行ウィンドウが終了すると配信が破棄されるため、RoomagenのドキュメントではWebhookを「正規の記録システムではなく、最適化のための手段」と呼んでいます。ポーリング単体でもスケールしません。3秒間隔の場合、各ジョブにつき毎分20回のリクエストが発生するため、GET /v1/jobs/{id}の毎分300回という制限では、同時にポーリングできるジョブ数は約15件にとどまります。
エンドポイントの設定。 リダイレクトは追跡されないため、最終的なURLを使用して、ポータルのWebhookカードにhttpsエンドポイントを保存します。whsec_で始まる署名シークレットはパスワードのように安全に保管し、検証処理を正しく実装する間は、テストイベントを送信を使用してjob.test配信をテストしてください。ジョブごとのwebhook_urlでも同じシークレットが使用されます。
const crypto = require("crypto");
const express = require("express");
const app = express();
// グローバルのexpress.json()より前に、このルートでraw bodyを受け取るよう設定
app.post("/hooks/roomagen", express.raw({ type: "application/json" }), async (req, res) => {
const ts = req.get("X-Roomagen-Timestamp");
const sig = req.get("X-Roomagen-Signature");
if (!ts || !sig) return res.sendStatus(401);
const expected = "v1=" + crypto
.createHmac("sha256", process.env.ROOMAGEN_WEBHOOK_SECRET) // whsec_...
.update(`${ts}.`)
.update(req.body) // 再シリアライズしたJSONではなく、生のバイト列
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
if (sig.length !== expected.length || !fresh ||
!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.sendStatus(401);
}
const job = JSON.parse(req.body);
if (job.event === "job.test") return res.sendStatus(200);
// 冪等性: 最初の配信(またはポーリング)のみがレコードを"processing"から更新する
const { rowCount } = await db.query(
"UPDATE staging_jobs SET status = $1, result_urls = $2, error = $3 WHERE job_id = $4 AND status = 'processing'",
[job.status, job.result_urls, job.error, job.job_id],
);
if (rowCount === 1 && job.status === "completed") {
await queue.add("store-results", { jobId: job.job_id }); // リクエスト経路外でダウンロードを実行
}
res.sendStatus(200);
});
重要なポイントが4点あります。
- 生のバイト列に対して検証する。 ヘッダーは
v1=と{X-Roomagen-Timestamp}.{raw body}の16進HMAC-SHA256で構成されます。再シリアライズされたJSONでは一致しません。 - 一定時間比較を行い、鮮度を確認する。 Nodeの
timingSafeEqualは長さが異なると例外をスローするため、まず長さを比較します。約5分以上前のタイムスタンプを拒否することで、StripeのWebhookドキュメントに記載されているのと同様の防御手法でリプレイ攻撃をブロックできます。サーバーの時計は常に同期させておいてください。 - 素早く応答する。 Roomagenは2xxの応答を10秒間待ちます。タイムアウトを含むそれ以外の応答は試行失敗とみなされ、再試行されます。
- 冪等性を確保する。 配信は少なくとも1回(at-least-once)かつ順不同で行われ、ポーラーがすでにジョブを完了させている可能性もあるため、
job_idで重複を排除してください。
開発中や照合処理用のポーリングについて、Pythonの実装例はシンプルです。
import os, time, requests
API = "https://api.roomagen.com/api/v1"
HEADERS = {"X-Api-Key": os.environ["ROOMAGEN_API_KEY"]}
def wait_for_job(job_id, interval=3, max_wait=300):
deadline = time.time() + max_wait
while time.time() < deadline:
r = requests.get(f"{API}/jobs/{job_id}", headers=HEADERS, timeout=30)
r.raise_for_status()
job = r.json()
if job["status"] != "processing":
return job # "completed"または"failed"。どちらも最終状態
time.sleep(interval)
return None # 処理中: 照合プロセスに任せる
ジョブは、result_urlsを伴うcompleted、またはerrorに理由が記載され自動返金が行われるfailedのいずれかで終了します。レイテンシを監視するためにprocessing_msをログに記録してください。数分経過してもまだprocessingのままのジョブについては、1〜2分ごとに照合プロセスを実行します。タイマーが切れたからといって、遅延しているジョブを安易に失敗とマークしないでください。作成時に課金されており、後から完了する可能性があります。
ステップ3: 結果をユーザーに届ける
完了したジョブは、レンダリングされたJPEG画像の配列であるresult_urlsを返します。これらを直接リンク(ホットリンク)しないでください。
結果を再ホストする。 Roomagenは自社のストレージから結果を配信しますが、これはアカウントの保持期間ポリシーの対象となります。そのため、バックグラウンドジョブでジョブ完了後すぐに各画像をダウンロードし、自社のバケット(S3、R2、GCSなど)に書き込んで、自社のCDNから配信するようにしてください。そうすれば、画像がプロバイダーの保持ポリシーに依存することはなくなります。
出力の隣に元の写真を保持する。 元の写真とステージングされた画像を、紐付いたペアとして保存します。このペアによってビフォー / アフターのスライダーが動作し、ユーザーが元に戻せるようになり、物件掲載時の開示ルールが要求する要件も満たせます(ステップ4)。
生成のばらつきを想定する。 生成AIの出力にはばらつきがあり、ソファの選定が適切でない場合もあります。Roomagenは失敗したレンダリングを返金しますが、ユーザーが気に入らない結果は返金対象外であるため、再実行は別の画像コストがかかる新規ジョブとなります。各再実行には、photo-4821-stage-2のように独自のIdempotency-Keyを割り当ててください。最初のキーを再利用すると元のジョブが返されるか、ボディが変更されている場合は409が返されます。「やり直す」ボタンを用意し、そのコストをユーザーに見せるか、自社の料金体系に組み込むかを決定してください。
待機状態と失敗状態を設計する。 ステージングの処理には通常1分弱かかりますが、これはインターフェースの観点からは長い時間です。リリース前に、進行状況の表示状態、失敗状態(「レンダリングに失敗したため返金されました」)、および再試行アクションを設計してください。
ステップ4: データモデルに開示を組み込む
ユーザーがバーチャルステージングされた写真を物件広告に使用する場合、開示を行うことは法的義務であり、それが容易に行えるかどうかはデータモデルの設計にかかっています。RoomagenのAPIは開示ラベルの付与や元画像と編集後画像のペアリングを行わず、利用規約においても開示はユーザーの責任と定められているため、統合側でそれらを保持・処理する必要があります。
- 2026年1月1日施行のカリフォルニア州AB 723。 物件の売買広告においてデジタル処理で加工された画像を使用するブローカー、営業担当者、またはそれらの代理を務める者は、加工された旨を画像上または画像の隣に明記し、元の未加工の画像を表示する公開サイトへのリンク、URL、またはQRコードを付加しなければなりません。カリフォルニア州の不動産規制当局は、AIツールが誤解を招く広告を生み出した場合、責任は「技術プロバイダーではなく、ライセンシーおよびその責任ブローカーにある」と補足しています。
- 2027年1月1日以降のカリフォルニア州賃貸広告。 AB 2025により、同様の開示義務が賃貸広告にも拡大され、ライセンシーだけでなく住宅提供者なども対象となります。
- MLSルールによる配置の相違。 Canopy MLSではキャプションだけでなく画像そのものへのラベル表示が義務付けられている一方、NWMLSではグラフィックやテキストが重ね合わされた写真の掲載は認められていません。
- EU向けプロダクト。 2026年8月2日以降、EU AI法第50条に基づき、実在の場所や物体に似ており真正であると誤認させるような「ディープフェイク」画像を生成または操作するAIシステムの導入者(deployer)には、その旨を開示することが義務付けられています。不動産そのもののAI編集写真は、この定義に該当する可能性があります(詳しくはEU AI法第50条のガイドをご覧ください)。
したがって、開示情報はピクセルとしてではなくデータとして保存してください。元の写真の公開URL、使用したツールとオプションを含むalteredフラグ、配信先ごとの開示テキストとラベルの配置位置などを保持します。ラベルの描画は保存時ではなく、エクスポート時に行ってください。
| ツール | AB 723におけるデジタル加工画像の定義がどのように適用されるか |
|---|---|
virtual-staging |
指定要素である家具を追加: 開示し、元画像へリンク |
item-removal |
画像から要素を削除: 開示 |
virtual-renovation |
備え付け設備、床材、壁、または塗装の色(すべて指定要素)を変更: 開示 |
day-to-dusk |
照明の除外規定は物件の表現内容を変えない編集のみに適用され、新しいviewTypeは窓からの眺め(指定要素)を置き換えるため、慎重を期すなら開示が適切 |
image-enhancement |
照明、ホワイトバランス、色補正、露出は、物件の表現内容を変えない限り除外 |
floor-plan-to-3d |
間取り図は指定要素。レンダリング画像は写真ではなくイラストとして提示 |
これは開発者向けの概要であり、法的助言ではありません。詳細については、AB 723ガイドおよびMLS写真要件ガイドを参照してください。
本番環境における考慮事項: レート制限、再試行、およびクレジット管理
レート制限。 キーごとに、60秒間のスライディングウィンドウで適用されます。POST /v1/jobsは毎分60リクエスト、GET /v1/jobs/{id}は毎分300リクエスト、GET /v1/toolsおよびGET /v1/accountは毎分120リクエストです。さらに、同一NATアドレス配下の全サーバーで共有されるクライアントIPごとに毎分600リクエストの制限があります。成功時のレスポンスにはX-RateLimit-LimitとX-RateLimit-Remainingが含まれます。429 rate_limitedには秒単位のRetry-Afterが含まれるため、独自にバックオフを実装するのではなく、これに従ってください。一括処理の場合は送信をキューイングしてください。毎分60ジョブのペースであれば、500枚の写真は8分強で送信できます。
再試行とエラーコード。 すべてのエラーは{ "error": { "code", "message", "doc_url" } }という形式をとります。messageではなく、必ずcodeに基づいて分岐処理を行ってください。
| レスポンス | コード側で取るべき対応 |
|---|---|
400 invalid_request、invalid_tool |
リクエストを修正(オプション名、値、またはAPIスラッグではなくウェブサイト名を使用していないか確認)。変更せずに再試行しない |
400 invalid_image、image_fetch_failed |
画像を直接配信している公開https URLから、単一の画像ソースのみを送信 |
401 invalid_api_key、key_revoked |
担当者にアラートを発報。再試行はしない |
402 insufficient_credits |
ジョブは作成されていません。チャージした上で再試行 |
409 idempotency_conflict |
元のリクエストボディを再送するか、完全に新しいリクエストの場合は新しいキーを使用 |
413 payload_too_large |
image_urlへの切り替えを行い、X-Api-Keyヘッダーが送信されているか確認 |
429 rate_limited、500 internal_error |
待機(429の場合はRetry-Afterに従う)し、同じIdempotency-Keyで再試行 |
ジョブstatus: "failed" |
自動返金済み。一度再試行し、再度失敗する場合は写真を確認 |
失敗時のコスト構造。 生成中に失敗したジョブは自動的に返金されますが、ジョブのimages_chargedは書き換えられないため、残高の正確な情報源としてはGET /v1/accountを参照してください。プロバイダーを比較する際は、価格と併せて失敗時の返金ポリシーも確認してください。
クレジットの予算管理。 RoomagenのAPIは画像単位で課金され、開発者ポータルからパックを事前購入します。
| パック | 画像数 | 価格 | 1枚あたり |
|---|---|---|---|
| 無料付与(初回キー作成時、1回のみ) | 50 | $0 | — |
| Pilot | 500 | $125 | $0.25 |
| Growth | 2,500 | $550 | $0.22 |
| Scale | 10,000 | $2,000 | $0.20 |
| Volume | 50,000以上 | 要相談 | — |
パックに有効期限はなく、追加購入で残高が累積されます。ドキュメント化されている各ツールは、2Kでのレンダリング1回につき画像1枚分のコストがかかります。これに対応しているツールでresolution: "4K"を指定するとコストは2倍になりますが、ステージングは常に画像1枚分です。予算を立てる際は、再実行分も含めて計算してください。月間1,200枚の写真をステージングし、そのうち10枚に1枚の再実行が見込まれるプラットフォームでは、約1,320枚分の画像が必要となるため、Growthパックで約2ヶ月間賄える計算になります。
公開価格は大きく異なります(2026年10月確認時点)。ModelsLabは室内レンダリング1回につき$0.02、Decor8は全API操作で画像1枚につき$0.20、AI HomeDesignは年払いの場合で写真1枚あたり$0.24、月払いの場合は約$0.49となっています。単価だけでなく、ツールの対応範囲、Webhook、失敗時のポリシー、出力品質も比較検討してください。プロバイダーごとの比較については、バーチャルステージングAPI料金ガイドおよびステージングAPI比較で詳しく解説しています。
成熟度に関する率直な注意点。 RoomagenのAPIは比較的新しく、バージョン1は2026年8月30日に1つのジョブエンドポイントとともにリリースされ、対応するすべてのツールがドキュメント化されたのは2026年10月3日からです。そのため、最新の設計標準には準拠しているものの、長年にわたる公開実績があるわけではありません。破壊的変更がある場合は、リリース前にアクティブなキーを持つアカウントへメールで通知されます。下位互換性のある追加の変更は随時適用される可能性があるため、認識できないレスポンスフィールドは無視するように実装してください。
連携の拡張: ドキュメント化されているその他のツール
ステージングのループが機能したら、「夕景バージョン」や「不用品の片付け」ボタンの実装に必要なのは、toolとoptionsの変更だけです。
| ツール | スラッグ | オプション |
|---|---|---|
| 仮想リノベーション&リフォーム | virtual-renovation |
style(10種類)、roomType(8種類) |
| 写真補正 | image-enhancement |
intensity: light、medium(デフォルト)、heavy |
| デイトゥダスク 写真編集 & 夕暮れ変換 | day-to-dusk |
timeShift(0〜23時、デフォルト20)、viewType、season、hasWindows |
| 写真からAIで不要な物・オブジェクトを削除 | item-removal |
なし: 目立つ散らかりを片付ける場合はオプションを省略、特定の物を指定する場合はtier: "custom"とcustomPromptを送信 |
| 間取り図を3Dに | floor-plan-to-3d |
outputStyle、interiorStyle、furnitureMode、fp3dOutdoor、fp3dLabels、inputType |
これらのツールでは、resolution(2Kまたは4K)、tier(auto、guided、custom)、およびcustomPrompt(最大500文字)も受け付けます。ステージングとは異なり、未定義のキーは無視され、レスポンスのwarningsリストに記載されますが、許容範囲外の値は拒否されます。窓のない部屋の場合は、デイトゥダスクにhasWindows: falseを送信して、窓や外の眺めに関する指示をプロンプトから除外してください。
GET /v1/toolsは、お使いのキーで呼び出し可能なすべてのスラッグを画像コストとともに返します。返されるすべてのスラッグはドキュメント化されています。値をハードコードするのではなくこのリストを読み出すようにしてください。また、roomagen.com上のツール名はAPIスラッグとは異なることに注意してください。
このAPIで対応していないこと
- 一括エンドポイントの非提供。 1つのジョブは、1つのツールを通す1枚の画像です。Webアプリの一括処理はAPIには含まれていないため、レート制限の範囲内でジョブをキューイングしてください。
- 開示ラベルの非付与。 出力画像には開示ラベルやビフォー/アフターのペアは含まれません。アカウントがパックを購入するまでレンダリング結果には透かしが入り、購入後はRoomagenのブランディング表示は一切なくなります。
- 無料での再生成の非提供。 再実行は新規ジョブとして扱われ、同様に課金されます。
- 寸法測定やCADファイルの非提供。 出力はJPEG画像であり、寸法データ、ベクター、DWGファイルではありません。写真からの部屋の寸法計測が必要な場合、画像生成APIは適切なツールではありません。
- 出力の完全な保証の非提供。 生成モデルは不自然な描写や不正確な描写を生み出す可能性があるため、物件情報に掲載する前に出力を目視確認してください。
- アプリ専用機能の非提供。 修正、ライブラリ、デザインコンパニオンのチャット機能は、RoomagenのWebアプリ専用です。
ステージングAPI連携でよくあるミス
- リクエストスレッドのブロック。 ジョブのレンダリング中にユーザーのリクエストを開いたまま保持すると、ロードバランサーのタイムアウトが発生します。自身のAPIからは
202 Acceptedを返し、クライアントにはプッシュ通知などで更新を伝えてください。 - 誤ったオプション名の指定。 ステージングジョブで
room_typeやresolutionを指定するとinvalid_requestが返されます。ステージングでは、定義されたリスト内のcamelCaseキーが必要であり、styleは常に必須です。 - Webhookのみへの依存。 約36分間の再試行の後、Roomagenは送信を停止します。照合プロセスがない場合、そのジョブは永久に「processing」のままになります。
- 不適切な署名検証。 パースされたJSONのハッシュ化、タイムスタンププレフィックスの欠落、
===による比較、鮮度チェックの省略などは、すべて検証強度を低下させます。 - リダイレクトされるWebhook URL。 通常のhttpやプライベートホストは事前に
webhook_url_rejectedで拒否され、リダイレクトは追跡されません。そのため、末尾のスラッシュやwwwへのリダイレクトがあると、すべての配信が失敗します。 - ランダムな冪等性キーや再署名されたURLの使用。 保存していないキーは再利用できないため、再試行時に再度課金されてしまいます。同じキーで再署名された
image_urlを送信すると、409が返されます。 - 結果URLの直接リンク(ホットリンク)。 結果はプロバイダーの保持ポリシーに従います。完了時に自社環境へ再ホストしてください。
- すべての配信先に同一の透かしを使用すること。 画像自体に「Virtually Staged」(バーチャルステージング済み)と焼き込まれたラベルは、テキストの重ね合わせを禁じるMLSルールに抵触する可能性があり、また元画像へのリンクがなければ、それ単体ではAB 723の要件を満たしません。
リリース前チェックリスト
- APIキーはサーバー側のみに保管され、環境ごとに1つずつ用意されている。
- ステージングリクエストには常に
styleが含まれ、ステージングのオプションリスト外のパラメータは送信されていない。 - すべてのジョブに自身のレコードから導出された
Idempotency-Keyが付与されており、再試行時には元のリクエストボディが再送される。 - Webhookエンドポイントは最終的なhttps URLであり、生のボディに対して
v1=署名を検証し、古いタイムスタンプを拒否し、10秒以内に応答する。 - ポータルからの
job.test配信の検証に成功している。 - 数分経過しても処理中のままのジョブを確認する照合プロセスが動作している。
- 結果画像が再ホストされ、それぞれの元画像と並んで保持されている。
- 開示データ(元画像のURL、加工フラグ、配信先ごとのラベル)がすべてのエクスポート経路に引き継がれている。
- 残高不足アラートが
image_creditsを監視しており、すべてのエラーコードがユーザー向けの分かりやすいメッセージにマッピングされている。
まとめ: まずは基本ループをリリースし、それから拡張する
アプリにバーチャルステージングを導入するのは小規模な連携で済みます。冪等性キーを付けた1つのPOSTリクエスト、照合処理を備えた検証済みのWebhookハンドラー、そして結果の隣に元の写真を保持するストレージ処理だけです。正常系のコードは数十行にすぎず、作業の大半は本番向けの堅牢化と開示データの取り扱いです。また、非同期送信、プッシュとプルを組み合わせた完了検知、結果の再ホスト、元画像と出力画像のペア管理といった設計は、特定のベンダーに依存せず、あらゆるステージングAPIに適用できます。
今回の実例に沿って構築を進めるには、Roomagen APIキーを取得してください。最初のキーには50枚分の無料画像が含まれており、詳細についてはクイックスタート、Webhookガイド、およびエラーリファレンスで解説されています。この同じジョブ処理ループを一度構築すれば、1つの統合の背後でバーチャルステージング、デイトゥダスク 写真編集 & 夕暮れ変換、写真からAIで不要な物・オブジェクトを削除、写真補正、仮想リノベーション&リフォーム、間取り図を3Dにの各機能を動作させることができます。
出典・参考文献
- 1.California Legislature – AB 723法案本文(Business and Professions Code §10140.8)
- 2.California DRE – カリフォルニア州不動産における人工知能(通知、2026年3月17日)
- 3.California Apartment Association – 加工された賃貸広告に対するAB 2025開示規則(2027年1月1日施行)
- 4.Canopy MLS – 物件画像:手順とよくある質問
- 5.NWMLS – 不動産写真撮影の基本101
- 6.EU AI Act – 第50条:提供者および導入者(deployer)に対する透明性の義務
- 7.Stripe Docs – Webhookイベントの受信(署名検証とリプレイ保護)
- 8.ModelsLab – インテリアデザインAPI(1レンダリングあたり$0.02)
- 9.Decor8 AI – 料金プラン(API:画像1枚あたり$0.20)
- 10.AI HomeDesign – B2BおよびAPIプラン
よくある質問
著者
Roomagen Team
Roomagenチームは、AIバーチャルステージング、不動産写真、物件マーケティング戦略に関する詳細なガイドを作成しています。






