この形状の理由。 ターゲティング、価格、キュレーションは一度の往復に折り込まれています——ブリーフがディスカバリーを駆動し、パブリッシャーはそれに対してキュレーションし、
pricing_options が確定価格を運び、バイヤーは pricing_option_id を通じてそれにコミットします。プロダクトと購入作成の間に別個の get_price_quote ステップを設けることは却下しました: それは一つの専門的判断を二つの不十分に規定された判断に分割し、ブリーフ→キュレーションの契約を壊します。反復は新しいタスクではなく、型付きの変更配列を伴う buying_mode: "refine" です。→ 設計原則: ブリーフがディスカバリーを駆動する。/schemas/v3/media-buy/get-products-request.json
Response Schema: /schemas/v3/media-buy/get-products-response.json
クイックスタート
自然言語のブリーフでプロダクトを検索:構造化フィルターの利用
ブリーフの代わりに(または併用して)構造化フィルターを使うこともできます。brief モードでは、フィルターはパブリッシャーのキュレーションに対するハード制約として機能します。ブリーフが意図を表し、フィルターが要件を強制します。
リクエストパラメーター
プロパティガバナンス
property_list フィルターは、プロパティガバナンスエージェント上で create_property_list を通じて作成されたプロパティリストを参照します。プロパティリストは、どのパブリッシャープロパティがコンプライアンス要件を満たすか——COPPA 認証済みサイト、サステナビリティスコア付き在庫、ブランドセーフなパブリッシャーなど——を定義します。プロパティリストフィルタリングを使うには:- プロパティガバナンスエージェントで
get_adcp_capabilitiesを呼び出し、利用可能なproperty_featuresを発見する - 機能要件を指定して
create_property_listでプロパティリストを作成する - 得られた
property_list_idをget_productsに渡して在庫をフィルタリングする
get_adcp_capabilities で features.property_list_filtering: true を宣言しなければなりません。完全なワークフローはプロパティガバナンス概要を参照してください。Filters オブジェクト
プレースメントフィールド
get_products は、セラーが placements を含める、またはバイヤーが fields で要求した場合に、プロダクトのプレースメントデータを返します。プレースメント ID はパブリッシャースコープです。プロダクトのプレースメントは、パブリッシャーの宣言が存在する場合、パブリッシャーの公開 adagents.json のプレースメント宣言を {publisher_domain, placement_id} で参照すべきです。セラー非公開のプレースメント ID、ソース/オリジンの詳細、配信システムのマッピングはレスポンスに含めてはなりません。
返される各プレースメントは以下を持ちうる:
パブリッシャーは、
adagents.json の authorized_agents[].placement_ids または authorized_agents[].placement_tags を使って、特定のパブリッシャープレースメントに対してセラーエージェントを認可できます。セラーは、自身が販売を認可されたパブリッシャー参照のプレースメントのみを返すべきです。
シグナルターゲティングフィルターの例:
通貨フィルタリング
バイヤーの制約が「取引可能なメディア価格を持つプロダクトのみ表示」の場合はfilters.pricing_currencies を使います。バイヤーが予算額やレンジも提供する場合は budget_range.currency を使います。
バイヤーは両方を送ってもよい(MAY)。セラーはそれらを論理積で適用します: budget_range.currency は予算額を建て、pricing_currencies はどの返却プロダクト pricing_options が対象かを絞ります。二つのフィールドが競合する場合、セラーは競合のみを理由にリクエストを拒否するのではなく、マッチするプロダクト0件を返すべきです(SHOULD)。プロダクトスコープのシグナル価格は別個のアドオン面であるため、このフィルターは必須のセラー適用シグナル課金のみをゲートします。任意のシグナル/ベンダーのアドオンは他通貨を広告してもよく、バイヤーは非対応のアドオン価格を選択すべきではありません。
is_fixed_price と組み合わせる場合、返却プロダクトの pricing_options は両方のフィルターを満たさなければなりません(MUST): 要求時にオプションは固定価格であり、その currency は pricing_currencies に含まれていなければなりません。
通貨のみのフィルター例:
pricing_currencies: ["USD"] を送ると、セラーはそのプロダクトを USD のプロダクトレベル pricing_options のみで返します。プロダクトが固定またはその他必須のプロダクトスコープのシグナル課金も持つ場合、その必須課金は USD で価格付けされているか、増分価格を持たないかのいずれかでなければならず、そうでなければプロダクトはフィルターにマッチしません。currency のない必須の custom シグナル価格は、セラーが正当に増分価格なしと扱える場合を除き、このフィルターでは満たせません。任意のシグナルアドオンはプロダクトのマッチングに影響しません。
Budget Range オブジェクト
*
min または max のいずれか一方は必ず指定しなければなりません。
Refine 配列
refine 配列は変更依頼のリストです。各エントリは scope と、バイヤーが求める内容を宣言します。少なくとも 1 エントリが必要。セラーはすべてのエントリをまとめて考慮してレスポンスを構成し、refinement_applied で各エントリに返答します。
各エントリは scope による判別共用体です。
scope: “request”
scope: “product”
scope: “proposal”
refinement_applied(レスポンス)
セラーがrefine 配列を受け取ると、レスポンスには位置でマッチする refinement_applied 配列が含まれます。各エントリは依頼が fulfilled されたかを報告します。
カタログによる探索
カタログアイテムを宣伝できる広告プロダクトを探すにはcatalog を渡します。セラーはカタログアイテムをインベントリに照合し、マッチが存在するプロダクトを返します。すべてのカタログ種別に対応しています。商品カタログはスポンサー商品枠を探し、求人カタログは求人広告プロダクトを、フライトカタログはダイナミックトラベル広告を探す。
catalog フィールドは AdCP 全体で使われる同じ Catalog オブジェクトを使います。catalog_id で同期済みカタログを参照したり、インラインでアイテムを指定したり、セレクターでフィルタリングしたりできます。
レスポンスのプロダクトには
catalog_types(対応するカタログ種別)と catalog_match(マッチしたアイテム)が含まれます。
レスポンス
products 配列と、必要に応じて proposals を返します。
Products 配列
非 URL 在庫向けのパブリッシャープロパティ
publisher_properties[].publisher_domain は、パブリッシャーの adagents.json 名前空間を固定するドメインです。広告が表示される URL である必要はなく、物理的な会場、刊行物、放送局、スクリーンネットワーク、印刷媒体のプレースホルダーでもありません。
デジタル/非デジタルのプロダクトで同じセレクター形状を使います:
- デジタルプロパティ:
publisher_domainは通常、ウェブサイト、アプリ、チャンネル、CTV プロパティをadagents.jsonで宣言するパブリッシャードメインです。 - 印刷、静的 OOH、ラジオ、映画館、ローカル TV:
publisher_domainは権威あるプロパティカタログを公開する運営パブリッシャーまたはネットワークのドメインです。実際の在庫はproperty_ids、property_tags、プレースメント、コレクション、プロダクトメタデータ、チャンネルフィールドで識別されます。 - 集約ネットワーク: プロダクトが多数のプロパティ(会場、刊行物、スクリーン、放送局、ローカル市場のタグ付き集合など)にまたがる場合は
property_tagsを使います。
publisher_domain に "print" や "ooh" のような値を作り出してはなりません。チャンネルの意味は channels に、プロパティの意味は参照先のプロパティ宣言に、販売可能なパッケージの意味はプロダクト自体に置きます。
例えば、タグ付けされたメトロプロパティにまたがるプロダクトは、publisher_properties 配列内でこのセレクターを使えます:
Proposals 配列(任意)
パブリッシャーはプロダクトと併せてプロポーザル(予算配分付きの構造化メディアプラン)を返すことがあります。詳細は Proposals を参照。
各
ForecastPoint は1つの予測行です。複合スライスは、同じポイント上の複数の dimensions[] 項目(例: placement × country)でエンコードされます。兄弟ポイントはネストされた子ではなく並列の行です。ディメンションの順序に意味はありません。バイヤーは (forecast_range_unit, budget があれば, product_id があれば, kind でソートした dimensions) から行の同一性を正規化します。バイヤーは同じ粒度の行を比較してもよいですが、返された行が完全で重複のないパーティションを形成するとセラーが文書化しない限り、それらを合計してはなりません(MUST NOT)。標準の配信レポートは、正確なディメンション横断の交差ではなく、一次元の周辺分布を検証します。
ページネーション
pagination はすべての get_products モードで有効ですが、その意味は購入モードに従います:
briefモードでは、ページネーションはブリーフに対するセラーのキュレーション回答を上限設定します。ページは、ブリーフの文言にマッチするすべてのプロダクトが列挙されたという約束ではありません。refineモードでは、ページネーションはrefine配列と現在のフィルターが示す絞り込み後のproducts[]結果を上限設定します。プロポーザルはプランメタデータとしてページに付随する場合がありますが、pagination.max_results・has_more・cursor・total_countはプロダクト結果セットにスコープされ、別個のプロポーザルリストや、プロダクト/プロポーザルの合算数にはスコープされません。wholesaleモードでは、ページネーションはホールセール・プロダクトフィードを辿ります。これは網羅的/フィード形式の読み取りで、ホールセールフィードバージョニングと組み合わさるモードです。
ページネーションは任意です。省略した場合、サーバーは完全な結果セット(またはサーバーが選択したデフォルトページ)を返します。レスポンスに
pagination.has_more: true が含まれる場合、更新された pagination.cursor を除いて同じ結果定義リクエストコンテキストを用い、次のリクエストで pagination.cursor を渡して次のページを取得します。
レスポンスメタデータ
filter_diagnostics
セラーが除外を特定のフィルターに帰属できる場合、レスポンスはfilter_diagnostics ブロックを含んでもよい(MAY)。これは可観測性であり、エラー報告ではありません——セラーは filter-not-fail の慣習に従って、マッチしないプロダクトを引き続き暗黙に除外します。バイヤーはこれを、その存在に依存せずに空/小さい結果をトリアージするために使います。total_candidates と excluded_by は独立して任意です——ベースライン候補セットのサイズが機密なセラーは、total_candidates なしで excluded_by を出してもよい(MAY)。
incomplete 配列
time_budget 内(またはセラー自身の内部制限により)すべての作業を完了できない場合、レスポンスには欠けている内容を宣言する incomplete 配列が含まれます。バイヤーは estimated_wait を使って、より大きな予算でリトライするかどうかを判断できます。
ホールセールフィードバージョニング
セラーのホールセール・プロダクトフィードを同期したばかりのバイヤーは、フィードのサイズに関わらず、一度の安価な呼び出しで「バージョン X 以降に何か変わったか?」を尋ねられます。セラーはすべてのホールセールモードレスポンスで不透明なwholesale_feed_version を返します。バイヤーは次の呼び出しで if_wholesale_feed_version を通じてそれを返し、セラーは unchanged: true でショートサーキットしてもよい(MAY)——プロダクトペイロードもページごとの差分もなし。HTTP の ETag / If-None-Match を踏襲しています。
これは get_products が返すセラー側のホールセール・プロダクトフィードです。sync_catalogs のフィードではありません。sync_catalogs はセラーアカウント上のバイヤー提供のキャンペーン入力フィードを管理します。
unchanged レスポンスの例:
リクエスト:
test=false
- トークンは不透明です。フォーマットも順序も検査もなし。
- 返された
wholesale_feed_versionは、それを生成したリクエストパラメータにスコープされます。バイヤーは、使用した(account, filters, buying_mode, property_list, catalog)タプルとともにバージョンをキャッシュしなければなりません(MUST)。 pricing_versionは任意のより細かいトークンです: 存在する場合、価格が動くと変わりますがwholesale_feed_versionは構造/メタデータが動くときのみ変わります。プロダクトメタデータを変えないレートカードの一括更新でよくあります。if_pricing_versionはif_wholesale_feed_versionを要求します。 価格はそれ自体の構造的ベースラインを持ちません。if_wholesale_feed_versionなしでif_pricing_versionを送るのはスキーマレベルのエラーです。セラーの評価は二段階です: ホールセールフィードの不一致は完全なペイロードを返し(価格は暗黙に古い)、ホールセールフィード一致で価格不一致も完全なペイロードを返し(バイヤーが更新後のpricing_optionsを見られるように)、両方一致でunchanged: true。filtersの正準化。 セラーはfiltersオブジェクトをwholesale_feed_versionのキー空間へハッシュする前に正準化済みとして扱わなければなりません(MUST): キーは辞書順にソートしなければならず(MUST)、省略された値とデフォルト値は同一に扱わなければならず(MUST。delivery_typeキーの欠如はdelivery_type: nullと同じスコープ)、配列値はフィルターがセット意味論を持つ場合はソートしなければならず(MUST。例:channels,format_ids,required_metrics)、シーケンス意味論を持つ場合は順序を保持しなければなりません(例:preferred_delivery_types)。等価だが形状の異なるフィルターオブジェクトを渡すバイヤーは、セラーから同じwholesale_feed_versionを受け取らなければなりません(MUST)。このルールは、バイヤー SDK 間のキー順やデフォルト省略の違いによる、静かな古いミラーのバグを防ぎます。前方互換のデフォルト: 3.x マイナーバージョンで追加される新しいフィルターフィールドは、スキーマでセット vs シーケンスの意味論を宣言しなければなりません(MUST。x-canonicalization: set | sequenceまたは同等の記述で)。明示的な宣言がない場合、ルールはセット意味論(ハッシュ前にソート)をデフォルトとします。このデフォルトでドリフトするセラーや SDK は、消費者が説明できないキャッシュミスを生みます。- ページネーションとの相互作用。
wholesale_feed_versionは個々のページではなくホールセール・プロダクトフィード全体を表します。wholesale_feed_versioning.supported: trueを宣言するセラーは、(最初のページだけでなく)すべてのページネーションページでwholesale_feed_versionを返さなければなりません(MUST)。バージョニングを宣言しないセラーも同様にすべきです(SHOULD)。ページ間でホールセールフィードが変化した場合、新しいバージョンが次のページで現れ、バイヤーはcursor: nullからページネーションを再開しなければなりません(MUST)——既に受け取った部分ページは古いバージョンを表します。セラーは代わりに、ページネーション開始時にフィードをスナップショットし、すべてのページを元のバージョンでそのスナップショットから提供してもよい(MAY)。あるページ上のwholesale_feed_versionがそのページが属するバージョンである限り、どちらの実装も適合です。 unchanged: trueと進行中のページネーション。cursor: Xでページネーション中のバイヤーは、これまでのページが引かれたバージョンに一致するif_wholesale_feed_versionを送ってもよい(MAY)。セラーがunchanged: trueを確認すると、レスポンスはproducts[]とページネーションエンベロープを完全に省略します。バイヤーは、そのバージョンの下でさらなるページが新しいデータを生まないと確信して、進行中のウォークを中止します。セラーは、アクティブなページネーション内の個々のページをスキップするために条件付きフェッチのショートサーキットを使ってはなりません——unchangedはフィード対キャッシュ済みバージョンであり、ページごとではありません。if_wholesale_feed_versionを無視する v3.1 以前のセラーは、単に完全なペイロードを返します——意味的には正しく、非効率なだけです(HTTP の unchanged-server パスと同じ)。
specs/wholesale-feed-webhooks.md を参照してください。ホールセールフィード Webhook は、変更されたプロダクトペイロード、価格ペイロード、削除トゥームストーン、または一括変更サマリーを運びます。get_products は修復と照合のための読み取りのままです。
キャッシュレイヤリング
セラーは二つの概念的レイヤーを公開します: パブリックレイヤー(レートカード/構造ビュー)とアカウントごとのオーバーレイ(カスタムディール、アカウント固有のレートカード)。条件付きフェッチの経路はcache_scope を通じてレイヤーを認識します。
なぜ重要か。 あるセラーで N アカウントにわたってホールセールプロダクトをミラーするバイヤーは、実際にはすべてのバイヤーで同一の在庫を N コピー持ちたくありません。パブリックレイヤーはセラーの公開レートカードで、ほとんどのセラーのほとんどのアカウントはそこから直接価格を付けます。プレミアムなカスタムディールが例外です。
二層キャッシュ。
振る舞い。
accountなしのリクエストは常にcache_scope: "public"を返します。バイヤーはパブリックキーの下でキャッシュします。accountありのリクエストはcache_scope: "public"または"account"を返します(セラーが宣言しなければならず、MUST、デフォルトなし)。"public": このアカウントはレートカードから価格を付けます。バイヤーは重複排除してもよい(MAY)——バージョンとペイロードは未認証ビューと同じです。バイヤーは"public"cache_scope の任意のアカウントの後続リクエストを、単一のパブリックレイヤーエントリから提供できます。"account": このレスポンスはアカウント固有のオーバーライドを運びます。バイヤーはアカウントオーバーレイキーの下でキャッシュします。
- セラーは、以前
"account"を得たリクエストでcache_scope: "public"を返すことで、アカウントを"account"から"public"へダウングレードしてもよい(MAY)——バイヤーはこれを「このアカウントにはもうオーバーライドがない」と解釈し、アカウントオーバーレイを破棄すべきです(SHOULD)。
if_wholesale_feed_version による条件付きフェッチ。 トークンを、それが返されたスコープと組にして送ります。セラーはそのスコープの現在のバージョンと比較します。バイヤーのトークンが "account" スコープに属するがセラーが cache_scope: "public" で応答する場合、それがダウングレードのシグナルです——バイヤーはオーバーレイを破棄します。
Webhook による無効化。 ホールセールフィード Webhook イベントは、*.priced と *.updated のペイロードで applies_to.scope を宣言します。セラーは、どのサブスクライバーがプロダクト Webhook を受け取るかを決める際、get_products buying_mode: "wholesale" が使う同じアカウント/呼び出し元の認可述語を適用しなければなりません(MUST):
applies_to: { scope: "public" }→ そのエンティティのパブリックレイヤーキャッシュを無効化します。そのパブリックバージョンを参照するすべてのアカウントオーバーレイも古くなり、再取得すべきです(SHOULD)。applies_to: { scope: "account", account_ids: [...] }→ 指定されたアカウントのオーバーレイのみを無効化します。パブリックレイヤーは影響を受けません。account_idsなしのapplies_to: { scope: "account" }→ セラーは影響を受ける集合を伏せています。サブスクライバーごとのスコープフィルターが、principal が影響を受ける集合に含まれるサブスクライバーにのみイベントをルーティングします。イベントを受け取ることは「あなたのオーバーレイは古い」を意味します。
specs/wholesale-feed-webhooks.md の §「Cache layering and event scoping」を参照してください。
完全なフィールドはスキーマを参照: get-products-response.json
よくあるシナリオ
タイムバジェット付きの探索
素早い結果が必要で部分的なデータを許容できる場合、タイムバジェットを宣言します。セラーはバジェット内で達成できる最善の結果を返し、不完全な内容を宣言します。test=false
ホールセールプロダクトの探索
マルチフォーマット探索
予算と日付でのフィルタリング
プロパティタグの解決
保証配信のプロダクト
標準フォーマットのみ
カタログ主導の探索
catalog とブランドを使って、カタログアイテムを宣伝できる広告プロダクトを探す。セラーはアイテムをインベントリに照合し、マッチが存在するプロダクトを返します。
プロパティリストでのフィルタリング
AdCP 3.0 - プロパティリストでのフィルタリングにはガバナンスエージェントの対応が必要です。
property_list_applied が省略または false の場合、セールスエージェントはプロダクトをフィルタリングしていません。これは以下の場合に発生する:
- エージェントがプロパティガバナンス機能をサポートしていません
- エージェントがプロパティリストにアクセスできなかった
- プロパティリストが利用可能なインベントリに影響しなかった
プロパティターゲティングの動作
プロダクトにはproperty_targeting_allowed フラグがあり、フィルタリングに影響します。
property_targeting_allowed: false(デフォルト): プロダクトは「all or nothing」— あなたのリストがプロダクトのすべてのプロパティを含まない限り除外されますproperty_targeting_allowed: true: プロダクトのプロパティとあなたのリストに交差がある場合にインクルードされます
リファインメント
初回探索の後、buying_mode: "refine" を使って特定のプロダクトやプロポーザルを反復できます。refine 配列は変更依頼のリストで、各エントリはスコープとバイヤーが求める内容を宣言します。セラーは更新された価格と設定を持つプロダクトを返し、各依頼を refinement_applied で確認します。
完全なウォークスルー(スコープタイプ、アクションの意味論、セラーのレスポンス、よくあるパターン)は Refinement ガイド を参照してください。パラメータ形状は上記の Refine 配列 セクションで定義されています。
最小の例:
test=false
refineはrefineモードでのみ有効。 このフィールドをbriefまたはwholesaleモードで含むリクエストはINVALID_REQUESTで拒否されます。- フィルターは絶対値でありデルタではない。適用したいフィルターのフルセットを常に送信すること。
- プロポーザルはステータスで操作可能。
proposal_status: "draft"は作成前に finalize が必要。proposal_status: "committed"はexpires_at前にcreate_media_buy(proposal_id)で実行可能。ステータスがなければレガシーの購入可能状態。 - プロポーザルはエフェメラル。 プロポーザルには通常
expires_atタイムスタンプが含まれます。期限切れ後、セラーはPROPOSAL_EXPIREDを返します。 - プロダクト ID は安定したカタログ識別子。 カスタムプロダクト(
is_custom: true)にはexpires_atタイムスタンプがある場合があり、その後のリファインはPRODUCT_NOT_FOUNDを返します。
Error Handling
Authentication Comparison
認証あり・なしのアクセスの違いを確認します。- プロダクト数: 認証ありのアクセスはプライベート/カスタムオファリングを含む多くのプロダクトを返す
- 価格情報: 認証ありのリクエストのみ詳細な価格オプション(CPM、CPCV など)を受け取れる
- ターゲティング詳細: カスタムターゲティング機能は認証ユーザーに限定される場合があります
- レート制限: 認証なしのリクエストはレート制限が低い
Authentication Behavior
- 認証情報なし: 制限された公開プロダクト結果を返します。価格なし、カスタムオファリングなし
- 認証情報あり: 価格とカスタムプロダクトを含む完全なプロダクト結果を返す
Asynchronous Operations
ほとんどのプロダクト検索は即時完了するが、一部のシナリオでは非同期処理が必要になります。その場合、completed 以外のステータスを受け取ります。task_id を持つ submitted レスポンスは常に get_task_status(レガシーの tasks/get)でポーリング可能です。push_notification_config はバックグラウンドワークフロー向けに Webhook 通知を追加します。
SDK でのステータス処理
非同期処理が発生するケース
以下の状況でプロダクト検索に非同期処理が必要になる場合があります。- 複雑な検索: 複数のインベントリソースをまたぐ検索やカスタムキュレーション
- 追加確認が必要: ブリーフが曖昧でシステムが追加情報を必要とします
- カスタムプロダクト: 人間のレビューが必要なオーダーメイドのプロダクトパッケージ
Async Status Flow
- MCP
- A2A
ステータス概要
注意: 完全なステータス一覧は Task Lifecycle を参照。
ほとんどの検索は即時完了します。 非同期処理が必要なのは複雑なケースや追加入力が必要な場合のみ。
次のステップ
プロダクトを見つけたら:- 選択肢を確認: プロダクト、価格、ターゲティング能力を比較
- メディアバイ作成:
create_media_buyでキャンペーンを実行 - クリエイティブ準備:
list_creative_formatsで要件を確認 - アセット提供: ライブラリ対応のセラーには
sync_creativesを、インライン専用のセラーにはインラインのpackages[].creativesを使用
さらに学ぶ
- Product Discovery Guide - ブリーフとプロダクトの理解
- Pricing Models - CPM, CPCV, CPP の解説
- Brief Expectations - 効果的なブリーフの書き方
- Media Products - プロダクト構造とフィールド