> ## Documentation Index
> Fetch the complete documentation index at: https://adcp-docs-ja.pier1.co.jp/llms.txt
> Use this file to discover all available pages before exploring further.

# get_products

> get_products タスク — AdCP で自然言語のキャンペーンブリーフや構造化フィルターを使って広告インベントリを探索します。価格やフォーマットとともにマッチしたプロダクトを返します。

キャンペーン要件に基づき、自然言語のブリーフまたは構造化フィルターで利用可能な広告プロダクトを検索します。

<Info>
  **この形状の理由。** ターゲティング、価格、キュレーションは一度の往復に折り込まれています——ブリーフがディスカバリーを駆動し、パブリッシャーはそれに対してキュレーションし、`pricing_options` が確定価格を運び、バイヤーは `pricing_option_id` を通じてそれにコミットします。プロダクトと購入作成の間に別個の `get_price_quote` ステップを設けることは却下しました: それは一つの専門的判断を二つの不十分に規定された判断に分割し、ブリーフ→キュレーションの契約を壊します。反復は新しいタスクではなく、型付きの変更配列を伴う `buying_mode: "refine"` です。→ [設計原則: ブリーフがディスカバリーを駆動する](/docs/protocol/design-principles#3-the-brief-drives-discovery-targeting-is-an-input-not-a-step)。
</Info>

**Authentication**: 任意（認証なしの場合は結果が制限されます）

**Response Time**: 約 60 秒（バックエンド連携を伴う推論）

**Request Schema**: [`/schemas/v3/media-buy/get-products-request.json`](https://adcontextprotocol.org/schemas/v3/media-buy/get-products-request.json)
**Response Schema**: [`/schemas/v3/media-buy/get-products-response.json`](https://adcontextprotocol.org/schemas/v3/media-buy/get-products-response.json)

## クイックスタート

自然言語のブリーフでプロダクトを検索:

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';
  import { GetProductsResponseSchema } from '@adcp/sdk';

  const result = await testAgent.getProducts({
    buying_mode: 'brief',
    brief: 'Premium athletic footwear with innovative cushioning',
    brand: {
      domain: 'acmecorp.com'
    }
  });

  if (!result.success) {
    throw new Error(`Request failed: ${result.error}`);
  }

  // Validate response against schema
  const validated = GetProductsResponseSchema.parse(result.data);
  console.log(`Found ${validated.products.length} products`);

  // Access validated product fields
  for (const product of validated.products) {
    console.log(`- ${product.name} (${product.delivery_type})`);
    console.log(`  Formats: ${product.format_ids.map(f => f.id).join(', ')}`);
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_products():
      result = await test_agent.simple.get_products(
          buying_mode='brief',
          brief='Premium athletic footwear with innovative cushioning',
          brand={
              'domain': 'acmecorp.com'
          }
      )
      print(f"Found {len(result.products)} products")

  asyncio.run(discover_products())
  ```

  ```bash CLI requires-env=ADCP_AUTH_TOKEN theme={null}
  uvx adcp \
    https://test-agent.adcontextprotocol.org/sales/mcp \
    get_products \
    '{"buying_mode":"brief","brief":"Premium athletic footwear with innovative cushioning","brand":{"domain":"acmecorp.com"}}' \
    --auth $ADCP_AUTH_TOKEN
  ```
</CodeGroup>

### 構造化フィルターの利用

ブリーフの代わりに（または併用して）構造化フィルターを使うこともできます。`brief` モードでは、フィルターはパブリッシャーのキュレーションに対するハード制約として機能します。ブリーフが意図を表し、フィルターが要件を強制します。

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  const result = await testAgent.getProducts({
    buying_mode: 'wholesale',
    brand: {
      domain: 'acmecorp.com'
    },
    filters: {
      channels: ['ctv'],
      delivery_type: 'guaranteed',
      standard_formats_only: true
    }
  });

  if (result.success && result.data) {
    console.log(`Found ${result.data.products.length} guaranteed CTV products`);
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_with_filters():
      result = await test_agent.simple.get_products(
          buying_mode='wholesale',
          brand={
              'domain': 'acmecorp.com'
          },
          filters={
              'channels': ['ctv'],
              'delivery_type': 'guaranteed',
              'standard_formats_only': True
          }
      )
      print(f"Found {len(result.products)} guaranteed CTV products")

  asyncio.run(discover_with_filters())
  ```
</CodeGroup>

## リクエストパラメーター

| Parameter                   | Type                               | Required    | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| --------------------------- | ---------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `buying_mode`               | string                             | Yes         | `"brief"`、`"wholesale"`、または `"refine"`。`"brief"`: パブリッシャーがブリーフからプロダクトをキュレーションします。`"wholesale"`: バイヤー主導のターゲティング用の生プロダクトフィードアクセス。`brief` は指定してはなりません。`"refine"`: `refine` 配列の変更依頼を使って前のレスポンスのプロダクトやプロポーザルを反復します。v3 クライアントは `buying_mode` を含めなければなりません。`buying_mode` を持たない v3 以前のクライアントからリクエストを受けたセラーは `"brief"` をデフォルトとすべきです。**タイミングの意味論:** `"wholesale"` はホールセール・プロダクトフィードの読み取りです——セラーは同期レスポンスを返すべきであり（SHOULD）、`"wholesale"` リクエストを非同期/Submitted の経路へルーティングしてはなりません（MUST NOT）。部分的な完了はタスクの引き継ぎではなく [`incomplete[]`](#incomplete-配列) で通知します。`"brief"` と `"refine"` は同期的に完了してもよく（MAY）、キュレーションが上流システムへの問い合わせや、セラーが `time_budget` 内に完了できない HITL レビューを要する場合は `Submitted` エンベロープを返してもよい（MAY）。予測可能な高速のホールセール・プロダクトフィードアクセスを必要とするバイヤーは `"wholesale"` を使わなければなりません（MUST）。 |
| `brief`                     | string                             | Conditional | キャンペーン要件の自然言語説明。`buying_mode` が `"brief"` の場合は必須。`"wholesale"` または `"refine"` の場合は指定してはなりません。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `refine`                    | [Refine\[\]](#refine-配列)           | Conditional | プロダクトやプロポーザルを反復するための変更依頼の配列。`buying_mode` が `"refine"` の場合は必須。`"brief"` または `"wholesale"` の場合は指定してはなりません。後述の [Refine 配列](#refine-配列) を参照。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `brand`                     | BrandRef                           | No          | ブランド参照（ドメイン＋オプションの brand\_id）。実行時に完全な識別情報へ解決されます。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `account`                   | AccountRef                         | No          | アカウント固有の価格設定に用いるアカウント参照。このアカウントのレートカードから価格付きのプロダクトを返します。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `catalog`                   | [Catalog](/docs/creative/catalogs) | No          | バイヤーが宣伝したいアイテムのカタログ。セラーはカタログアイテムをインベントリに照合し、マッチが存在するプロダクトを返します。`brand` が必要。後述の [カタログによる探索](#カタログによる探索) を参照。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `filters`                   | Filters                            | No          | 構造化フィルター（後述）                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `fields`                    | string\[]                          | No          | 軽量なディスカバリーのためにレスポンスへ含める特定のプロダクトフィールド。シグナルのメタデータを要求する場合、バイヤーは選択不可のバンドル済み/計画済みシグナルには `included_signals` を、パッケージレベルのシグナル選択には `signal_targeting_allowed`・`signal_targeting_options`・`signal_targeting_rules` を要求すべきです（SHOULD）。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `property_list`             | PropertyListRef                    | No          | \[AdCP 3.0] フィルタリングに用いるプロパティリスト参照。[Property Lists](/docs/governance/property/tasks/property_lists) 参照                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `pagination`                | PaginationRequest                  | No          | キュレーション/リファインされたレスポンスで返される `products[]` を上限設定するため、またはホールセール・プロダクトフィードを辿るためのカーソルベースページネーション（後述）                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `if_wholesale_feed_version` | string                             | No          | このエージェントの以前のホールセールモード `get_products` レスポンスから得た不透明な `wholesale_feed_version` トークン。`buying_mode: "wholesale"` の場合のみ有効。指定されると、セラーはバイヤーの `cache_scope` に対する現在のホールセール・プロダクトフィードのバージョンと比較し、何も変わっていなければ `unchanged: true`（`products` を省略）を返してもよい（MAY）。バージョンのスコープは `pagination.cursor` を除外します: `public` は（エージェント、`buying_mode`、`filters`、`property_list`、`catalog`）でキー付けされ、`account` はアカウント識別を追加します。[ホールセールフィードのバージョニング](#ホールセールフィードバージョニング)参照。                                                                                                                                                                                                                                                                                                                        |
| `if_pricing_version`        | string                             | No          | 以前のレスポンスからの不透明な `pricing_version` トークン。`if_wholesale_feed_version` と一緒にのみ送らなければなりません（MUST）。評価順: `if_wholesale_feed_version` の不一致 → 完全なペイロード。`if_wholesale_feed_version` は一致するが `if_pricing_version` が不一致 → 完全なペイロード（バイヤーが更新後の `pricing_options` を見られるように）。両方一致 → セラーは `unchanged: true` を返してもよい（MAY）。価格を別途追跡しないセラーはこれを無視します。                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `time_budget`               | Duration                           | No          | バイヤーがこのリクエストに割り当てる最大時間。セラーはその時間内で最善の結果を返し、その時間内に完了できないプロセス（人間の承認や高コストな外部クエリ）は開始しません。省略した場合はセラーがタイミングを決定します。例: `{"interval": 30, "unit": "seconds"}`。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `push_notification_config`  | PushNotificationConfig             | No          | `brief` / `refine` のキュレーションディスカバリーにおける、非同期の最終完了/失敗通知のための任意の Webhook チャネル。`task_id` を持つ `submitted` レスポンスは、このフィールドの有無に関わらず `get_task_status`（レガシーの `tasks/get`）でポーリング可能なままです。リクエストがこのフィールドを含み、かつセラーが `submitted` を返す場合、セラーは少なくとも最終の完了/失敗通知を設定された Webhook へ配信しなければなりません（MUST）。途中経過の通知は任意です（MAY）。セラーが Webhook チャネルに対応できない場合は、暗黙に受け付けるのではなく構造化エラーでリクエストを拒否しなければなりません（MUST）。`wholesale` では無視されます。このフィールドが存在するからといって、セラーがホールセール読み取りを Submitted 経路へルーティングしてはなりません（MUST NOT）。                                                                                                                                                                                                                                                                                          |

<Note>
  **プロパティガバナンス**

  `property_list` フィルターは、プロパティガバナンスエージェント上で [`create_property_list`](/docs/governance/property/tasks/property_lists#create_property_list) を通じて作成されたプロパティリストを参照します。プロパティリストは、どのパブリッシャープロパティがコンプライアンス要件を満たすか——COPPA 認証済みサイト、サステナビリティスコア付き在庫、ブランドセーフなパブリッシャーなど——を定義します。

  プロパティリストフィルタリングを使うには:

  1. プロパティガバナンスエージェントで `get_adcp_capabilities` を呼び出し、利用可能な `property_features` を発見する
  2. 機能要件を指定して `create_property_list` でプロパティリストを作成する
  3. 得られた `property_list_id` を `get_products` に渡して在庫をフィルタリングする

  このフィルターをサポートするには、セラーが [`get_adcp_capabilities`](/docs/protocol/get_adcp_capabilities) で `features.property_list_filtering: true` を宣言しなければなりません。完全なワークフローは[プロパティガバナンス概要](/docs/governance/property/index)を参照してください。
</Note>

### Filters オブジェクト

| Parameter                        | Type                                                                                                                  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `delivery_type`                  | string                                                                                                                | `"guaranteed"` または `"non_guaranteed"` でフィルタリング                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `is_fixed_price`                 | boolean                                                                                                               | 固定価格かオークションかでフィルタリング。両方の価格タイプを持つプロダクトはどちらの値にもマッチしますが、返される `pricing_options` 配列には要求された価格タイプに一致するオプションのみを含めなければならず、バイヤーがディスカバリーから確定的に選択できるようにします。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `pricing_currencies`             | string\[]                                                                                                             | バイヤーがメディアプロダクトの取引に使える ISO 4217 通貨でフィルタリング（例: `["USD"]`）。プロダクトは、要求された通貨のいずれかでプロダクトレベルの `pricing_options` エントリを少なくとも1つ提供し、かつセラーが適用する（またはその他必須の）プロダクトスコープのシグナル課金がそれらの通貨のいずれかで満たせるか、増分価格を持たない場合にマッチします。セラーはマッチするプロダクトの `pricing_options` のみを返さなければなりません（MUST）。任意のシグナル/ベンダーのアドオン価格はこのフィルターで除外されません。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `format_ids`                     | FormatID\[]                                                                                                           | 特定のフォーマット ID でフィルタリング                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `standard_formats_only`          | boolean                                                                                                               | IAB 標準フォーマットを受け付けるプロダクトのみ返す                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `min_exposures`                  | integer                                                                                                               | 計測妥当性に必要な最小エクスポージャ数                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `start_date`                     | string                                                                                                                | 可用性確認のための開始日 (ISO 8601, YYYY-MM-DD)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `end_date`                       | string                                                                                                                | 可用性確認のための終了日 (ISO 8601, YYYY-MM-DD)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `budget_range`                   | object                                                                                                                | 適切なプロダクトを絞る予算レンジ（下記 Budget Range オブジェクト参照）                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `countries`                      | string\[]                                                                                                             | ISO 3166-1 alpha-2 コードで国を指定（例: `["US", "CA", "GB"]`）                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `regions`                        | string\[]                                                                                                             | ISO 3166-2 コードでリージョンのカバレッジをフィルタリング（例: `["US-NY", "GB-SCT"]`）。ローカルに限定された在庫に最適                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `metros`                         | object\[]                                                                                                             | メトロのカバレッジでフィルタリング。各エントリ: `{ system, code }`（例: `[{ "system": "nielsen_dma", "code": "501" }]`）                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `channels`                       | string\[]                                                                                                             | 広告チャンネルでフィルタリング（例: `["display", "ctv", "social", "streaming_audio"]`）。[Media Channel Taxonomy](/docs/reference/media-channel-taxonomy) 参照                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `video_placement_types`          | string\[]                                                                                                             | 許容する宣言済みの動画プレースメントタイプで動画プロダクトをフィルタリング: `instream`、`accompanying_content`、`interstitial`、`standalone`。セラーは要求されたタイプの少なくとも1つで満たせるプロダクトのみを返すべきで、配信を要求タイプに制約できない限り、混在した非ターゲット可能なバンドルは除外すべきです。IAB Tech Lab/OpenRTB 2.6 の `video.plcmt` 定義を AdCP ネイティブ名で使用します。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `audio_distribution_types`       | string\[]                                                                                                             | 許容する宣言済みのオーディオ配信タイプでオーディオプロダクトをフィルタリング: `music_streaming_service`、`fm_am_broadcast`、`podcast`、`catch_up_radio`、`web_radio`、`video_game`、`text_to_speech`。セラーは要求されたタイプの少なくとも1つで満たせるプロダクトのみを返すべきで、配信を要求タイプに制約できない限り、混在した非ターゲット可能なバンドルは除外すべきです。IAB Tech Lab/OpenRTB 2.6 の `audio.feed` 定義を AdCP ネイティブ名で使用します。                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `sponsored_placement_types`      | string\[]                                                                                                             | 許容する宣言済みのスポンサープレースメントタイプでカタログ駆動のリテールメディアプロダクトをフィルタリング: `sponsored_search`、`sponsored_display`、`sponsored_native`。セラーは要求されたタイプの少なくとも1つで満たせるプロダクトのみを返すべきで、配信を要求タイプに制約できない限り、混在した非ターゲット可能なバンドルは除外すべきです。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `social_placement_surfaces`      | string\[]                                                                                                             | 許容する宣言済みのソーシャルプレースメント面でソーシャルプロダクトをフィルタリング: `feed`、`stories`、`short_video`、`explore`、`search`。セラーは要求された面の少なくとも1つで満たせるプロダクトのみを返すべきで、配信を要求面に制約できない限り、混在した非ターゲット可能なバンドルは除外すべきです。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `postal_areas`                   | object\[]                                                                                                             | 郵便エリアのカバレッジでフィルタリング。各エントリ: `{ country, system, values }`（例: `[{ "country": "US", "system": "zip", "values": ["10001"] }]`）                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `geo_proximity`                  | object\[]                                                                                                             | 地理的地点への近接でフィルタリング。各エントリは正確に1つの境界方式を使用: `radius`、`travel_time` + `transport_mode`、または `geometry`。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `keywords`                       | object\[]                                                                                                             | 検索/リテールメディア向けのキーワード関連性でフィルタリング。各エントリ: `{ keyword, match_type? }`。`match_type` は省略時 `broad`。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `signal_targeting`               | SignalTargeting\[]                                                                                                    | 要求されたシグナルがバイヤー選択可能かつ共同で構成可能なプロダクトを対象とするディスカバリーフィルター: インラインの `signal_targeting_options` および/または、シグナルターゲティングを許可するがインラインオプションを省略するホールセールプロダクト向けのセラーの `get_signals` フィード経由で利用でき（`signal_targeting_allowed: true`）、プロダクトの `signal_targeting_rules` の下で互換なもの。各エントリは `signal_ref` を使用し（`signal_id` は非推奨の移行ブリッジとしてのみ受け付け）、`any` または `none` グループのサポートを要求するために `targeting_mode: "include"` または `"exclude"` を含めてもよい（省略時は `"include"`）。`scope: "product"` はセラーローカルな厳密オプションマッチングのみで、プロダクトやセラーをまたぐ可搬な意味識別子ではありません。可搬なディスカバリーを望むバイヤーは `scope: "data_provider"` または `get_signals` を使うべきです。`included_signals` および非推奨の `data_provider_signals` のメタデータは、`create_media_buy` で選択できないためこのフィルターを満たしません。これは購入時のリクエスト形状ではありません。パッケージ選択は常に `packages[].targeting_overlay.signal_targeting_groups` を使用します。 |
| `required_performance_standards` | [PerformanceStandard\[\]](/docs/media-buy/advanced-topics/pricing-models#measurement-terms-and-performance-standards) | バイヤーのパフォーマンス基準要件を満たせるプロダクトに絞り込みます。各エントリはメトリクス、閾値、ベンダーを指定します（例: 「70% MRC のビューアビリティに対して DoubleVerify」）。これらの閾値を満たせない、または指定ベンダーをサポートしないプロダクトは除外されます。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `required_metrics`               | string\[]（[メトリクス語彙](/docs/media-buy/media-buys/optimization-reporting)）                                               | `reporting_capabilities.available_metrics` がこれらのメトリクスの上位集合であるプロダクト——すなわち、配信時に列挙されたすべてのメトリクスの報告にコミットするプロダクト——に絞り込みます。機能ディスカバリーに使用します（例: CTV CPCV 購入向けの `["completed_views"]`）。セラーはリストを満たせないプロダクトを暗黙に除外しなければならず（MUST）——fail ではなく filter——エラーを返してはなりません。プロダクトが宣言した `available_metrics` は、結果のメディアバイに引き継がれる拘束的な報告契約となります。                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `required_vendor_metrics`        | object\[]                                                                                                             | `reporting_capabilities.vendor_metrics` がベンダー定義のメトリクス（独自のアテンション、排出量、パネルデモグラフィック、ブランドリフト調査など）をカバーするプロダクトに絞り込みます。各エントリは `vendor`（BrandRef）および/または `metric_id` を指定します（少なくとも一方）。ベンダー横断のディスカバリー（例: 「任意のアテンション計測」）はバイヤーエージェントの責任です: どのベンダーがカテゴリを提供するかをベンダーの `brand.json` レコードで解決し、それらをフィルターエントリとして列挙します。`required_metrics` と同じ filter-not-fail の意味論。                                                                                                                                                                                                                                                                                                                                                                                                                                  |

### プレースメントフィールド

`get_products` は、セラーが `placements` を含める、またはバイヤーが `fields` で要求した場合に、プロダクトのプレースメントデータを返します。プレースメント ID はパブリッシャースコープです。プロダクトのプレースメントは、パブリッシャーの宣言が存在する場合、パブリッシャーの公開 `adagents.json` のプレースメント宣言を `{publisher_domain, placement_id}` で参照すべきです。セラー非公開のプレースメント ID、ソース/オリジンの詳細、配信システムのマッピングはレスポンスに含めてはなりません。

返される各プレースメントは以下を持ちうる:

| Field                           | Meaning                                                                                                                                                      |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `placement_id`                  | パブリッシャー名前空間におけるプレースメント識別子。バイヤーは `creative_assignments[].placement_refs` で `publisher_domain` とともに参照します。レガシーの `placement_ids` 文字列は単一パブリッシャーの文脈でのみ一意です。        |
| `publisher_domain`              | パブリッシャー参照のプレースメントを定義する `adagents.json` を持つドメイン。新しいマルチパブリッシャープロダクトは含めるべきです（SHOULD）。レガシープロダクトで省略された場合、バイヤーは `placement_id` をセラーエージェント自身のパブリッシャードメインに対して解釈してよい。 |
| `mode`                          | `targetable` はバイヤーがパブリッシャースコープのプレースメントを（例えば `creative_assignments[].placement_refs` で）参照できることを意味します。`included` はプレースメントがプロダクト構成の一部だがバイヤー選択不可であることを意味します。     |
| `video_placement_types`         | OLV その他の動画在庫の宣言済み動画プレースメントタイプ。IAB Tech Lab/OpenRTB 2.6 の `video.plcmt` 定義を AdCP ネイティブ名で使用。具体的なプレースメントは通常1値を宣言し、集約プレースメントは複数を宣言しうる。                           |
| `audio_distribution_types`      | ラジオ、ストリーミングオーディオ、ポッドキャスト、ゲームその他のオーディオ在庫の宣言済みオーディオ配信タイプ。IAB Tech Lab/OpenRTB 2.6 の `audio.feed` 定義を AdCP ネイティブ名で使用。                                           |
| `sponsored_placement_types`     | カタログ駆動のリテールメディア在庫の宣言済みスポンサープレースメントタイプ。                                                                                                                       |
| `social_placement_surfaces`     | ソーシャル在庫の宣言済みソーシャルプレースメント面。                                                                                                                                   |
| `format_ids` / `format_options` | プレースメント固有のクリエイティブサポート。プロダクトレベルのフォーマットが上限であり、プレースメントレベルのフォーマットはそのプレースメントで実効的に受け付ける集合を狭めるもので、プロダクトが受け付けないフォーマットを追加してはなりません。                                    |

パブリッシャーは、`adagents.json` の `authorized_agents[].placement_ids` または `authorized_agents[].placement_tags` を使って、特定のパブリッシャープレースメントに対してセラーエージェントを認可できます。セラーは、自身が販売を認可されたパブリッシャー参照のプレースメントのみを返すべきです。

シグナルターゲティングフィルターの例:

```json theme={null}
{
  "$schema": "/schemas/media-buy/get-products-request.json",
  "buying_mode": "wholesale",
  "filters": {
    "signal_targeting": [
      {
        "signal_ref": {
          "scope": "data_provider",
          "data_provider_domain": "pinnacle-data.example",
          "signal_id": "auto_intenders"
        },
        "value_type": "binary",
        "value": true,
        "targeting_mode": "include"
      }
    ]
  },
  "fields": [
    "product_id",
    "name",
    "included_signals",
    "signal_targeting_allowed",
    "signal_targeting_options",
    "signal_targeting_rules",
    "pricing_options"
  ]
}
```

### 通貨フィルタリング

バイヤーの制約が「取引可能なメディア価格を持つプロダクトのみ表示」の場合は `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` に含まれていなければなりません。

通貨のみのフィルター例:

```json theme={null}
{
  "$schema": "/schemas/media-buy/get-products-request.json",
  "buying_mode": "wholesale",
  "filters": {
    "pricing_currencies": ["USD"]
  },
  "fields": ["product_id", "name", "pricing_options"]
}
```

プロダクトが USD と EUR の両方のメディア価格を持ち、バイヤーが `pricing_currencies: ["USD"]` を送ると、セラーはそのプロダクトを USD のプロダクトレベル `pricing_options` のみで返します。プロダクトが固定またはその他必須のプロダクトスコープのシグナル課金も持つ場合、その必須課金は USD で価格付けされているか、増分価格を持たないかのいずれかでなければならず、そうでなければプロダクトはフィルターにマッチしません。`currency` のない必須の `custom` シグナル価格は、セラーが正当に増分価格なしと扱える場合を除き、このフィルターでは満たせません。任意のシグナルアドオンはプロダクトのマッチングに影響しません。

### Budget Range オブジェクト

| Parameter  | Type   | Required | Description                                  |
| ---------- | ------ | -------- | -------------------------------------------- |
| `currency` | string | Yes      | ISO 4217 通貨コード（例: `"USD"`, `"EUR"`, `"GBP"`） |
| `min`      | number | No\*     | 最低予算額                                        |
| `max`      | number | No\*     | 最高予算額                                        |

\*`min` または `max` のいずれか一方は必ず指定しなければなりません。

### Refine 配列

`refine` 配列は変更依頼のリストです。各エントリは `scope` と、バイヤーが求める内容を宣言します。少なくとも 1 エントリが必要。セラーはすべてのエントリをまとめて考慮してレスポンスを構成し、`refinement_applied` で各エントリに返答します。

各エントリは `scope` による判別共用体です。

#### scope: "request"

| Field   | Type   | Required | Description                                                                      |
| ------- | ------ | -------- | -------------------------------------------------------------------------------- |
| `scope` | string | Yes      | `"request"`                                                                      |
| `ask`   | string | Yes      | 選択全体への方向指示（例: `"more video options"`、`"suggest how to combine these products"`）。 |

#### scope: "product"

| Field        | Type   | Required | Description                                                                                                                                                       |
| ------------ | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scope`      | string | Yes      | `"product"`                                                                                                                                                       |
| `product_id` | string | Yes      | 前回の `get_products` レスポンスのプロダクト ID                                                                                                                                 |
| `action`     | string | No       | `"include"`（デフォルト）: 更新された価格とデータでこのプロダクトを返します。`"omit"`: レスポンスから除外します。`"more_like_this"`: 類似プロダクトを探す（元のプロダクトも返されます）。省略時、セラーはエントリを `"include"` として扱います。              |
| `ask`        | string | No       | バイヤーが求める内容。`"include"` の場合: 具体的な変更（例: `"add 16:9 format"`）。`"more_like_this"` の場合: 「類似」の意味（例: `"same audience but video format"`）。`action` が `"omit"` の場合は無視されます。 |

#### scope: "proposal"

| Field         | Type   | Required | Description                                                                                                                                                   |
| ------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scope`       | string | Yes      | `"proposal"`                                                                                                                                                  |
| `proposal_id` | string | Yes      | 前回の `get_products` レスポンスのプロポーザル ID                                                                                                                            |
| `action`      | string | No       | `"include"`（デフォルト）: 更新された配分と価格で返します。`"omit"`: レスポンスから除外します。`"finalize"`: 確定価格とインベントリのホールドを要求します（ドラフトのプロポーザルをコミット済みに遷移させます）。省略時、セラーはエントリを `"include"` として扱います。 |
| `ask`         | string | No       | バイヤーが求める内容（例: `"shift more budget toward video"`、`"reduce total by 10%"`）。`action` が `"omit"` の場合は無視されます。                                                     |

### refinement\_applied（レスポンス）

セラーが `refine` 配列を受け取ると、レスポンスには位置でマッチする `refinement_applied` 配列が含まれます。各エントリは依頼が fulfilled されたかを報告します。

| Field         | Type   | Required                      | Description                                                                                      |
| ------------- | ------ | ----------------------------- | ------------------------------------------------------------------------------------------------ |
| `scope`       | string | Yes                           | 対応する `refine` エントリの scope（`"request"` / `"product"` / `"proposal"`）をエコーします。                      |
| `product_id`  | string | `scope` が `"product"` の場合は必須  | 対応する refine エントリの `product_id` をエコーします。                                                          |
| `proposal_id` | string | `scope` が `"proposal"` の場合は必須 | 対応する refine エントリの `proposal_id` をエコーします。                                                         |
| `status`      | string | Yes                           | `"applied"`: 依頼が fulfilled されました。`"partial"`: 部分的に fulfilled されました。`"unable"`: fulfilled できなかった。 |
| `notes`       | string | No                            | セラーの説明。`status` が `"partial"` または `"unable"` の場合に推奨。                                             |

### カタログによる探索

カタログアイテムを宣伝できる広告プロダクトを探すには `catalog` を渡します。セラーはカタログアイテムをインベントリに照合し、マッチが存在するプロダクトを返します。すべてのカタログ種別に対応しています。商品カタログはスポンサー商品枠を探し、求人カタログは求人広告プロダクトを、フライトカタログはダイナミックトラベル広告を探す。

`catalog` フィールドは AdCP 全体で使われる同じ [Catalog](/docs/creative/catalogs) オブジェクトを使います。`catalog_id` で同期済みカタログを参照したり、インラインでアイテムを指定したり、セレクターでフィルタリングしたりできます。

| Field        | Type        | Description                                                |
| ------------ | ----------- | ---------------------------------------------------------- |
| `type`       | CatalogType | カタログ種別（必須）— `product`、`job`、`hotel`、`flight`、`offering` など |
| `catalog_id` | string      | ID で同期済みカタログを参照する                                          |
| `ids`        | string\[]   | 特定のアイテム ID に絞り込む                                           |
| `gtins`      | string\[]   | クロスリテーラーマッチング用に GTIN でフィルタリング（product 種別のみ）                |
| `tags`       | string\[]   | タグでフィルタリング（OR ロジック）                                        |
| `category`   | string      | カテゴリでフィルタリング                                               |
| `query`      | string      | 自然言語フィルター                                                  |

レスポンスのプロダクトには `catalog_types`（対応するカタログ種別）と `catalog_match`（マッチしたアイテム）が含まれます。

## レスポンス

`products` 配列と、必要に応じて `proposals` を返します。

### Products 配列

| Field                          | Type                                                                                                                  | Description                                                                                                                                                                                                                                                                    |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `product_id`                   | string                                                                                                                | プロダクトの一意 ID                                                                                                                                                                                                                                                                    |
| `name`                         | string                                                                                                                | 人が読めるプロダクト名                                                                                                                                                                                                                                                                    |
| `description`                  | string                                                                                                                | プロダクトの詳細説明                                                                                                                                                                                                                                                                     |
| `publisher_properties`         | PublisherProperty\[]                                                                                                  | パブリッシャーごとのエントリ。`publisher_domain` と `property_ids` または `property_tags` を含む                                                                                                                                                                                                     |
| `format_ids`                   | FormatID\[]                                                                                                           | サポートするクリエイティブフォーマット ID                                                                                                                                                                                                                                                         |
| `delivery_type`                | string                                                                                                                | `"guaranteed"` または `"non_guaranteed"`                                                                                                                                                                                                                                          |
| `delivery_measurement`         | DeliveryMeasurement                                                                                                   | （任意）配信の計測方法（インプレッション、ビュー等）                                                                                                                                                                                                                                                     |
| `pricing_options`              | PricingOption\[]                                                                                                      | 利用可能な価格モデル（CPM、CPCV など）。オークションオプションは `floor_price` とオプションの `price_guidance` を含む場合があります。入札ベースのオークションモデル（CPM、vCPM、CPC、CPCV、CPV）はオプションの `max_bid`（boolean）を含む場合もあります。                                                                                                             |
| `shows`                        | CollectionSelector\[]                                                                                                 | （任意）このプロダクトで利用可能なコレクション。各エントリは `publisher_domain` と `collection_ids` を持ちます。バイヤーは参照先の `adagents.json` から完全なコレクションオブジェクトを解決します。[Collections and installments](/docs/media-buy/product-discovery/collections-and-installments) 参照。                                                |
| `collection_targeting_allowed` | boolean                                                                                                               | （任意、デフォルト: false）バイヤーがこのプロダクトの shows のサブセットをターゲットできるかどうか。false の場合、プロダクトはバンドルです。                                                                                                                                                                                               |
| `data_provider_signals`        | DataProviderSignalSelector\[]                                                                                         | （任意、非推奨）このプロダクトに既にバンドル/関連付けられたデータプロバイダーシグナルのレガシー/選択不可メタデータ。新規実装は `included_signals` を使うべきです。                                                                                                                                                                                   |
| `included_signals`             | SignalListing\[]                                                                                                      | （任意）このプロダクトに既に含まれる/バンドルされる/計画されたシグナルの選択不可メタデータ。これらはプロダクトが何であるかを説明するもので、バイヤーはパッケージの `signal_targeting_groups` では選択しません。データプロバイダー/シグナルソースの参照は参照のみの場合があり、プロダクトローカルの参照はインラインの `name` と `value_type` を含みます。                                                                         |
| `signal_targeting_allowed`     | boolean                                                                                                               | （任意、デフォルト: false）このプロダクトがパッケージレベルのシグナルターゲティング面を持つかどうか。編集可能性は `signal_targeting_rules` で制御されます。固定/デフォルトのみのプロダクトも、適用済みのシグナルグループがエコーされる場合はこれを true に設定します。                                                                                                                        |
| `signal_targeting_options`     | ProductSignalTargetingOption\[]                                                                                       | （任意）バイヤーが `packages[].targeting_overlay.signal_targeting_groups` を通じて選択できる（または固定/デフォルト時にセラーが適用する）インラインのプロダクトスコープのシグナルオプション。シグナルごとの `pricing_options` を含む場合があります。プロダクトスコープの価格はこのプロダクトについて権威的です。データプロバイダー/シグナルソースの参照は参照のみの場合があり、プロダクトローカルの参照はインラインの `name` と `value_type` を含みます。 |
| `signal_targeting_rules`       | SignalTargetingRules                                                                                                  | （任意）選択可能なシグナルのプロダクトスコープの構成ルール。直接解決 vs セラー計画による解決、任意、必須、最大数、相互排他、固定選択、グループサイズ上限など。これらの上限はセラー全体の `get_adcp_capabilities` ではなくプロダクトに属します。プロダクトは異なるアドサーバーやセラーの計画レイヤーに支えられている場合があるためです。固定/デフォルトの選択はセラーが適用し、結果のパッケージ状態にエコーされます。                                                      |
| `brief_relevance`              | string                                                                                                                | ブリーフに合致する理由（ブリーフ提供時）                                                                                                                                                                                                                                                           |
| `measurement_readiness`        | [MeasurementReadiness](/docs/media-buy/conversion-tracking/#measurement-readiness)                                    | （任意）バイヤーのイベント設定がこのプロダクトの最適化に十分かどうか。セラーがバイヤーのアカウントコンテキストを評価できる場合のみ存在します。                                                                                                                                                                                                        |
| `measurement_terms`            | [MeasurementTerms](/docs/media-buy/advanced-topics/pricing-models#measurement-terms-and-performance-standards)        | （任意）セラーのデフォルトの課金計測とメイクグッド条件。バイヤーは `create_media_buy` で異なる条件を提案できます。                                                                                                                                                                                                            |
| `performance_standards`        | [PerformanceStandard\[\]](/docs/media-buy/advanced-topics/pricing-models#measurement-terms-and-performance-standards) | （任意）セラーのデフォルトのパフォーマンス基準（ビューアビリティ、IVT、完了率、ブランドセーフティ、アテンションスコア）。バイヤーは `create_media_buy` で異なる基準を提案できます。                                                                                                                                                                          |
| `cancellation_policy`          | [CancellationPolicy](/docs/media-buy/advanced-topics/pricing-models#cancellation-policy)                              | （任意）保証プロダクトのキャンセル通知期間とペナルティ。バイヤーはプロダクトに対してメディアバイを作成することでこれらの条件を受諾します。                                                                                                                                                                                                          |

### 非 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` 配列内でこのセレクターを使えます:

```json theme={null}
[
  {
    "selection_type": "by_tag",
    "property_tags": ["metro", "station"]
  }
]
```

### Proposals 配列（任意）

パブリッシャーはプロダクトと併せてプロポーザル（予算配分付きの構造化メディアプラン）を返すことがあります。詳細は [Proposals](/docs/media-buy/product-discovery/media-products#proposals) を参照。

| Field                   | Type                 | Description                                                                                                                                                                                    |
| ----------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `proposal_id`           | string               | このプロポーザルを finalize し、コミット後に `create_media_buy` で実行するための一意 ID                                                                                                                                   |
| `proposal_status`       | string               | ライフサイクル状態。`draft` は、作成前に `get_products` の refine アクション `finalize` を通じてプロポーザルを finalize する必要があることを意味します。`committed` は、`expires_at` 前に `create_media_buy` で実行できることを意味します。省略時は後方互換のため購入可能として扱います。 |
| `name`                  | string               | メディアプランの人が読める名称                                                                                                                                                                                |
| `allocations`           | ProductAllocation\[] | プロダクト間の予算配分（合計 100% 必須）。各配分にはフライトごとのスケジューリング用にオプションの `start_time` と `end_time` を含む場合があります。                                                                                                     |
| `forecast`              | DeliveryForecast     | プロポーザルの集計配信予測。メトリクスの範囲を持つ予測ポイントを含みます。[Delivery Forecasts](/docs/media-buy/product-discovery/media-products#delivery-forecasts) 参照                                                              |
| `total_budget_guidance` | object               | 最小/推奨/最大の予算ガイダンス（任意）                                                                                                                                                                           |
| `brief_alignment`       | string               | キャンペーンブリーフへの対応内容                                                                                                                                                                               |
| `expires_at`            | string               | プロポーザルの有効期限 (ISO 8601)。コミット済みプロポーザルでは、これは `create_media_buy` のためのインベントリホールドの期限です。                                                                                                              |

各 `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` モードでは、ページネーションはホールセール・プロダクトフィードを辿ります。これは網羅的/フィード形式の読み取りで、ホールセールフィードバージョニングと組み合わさるモードです。

キュレーション/絞り込み後のレスポンスで返されるプロダクトを上限設定する、またはホールセール・プロダクトフィードを辿るために、カーソルベースのページネーションを使います:

| Request Parameter        | Type    | Description                      |
| ------------------------ | ------- | -------------------------------- |
| `pagination.max_results` | integer | ページあたりの最大プロダクト数（1〜100、デフォルト: 50） |
| `pagination.cursor`      | string  | 次のページを取得するための前のレスポンスのカーソル        |

| Response Field           | Type    | Description                                                                                                           |
| ------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------- |
| `pagination.has_more`    | boolean | さらにプロダクトがあるかどうか                                                                                                       |
| `pagination.cursor`      | string  | 次のページを取得するために渡すカーソル                                                                                                   |
| `pagination.total_count` | integer | このページネーション結果セット内のプロダクト総数（任意。すべてのバックエンドがサポートするわけではない）。`brief` / `refine` では、これはセラーの全カタログではなく、キュレーション/絞り込み後のプロダクトセットです。 |

ページネーションは任意です。省略した場合、サーバーは完全な結果セット（またはサーバーが選択したデフォルトページ）を返します。レスポンスに `pagination.has_more: true` が含まれる場合、更新された `pagination.cursor` を除いて同じ結果定義リクエストコンテキストを用い、次のリクエストで `pagination.cursor` を渡して次のページを取得します。

### レスポンスメタデータ

| Field                    | Type                                              | Description                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ------------------------ | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `property_list_applied`  | boolean                                           | \[AdCP 3.0] 提供された `property_list` に基づきフィルタした場合 `true`。未指定または非対応なら省略/`false`。                                                                                                                                                                                                                                                                                                                                                     |
| `catalog_applied`        | boolean                                           | セラーが提供された `catalog` に基づき結果をフィルタした場合 `true`。カタログが提供されていないか、セラーがカタログマッチングをサポートしない場合は省略/`false`。                                                                                                                                                                                                                                                                                                                                    |
| `refinement_applied`     | [RefinementResult\[\]](#refinement_applied-レスポンス) | 各 `refine` エントリへのセラーの確認応答（位置でマッチ）。`buying_mode` が `"refine"` の場合のみ存在します。上記 [refinement\_applied](#refinement_applied-レスポンス) 参照。                                                                                                                                                                                                                                                                                                  |
| `incomplete`             | [IncompleteEntry\[\]](#incomplete-配列)             | `time_budget` 内またはセラー内部の制限により完了できなかった内容を宣言します。各エントリはスコープと人が読める説明を持ちます。レスポンスが完全に完了している場合は省略されます。後述の [incomplete 配列](#incomplete-配列) 参照。                                                                                                                                                                                                                                                                                           |
| `filter_diagnostics`     | object                                            | `filters` が候補セットをどう絞り込んだかを説明する、任意の非致命的な可観測性ブロック——`total_candidates` に加え、フィルター単位の `excluded_by` カウント（フィルター名でキー付け）。結果リストが空、または想定外に小さいときに「在庫がない」と「フィルターがすべて除外した」を区別します。競争上の情報漏洩を避けるため、プロダクト名ではなくカウントのみ。後述の [filter\_diagnostics](#filter_diagnostics) 参照。                                                                                                                                                                           |
| `wholesale_feed_version` | string                                            | このレスポンスの構成に用いたホールセール・プロダクトフィード状態のバージョンを表す不透明トークン。条件付きフェッチ（`if_wholesale_feed_version`）を実装するセラーは、バイヤーがキャッシュして後で照会できるよう、すべてのホールセールモードレスポンスでこれを返さなければなりません（MUST）。不透明として扱う——フォーマットも順序も検査もなし。[ホールセールフィードバージョニング](#ホールセールフィードバージョニング)参照。                                                                                                                                                                                               |
| `pricing_version`        | string                                            | プロダクトの `pricing_options` とネストした `signal_targeting_options[].pricing_options` を含む価格レイヤーのバージョンを表す任意の不透明トークン。セラーが独立した価格バージョニングをサポートする場合、`pricing_version` は価格が動くと変わり、`wholesale_feed_version` は構造/メタデータが動くときのみ変わります。両者を分離しないセラーは `pricing_version` を省略し、両方に `wholesale_feed_version` を使ってもよい（MAY）。                                                                                                                                  |
| `cache_scope`            | string                                            | `"public"` または `"account"`。**すべてのレスポンスで必須**（スキーマで強制——二層キャッシュの安全性はこれに依存します）。リクエストに `account` がなかった場合は `"public"` でなければなりません（MUST）。`account` があった場合、セラーは `"public"`（レートカードからのアカウント価格——バイヤーが重複排除）または `"account"`（アカウント固有のオーバーライド）のいずれかを宣言します。[キャッシュレイヤリング](#キャッシュレイヤリング)参照。                                                                                                                                                         |
| `unchanged`              | boolean                                           | リクエストがバイヤーの `cache_scope` に対するセラーの現在のバージョンに一致する `if_wholesale_feed_version`（および/または `if_pricing_version`）を運んだ場合にのみ `true` として存在し、その場合 `products[]` は省略されなければなりません（MUST）。`wholesale_feed_version`・`cache_scope`・（使用時は）`pricing_version` は引き続きエコーされなければなりません（MUST）。セラーは `unchanged: false` を出してはなりません（MUST NOT）——フィールドの不在が「レスポンスがプロダクトを含む」シグナルです（状態ごとに1形状）。`unchanged: true` を受け取ったバイヤーは、ローカルのホールセールプロダクトミラーを変更してはなりません（MUST NOT）。 |

### filter\_diagnostics

セラーが除外を特定のフィルターに帰属できる場合、レスポンスは `filter_diagnostics` ブロックを含んでもよい（MAY）。これは可観測性であり、エラー報告ではありません——セラーは filter-not-fail の慣習に従って、マッチしないプロダクトを引き続き暗黙に除外します。バイヤーはこれを、その存在に依存せずに空/小さい結果をトリアージするために使います。`total_candidates` と `excluded_by` は独立して任意です——ベースライン候補セットのサイズが機密なセラーは、`total_candidates` なしで `excluded_by` を出してもよい（MAY）。

| Field                         | Type    | Description                                                                                                                                                                                          |
| ----------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `semantics`                   | string  | `"only"`（決定的。*このフィルター単独*でなければ含まれたであろうプロダクトを数える——トリアージ推奨）、`"any"`（いずれかのフィルターで除外されたプロダクトを数える。カウントは重複しうる）、または `"approximate"`（セラーが除外を単一フィルターにきれいに帰属できない）。バイヤーはカウントで算術する前に `semantics` を確認すべきです（SHOULD）。 |
| `total_candidates`            | integer | フィルター適用前に検討されたプロダクト数。候補プールが大きい場合はサンプリング/上限設定されることがあります。任意。                                                                                                                                           |
| `excluded_by`                 | object  | キーはリクエストのフィルタープロパティ名（`pricing_currencies`、`required_metrics`、`required_geo_targeting`、`budget_range` など）。各値は `{ count, values?, notes? }`。有意にセットを絞ったフィルターのみ現れればよい。                                   |
| `excluded_by.<filter>.count`  | integer | このフィルターで除外されたプロダクト数。親の `semantics` フィールドに従って解釈します。                                                                                                                                                   |
| `excluded_by.<filter>.values` | array   | 除外に寄与した具体的なフィルター値の任意のリスト（例: `required_metrics` の `["completed_views"]`）。項目はフィルター形状に応じて文字列またはオブジェクト。フィルター固有の知識なしでは不透明。                                                                                |
| `excluded_by.<filter>.notes`  | string  | 絞り込みに関する任意の人が読めるメモ。                                                                                                                                                                                  |

```json theme={null}
{
  "products": [],
  "filter_diagnostics": {
    "semantics": "only",
    "total_candidates": 47,
    "excluded_by": {
      "required_metrics": { "count": 31, "values": ["completed_views"] },
      "required_geo_targeting": { "count": 9 },
      "pricing_currencies": { "count": 3, "values": ["USD"] },
      "budget_range": { "count": 7 }
    }
  }
}
```

### incomplete 配列

`time_budget` 内（またはセラー自身の内部制限により）すべての作業を完了できない場合、レスポンスには欠けている内容を宣言する `incomplete` 配列が含まれます。バイヤーは `estimated_wait` を使って、より大きな予算でリトライするかどうかを判断できます。

| Field            | Type     | Required | Description                                                                                                                                                                                         |
| ---------------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scope`          | string   | Yes      | `"products"`: すべてのインベントリソースを検索できなかった。`"pricing"`: プロダクトは返されたが価格が欠けているか未確定。`"forecast"`: プロダクトは返されたが予測データが欠けています。`"proposals"`: プロポーザルが生成されないか不完全。`"wholesale_feed"`: ホールセールモードで、完全なフィード列挙を完了できなかった。 |
| `description`    | string   | Yes      | 欠けている内容とその理由の人が読める説明。                                                                                                                                                                               |
| `estimated_wait` | Duration | No       | このスコープを解決するのに必要な追加時間。                                                                                                                                                                               |

### ホールセールフィードバージョニング

セラーのホールセール・プロダクトフィードを同期したばかりのバイヤーは、フィードのサイズに関わらず、一度の安価な呼び出しで「バージョン X 以降に何か変わったか？」を尋ねられます。セラーはすべてのホールセールモードレスポンスで不透明な `wholesale_feed_version` を返します。バイヤーは次の呼び出しで `if_wholesale_feed_version` を通じてそれを返し、セラーは `unchanged: true` でショートサーキットしてもよい（MAY）——プロダクトペイロードもページごとの差分もなし。HTTP の `ETag` / `If-None-Match` を踏襲しています。

これは `get_products` が返すセラー側のホールセール・プロダクトフィードです。`sync_catalogs` のフィードではありません。`sync_catalogs` はセラーアカウント上のバイヤー提供のキャンペーン入力フィードを管理します。

**unchanged レスポンスの例:**

リクエスト:

```json theme={null}
{
  "$schema": "/schemas/media-buy/get-products-request.json",
  "buying_mode": "wholesale",
  "if_wholesale_feed_version": "v2026-05-18T08:00:00Z-acme-rev412"
}
```

レスポンス（ホールセール・プロダクトフィードに変更なし）:

```json theme={null}
{
  "$schema": "/schemas/media-buy/get-products-response.json",
  "status": "completed",
  "message": "Wholesale product feed unchanged since v2026-05-18T08:00:00Z-acme-rev412.",
  "context_id": "ctx-abc-789",
  "unchanged": true,
  "wholesale_feed_version": "v2026-05-18T08:00:00Z-acme-rev412",
  "pricing_version": "v2026-05-18T08:00:00Z-acme-rev412",
  "cache_scope": "public"
}
```

レスポンス（ホールセール・プロダクトフィードに変更あり——完全なペイロードを返す。抜粋）:

```json test=false theme={null}
{
  "message": "Returning 50 of 312 products (wholesale feed version advanced).",
  "context_id": "ctx-abc-790",
  "wholesale_feed_version": "v2026-05-18T10:15:00Z-acme-rev415",
  "pricing_version": "v2026-05-18T10:15:00Z-acme-rev415",
  "cache_scope": "public",
  "products": [
    {
      "product_id": "prod_premium_ctv_us",
      "name": "Premium CTV — US",
      "description": "Run-of-network CTV inventory across premium publishers.",
      "publisher_properties": [{ "publisher_domain": "streamhaus.example.com", "property_ids": ["primetime_ctv"] }],
      "format_ids": [{ "id": "video_ctv_1080p_30s" }],
      "delivery_type": "guaranteed",
      "pricing_options": [
        { "pricing_option_id": "po_cpm_v2", "pricing_model": "cpm", "currency": "USD", "fixed_price": 18.50 }
      ]
    }
  ],
  "pagination": { "has_more": true, "cursor": "eyJvIjo1MH0=", "total_count": 312 }
}
```

**ルール**

* トークンは**不透明**です。フォーマットも順序も検査もなし。
* 返された `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 コピー持ちたくありません。パブリックレイヤーはセラーの公開レートカードで、ほとんどのセラーのほとんどのアカウントはそこから直接価格を付けます。プレミアムなカスタムディールが例外です。

**二層キャッシュ。**

| Layer           | Cache key                                                           | What's stored                                                                                           |
| --------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Public          | `(agent, buying_mode, filters, property_list, catalog)`             | `wholesale_feed_version_public`、アカウント参照なしで見たホールセール・プロダクトフィードのペイロード                                      |
| Account overlay | `(agent, buying_mode, filters, property_list, catalog, account_id)` | `wholesale_feed_version_account`、`cache_scope: "account"` が返されたときの、このアカウント参照ありで見たホールセール・プロダクトフィードのペイロード |

**振る舞い。**

* `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 が影響を受ける集合に含まれるサブスクライバーにのみイベントをルーティングします。イベントを受け取ることは「あなたのオーバーレイは古い」を意味します。

Webhook 側の完全な仕様は `specs/wholesale-feed-webhooks.md` の §「Cache layering and event scoping」を参照してください。

**完全なフィールドはスキーマを参照**: [`get-products-response.json`](https://adcontextprotocol.org/schemas/v3/media-buy/get-products-response.json)

## よくあるシナリオ

### タイムバジェット付きの探索

素早い結果が必要で部分的なデータを許容できる場合、タイムバジェットを宣言します。セラーはバジェット内で達成できる最善の結果を返し、不完全な内容を宣言します。

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  const result = await testAgent.getProducts({
    buying_mode: 'brief',
    brief: 'CTV and display for brand awareness',
    brand: {
      domain: 'acmecorp.com'
    },
    time_budget: {
      interval: 10,
      unit: 'seconds'
    }
  });

  if (result.success && result.data) {
    console.log(`Found ${result.data.products.length} products`);

    if (result.data.incomplete) {
      for (const entry of result.data.incomplete) {
        console.log(`Incomplete: ${entry.scope} — ${entry.description}`);
        if (entry.estimated_wait) {
          console.log(`  Would resolve in ${entry.estimated_wait.interval} ${entry.estimated_wait.unit}`);
        }
      }
    }
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_with_time_budget():
      result = await test_agent.simple.get_products(
          buying_mode='brief',
          brief='CTV and display for brand awareness',
          brand={
              'domain': 'acmecorp.com'
          },
          time_budget={
              'interval': 10,
              'unit': 'seconds'
          }
      )
      print(f"Found {len(result.products)} products")

      for entry in result.get('incomplete', []):
          print(f"Incomplete: {entry['scope']} — {entry['description']}")
          if 'estimated_wait' in entry:
              wait = entry['estimated_wait']
              print(f"  Would resolve in {wait['interval']} {wait['unit']}")

  asyncio.run(discover_with_time_budget())
  ```
</CodeGroup>

不完全なデータを含むレスポンスの例 — プロダクトは返されているが一部のスコープが欠けている:

```json test=false theme={null}
{
  "products": [
    {
      "product_id": "prog-display-ros",
      "name": "Programmatic Display — Run of Site",
      "delivery_type": "non_guaranteed",
      "pricing_options": [{ "pricing_option_id": "cpm-ros", "pricing_model": "cpm", "currency": "USD", "fixed_price": 12.00 }]
    }
  ],
  "incomplete": [
    {
      "scope": "products",
      "description": "Premium inventory not searched — requires publisher approval",
      "estimated_wait": { "interval": 60, "unit": "minutes" }
    },
    {
      "scope": "forecast",
      "description": "Forecast model did not complete within budget",
      "estimated_wait": { "interval": 45, "unit": "seconds" }
    }
  ]
}
```

### ホールセールプロダクトの探索

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  // wholesale モード: バイヤー独自のオーディエンスを適用、パブリッシャーキュレーションなし
  const result = await testAgent.getProducts({
    buying_mode: 'wholesale',
    brand: {
      domain: 'acmecorp.com'
    },
    filters: {
      delivery_type: 'non_guaranteed'
    }
  });

  if (result.success && result.data) {
    console.log(`Found ${result.data.products.length} standard wholesale products`);
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_standard_wholesale_products():
      # wholesale モード: バイヤー独自のオーディエンスを適用、パブリッシャーキュレーションなし
      result = await test_agent.simple.get_products(
          buying_mode='wholesale',
          brand={
              'domain': 'acmecorp.com'
          },
          filters={
              'delivery_type': 'non_guaranteed'
          }
      )
      print(f"Found {len(result.products)} standard wholesale products")

  asyncio.run(discover_standard_wholesale_products())
  ```
</CodeGroup>

### マルチフォーマット探索

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  // video と display の両方をサポートするプロダクトを探す
  const result = await testAgent.getProducts({
    buying_mode: 'brief',
    brief: 'Brand awareness campaign with video and display',
    brand: {
      domain: 'acmecorp.com'
    },
    filters: {
      channels: ['display', 'ctv']
    }
  });

  if (result.success && result.data) {
    console.log(`Found ${result.data.products.length} products supporting video and display`);
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_multi_format():
      # Find products supporting both video and display
      result = await test_agent.simple.get_products(
          buying_mode='brief',
          brief='Brand awareness campaign with video and display',
          brand={
              'domain': 'acmecorp.com'
          },
          filters={
              'channels': ['display', 'ctv']
          }
      )
      print(f"Found {len(result.products)} products supporting video and display")

  asyncio.run(discover_multi_format())
  ```
</CodeGroup>

### 予算と日付でのフィルタリング

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  // 指定国とチャンネルで、予算と期間に収まるプロダクトを探す
  const result = await testAgent.getProducts({
    buying_mode: 'brief',
    brief: 'Q2 campaign for athletic footwear in North America',
    brand: {
      domain: 'acmecorp.com'
    },
    filters: {
      start_date: '2025-04-01',
      end_date: '2025-06-30',
      budget_range: {
        min: 50000,
        max: 100000,
        currency: 'USD'
      },
      countries: ['US', 'CA'],
      channels: ['display', 'ctv', 'podcast'],
      delivery_type: 'guaranteed'
    }
  });

  if (result.success && result.data) {
    console.log(`Found ${result.data.products.length} products for Q2 within budget`);
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_with_budget_and_dates():
      # Find products within budget and date range for specific countries and channels
      result = await test_agent.simple.get_products(
          buying_mode='brief',
          brief='Q2 campaign for athletic footwear in North America',
          brand={
              'domain': 'acmecorp.com'
          },
          filters={
              'start_date': '2025-04-01',
              'end_date': '2025-06-30',
              'budget_range': {
                  'min': 50000,
                  'max': 100000,
                  'currency': 'USD'
              },
              'countries': ['US', 'CA'],
              'channels': ['display', 'ctv', 'podcast'],
              'delivery_type': 'guaranteed'
          }
      )
      print(f"Found {len(result.products)} products for Q2 within budget")

  asyncio.run(discover_with_budget_and_dates())
  ```
</CodeGroup>

### プロパティタグの解決

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  // property_tags を持つプロダクトを取得
  const result = await testAgent.getProducts({
    buying_mode: 'brief',
    brief: 'Sports content',
    brand: {
      domain: 'acmecorp.com'
    }
  });

  if (result.success && result.data) {
    // publisher_properties に property_tags がある場合は大規模ネットワークを意味する
    // エージェントのポートフォリオは get_adcp_capabilities で確認する
    const productsWithTags = result.data.products.filter(p =>
      p.publisher_properties?.some(pub => pub.property_tags && pub.property_tags.length > 0)
    );
    console.log(`${productsWithTags.length} products use property tags (large networks)`);
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_property_tags():
      # Get products with property tags
      result = await test_agent.simple.get_products(
          buying_mode='brief',
          brief='Sports content',
          brand={
              'domain': 'acmecorp.com'
          }
      )

      # publisher_properties に property_tags がある場合は大規模ネットワークを意味する
      # エージェントのポートフォリオは get_adcp_capabilities で確認する
      products_with_tags = [p for p in result.products
          if any(pub.get('property_tags') for pub in p.get('publisher_properties', []))]
      print(f"{len(products_with_tags)} products use property tags (large networks)")

  asyncio.run(discover_property_tags())
  ```
</CodeGroup>

### 保証配信のプロダクト

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  // Find guaranteed delivery products for measurement
  const result = await testAgent.getProducts({
    buying_mode: 'brief',
    brief: 'Guaranteed delivery for lift study',
    brand: {
      domain: 'acmecorp.com'
    },
    filters: {
      delivery_type: 'guaranteed',
      min_exposures: 100000
    }
  });

  if (result.success && result.data) {
    console.log(`Found ${result.data.products.length} guaranteed products with 100k+ exposures`);
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_guaranteed():
      # 計測用に保証配信のプロダクトを探す
      result = await test_agent.simple.get_products(
          buying_mode='brief',
          brief='Guaranteed delivery for lift study',
          brand={
              'domain': 'acmecorp.com'
          },
          filters={
              'delivery_type': 'guaranteed',
              'min_exposures': 100000
          }
      )
      print(f"Found {len(result.products)} guaranteed products with 100k+ exposures")

  asyncio.run(discover_guaranteed())
  ```
</CodeGroup>

### 標準フォーマットのみ

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  // IAB 標準フォーマットのみ受け付けるプロダクトを探す
  const result = await testAgent.getProducts({
    buying_mode: 'wholesale',
    brand: {
      domain: 'acmecorp.com'
    },
    filters: {
      standard_formats_only: true
    }
  });

  if (result.success && result.data) {
    console.log(`Found ${result.data.products.length} products with standard formats only`);
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_standard_formats():
      # IAB 標準フォーマットのみ受け付けるプロダクトを探す
      result = await test_agent.simple.get_products(
          buying_mode='wholesale',
          brand={
              'domain': 'acmecorp.com'
          },
          filters={
              'standard_formats_only': True
          }
      )
      print(f"Found {len(result.products)} products with standard formats only")

  asyncio.run(discover_standard_formats())
  ```
</CodeGroup>

### カタログ主導の探索

`catalog` とブランドを使って、カタログアイテムを宣伝できる広告プロダクトを探す。セラーはアイテムをインベントリに照合し、マッチが存在するプロダクトを返します。

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  // 特定のカタログアイテム向けのリテールメディアプロダクトを探す
  const result = await testAgent.getProducts({
    buying_mode: 'wholesale',
    brand: {
      domain: 'acmecorp.com'
    },
    catalog: {
      type: 'product',
      tags: ['ketchup', 'organic'],
      category: 'food/condiments'
    },
    filters: {
      channels: ['retail_media']
    }
  });

  if (result.success && result.data) {
    if (result.data.catalog_applied) {
      console.log(`Found ${result.data.products.length} products with catalog matches`);
    } else {
      console.log('Seller does not support catalog matching');
    }
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_commerce_products():
      # 特定のカタログアイテム向けのリテールメディアプロダクトを探す
      result = await test_agent.simple.get_products(
          buying_mode='wholesale',
          brand={
              'domain': 'acmecorp.com'
          },
          catalog={
              'type': 'product',
              'tags': ['ketchup', 'organic'],
              'category': 'food/condiments'
          },
          filters={
              'channels': ['retail_media']
          }
      )
      if result.get('catalog_applied'):
          print(f"Found {len(result.products)} products with catalog matches")
      else:
          print("Seller does not support catalog matching")

  asyncio.run(discover_commerce_products())
  ```

  ```bash CLI requires-env=ADCP_AUTH_TOKEN theme={null}
  uvx adcp \
    https://test-agent.adcontextprotocol.org/sales/mcp \
    get_products \
    '{"buying_mode":"wholesale","brand":{"domain":"acmecorp.com"},"catalog":{"type":"product","tags":["ketchup","organic"],"category":"food/condiments"},"filters":{"channels":["retail_media"]}}' \
    --auth $ADCP_AUTH_TOKEN
  ```
</CodeGroup>

GTIN マッチング、同期済みカタログの参照、または他のカタログ種別向けのプロダクト探索も利用できます。

```json theme={null}
{
  "catalog": {
    "type": "product",
    "gtins": ["00013000006040", "00013000006057"]
  }
}
```

```json theme={null}
{
  "catalog": {
    "catalog_id": "gmc-primary",
    "type": "product"
  }
}
```

```json theme={null}
{
  "catalog": {
    "type": "job",
    "catalog_id": "chef-vacancies"
  }
}
```

### プロパティリストでのフィルタリング

<Info>
  **AdCP 3.0** - プロパティリストでのフィルタリングにはガバナンスエージェントの対応が必要です。
</Info>

承認済みリストのプロパティで利用できるプロダクトだけに絞る。

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';

  // Filter products by property list from governance agent
  const result = await testAgent.getProducts({
    buying_mode: 'brief',
    brief: 'Brand-safe inventory for family brand',
    brand: {
      domain: 'acmecorp.com'
    },
    property_list: {
      agent_url: 'https://governance.example.com',
      list_id: 'pl_brand_safe_2024'
    }
  });

  if (result.success && result.data) {
    // フィルタが適用されたか確認
    if (result.data.property_list_applied) {
      console.log(`Found ${result.data.products.length} products on approved properties`);
    } else {
      console.log('Agent does not support property list filtering');
      console.log(`Found ${result.data.products.length} products (unfiltered)`);
    }
  }
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent

  async def discover_with_property_list():
      # ガバナンスエージェントのプロパティリストでフィルタリング
      result = await test_agent.simple.get_products(
          buying_mode='brief',
          brief='Brand-safe inventory for family brand',
          brand={
              'domain': 'acmecorp.com'
          },
          property_list={
              'agent_url': 'https://governance.example.com',
              'list_id': 'pl_brand_safe_2024'
          }
      )

      # Check if filtering was actually applied
      if result.get('property_list_applied'):
          print(f"Found {len(result['products'])} products on approved properties")
      else:
          print("Agent does not support property list filtering")
          print(f"Found {len(result['products'])} products (unfiltered)")

  asyncio.run(discover_with_property_list())
  ```
</CodeGroup>

**注意**: `property_list_applied` が省略または `false` の場合、セールスエージェントはプロダクトをフィルタリングしていません。これは以下の場合に発生する:

* エージェントがプロパティガバナンス機能をサポートしていません
* エージェントがプロパティリストにアクセスできなかった
* プロパティリストが利用可能なインベントリに影響しなかった

#### プロパティターゲティングの動作

プロダクトには `property_targeting_allowed` フラグがあり、フィルタリングに影響します。

* **`property_targeting_allowed: false`（デフォルト）**: プロダクトは「all or nothing」— あなたのリストがプロダクトのすべてのプロパティを含まない限り除外されます
* **`property_targeting_allowed: true`**: プロダクトのプロパティとあなたのリストに交差がある場合にインクルードされます

これにより、パブリッシャーはバイヤーが個別選択できないラン・オブ・ネットワークプロダクトと、バイヤーがフィルタリングできる柔軟なインベントリを提供できます。

詳細は [Property Targeting](/docs/media-buy/product-discovery/media-products#property-targeting) を参照。プロパティリストについては [Property Governance](/docs/governance/property/specification) を参照。

## リファインメント

初回探索の後、`buying_mode: "refine"` を使って特定のプロダクトやプロポーザルを反復できます。`refine` 配列は変更依頼のリストで、各エントリはスコープとバイヤーが求める内容を宣言します。セラーは更新された価格と設定を持つプロダクトを返し、各依頼を `refinement_applied` で確認します。

完全なウォークスルー（スコープタイプ、アクションの意味論、セラーのレスポンス、よくあるパターン）は [Refinement ガイド](/docs/media-buy/product-discovery/refinement) を参照してください。パラメータ形状は上記の [Refine 配列](#refine-配列) セクションで定義されています。

最小の例:

```json test=false theme={null}
{
  "buying_mode": "refine",
  "refine": [
    { "scope": "request",                                             "ask": "more video, less display" },
    { "scope": "product",  "product_id":  "prod_premium_video",       "ask": "add 16:9 format option" },
    { "scope": "product",  "product_id":  "prod_display_run_of_site", "action": "omit" },
    { "scope": "proposal", "proposal_id": "prop_awareness_q2",        "ask": "reallocate display budget to video" }
  ],
  "filters": {
    "start_date": "2026-04-01",
    "end_date": "2026-04-30",
    "budget_range": { "min": 200000, "max": 200000, "currency": "USD" }
  }
}
```

送信前に知っておくべき主なルール:

* **`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

| Error Code                   | Description                                                                   | Resolution                                                                           |
| ---------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `AUTH_MISSING`               | 認証情報が提示されていない                                                                 | auth ヘッダーで認証情報を提供する                                                                  |
| `AUTH_INVALID`               | 認証情報が拒否された（期限切れ/失効）                                                           | 人による認証情報のローテーションが必要。自動リトライしない                                                        |
| `INVALID_REQUEST`            | ブリーフが長すぎるか、フィルターが不正                                                           | リクエストパラメーターを確認する                                                                     |
| `PRODUCT_NOT_FOUND`          | 1 つ以上の参照プロダクト ID が未知または期限切れ                                                   | 無効な ID を削除して再試行するか、`brief` リクエストで再探索する                                               |
| `PROPOSAL_EXPIRED`           | 参照したプロポーザル ID が `expires_at` タイムスタンプを過ぎている                                    | 新しい `brief` または `wholesale` リクエストで再探索する                                              |
| `PROPOSAL_NOT_FOUND`         | 参照した `proposal_id` がセラーにとって未知（finalize されていない、テナント違い、キャッシュから追い出された）           | `refine` モードで `action: 'finalize'` を指定して `get_products` を再発行し、現在の proposal\_id を取得する |
| `MULTI_FINALIZE_UNSUPPORTED` | `refine[]` が複数の `action: 'finalize'` エントリを運んだが、セラーがアトミックな複数プロポーザルのコミットを保証できない | 単一プロポーザルの finalize 呼び出しを順に実行——`get_products` 呼び出しごとに finalize エントリを1つ                |
| `POLICY_VIOLATION`           | 広告主に対してカテゴリがブロックされている                                                         | ポリシーレスポンスメッセージで詳細を確認する                                                               |

### Authentication Comparison

認証あり・なしのアクセスの違いを確認します。

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { testAgent, testAgentNoAuth } from '@adcp/sdk/testing';

  // WITH authentication - full catalog with pricing
  const fullCatalog = await testAgent.getProducts({
    buying_mode: 'brief',
    brief: 'Premium CTV inventory for brand awareness',
    brand: {
      domain: 'acmecorp.com'
    }
  });

  if (!fullCatalog.success) {
    throw new Error(`Failed to get products: ${fullCatalog.error}`);
  }

  console.log(`With auth: ${fullCatalog.data.products.length} products`);
  console.log(`First product pricing: ${fullCatalog.data.products[0].pricing_options.length} options`);

  // WITHOUT authentication - limited public catalog
  const publicCatalog = await testAgentNoAuth.getProducts({
    buying_mode: 'brief',
    brief: 'Premium CTV inventory for brand awareness',
    brand: {
      domain: 'acmecorp.com'
    }
  });

  if (!publicCatalog.success) {
    throw new Error(`Failed to get products: ${publicCatalog.error}`);
  }

  console.log(`Without auth: ${publicCatalog.data.products.length} products`);
  console.log(`First product pricing: ${publicCatalog.data.products[0].pricing_options?.length || 0} options`);
  ```

  ```python Python theme={null}
  import asyncio
  from adcp.testing import test_agent, test_agent_no_auth

  async def compare_auth():
      # WITH authentication - full catalog with pricing
      full_catalog = await test_agent.simple.get_products(
          buying_mode='brief',
          brief='Premium CTV inventory for brand awareness',
          brand={
              'domain': 'acmecorp.com'
          }
      )

      print(f"With auth: {len(full_catalog['products'])} products")
      print(f"First product pricing: {len(full_catalog['products'][0]['pricing_options'])} options")

      # WITHOUT authentication - limited public catalog
      public_catalog = await test_agent_no_auth.simple.get_products(
          buying_mode='brief',
          brief='Premium CTV inventory for brand awareness',
          brand={
              'domain': 'acmecorp.com'
          }
      )

      print(f"Without auth: {len(public_catalog['products'])} products")
      print(f"First product pricing: {len(public_catalog['products'][0].get('pricing_options', []))} options")

  asyncio.run(compare_auth())
  ```
</CodeGroup>

**主な違い:**

* **プロダクト数**: 認証ありのアクセスはプライベート/カスタムオファリングを含む多くのプロダクトを返す
* **価格情報**: 認証ありのリクエストのみ詳細な価格オプション（CPM、CPCV など）を受け取れる
* **ターゲティング詳細**: カスタムターゲティング機能は認証ユーザーに限定される場合があります
* **レート制限**: 認証なしのリクエストはレート制限が低い

## Authentication Behavior

* **認証情報なし**: 制限された公開プロダクト結果を返します。価格なし、カスタムオファリングなし
* **認証情報あり**: 価格とカスタムプロダクトを含む完全なプロダクト結果を返す

詳細は [Authentication Guide](/docs/building/by-layer/L2/authentication) を参照。

## Asynchronous Operations

ほとんどのプロダクト検索は即時完了するが、一部のシナリオでは非同期処理が必要になります。その場合、`completed` 以外のステータスを受け取ります。`task_id` を持つ `submitted` レスポンスは常に `get_task_status`（レガシーの `tasks/get`）でポーリング可能です。`push_notification_config` はバックグラウンドワークフロー向けに Webhook 通知を追加します。

#### SDK でのステータス処理

```typescript theme={null}
const initial = await agent.getProducts(params);
const final =
  initial.status === 'submitted'
    ? await initial.submitted!.waitForCompletion(30000)
    : initial;

if (final.status === 'failed') {
  throw new Error(final.error?.message ?? 'get_products failed');
}

if (final.status !== 'completed') {
  throw new Error(`Unhandled get_products status: ${final.status}`);
}

for (const product of final.products) {
  console.log(product.name);
}
```

### 非同期処理が発生するケース

以下の状況でプロダクト検索に非同期処理が必要になる場合があります。

* **複雑な検索**: 複数のインベントリソースをまたぐ検索やカスタムキュレーション
* **追加確認が必要**: ブリーフが曖昧でシステムが追加情報を必要とします
* **カスタムプロダクト**: 人間のレビューが必要なオーダーメイドのプロダクトパッケージ

### Async Status Flow

<Tabs>
  <Tab title="MCP">
    #### 即時完了（最も一般的）

    ```json theme={null}
    POST /api/mcp/call_tool

    {
      "name": "get_products",
      "arguments": {
        "buying_mode": "brief",
        "brief": "CTV inventory for sports audience",
        "brand": { "domain": "acmecorp.com" }
      }
    }

    Response (200 OK):
    {
      "status": "completed",
      "message": "Found 3 products matching your requirements",
      "products": [...]
    }
    ```

    #### Needs Clarification

    ブリーフが不明確な場合、システムは詳細情報を求める。

    ```json theme={null}
    Response (200 OK):
    {
      "status": "input-required",
      "message": "I need a bit more information. What's your budget range and campaign duration?",
      "task_id": "task_789",
      "context_id": "ctx_123",
      "reason": "CLARIFICATION_NEEDED",
      "partial_results": [],
      "suggestions": ["$50K-$100K", "1 month", "Q1 2024"]
    }
    ```

    同じ `context_id` で会話を続ける:

    ```json theme={null}
    POST /api/mcp/continue

    {
      "context_id": "ctx_123",
      "message": "Budget is $75K for a 3-week campaign in March"
    }

    Response (200 OK):
    {
      "status": "completed",
      "message": "Perfect! Found 5 products within your budget",
      "products": [...]
    }
    ```

    #### Complex Search (With Webhook and Polling)

    深いインベントリ分析が必要な検索には、最終の完了/失敗通知のための Webhook を設定します。返される `task_id` は `get_task_status`（レガシーの `tasks/get`）によるポーリング用に有効なままです。

    ```json theme={null}
    POST /api/mcp/call_tool

    {
      "name": "get_products",
      "arguments": {
        "buying_mode": "brief",
        "brief": "Premium inventory across all formats for luxury automotive brand",
        "brand": { "domain": "acmecorp.com" },
        "push_notification_config": {
          "url": "https://buyer.com/webhooks/adcp/get_products",
          "authentication": {
            "schemes": ["Bearer"],
            "credentials": "secret_token_32_chars"
          }
        }
      }
    }

    Response (200 OK):
    {
      "status": "submitted",
      "message": "Custom curation queued; typical turnaround 10-30 minutes",
      "task_id": "task_456",
      "context_id": "ctx_123",
      "estimated_completion": "2025-01-22T10:30:00Z"
    }

    // 後で task_id で get_task_status/tasks/get をポーリングするか、https://buyer.com/webhooks/adcp/get_products に Webhook POST が届く
    {
      "task_id": "task_456",
      "task_type": "get_products",
      "status": "completed",
      "timestamp": "2025-01-22T10:30:00Z",
      "message": "Found 12 premium products across all formats",
      "result": {
        "products": [...]
      }
    }
    ```
  </Tab>

  <Tab title="A2A">
    #### Immediate Completion (Most Common)

    ```json theme={null}
    POST /api/a2a

    {
      "message": {
        "role": "user",
        "parts": [{
          "kind": "data",
          "data": {
            "skill": "get_products",
            "parameters": {
              "buying_mode": "brief",
              "brief": "CTV inventory for sports audience",
              "brand": { "domain": "acmecorp.com" }
            }
          }
        }]
      }
    }

    Response (200 OK):
    {
      "id": "task_123",
      "contextId": "ctx_456",
      "artifact": {
        "kind": "data",
        "data": {
          "products": [...]
        }
      },
      "status": {
        "state": "completed",
        "message": {
          "role": "agent",
          "parts": [{ "text": "Found 3 products matching your requirements" }]
        }
      }
    }
    ```

    #### 追加確認が必要な場合

    確認が必要な場合、SSE でリアルタイム更新を受け取ります。

    ```json theme={null}
    // Initial response
    {
      "id": "task_789",
      "contextId": "ctx_123",
      "status": {
        "state": "input-required",
        "message": {
          "role": "agent",
          "parts": [
            { "text": "I need a bit more information. What's your budget range and campaign duration?" },
            {
              "data": {
                "reason": "CLARIFICATION_NEEDED",
                "suggestions": ["$50K-$100K", "1 month", "Q1 2024"]
              }
            }
          ]
        }
      }
    }

    // 追いメッセージを送る
    POST /api/a2a

    {
      "contextId": "ctx_123",
      "message": {
        "role": "user",
        "parts": [{ "text": "Budget is $75K for a 3-week campaign in March" }]
      }
    }

    // SSE 更新: タスク完了
    {
      "id": "task_789",
      "contextId": "ctx_123",
      "artifact": {
        "kind": "data",
        "data": { "products": [...] }
      },
      "status": {
        "state": "completed",
        "message": {
          "role": "agent",
          "parts": [{ "text": "Perfect! Found 5 products within your budget" }]
        }
      }
    }
    ```

    #### 複雑な検索（Webhook 併用・ポーリング）

    A2A では、プッシュ通知はトランスポートレベルの `configuration.pushNotificationConfig` フィールドを使います。snake\_case の `push_notification_config` を skill パラメータ内に入れてはいけません。A2A のタスク ID はタスクのポーリング用に有効なままです。

    ```json theme={null}
    POST /api/a2a

    {
      "message": {
        "role": "user",
        "parts": [{
          "kind": "data",
          "data": {
            "skill": "get_products",
            "parameters": {
              "buying_mode": "brief",
              "brief": "Premium inventory across all formats for luxury automotive brand",
              "brand": { "domain": "acmecorp.com" }
            }
          }
        }]
      },
      "configuration": {
        "pushNotificationConfig": {
          "url": "https://buyer.com/webhooks/a2a/get_products",
          "authentication": {
            "schemes": ["bearer"],
            "credentials": "secret_token_32_chars"
          }
        }
      }
    }

    Response (200 OK):
    {
      "id": "task_456",
      "contextId": "ctx_789",
      "status": {
        "state": "submitted",
        "message": {
          "role": "agent",
          "parts": [
            { "text": "Custom curation queued; typical turnaround 10-30 minutes" },
            {
              "data": {
                "estimated_completion": "2025-01-22T10:30:00Z"
              }
            }
          ]
        }
      }
    }

    // 後で A2A タスクをポーリングするか、https://buyer.com/webhooks/a2a/get_products に Webhook POST が届く
    {
      "id": "task_456",
      "contextId": "ctx_789",
      "artifact": {
        "kind": "data",
        "data": {
          "products": [...]
        }
      },
      "status": {
        "state": "completed",
        "message": {
          "role": "agent",
          "parts": [
            { "text": "Found 12 premium products across all formats" },
            {
              "data": {
                "products": [...]
              }
            }
          ]
        },
        "timestamp": "2025-01-22T10:30:00Z"
      }
    }
    ```
  </Tab>
</Tabs>

### ステータス概要

| Status           | 発生タイミング           | 対応                                                                                                                                                     |
| ---------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `completed`      | 検索が正常完了           | プロダクト結果を処理                                                                                                                                             |
| `input-required` | ブリーフに追加確認が必要      | 質問に回答して続行                                                                                                                                              |
| `working`        | 複数ソースを検索中         | オープンな接続/トランスポートの進捗ストリームで待つ                                                                                                                             |
| `submitted`      | カスタムキュレーションがキュー入り | `task_id` で `get_task_status`（レガシーの `tasks/get`）をポーリング。`push_notification_config` / A2A `configuration.pushNotificationConfig` が受理された場合は Webhook 通知も待つ |
| `failed`         | 検索を完了できなかった       | エラーメッセージを確認しブリーフ調整                                                                                                                                     |

**注意:** 完全なステータス一覧は [Task Lifecycle](/docs/building/by-layer/L3/task-lifecycle) を参照。

**ほとんどの検索は即時完了します。** 非同期処理が必要なのは複雑なケースや追加入力が必要な場合のみ。

## 次のステップ

プロダクトを見つけたら:

1. **選択肢を確認**: プロダクト、価格、ターゲティング能力を比較
2. **メディアバイ作成**: [`create_media_buy`](/docs/media-buy/task-reference/create_media_buy) でキャンペーンを実行
3. **クリエイティブ準備**: [`list_creative_formats`](/docs/creative/task-reference/list_creative_formats) で要件を確認
4. **アセット提供**: ライブラリ対応のセラーには [`sync_creatives`](/docs/creative/task-reference/sync_creatives) を、インライン専用のセラーにはインラインの `packages[].creatives` を使用

## さらに学ぶ

* [Product Discovery Guide](/docs/media-buy/product-discovery/) - ブリーフとプロダクトの理解
* [Pricing Models](/docs/media-buy/advanced-topics/pricing-models) - CPM, CPCV, CPP の解説
* [Brief Expectations](/docs/media-buy/product-discovery/brief-expectations) - 効果的なブリーフの書き方
* [Media Products](/docs/media-buy/product-discovery/media-products) - プロダクト構造とフィールド
