> ## Documentation Index
> Fetch the complete documentation index at: https://agenticadvertisingorg-fix-release-bump-classification.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# get_media_buys

> get_media_buys task — retrieve media buy status in AdCP including creative approvals, missing assets, configuration, and optional near-real-time delivery snapshots.

Retrieve the current operational state of media buys: configuration, creative approval status, missing assets, and optional near-real-time delivery snapshots.

**Response Time**: \~1 second

## Scope of Results

Sales agents MUST return every media buy owned by the authenticated account, regardless of how the buy was created — via AdCP `create_media_buy`, via the seller's own APIs, via manual trafficking, via legacy or third-party systems. Scope is **account ownership**, not creation surface. A `media_buy_id` returned here identifies any order in the seller's ad server accessible to the authenticated caller.

Any media buy returned by `get_media_buys` MUST be reachable by every task in its `valid_actions`. Sales agents MUST NOT mark a buy read-only, hide it, or refuse updates on the basis that it was not originally created via AdCP. When an action is unavailable for business reasons (contractual obligations, platform constraints, policy), the seller MUST omit only that action from `valid_actions` — never the whole set, and never merely because the buy was created outside AdCP. A seller that returns non-AdCP buys with a systematically empty `valid_actions` is non-conformant; that pattern is indistinguishable from hiding the buy.

Sellers that need to partition inventory away from a caller MUST do so at the **account boundary**, not within-account. See [Account Ownership vs. Creation Surface](/dist/docs/3.0.19/media-buy/specification#account-ownership-vs-creation-surface).

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

## Request Parameters

| Parameter          | Type                                                                                         | Required | Description                                                                                                                                                                                         |
| ------------------ | -------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account`          | [account-ref](/dist/docs/3.0.19/building/by-layer/L2/accounts-and-agents#account-references) | No       | Account reference. Pass `{ "account_id": "..." }` or `{ "brand": {...}, "operator": "..." }` if the seller supports implicit resolution. When omitted, returns data across all accessible accounts. |
| `media_buy_ids`    | string\[]                                                                                    | No\*     | Array of media buy IDs to retrieve                                                                                                                                                                  |
| `status_filter`    | string \| string\[]                                                                          | No       | Status filter: `"pending_creatives"`, `"pending_start"`, `"active"`, `"paused"`, `"completed"`, `"rejected"`, `"canceled"`. Defaults to `["active"]` only when `media_buy_ids` is omitted.          |
| `include_snapshot` | boolean                                                                                      | No       | When true, include near-real-time delivery snapshots for each package. Defaults to `false`.                                                                                                         |
| `include_history`  | integer                                                                                      | No       | Include the last N revision history entries per media buy (returns min(N, available)). 0 or omit to exclude. Max 1000.                                                                              |
| `pagination`       | object                                                                                       | No       | Cursor-based pagination controls (`max_results`, `cursor`) for broad queries.                                                                                                                       |

\*`media_buy_ids` filters results to specific media buys. If neither is provided, the query is scope-based and uses `status_filter` + `pagination`.

When `media_buy_ids` are provided, no implicit status filtering is applied. Pass `status_filter` explicitly if you want to filter identified buys by status.

## Response

Returns an array of media buys with current status, creative approval state, and optionally delivery snapshots:

| Field        | Description                                                               |
| ------------ | ------------------------------------------------------------------------- |
| `media_buys` | Array of media buy objects                                                |
| `pagination` | Cursor pagination metadata (`has_more`, `cursor`, optional `total_count`) |
| `errors`     | Task-specific errors (e.g., media buy not found)                          |

### Media Buy Object

| Field               | Description                                                                                                                                                             |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `media_buy_id`      | Seller's media buy identifier                                                                                                                                           |
| `invoice_recipient` | Per-buy invoice recipient when provided at creation. Confirms the seller accepted the billing override. Bank details are omitted (write-only).                          |
| `status`            | Current status (`pending_creatives`, `pending_start`, `active`, `paused`, `completed`, `rejected`, `canceled`)                                                          |
| `currency`          | ISO 4217 currency for media-buy-level monetary values                                                                                                                   |
| `total_budget`      | Total campaign budget (in `currency`)                                                                                                                                   |
| `creative_deadline` | Creative upload deadline (ISO 8601)                                                                                                                                     |
| `confirmed_at`      | ISO 8601 timestamp when the seller confirmed this media buy                                                                                                             |
| `cancellation`      | Cancellation metadata (present only when `status` is `canceled`). Object with `canceled_at` (ISO 8601), `canceled_by` (`"buyer"` or `"seller"`), and optional `reason`. |
| `revision`          | Current revision number. Pass in `update_media_buy` for optimistic concurrency.                                                                                         |
| `valid_actions`     | Actions the buyer can perform in the current state (e.g., `["pause", "cancel", "update_budget"]`). See [valid actions mapping](#valid-actions-mapping).                 |
| `history`           | Revision history entries, most recent first. Only present when `include_history > 0`. Append-only — entries are never modified or deleted.                              |
| `packages`          | Array of packages with creative status and optional snapshots                                                                                                           |

### Package Object

| Field                         | Description                                                                                                                                                         |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package_id`                  | Seller's package identifier                                                                                                                                         |
| `currency`                    | Optional package-level currency override (defaults to media buy `currency`)                                                                                         |
| `bid_price`                   | Current bid price for auction-based packages (in package `currency` if present, otherwise media buy `currency`)                                                     |
| `start_time`                  | Flight start time (ISO 8601). Check this before interpreting delivery status.                                                                                       |
| `end_time`                    | Flight end time (ISO 8601)                                                                                                                                          |
| `paused`                      | Whether buyer has paused this package                                                                                                                               |
| `canceled`                    | Whether this package has been canceled (irreversible)                                                                                                               |
| `cancellation`                | Cancellation metadata (present only when `canceled` is true). Object with `canceled_at` (ISO 8601), `canceled_by` (`"buyer"` or `"seller"`), and optional `reason`. |
| `creative_deadline`           | Per-package creative deadline (ISO 8601). When absent, the media buy's `creative_deadline` applies.                                                                 |
| `creative_approvals`          | Array of creative approval states (see below)                                                                                                                       |
| `format_ids_pending`          | Format IDs from `format_ids_to_provide` not yet uploaded                                                                                                            |
| `snapshot_unavailable_reason` | Reason code when `include_snapshot: true` but no snapshot is returned for this package                                                                              |
| `snapshot`                    | Near-real-time delivery snapshot (when `include_snapshot: true`)                                                                                                    |

### Creative Approval Object

| Field              | Description                                                     |
| ------------------ | --------------------------------------------------------------- |
| `creative_id`      | Creative identifier                                             |
| `approval_status`  | `pending_review`, `approved`, or `rejected`                     |
| `rejection_reason` | Explanation of rejection (when `approval_status` is `rejected`) |

Creative revisions are represented as `approval_status: "rejected"` with a specific `rejection_reason`. There is no package-level `input-required` status for creative edits; upload corrected assets via [`sync_creatives`](/dist/docs/3.0.19/creative/task-reference/sync_creatives).

### History Entry Object

| Field        | Required | Description                                                                                                                                                                                                     |
| ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `revision`   | Yes      | Revision number after this change was applied                                                                                                                                                                   |
| `timestamp`  | Yes      | ISO 8601 timestamp when this change occurred                                                                                                                                                                    |
| `action`     | Yes      | What happened: `created`, `activated`, `paused`, `resumed`, `canceled`, `rejected`, `completed`, `updated_budget`, `updated_dates`, `updated_packages`, `package_canceled`, `package_paused`, `package_resumed` |
| `actor`      | No       | Identity of who made the change (server-derived from auth context, not caller-provided)                                                                                                                         |
| `summary`    | No       | Human-readable description (e.g., "Budget changed from $5,000 to $7,500 on pkg\_abc")                                                                                                                           |
| `package_id` | No       | Package affected, when the change targeted a specific package                                                                                                                                                   |

History entries are **append-only** — sellers MUST NOT modify or delete previously emitted entries. Callers MAY cache entries by revision number.

### Snapshot Object

| Field               | Description                                                                                                                                                      |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `as_of`             | ISO 8601 timestamp when the platform captured this snapshot                                                                                                      |
| `staleness_seconds` | Maximum data age in seconds. Use this to interpret zero delivery: 900 (15 min) means zero is likely real; 14400 (4 hr) means reporting may still be catching up. |
| `impressions`       | Total impressions delivered since package start                                                                                                                  |
| `spend`             | Total spend since package start                                                                                                                                  |
| `currency`          | Optional snapshot currency override for `spend`                                                                                                                  |
| `clicks`            | Total clicks since package start (when available)                                                                                                                |
| `pacing_index`      | Delivery pace (1.0 = on track, \<1.0 = behind, >1.0 = ahead)                                                                                                     |
| `delivery_status`   | `delivering`, `not_delivering`, `completed`, `budget_exhausted`, `flight_ended`, `goal_met`                                                                      |
| `ext`               | Optional extension object for seller-specific operational fields                                                                                                 |

**`not_delivering`** means the package is within its scheduled flight but has delivered zero impressions for at least one full staleness cycle. Implementers must not return `not_delivering` until `staleness_seconds` have elapsed since package activation — a new package with no impressions in its first minutes is expected, not a problem. Check `start_time` to confirm the package is within its flight before acting on this status.

Money fields use this currency precedence: `snapshot.currency` -> `package.currency` -> `media_buy.currency`.

## Valid Actions Mapping

The `valid_actions` array tells agents what operations are permitted on a media buy in its current state. Sellers SHOULD include this field. Expected values by status:

| Status              | Expected `valid_actions`                                                                                 |
| ------------------- | -------------------------------------------------------------------------------------------------------- |
| `pending_creatives` | `cancel`, `sync_creatives`                                                                               |
| `pending_start`     | `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`         | *(empty array)*                                                                                          |
| `rejected`          | *(empty array)*                                                                                          |
| `canceled`          | *(empty array)*                                                                                          |

Sellers MAY omit actions based on business rules (e.g., omit `cancel` when the media buy has contractual obligations that prevent cancellation).

## Common Scenarios

### Check creative approval status

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

  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>

### Monitor delivery with snapshots

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

  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>

### Campaign readiness check

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

  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>

## Snapshot vs. `get_media_buy_delivery`

|                     | `get_media_buys` (with snapshot) | `get_media_buy_delivery`     |
| ------------------- | -------------------------------- | ---------------------------- |
| **Purpose**         | Operational monitoring           | Reporting and reconciliation |
| **Freshness**       | Minutes (entity-level stats)     | Hours (batch report jobs)    |
| **Accuracy**        | Best-effort                      | Authoritative, billing-grade |
| **Date range**      | Always "since campaign start"    | Configurable period          |
| **Daily breakdown** | No                               | Yes                          |
| **Creative status** | Yes                              | No                           |
| **Missing assets**  | Yes                              | No                           |

Use `get_media_buys` to answer "what is the current state of my campaigns?" and `get_media_buy_delivery` for "how did my campaigns perform over a period?"

Status taxonomy is shared for lifecycle filters across both tasks (`pending_creatives`, `pending_start`, `active`, `paused`, `completed`). `get_media_buy_delivery` may additionally return reporting-only statuses (`reporting_delayed`, `failed`) in webhook contexts.

## Data Freshness

Snapshot `staleness_seconds` varies by platform:

| Platform type                                  | Typical `staleness_seconds` |
| ---------------------------------------------- | --------------------------- |
| Entity-level stats (e.g., GAM LineItemService) | 900 (15 min)                |
| Near-real-time insights API                    | 60–300                      |
| Batch-only reporting                           | 14400 (4 hr)                |

When the platform only has batch reporting, the seller agent should return the most recent cached data with the appropriate `staleness_seconds`.

If `include_snapshot: true` and `snapshot` is omitted for a package, check `snapshot_unavailable_reason`:

* `SNAPSHOT_UNSUPPORTED`: the seller does not support package snapshots for this integration
* `SNAPSHOT_TEMPORARILY_UNAVAILABLE`: snapshot pipeline is delayed or degraded; retry later
* `SNAPSHOT_PERMISSION_DENIED`: caller lacks permission to view snapshot metrics for that package

## Pagination

Use cursor pagination for broad status queries to avoid large payloads:

* Request: set `pagination.max_results` (1-100, default 50) and optional `pagination.cursor`
* Response: read `pagination.has_more`; when true, pass `pagination.cursor` into the next request
* ID-targeted queries (`media_buy_ids`) can omit pagination unless the ID set is very large

## Error Handling

| Error Code            | Description                                 | Resolution                                                         |
| --------------------- | ------------------------------------------- | ------------------------------------------------------------------ |
| `MEDIA_BUY_NOT_FOUND` | Media buy ID does not exist                 | Verify `media_buy_id`                                              |
| `CONTEXT_REQUIRED`    | No media buys found for the requested scope | Provide valid IDs/refs or broaden `status_filter`/pagination scope |
| `AUTH_REQUIRED`       | Authentication needed                       | Provide credentials                                                |

## Next Steps

* **Upload missing creatives**: Use [`sync_creatives`](/dist/docs/3.0.19/creative/task-reference/sync_creatives) for formats in `format_ids_pending`
* **Investigate zero delivery**: Check `delivery_status: "not_delivering"` and `start_time` to confirm the flight is active, then use [`update_media_buy`](/dist/docs/3.0.19/media-buy/task-reference/update_media_buy) to adjust pricing or targeting
* **Detailed reporting**: Use [`get_media_buy_delivery`](/dist/docs/3.0.19/media-buy/task-reference/get_media_buy_delivery) for date-range reporting and daily breakdowns
* **Optimize campaigns**: Use [`provide_performance_feedback`](/dist/docs/3.0.19/media-buy/task-reference/provide_performance_feedback) to share results with the seller
