> ## 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_media_buys

> get_media_buys タスク — クリエイティブ承認、不足アセット、設定、オプションのほぼリアルタイム配信スナップショットを含む AdCP のメディアバイステータスを取得します。

メディアバイの現在の運用状態（設定、クリエイティブ承認ステータス、不足アセット、オプションのほぼリアルタイム配信スナップショット）を取得します。

**応答時間**: 約1秒

## 結果のスコープ

セールスエージェントは、認証済みアカウントが所有するすべてのメディアバイを返さなければなりません（MUST）。そのバイがどのように作成されたか——AdCP の `create_media_buy` 経由、セラー自身の API 経由、手動トラフィッキング経由、レガシーまたはサードパーティのシステム経由——は問いません。スコープは**アカウントの所有権**であり、作成のサーフェスではありません。ここで返される `media_buy_id` は、認証済みの呼び出し元がアクセスできるセラーのアドサーバー上の任意のオーダーを識別します。

`get_media_buys` が返すメディアバイはすべて、その `valid_actions` にあるすべてのタスクから到達可能でなければなりません（MUST）。セールスエージェントは、元々 AdCP 経由で作成されたものではないことを理由に、バイを読み取り専用としたり、隠したり、更新を拒否したりしてはなりません（MUST NOT）。ビジネス上の理由（契約上の義務、プラットフォームの制約、ポリシー）でアクションが利用できない場合、セラーはそのアクションのみを `valid_actions` から省略しなければなりません（MUST）——セット全体を省略してはならず、単に AdCP の外で作成されたという理由だけで省略してもなりません。AdCP 外のバイを体系的に空の `valid_actions` で返すセラーは非準拠です。そのパターンは、バイを隠しているのと区別がつきません。

呼び出し元からインベントリを分離する必要があるセラーは、アカウント内ではなく**アカウント境界**で行わなければなりません（MUST）。[アカウントの所有権と作成サーフェス](/docs/media-buy/specification#アカウントの所有権と作成サーフェス)を参照してください。

**リクエストスキーマ**: [`/schemas/v3/media-buy/get-media-buys-request.json`](https://adcontextprotocol.org/schemas/v3/media-buy/get-media-buys-request.json)
**レスポンススキーマ**: [`/schemas/v3/media-buy/get-media-buys-response.json`](https://adcontextprotocol.org/schemas/v3/media-buy/get-media-buys-response.json)

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

| パラメータ                      | 型                                                                                | 必須    | 説明                                                                                                                                                                      |
| -------------------------- | -------------------------------------------------------------------------------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account`                  | [account-ref](/docs/building/by-layer/L2/accounts-and-agents#account-references) | いいえ   | アカウント参照。`{ "account_id": "..." }` または、セラーが暗黙的な解決をサポートしている場合は `{ "brand": {...}, "operator": "..." }` を渡します。省略した場合、アクセス可能なすべてのアカウントのデータを返します。                            |
| `media_buy_ids`            | string\[]                                                                        | いいえ\* | 取得するメディアバイIDの配列                                                                                                                                                         |
| `status_filter`            | string \| string\[]                                                              | いいえ   | ステータスフィルター: `"pending_creatives"`、`"pending_start"`、`"active"`、`"paused"`、`"completed"`、`"rejected"`、`"canceled"`。`media_buy_ids` が省略された場合のみ、デフォルトで `["active"]` になります。 |
| `include_snapshot`         | boolean                                                                          | いいえ   | true の場合、各パッケージのほぼリアルタイム配信スナップショットを含めます。デフォルトは `false`。                                                                                                                 |
| `include_history`          | integer                                                                          | いいえ   | メディアバイごとに直近 N 件のリビジョン履歴エントリを含めます（min(N, 利用可能数) を返します）。除外するには 0 または省略。最大 1000。                                                                                           |
| `include_webhook_activity` | boolean                                                                          | いいえ   | true の場合、各メディアバイに、呼び出し元プリンシパル向けの最近の配信レポートウェブフック発火を含む `webhook_activity` 配列が含まれます。デフォルトは `false`。[ウェブフックアクティビティ](#ウェブフックアクティビティ)を参照。                                     |
| `webhook_activity_limit`   | integer                                                                          | いいえ   | バイごとに返すウェブフックレコードの上限（新しい順）。範囲 1〜200、デフォルト 50。`include_webhook_activity` が false の場合は無視されます。                                                                             |
| `pagination`               | object                                                                           | いいえ   | 広範なクエリのカーソルベースのページネーション制御（`max_results`、`cursor`）。                                                                                                                      |

\*`media_buy_ids` は結果を特定のメディアバイに絞り込む。どちらも指定しない場合、クエリはスコープベースとなり `status_filter` と `pagination` を使用します。

`media_buy_ids` を指定した場合、暗黙的なステータスフィルタリングは適用されない。特定のバイをステータスでフィルタリングしたい場合は `status_filter` を明示的に渡すこと。

## レスポンス

現在のステータス、クリエイティブ承認状態、オプションの配信スナップショットを含むメディアバイの配列を返します:

| フィールド        | 説明                                                          |
| ------------ | ----------------------------------------------------------- |
| `media_buys` | メディアバイオブジェクトの配列                                             |
| `pagination` | カーソルページネーションメタデータ（`has_more`、`cursor`、オプションの `total_count`） |
| `errors`     | タスク固有のエラー（例: メディアバイが見つからない）                                 |

### メディアバイオブジェクト

<Note>
  **3.1 の語彙に関する注記。** `get_media_buys` はライフサイクルの状態をネストされた `media_buys[].status` フィールドで返します（深さ 1 にネストされているため、エンベロープとの衝突はありません）。`create_media_buy` と `update_media_buy` の成功レスポンスは、同じ状態をトップレベルの **`media_buy_status`** フィールドで返します（エンベロープのタスクステータス `status` との衝突を避けるため 3.1 で追加）。3.1 では同じ列挙に対して二つのフィールド名が存在し、この連鎖は 4.0 で統合されます（[#4905](https://github.com/adcontextprotocol/adcp/issues/4905)）。呼び出しをまたいで状態を保持するバイヤーは、両者を同じ論理的な値として扱うべきです。全体像については[マイグレーション › `media_buy_status`](/docs/reference/migration/media-buy-status)を参照してください。
</Note>

| フィールド               | 説明                                                                                                                                                                                                                                                                                                    |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `media_buy_id`      | セラーのメディアバイ識別子                                                                                                                                                                                                                                                                                         |
| `invoice_recipient` | 作成時に指定された場合の、バイごとの請求書送付先。セラーが請求のオーバーライドを受理したことを確認します。銀行の詳細は省略されます（書き込み専用）。                                                                                                                                                                                                                            |
| `status`            | 現在のステータス（`pending_creatives`、`pending_start`、`active`、`paused`、`completed`、`rejected`、`canceled`）。`create_media_buy` / `update_media_buy` の成功レスポンスの `media_buy_status` に対応します（上記 3.1 の語彙に関する注記を参照）。                                                                                                   |
| `status_as_of`      | セラーが、返されたメディアバイレベルの `status` を信頼できる情報源から最後に更新した ISO 8601 タイムスタンプ。ロールアップされたステータスの場合、返されるロールアップに影響しうる上流ステータス観測のうち最も古いものより後であってはなりません（MUST NOT）。任意です。省略または `null` の場合は鮮度について何も主張せず、バイヤーは不在からライブなステータスを推論してはなりません（MUST NOT）。キャッシュされた、またはロールアップされたステータスを、メディアバイの最終更新時刻を意味する `updated_at` とは別に解釈するために使用します。 |
| `currency`          | メディアバイレベルの金額に使用する ISO 4217 通貨                                                                                                                                                                                                                                                                         |
| `total_budget`      | キャンペーンの合計予算（`currency` 単位）                                                                                                                                                                                                                                                                            |
| `creative_deadline` | クリエイティブのアップロード期限（ISO 8601）                                                                                                                                                                                                                                                                            |
| `confirmed_at`      | セラーがこのメディアバイにコミットした ISO 8601 タイムスタンプ。遅延承認/手動承認のフローでは、セラーのコミットが発生するまで `null` の場合があります。設定後は安定します。                                                                                                                                                                                                       |
| `cancellation`      | キャンセルのメタデータ（`status` が `canceled` の場合にのみ存在）。`canceled_at`（ISO 8601）、`canceled_by`（`"buyer"` または `"seller"`）、任意の `reason` を持つオブジェクト。                                                                                                                                                                   |
| `revision`          | 現在のリビジョン番号。楽観的並行性制御のために `update_media_buy` に渡します。                                                                                                                                                                                                                                                     |
| `valid_actions`     | 現在の状態でバイヤーが実行できるアクション（例: `["pause", "cancel", "update_budget"]`）。[有効なアクションのマッピング](#有効なアクションのマッピング)を参照。                                                                                                                                                                                                |
| `history`           | リビジョン履歴のエントリ、新しい順。`include_history > 0` の場合にのみ存在します。追記専用——エントリが変更または削除されることはありません。                                                                                                                                                                                                                    |
| `webhook_activity`  | 呼び出し元プリンシパル向けの最近のレポーティングおよびヘルスのウェブフック発火、新しい順。`include_webhook_activity` が true で、**かつ**セラーがこのバイの発火履歴を公開している場合にのみ存在します。三状態の存在セマンティクスについては[ウェブフックアクティビティ](#ウェブフックアクティビティ)を参照。                                                                                                                           |
| `context`           | `create_media_buy` からそのままエコーされる、メディアバイレベルの不透明な相関データ。メディアバイが context 付きで AdCP を通じて作成された場合、セラーは永続化した context を含めなければならず（MUST）、AdCP 外で、または context なしで作成されたメディアバイでは省略してもかまいません（MAY）。`media_buy_id` をバイヤーのトラッキング状態と突き合わせるために使用します。                                                                        |
| `packages`          | クリエイティブステータスとオプションのスナップショットを含むパッケージの配列                                                                                                                                                                                                                                                                |

### パッケージオブジェクト

| フィールド                         | 説明                                                                                                                                                                                                                                                                                                                                               |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `package_id`                  | セラーのパッケージ識別子                                                                                                                                                                                                                                                                                                                                     |
| `product_id`                  | このパッケージの購入元となるプロダクト識別子。明示的な `create_media_buy` のパッケージリクエストから作成されたパッケージについて、セラーは、そのリクエストされたパッケージを表すすべてのレスポンスパッケージオブジェクトで、リクエストパッケージの `product_id` をエコーしなければなりません（MUST）。                                                                                                                                                                           |
| `currency`                    | オプションのパッケージレベルの通貨オーバーライド（デフォルトはメディアバイの `currency`）                                                                                                                                                                                                                                                                                               |
| `bid_price`                   | オークションベースパッケージの現在の入札価格（パッケージの `currency` が存在する場合はその通貨、なければメディアバイの `currency`）                                                                                                                                                                                                                                                                    |
| `format_ids`                  | `create_media_buy` で指定されたレガシーの名前付きフォーマット ID。元のリクエストに含まれていた場合は常にエコーされます。別のセレクターが優先された二重出力のケースも含みます。                                                                                                                                                                                                                                               |
| `format_option_refs`          | `create_media_buy` で指定された構造化された 3.1+ のフォーマットオプション参照。元のリクエストに含まれていた場合は常にエコーされます。                                                                                                                                                                                                                                                                  |
| `format_kind`                 | `create_media_buy` で指定された直接的な正規セレクター。元のリクエストに含まれていた場合は常にエコーされます。別のセレクターが優先された情報提供目的のエコーのケースも含みます。                                                                                                                                                                                                                                                |
| `params`                      | `format_kind` の直接的な正規セレクター向けのパラメータ。元のリクエストに含まれていた場合は常にエコーされます。`format_kind` が必要です。                                                                                                                                                                                                                                                               |
| `start_time`                  | フライト開始時刻（ISO 8601）。配信ステータスを解釈する前にこれを確認すること。                                                                                                                                                                                                                                                                                                      |
| `end_time`                    | フライト終了時刻（ISO 8601）                                                                                                                                                                                                                                                                                                                               |
| `paused`                      | バイヤーがこのパッケージを一時停止しているかどうか                                                                                                                                                                                                                                                                                                                        |
| `canceled`                    | このパッケージがキャンセルされたかどうか（取り消し不可）                                                                                                                                                                                                                                                                                                                     |
| `cancellation`                | キャンセルのメタデータ（`canceled` が true の場合にのみ存在）。`canceled_at`（ISO 8601）、`canceled_by`（`"buyer"` または `"seller"`）、任意の `reason` を持つオブジェクト。                                                                                                                                                                                                                  |
| `creative_deadline`           | パッケージごとのクリエイティブ期限（ISO 8601）。不在の場合、メディアバイの `creative_deadline` が適用されます。                                                                                                                                                                                                                                                                           |
| `context`                     | `create_media_buy` のパッケージリクエストからそのままエコーされる、パッケージレベルの不透明な相関データ。パッケージが context 付きで AdCP を通じて作成された場合、セラーは永続化した context を含めなければならず（MUST）、AdCP 外で、または context なしで作成されたパッケージでは省略してもかまいません（MAY）。混在するセラー群を対象とするバイヤーは、レガシーな create レスポンスが `product_id` をエコーしなかった場合に、作成時に含めたパッケージごとの相関値（一般には `context.buyer_ref`）を使って `package_id` を自分たちのラインアイテムに対応付けられます。 |
| `creative_approvals`          | クリエイティブ承認状態の配列（下記参照）                                                                                                                                                                                                                                                                                                                             |
| `format_ids_pending`          | まだアップロードされていない `format_ids_to_provide` のフォーマットID                                                                                                                                                                                                                                                                                                 |
| `snapshot_unavailable_reason` | `include_snapshot: true` であるがこのパッケージのスナップショットが返されない場合の理由コード                                                                                                                                                                                                                                                                                      |
| `snapshot`                    | ほぼリアルタイムの配信スナップショット（`include_snapshot: true` の場合）                                                                                                                                                                                                                                                                                                |

### クリエイティブ承認オブジェクト

| フィールド              | 説明                                         |
| ------------------ | ------------------------------------------ |
| `creative_id`      | クリエイティブ識別子                                 |
| `approval_status`  | `pending_review`、`approved`、または `rejected` |
| `rejection_reason` | 却下の説明（`approval_status` が `rejected` の場合）  |

クリエイティブライブラリを持たずに `inline_creative_management` を表明しているセラーの場合、`creative_approvals` は、パッケージに現在割り当てられているインラインクリエイティブの承認状態を読み戻す唯一の標準化されたサーフェスです。`creative_id`、`approval_status`、任意の `rejection_reason` をレポートしますが、`create_media_buy` や `update_media_buy` で送信された完全な `CreativeAsset` のペイロード、プレースメントのルーティング、ウェイト、過去のリビジョンは含みません。インライン専用のセラーと連携するバイヤーは、自分たちが送信したクリエイティブ本体を保持しておくべきです。

クリエイティブの修正は `approval_status: "rejected"` と特定の `rejection_reason` で表現されます。クリエイティブ編集のためのパッケージレベルの `input-required` ステータスは存在しません。修正済みのライブラリアセットは [`sync_creatives`](/docs/creative/task-reference/sync_creatives) で、修正済みのインライン専用パッケージアセットは [`update_media_buy`](/docs/media-buy/task-reference/update_media_buy) の `packages[].creatives` でアップロードすること。

### 履歴エントリオブジェクト

| フィールド        | 必須  | 説明                                                                                                                                                                                           |
| ------------ | --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `revision`   | はい  | この変更が適用された後のリビジョン番号                                                                                                                                                                          |
| `timestamp`  | はい  | この変更が発生した ISO 8601 タイムスタンプ                                                                                                                                                                   |
| `action`     | はい  | 何が起きたか: `created`、`activated`、`paused`、`resumed`、`canceled`、`rejected`、`completed`、`updated_budget`、`updated_dates`、`updated_packages`、`package_canceled`、`package_paused`、`package_resumed` |
| `actor`      | いいえ | 変更を行った者の識別情報（呼び出し元が指定するのではなく、認証コンテキストからサーバーが導出します）                                                                                                                                           |
| `summary`    | いいえ | 人が読める説明（例: "Budget changed from $5,000 to $7,500 on pkg\_abc"）                                                                                                                               |
| `package_id` | いいえ | 変更が特定のパッケージを対象としていた場合の、影響を受けたパッケージ                                                                                                                                                           |

履歴エントリは**追記専用**です——セラーは既に出力したエントリを変更または削除してはなりません（MUST NOT）。呼び出し元はリビジョン番号でエントリをキャッシュしてもかまいません（MAY）。

`revision` は、セラーが状態を変更する変更または更新を適用した場合にのみ増加します。読み取り、バリデーションのみの呼び出し、完全に冪等な再実行では、履歴エントリは作成されず、リビジョンも増えません。バイヤーは、返されたリビジョンを、状態変更を意図した次の `update_media_buy` 呼び出しのためのトークンとして扱うべきです。

`confirmed_at` は配信ステータスのタイムスタンプではありません。セラーのコミットを記録するものであり、その後の一時停止/再開、アクティベーション、完了、キャンセル、レポーティングの変更を通じて安定したままです。

### スナップショットオブジェクト

| フィールド               | 説明                                                                                                |
| ------------------- | ------------------------------------------------------------------------------------------------- |
| `as_of`             | プラットフォームがこのスナップショットを取得した際の ISO 8601 タイムスタンプ                                                       |
| `staleness_seconds` | データの最大経過時間（秒）。ゼロ配信の解釈に使用します: 900（15分）はゼロが実際の値である可能性が高いことを意味し、14400（4時間）はレポートがまだ追いついていない可能性を意味します。 |
| `impressions`       | パッケージ開始以降の合計インプレッション数                                                                             |
| `spend`             | パッケージ開始以降の合計支出                                                                                    |
| `currency`          | `spend` に対するオプションのスナップショット通貨オーバーライド                                                               |
| `clicks`            | パッケージ開始以降の合計クリック数（利用可能な場合）                                                                        |
| `pacing_index`      | 配信ペース（1.0 = 順調、\<1.0 = 遅れ、>1.0 = 進みすぎ）                                                            |
| `delivery_status`   | `delivering`、`not_delivering`、`completed`、`budget_exhausted`、`flight_ended`、`goal_met`            |
| `ext`               | セラー固有の運用フィールドのためのオプションの拡張オブジェクト                                                                   |

**`not_delivering`** は、パッケージが予定されたフライト期間内にあるにもかかわらず、少なくとも1回分の staleness サイクルでゼロインプレッションを記録したことを意味します。実装者はパッケージ起動から `staleness_seconds` が経過するまで `not_delivering` を返してはなりません — 最初の数分間インプレッションのない新しいパッケージは想定内であり、問題ではありません。このステータスに基づいて行動する前に、`start_time` を確認してパッケージがフライト期間内にあることを確認すること。

金額フィールドは次の通貨優先順位を使用します: `snapshot.currency` -> `package.currency` -> `media_buy.currency`。

### ウェブフックアクティビティ

`include_webhook_activity: true` の場合、返される各メディアバイは、セラーからバイヤーの登録済みエンドポイントへの最近のレポーティングおよびヘルスのウェブフック発火を記述する `webhook_activity` 配列を持つことがあります（MAY）。これは[永続チャネルのウェブフック契約](/docs/building/by-layer/L3/webhooks#persistent-channel-contract)におけるバイヤー側のデバッグ用サーフェスです——バイヤーはこれを使って、セラーのログに対するオペレーターレベルのクエリを必要とせずに、パブリッシャーが発火したか、バイヤーのゲートウェイが何を返したか、リトライがまだ進行中かを確認します。

レコードの形状、リクエストフィールド名、スコープ、保持期間の下限、三状態の存在、カーディナリティのルールは、このサーフェスを採用する AdCP のリソース全体で統一されています。リソース横断の規範的な節については、スナップショット/ログ契約のページの[ウェブフックアクティビティログのパターン](/docs/protocol/snapshot-and-log#webhook-activity-log-pattern)を参照してください——以下のルールは、それをメディアバイの呼び出し箇所向けに再掲し、メディアバイ固有のケイパビリティゲートを追加したものです。

このサーフェスは、配信レポートの通知タイプ（`scheduled`、`final`、`delayed`、`adjusted`）とヘルスの通知タイプ（`impairment`）の両方を対象とします。いずれも同じウェブフック配信契約と、同じバイヤー側のデバッグ上のニーズを共有します。

| フィールド                | 説明                                                                                                                                                                                                                                                    |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `idempotency_key`    | ウェブフックのペイロード自体が持つ `idempotency_key` と等しくなります（[§ `idempotency_key` による重複排除](/docs/building/by-layer/L3/webhooks#dedup-by-idempotency_key)）。同じ論理的な発火のリトライをまたいで安定しています——バイヤーはまさにこのフィールドを介して、このサーフェスを自分たちのエンドポイントのログと突き合わせます。サポートチケットを起票する際にはこれを参照してください。 |
| `subscriber_id`      | どの登録済みウェブフックサブスクライバーがこの発火を受け取ったかを識別します。単一サブスクライバーの構成では不在です。複数サブスクライバーのバイでは値が入ります（4.0+、[#3009](https://github.com/adcontextprotocol/adcp/issues/3009) を参照）。                                                                                            |
| `fired_at`           | セラーがこの試行を開始した ISO 8601 タイムスタンプ。                                                                                                                                                                                                                       |
| `completed_at`       | レスポンスが観測された（または終端の失敗となった）ISO 8601 タイムスタンプ。`status` が `pending` の間は null。                                                                                                                                                                              |
| `notification_type`  | ウェブフックのペイロードのまま: `scheduled`、`final`、`delayed`、`adjusted`、`impairment`。                                                                                                                                                                               |
| `sequence_number`    | ウェブフックのペイロードのシーケンス番号——古いシーケンスの破棄や欠落の発見に有用です。通知タイプがシーケンス番号を持たない場合は不在。                                                                                                                                                                                  |
| `attempt`            | この論理的な発火に対する 1 始まりのリトライカウンタ。最初の発火は `attempt: 1`。                                                                                                                                                                                                      |
| `status`             | `success`、`failed`、`timeout`、`connection_error`、または `pending`。セマンティクスは以下を参照。                                                                                                                                                                          |
| `url`                | **クエリ文字列とフラグメントが除去され**、高エントロピー/トークン状のパスセグメントが伏せられた対象 URL。完全な URL ではなく、オリジン + パスで登録済み URL と突き合わせてください。                                                                                                                                                 |
| `http_status_code`   | バイヤーのエンドポイントからの HTTP ステータス。HTTP レスポンスを受け取らなかった場合は null（`timeout`、`connection_error`、`pending`）。                                                                                                                                                       |
| `response_time_ms`   | リクエスト送信からレスポンス受信までの実時間レイテンシ。完了していない試行では null。                                                                                                                                                                                                         |
| `payload_size_bytes` | セラーが送信したリクエストボディのサイズ——ペイロードのサイズ超過による拒否の診断に有用です。                                                                                                                                                                                                       |
| `error_message`      | 失敗に関する短い、人が読めるサーバー側の分類。`success` では null。セラーはここにリクエスト/レスポンスのボディやヘッダーを含めてはなりません（MUST NOT）。                                                                                                                                                             |

**ステータスのセマンティクス:**

* `success` — 2xx ステータスのレスポンスを受信。`http_status_code` に値が入ります。
* `failed` — 2xx 以外のステータスのレスポンスを受信。`http_status_code` に値が入り、`error_message` がレスポンスを説明します。
* `timeout` — セラーが設定したタイムアウト内にレスポンスがありませんでした。`http_status_code` は null。運用上の意味: バイヤーのエンドポイントには到達できるが、遅いか過負荷である。
* `connection_error` — HTTP レスポンスの前に DNS、TLS、またはソケットが失敗しました。`http_status_code` は null。運用上の意味: バイヤーのエンドポイントに到達できないか、設定が誤っている。
* `pending` — 試行が実行中またはリトライのためにキューに入っています。`completed_at` は null。後続の試行は同じ `idempotency_key` と増加した `attempt` で現れます。

**レコードのカーディナリティ:** 試行ごとに 1 レコード。初回試行で成功した発火は `attempt: 1` の単一レコードとして現れます。3 回試行のリトライの軌跡（例: 2 回失敗して 1 回成功）は、`idempotency_key` を共有する 3 レコードとして現れます。

**スコープ（規範的）:**

* `webhook_activity` は**呼び出し元プリンシパル**にスコープされなければなりません（MUST）。複数のバイヤープリンシパルがアカウントレベルのアクセスを通じて同じメディアバイを閲覧できる場合、各プリンシパルは自分自身のエンドポイントを対象とする発火のみを見ます。
* このフィールドを公開するセラーは、各レコードの `completed_at` から少なくとも 30 日間、レコードを保持しなければなりません（**MUST**）——`success`、`failed`、`timeout`、`connection_error` の各結果（いずれも `completed_at` に値が入ります）にわたって一律にです。まだ `pending` ステータスのレコードでは、試行が終了するまでは `fired_at` から起算し、その後 `completed_at` から 30 日間に移行します——リトライの軌跡が途中で消えることはありません。この下限を守れないセラーは、より短いウィンドウを返すのではなく、フィールドを完全に省略しなければなりません（MUST）。三状態の存在セマンティクスは、セラーにきれいなオプトアウトを、バイヤーには依拠できる単一の保証を与えます。
* このサーフェスはデバッグの補助であり、完全な監査ログではありません。`webhook_activity_limit` を超えた古い発火のためのカーソルはありません——完全な履歴が必要なバイヤーは、自分たちの側でウェブフックのレコードを永続化しなければなりません。

**三状態の存在セマンティクス:**

| 状態           | 意味                                                                                                                                                                                             |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| フィールドが**省略** | セラーはこのバイのウェブフックアクティビティを公開していません。セラーが発火履歴を永続化していないか、セラーの宣言した [`propagation_surfaces`](/docs/media-buy/media-buys/lifecycle) が `webhook` を含まないか、そのバイに呼び出し元プリンシパル向けの登録済みウェブフックエンドポイントがないかのいずれかです。 |
| 空配列 `[]`     | セラーは発火履歴を永続化していますが、このプリンシパル向けに最近何も発火していません。                                                                                                                                                    |
| 空でない配列       | 実際の発火レコード、新しい順。                                                                                                                                                                                |

宣言した `propagation_surfaces` に `webhook` が含まれないセラーは、フィールドを省略しなければなりません（MUST）。`include_webhook_activity: true` でオプトインしても、それは上書きされません。

**予期しない省略の診断。** 発火があるはずなのにフィールドが省略されていた場合、チケットを起票せずに原因を切り分けられる観測点が二つあります。(1) このバイに対する自分の `push_notification_config` の登録状態を確認する——登録されていなければ、それが原因です。(2) `get_adcp_capabilities` を通じてセラーの `capabilities.media_buy.propagation_surfaces` を確認する——`webhook` が不在なら、それが原因です。両方とも問題なければ、残る原因は「セラーが発火履歴を永続化していない」であり、これはセラー側のギャップなのでオペレーターへのチケットを起票する価値があります。

**プライバシー:**

* `url` フィールドはクエリ文字列とフラグメントが**除去**されており、セラーは共有シークレットに見えるパスセグメント（高エントロピーのランダムな素材、UUID/トークン状のもの）を伏せるべきです（SHOULD）。
* リクエストとレスポンスのボディはこのフィールドでは**公開されません**。将来の `include_webhook_payloads` 拡張が、より厳格な認可制御のもとでそれらを追加する可能性がありますが、ここではスコープ外です。
* `error_message` はサーバー側の分類文字列のみです——リクエストヘッダー、レスポンスボディ、バイヤーエンドポイントのスタックトレースは決して含みません。

#### ウェブフック配信の問題を診断する

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { testAgent } from '@adcp/sdk/testing';
  import { GetMediaBuysResponseSchema, type WebhookActivityRecord } from '@adcp/sdk';

  // The WebhookActivityRecord type is regenerated by the SDK from
  // /schemas/core/webhook-activity-record.json — once the SDK rebuilds against this
  // branch's schemas the import resolves. The same type appears on every AdCP resource
  // that surfaces webhook_activity[], so debug helpers can be written once and reused.
  function latestAttempt(trail: WebhookActivityRecord[]): WebhookActivityRecord {
    return trail.reduce((a, b) => (a.attempt >= b.attempt ? a : b));
  }

  const result = await testAgent.getMediaBuys({
    media_buy_ids: ['mb_12345'],
    include_webhook_activity: true,
    webhook_activity_limit: 20,
  });

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

  const validated = GetMediaBuysResponseSchema.parse(result.data);

  for (const mediaBuy of validated.media_buys) {
    // Three-state semantics — distinguish "seller does not surface" from "no recent fires".
    if (mediaBuy.webhook_activity === undefined) {
      console.log(`${mediaBuy.media_buy_id}: seller does not surface webhook activity for this buy`);
      continue;
    }

    const fires = mediaBuy.webhook_activity;
    if (fires.length === 0) {
      console.log(`${mediaBuy.media_buy_id}: no recent fires for this principal`);
      continue;
    }

    // Group attempts by idempotency_key so we can see the retry trail per logical fire.
    const trails = new Map();
    for (const fire of fires) {
      const trail = trails.get(fire.idempotency_key) ?? [];
      trail.push(fire);
      trails.set(fire.idempotency_key, trail);
    }

    for (const [idempotencyKey, trail] of trails) {
      // Pick the latest attempt by `attempt` number — robust against any iteration order.
      const latest = latestAttempt(trail);
      if (latest.status === 'success') continue;

      const detail = latest.error_message ?? latest.http_status_code ?? '—';
      console.log(
        `${mediaBuy.media_buy_id} ${idempotencyKey} ` +
        `(${latest.notification_type} seq=${latest.sequence_number}): ` +
        `${latest.status} after ${trail.length} attempt(s) — ${detail}`
      );
    }
  }
  ```

  ```python Python theme={null}
  import asyncio
  from collections import defaultdict
  from adcp.testing import test_agent
  from adcp.types import GetMediaBuysRequest, WebhookActivityRecord

  # WebhookActivityRecord is regenerated by the SDK from
  # /schemas/core/webhook-activity-record.json — once the SDK rebuilds against this
  # branch's schemas the import resolves. The same type appears on every AdCP resource
  # that surfaces webhook_activity[].
  def latest_attempt(trail: list[WebhookActivityRecord]) -> WebhookActivityRecord:
      return max(trail, key=lambda f: f.attempt)

  async def main():
      result = await test_agent.get_media_buys(
          GetMediaBuysRequest(
              media_buy_ids=['mb_12345'],
              include_webhook_activity=True,
              webhook_activity_limit=20,
          )
      )

      for media_buy in result.media_buys:
          # Three-state semantics: distinguish "seller does not surface" from "no recent fires".
          if media_buy.webhook_activity is None:
              print(f"{media_buy.media_buy_id}: seller does not surface webhook activity for this buy")
              continue

          fires = media_buy.webhook_activity
          if not fires:
              print(f"{media_buy.media_buy_id}: no recent fires for this principal")
              continue

          trails = defaultdict(list)
          for fire in fires:
              trails[fire.idempotency_key].append(fire)

          for idempotency_key, trail in trails.items():
              latest = latest_attempt(trail)
              if latest.status == 'success':
                  continue

              detail = latest.error_message or latest.http_status_code or '—'
              print(f"{media_buy.media_buy_id} {idempotency_key} "
                    f"({latest.notification_type} seq={latest.sequence_number}): "
                    f"{latest.status} after {len(trail)} attempt(s) — {detail}")

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

## 有効なアクションのマッピング

`valid_actions` 配列は、メディアバイの現在の状態でどの操作が許可されているかをエージェントに伝えます。セラーはこのフィールドを含めるべきです（SHOULD）。ステータスごとに期待される値:

| ステータス               | 期待される `valid_actions`                                                                              |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| `pending_creatives` | `pause`、`cancel`、`sync_creatives`                                                                  |
| `pending_start`     | `pause`、`cancel`、`sync_creatives`                                                                  |
| `active`            | `pause`、`cancel`、`update_budget`、`update_dates`、`update_packages`、`add_packages`、`sync_creatives`  |
| `paused`            | `resume`、`cancel`、`update_budget`、`update_dates`、`update_packages`、`add_packages`、`sync_creatives` |
| `completed`         | *（空配列）*                                                                                            |
| `rejected`          | *（空配列）*                                                                                            |
| `canceled`          | *（空配列）*                                                                                            |

セラーはビジネスルールに基づいてアクションを省略してもかまいません（MAY）（例: メディアバイにキャンセルを妨げる契約上の義務がある場合に `cancel` を省略する）。

クリエイティブの変更について、`valid_actions` にある `sync_creatives` はレガシーなクリエイティブ変更のアクションラベルであり、`sync_creatives` タスクが存在する証明ではありません。セラーが表明しているクリエイティブの経路を使用してください: `creative.has_creative_library: true` のセラーでは `sync_creatives` と `creative_assignments`、インライン専用のセラーでは `update_media_buy` の `packages[].creatives` です。

## 一般的なユースケース

### クリエイティブ承認ステータスの確認

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

  const result = await testAgent.getMediaBuys({
    media_buy_ids: ['mb_12345']
  });

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

  const validated = GetMediaBuysResponseSchema.parse(result.data);

  if (validated.errors?.length > 0) {
    throw new Error(`Query failed: ${JSON.stringify(validated.errors)}`);
  }

  for (const mediaBuy of validated.media_buys) {
    for (const pkg of mediaBuy.packages) {
      // Check for missing creatives
      if (pkg.format_ids_pending?.length > 0) {
        console.log(`Package ${pkg.package_id}: missing formats ${pkg.format_ids_pending.map(f => f.id).join(', ')}`);
      }

      // Check approval states
      for (const approval of pkg.creative_approvals ?? []) {
        if (approval.approval_status === 'rejected') {
          console.log(`Creative ${approval.creative_id} rejected: ${approval.rejection_reason}`);
        } else if (approval.approval_status === 'pending_review') {
          console.log(`Creative ${approval.creative_id} pending review`);
        }
      }
    }
  }
  ```

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

  async def main():
      result = await test_agent.get_media_buys(
          GetMediaBuysRequest(media_buy_ids=['mb_12345'])
      )

      if result.errors:
          raise Exception(f"Query failed: {result.errors}")

      for media_buy in result.media_buys:
          for pkg in media_buy.packages:
              # Check for missing creatives
              if pkg.format_ids_pending:
                  ids = [f.id for f in pkg.format_ids_pending]
                  print(f"Package {pkg.package_id}: missing formats {', '.join(ids)}")

              # Check approval states
              for approval in pkg.creative_approvals or []:
                  if approval.approval_status == 'rejected':
                      print(f"Creative {approval.creative_id} rejected: {approval.rejection_reason}")
                  elif approval.approval_status == 'pending_review':
                      print(f"Creative {approval.creative_id} pending review")

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

### スナップショットを使った配信モニタリング

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

  const result = await testAgent.getMediaBuys({
    status_filter: 'active',
    include_snapshot: true
  });

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

  const validated = GetMediaBuysResponseSchema.parse(result.data);

  for (const mediaBuy of validated.media_buys) {
    for (const pkg of mediaBuy.packages) {
      const snap = pkg.snapshot;
      if (!snap) continue;

      if (snap.delivery_status === 'not_delivering') {
        console.log(`Package ${pkg.package_id}: zero delivery (data up to ${snap.staleness_seconds}s old)`);
      } else if (snap.pacing_index !== undefined && snap.pacing_index < 0.8) {
        console.log(`Package ${pkg.package_id}: underpacing at ${(snap.pacing_index * 100).toFixed(0)}%`);
      } else {
        console.log(`Package ${pkg.package_id}: ${snap.impressions.toLocaleString()} impressions, pacing ${snap.pacing_index?.toFixed(2)}`);
      }
    }
  }
  ```

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

  async def main():
      result = await test_agent.get_media_buys(
          GetMediaBuysRequest(
              status_filter='active',
              include_snapshot=True
          )
      )

      if result.errors:
          raise Exception(f"Query failed: {result.errors}")

      for media_buy in result.media_buys:
          for pkg in media_buy.packages:
              snap = pkg.snapshot
              if not snap:
                  continue

              if snap.delivery_status == 'not_delivering':
                  print(f"Package {pkg.package_id}: zero delivery (data up to {snap.staleness_seconds}s old)")
              elif snap.pacing_index is not None and snap.pacing_index < 0.8:
                  print(f"Package {pkg.package_id}: underpacing at {snap.pacing_index * 100:.0f}%")
              else:
                  print(f"Package {pkg.package_id}: {snap.impressions:,} impressions, pacing {snap.pacing_index:.2f}")

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

### キャンペーン配信準備チェック

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

  const result = await testAgent.getMediaBuys({
    media_buy_ids: ['mb_12345']
  });

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

  const validated = GetMediaBuysResponseSchema.parse(result.data);
  const [mediaBuy] = validated.media_buys;
  const issues = [];

  for (const pkg of mediaBuy.packages) {
    if (pkg.format_ids_pending?.length > 0) {
      issues.push(`Package ${pkg.package_id}: ${pkg.format_ids_pending.length} format(s) not yet uploaded`);
    }

    const rejected = (pkg.creative_approvals ?? []).filter(a => a.approval_status === 'rejected');
    if (rejected.length > 0) {
      issues.push(`Package ${pkg.package_id}: ${rejected.length} creative(s) rejected`);
    }
  }

  if (issues.length === 0) {
    console.log('Campaign ready to launch');
  } else {
    console.log('Campaign has blocking issues:');
    issues.forEach(issue => console.log(`  - ${issue}`));
  }
  ```

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

  async def main():
      result = await test_agent.get_media_buys(
          GetMediaBuysRequest(media_buy_ids=['mb_12345'])
      )

      media_buy = result.media_buys[0]
      issues = []

      for pkg in media_buy.packages:
          if pkg.format_ids_pending:
              issues.append(f"Package {pkg.package_id}: {len(pkg.format_ids_pending)} format(s) not yet uploaded")

          rejected = [a for a in (pkg.creative_approvals or []) if a.approval_status == 'rejected']
          if rejected:
              issues.append(f"Package {pkg.package_id}: {len(rejected)} creative(s) rejected")

      if not issues:
          print("Campaign ready to launch")
      else:
          print("Campaign has blocking issues:")
          for issue in issues:
              print(f"  - {issue}")

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

## スナップショットと `get_media_buy_delivery` の比較

|                  | `get_media_buys`（スナップショットあり） | `get_media_buy_delivery` |
| ---------------- | ---------------------------- | ------------------------ |
| **目的**           | 運用モニタリング                     | レポーティングと照合               |
| **鮮度**           | 数分（エンティティレベルの統計）             | 数時間（バッチレポートジョブ）          |
| **精度**           | ベストエフォート                     | 権威ある請求グレード               |
| **日付範囲**         | 常に「キャンペーン開始以降」               | 設定可能な期間                  |
| **日別内訳**         | なし                           | あり                       |
| **クリエイティブステータス** | あり                           | なし                       |
| **不足アセット**       | あり                           | なし                       |

「現在のキャンペーン状態は何か？」という質問には `get_media_buys` を使い、「ある期間にキャンペーンがどのように機能したか？」には `get_media_buy_delivery` を使うこと。

ステータスの分類は両タスクのライフサイクルフィルター（`pending_creatives`、`pending_start`、`active`、`paused`、`completed`）で共有されています。`get_media_buy_delivery` はウェブフックコンテキストで追加のレポーティング専用ステータス（`reporting_delayed`、`failed`）を返すことがあります。

## データの鮮度

スナップショットの `staleness_seconds` はプラットフォームによって異なる:

| プラットフォームの種類                          | 典型的な `staleness_seconds` |
| ------------------------------------ | ------------------------ |
| エンティティレベルの統計（例: GAM LineItemService） | 900（15分）                 |
| ほぼリアルタイムのインサイト API                   | 60〜300                   |
| バッチ専用レポーティング                         | 14400（4時間）               |

プラットフォームがバッチレポーティングのみの場合、セラーエージェントは適切な `staleness_seconds` を設定して最新のキャッシュデータを返すべきです。

`include_snapshot: true` でパッケージの `snapshot` が省略されている場合、`snapshot_unavailable_reason` を確認すること:

* `SNAPSHOT_UNSUPPORTED`: セラーがこの統合でパッケージスナップショットをサポートしていません
* `SNAPSHOT_TEMPORARILY_UNAVAILABLE`: スナップショットパイプラインが遅延または低下しています。後でリトライすること
* `SNAPSHOT_PERMISSION_DENIED`: 呼び出し元がそのパッケージのスナップショットメトリクスを閲覧する権限を持っていません

## ページネーション

大きなペイロードを避けるため、広範なステータスクエリにはカーソルページネーションを使用すること:

* リクエスト: `pagination.max_results`（1〜100、デフォルト50）と オプションの `pagination.cursor` を設定します
* レスポンス: `pagination.has_more` を読み取り、true の場合は `pagination.cursor` を次のリクエストに渡します
* ID指定クエリ（`media_buy_ids`）は、IDセットが非常に大きい場合を除きページネーションを省略してよいです

## エラーハンドリング

| エラーコード                | 説明                         | 対処法                                                |
| --------------------- | -------------------------- | -------------------------------------------------- |
| `MEDIA_BUY_NOT_FOUND` | メディアバイIDが存在しない             | `media_buy_id` を確認すること                             |
| `CONTEXT_REQUIRED`    | リクエストされたスコープにメディアバイが見つからない | 有効なIDや参照を指定するか、`status_filter`/ページネーションのスコープを広げること |
| `AUTH_MISSING`        | 認証情報が提示されていない              | 認証ヘッダーで認証情報を提供すること                                 |
| `AUTH_INVALID`        | 認証情報が拒否された（期限切れ/失効）        | 人による認証情報のローテーションが必要。自動リトライしないこと                    |

## 次のステップ

* **不足クリエイティブのアップロード**: ライブラリを持つセラーには [`sync_creatives`](/docs/creative/task-reference/sync_creatives) を、インライン専用のセラーには [`update_media_buy`](/docs/media-buy/task-reference/update_media_buy) の `packages[].creatives` を使うこと
* **ゼロ配信の調査**: `delivery_status: "not_delivering"` と `start_time` を確認してフライトがアクティブであることを確かめ、次に [`update_media_buy`](/docs/media-buy/task-reference/update_media_buy) を使って価格やターゲティングを調整すること
* **詳細レポーティング**: 日付範囲レポーティングや日別内訳には [`get_media_buy_delivery`](/docs/media-buy/task-reference/get_media_buy_delivery) を使うこと
* **キャンペーンの最適化**: セラーに結果を共有するには [`provide_performance_feedback`](/docs/media-buy/task-reference/provide_performance_feedback) を使うこと
