リファインメントは、プロダクト発見を対話形式に変える仕組みです。最初の brief または wholesale による発見の後、buying_mode: "refine" を使って特定のプロダクトやプロポーザルを繰り返し改善できます。選択内容の調整、変更のリクエスト、代替案の探索などを行ってから、create_media_buy で確定します。
リファインメントのライフサイクル
典型的なメディアバイのワークフローは以下のパターンに従う:
discover → refine → refine → ... → buy
-
Discover —
buying_mode: "brief" または "wholesale" で get_products を呼び出し、マッチするインベントリを見つける。セラーはプロダクト(オプションでプロポーザルも)を返します。
-
Refine —
buying_mode: "refine" と変更リクエストの refine 配列を指定して get_products を呼び出す。各エントリはスコープと、バイヤーが求める内容を宣言します。セラーは更新された価格と設定を持つプロダクトを返します。
-
Repeat — 必要な回数だけリファインを繰り返します。各呼び出しは独立しており、ステートレスです。
-
Buy — 満足したら、
create_media_buy で最終的な選択を実行します。
リファインメントは必須ではありません。シンプルなキャンペーンは発見から購入へ直接進むことができます。ただし、複数のプロダクトを含むキャンペーン、予算配分を含むプロポーザル、または反復的な交渉が必要な場合、リファインメントこそが価値を生む場面です。
refine 配列
refine 配列は変更リクエストのリストです。各エントリは scope と、バイヤーが求める内容を宣言する:
| スコープ | 目的 | 必須フィールド |
|---|
request | 選択全体に対する方向性 | ask |
product | 特定のプロダクトへのアクション | id, action |
proposal | 特定のプロポーザルへのアクション | id, action |
refine 配列には少なくとも1つのエントリが必要です。セラーはレスポンスを構成する際にすべてのエントリを総合的に考慮し、refinement_applied を通じて各エントリに返答します。
プロダクトアクション
プロダクトスコープのエントリは明示的なアクションを宣言する:
| アクション | 動作 | ask |
|---|
include | このプロダクトを更新された価格とデータで返す | オプション — リクエストする具体的な変更(例: “add 16:9 format”) |
omit | このプロダクトをレスポンスから除外する | 無視される |
more_like_this | このプロダクトに類似した追加のプロダクトを見つける。元のプロダクトも返されます。 | オプション — 「類似」の意味(例: “same audience but video format”) |
{
"buying_mode": "refine",
"refine": [
{ "scope": "product", "id": "prod_video_premium", "action": "include", "ask": "add 16:9 format option" },
{ "scope": "product", "id": "prod_display_ros", "action": "omit" },
{ "scope": "product", "id": "prod_native", "action": "more_like_this", "ask": "same audience but video format" }
]
}
リクエストレベルの方向性
scope: "request" を使って、選択全体に対して求める内容を記述する:
{
"buying_mode": "refine",
"refine": [
{ "scope": "request", "ask": "good selection but I want more video options and less display" },
{ "scope": "product", "id": "prod_video_premium", "action": "include" },
{ "scope": "product", "id": "prod_display_ros", "action": "include" },
{ "scope": "product", "id": "prod_native", "action": "include" }
]
}
セラーはこの方向性に基づいてプロダクトを追加・削除・再バランスしてもよい。refine 配列で参照されていないプロダクトも、セラーが方向性に合うと判断した場合はレスポンスに含まれることがあります。
優先順位: プロダクト個別のアクションはリクエストレベルの方向性より優先されます。リクエストレベルで「ディスプレイを減らして」と指定していても、特定のプロダクトに action: "include" が設定されていれば、そのプロダクトは必ず返されます。
プロポーザルのリファインメント
プロポーザルを ID で参照して、調整や削除をリクエストする:
{
"buying_mode": "refine",
"refine": [
{ "scope": "product", "id": "prod_video_premium", "action": "include" },
{ "scope": "product", "id": "prod_display_ros", "action": "include" },
{ "scope": "proposal", "id": "prop_balanced_v1", "action": "include", "ask": "shift 20% from display to video" }
]
}
スコープの組み合わせ
すべてのスコープは組み合わせて使える。1回のリファインメント呼び出しで、選択への方向性の設定、特定プロダクトへのアクション、プロポーザルへの変更リクエストを同時に行うことができる:
{
"buying_mode": "refine",
"refine": [
{ "scope": "request", "ask": "increase emphasis on video across the plan" },
{ "scope": "product", "id": "prod_video_premium", "action": "include" },
{ "scope": "product", "id": "prod_display_ros", "action": "include" },
{ "scope": "product", "id": "prod_native", "action": "omit" },
{ "scope": "product", "id": "prod_audio_spot", "action": "include" },
{ "scope": "proposal", "id": "prop_awareness_q2", "action": "include", "ask": "reallocate native budget to video products" }
],
"filters": {
"budget_range": { "min": 200000, "max": 200000, "currency": "USD" }
}
}
セラーのレスポンス
バイヤーが refine 配列を送信すると、セラーは refinement_applied で応答します。これはバイヤーの変更リクエストと位置が一致する配列です。各エントリはリクエストが満たされたかどうかを報告する:
| フィールド | 型 | 必須 | 説明 |
|---|
scope | string | No | 対応する refine エントリのスコープをエコーします。オーケストレーターがアライメントをクロスバリデーションするために使用できます。 |
id | string | No | 対応する refine エントリの id をエコーする(プロダクトおよびプロポーザルスコープの場合)。 |
status | string | Yes | "applied": リクエスト充足。"partial": 部分的に充足。"unable": 充足できなかった。 |
notes | string | No | セラーの説明。"partial" または "unable" の場合に推奨されます。 |
{
"products": ["..."],
"proposals": ["..."],
"refinement_applied": [
{ "scope": "request", "status": "applied", "notes": "Added 3 video products. No CTV inventory for those dates." },
{ "scope": "product", "id": "prod_video_premium", "status": "applied" },
{ "scope": "product", "id": "prod_display_ros", "status": "applied" },
{ "scope": "product", "id": "prod_native", "status": "applied" },
{ "scope": "product", "id": "prod_audio_spot", "status": "partial", "notes": "16:9 not available for this placement — returning 4:3 and 1:1" },
{ "scope": "proposal", "id": "prop_awareness_q2", "status": "applied", "notes": "Shifted 22% to video (nearest allocation boundary)" }
]
}
refinement_applied 配列は refine 配列と同じ数のエントリを同じ順序で含まなければなりません(MUST)。エントリはクロスバリデーションのために scope と id をエコーすべきだ(SHOULD)。このフィールド全体はオプションであり、リクエストごとの結果を追跡しないセラーは省略してもよい。
よくあるリファインメントパターン
類似プロダクトを見つける
more_like_this を使って、気に入ったプロダクトに類似したプロダクトを発見します。セラーは元のプロダクトに加えて、その特性に合った追加の選択肢を返します:
{
"buying_mode": "refine",
"refine": [
{ "scope": "product", "id": "prod_video_premium", "action": "more_like_this", "ask": "same premium audience but different formats" }
]
}
フィルターを調整します
リファインリクエストのフィルターは、差分ではなく完全な目標状態を表します。適用したいフィルターセット全体を常に送信すること:
{
"buying_mode": "refine",
"refine": [
{ "scope": "product", "id": "prod_video_premium", "action": "include" },
{ "scope": "product", "id": "prod_display_ros", "action": "include" }
],
"filters": {
"start_date": "2026-04-01",
"end_date": "2026-06-30",
"budget_range": { "min": 150000, "max": 150000, "currency": "USD" }
}
}
プロポーザルを絞り込む、または拡張します
プロダクトエントリは、セラーがプロポーザルに対して考慮すべきプロダクトを定義します。プロポーザルエントリと組み合わせることで、プロポーザルのプロダクトセットを絞り込んだり拡張したりできる:
{
"buying_mode": "refine",
"refine": [
{ "scope": "product", "id": "prod_video_premium", "action": "include" },
{ "scope": "product", "id": "prod_display_ros", "action": "include" },
{ "scope": "proposal", "id": "prop_balanced_v1", "action": "include", "ask": "rebalance for just these two products" }
]
}
リファインモードにおけるプロポーザル
セラーはバイヤーがプロポーザルエントリを含めなかった場合でも、リファインされたプロダクトと一緒にプロポーザルを返してもよい(MAY)。例えば、3つのプロダクトをリファインしているバイヤーが、それらのプロダクトを更新された価格で受け取ると同時に、それらを組み合わせる方法を提案するプロポーザルも受け取ることがあります。
重要なポイント:
- プロポーザルは保証されない。 セラーはリファインモードでプロポーザルを生成することを要求されない。配分とキャンペーン最適化は主にオーケストレーター(バイヤーサイドエージェント)の責任です。
- リクエストレベルの ask で関心を示します。
{ "scope": "request", "ask": "suggest how to combine these products" } を含めることで、プロポーザルを歓迎することを示せる。
- 求めていないプロポーザルはリファインするか無視できます。 セラーがリクエストしていないプロポーザルを返した場合、フォローアップ呼び出しでリファインするか、単純に無視して
create_media_buy でパッケージを手動で構築することができます。
パブリッシャーは通常、バイヤーが自身でターゲティングと配分を指示する wholesale モードではプロポーザルを省略します。
ステートレス性
buying_mode: "refine" を使った各 get_products リクエストは独立しています。各リクエストの refine 配列と filters がリファインメントの意図を完全に指定します。セールスエージェントはトランスポートレベルのセッション状態(例: 前のリクエストで送信された内容を記憶すること)に依存してはなりません(MUST NOT)。
セラーは引き続き独自のプロダクトおよびプロポーザルレジストリを管理します。「ステートレス」とは、プロトコル交換が呼び出し間で暗黙的な状態を持たないことを意味します。
この設計により以下が可能になる:
- ステートレス実装 — セラーはリファインメントセッションを追跡する必要がない
- 安全なリトライ — 失敗したリファインメント呼び出しは同じパラメーターで再試行できます
- 並列探索 — オーケストレーターが複数のリファインメントパスを同時に探索できます
クライアントバリデーション
オーケストレーターはリファインメントリクエストを送信前にバリデーションすべきだ(SHOULD):
- 空でない refine —
refine 配列には少なくとも1つのエントリが必要です。空の [] はスキーマバリデーションで拒否されます。
- 有効なエントリ — 各プロダクトエントリには
scope、id、action(include、omit、more_like_this)が必要です。各プロポーザルエントリには scope、id、action(include または omit)が必要です。リクエストレベルエントリには scope と ask が必要です。
- フィルターは絶対値 — 前のリクエストからの差分ではなく、適用したいフィルターセット全体を送信すること。
クライアント実装は送信前にリクエストスキーマに対してリファインメントリクエストをバリデーションすべきだ(SHOULD)。
エラーハンドリング
| エラーコード | 発生条件 | 対処法 |
|---|
PRODUCT_NOT_FOUND | 参照されたプロダクト ID の1つ以上が不明または期限切れ | 無効な ID を削除して再試行するか、brief リクエストで再発見する |
PROPOSAL_EXPIRED | 参照されたプロポーザル ID が expires_at を過ぎている | 新しい brief または wholesale リクエストで再発見する |
INVALID_REQUEST | brief または wholesale モードで refine が指定された、refine 配列が空、または必須フィールドが欠落している | buying_mode と必須フィールドを確認する |
規範的要件
メディアバイ仕様 はリファインメントに関して以下の規範的要件を定義している:
オーケストレーター:
buying_mode が "refine" の場合、refine を含めなければなりません(MUST)
buying_mode が "brief" または "wholesale" の場合、refine を含めてはなりません(MUST NOT)
- 各プロダクトおよびプロポーザルエントリに
scope、id、action を提供しなければなりません(MUST)
- 1つの
refine 配列に同じプロダクト ID またはプロポーザル ID を持つ複数のエントリを含めてはなりません(MUST NOT)
セールスエージェント:
action: "omit" のプロダクトをレスポンスから除外しなければなりません(MUST)
action: "omit" のプロポーザルをレスポンスから除外しなければなりません(MUST)
action: "include" のプロダクトを更新された価格で返さなければなりません(MUST)
action: "include" のプロダクトエントリの ask を満たすべきだ(SHOULD)
action: "more_like_this" のプロダクトに類似した追加のプロダクトを元のプロダクトと共に返すべきだ(SHOULD)
- レスポンスを構成する際にリクエストレベルの ask を考慮すべきだ(SHOULD)。これにより、明示的に参照されたプロダクト以外の追加プロダクトが含まれることがある(MAY)。プロダクト個別のアクションはリクエストレベルの方向性より優先されます。
action: "include" のプロポーザルエントリの ask を満たすべきだ(SHOULD)
- バイヤーが
refine を提供する場合、位置で一致した1エントリあたりの変更リクエストを持つ refinement_applied をレスポンスに含めるべきだ(SHOULD)
- バイヤーがプロポーザルエントリを含めなかった場合でもプロポーザルを返してもよい(MAY)
関連情報