> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adcontextprotocol.org/llms.txt
> Use this file to discover all available pages before exploring further.

# get_media_buy_delivery

> get_media_buy_delivery task — retrieve impressions, spend, pacing, and dimensional breakdowns for active AdCP campaigns. Supports custom date ranges and metric filtering.

Retrieve comprehensive delivery metrics and performance data for media buy reporting.

**Response Time**: \~60 seconds (reporting query)

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

## Request Parameters

| Parameter              | Type                                                                                             | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ---------------------- | ------------------------------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account`              | [account-ref](/dist/docs/3.0.0-rc.2/building/integration/accounts-and-agents#account-references) | No       | Account reference. Pass `{ "account_id": "..." }` or `{ "brand": {...}, "operator": "..." }` if the seller supports implicit resolution. Only returns media buys belonging to this account. When omitted, returns data across all accessible accounts.                                                                                                                                                                                                                                                                          |
| `media_buy_ids`        | string\[]                                                                                        | No\*     | Array of media buy IDs to retrieve                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `buyer_refs`           | string\[]                                                                                        | No\*     | Array of buyer reference IDs                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `status_filter`        | string \| string\[]                                                                              | No       | Status filter: `"pending_activation"`, `"active"`, `"paused"`, `"completed"`. Defaults to `["active"]` when omitted.                                                                                                                                                                                                                                                                                                                                                                                                            |
| `start_date`           | string                                                                                           | No       | Report start date (YYYY-MM-DD), inclusive. Omit for campaign lifetime data. Only accepted when product supports `date_range`.                                                                                                                                                                                                                                                                                                                                                                                                   |
| `end_date`             | string                                                                                           | No       | Report end date (YYYY-MM-DD), **exclusive**. Omit for campaign lifetime data. Only accepted when product supports `date_range`.                                                                                                                                                                                                                                                                                                                                                                                                 |
| `reporting_dimensions` | object                                                                                           | No       | Request dimensional breakdowns within `by_package`. Include a key as an empty object (e.g., `"device_type": {}`) to activate with defaults. Keys: `geo`, `device_type`, `device_platform`, `audience`, `placement`. Each accepts optional `limit` (defaults to 25 for geo, audience, placement) and `sort_by` (sort-metric enum, default: `spend`). Geo requires `geo_level` (one per request) and `system` for metro/postal levels. Unsupported dimensions are silently omitted; malformed requests return a validation error. |

> **Date Range Behavior**: The date range is **start-inclusive, end-exclusive**. For example, `start_date: "2026-01-01"` and `end_date: "2026-01-02"` returns delivery data for January 1st only (from `2026-01-01 00:00:00` up to, but not including, `2026-01-02 00:00:00`). To get a full week of data (Jan 1-7), use `end_date: "2026-01-08"`.

**Date Range Examples**:

| start\_date  | end\_date    | Data Returned                    |
| ------------ | ------------ | -------------------------------- |
| `2026-01-01` | `2026-01-02` | January 1st only (1 day)         |
| `2026-01-01` | `2026-01-08` | January 1st through 7th (7 days) |
| `2026-01-01` | `2026-02-01` | Full month of January (31 days)  |
| `2026-01-15` | `2026-01-16` | January 15th only (1 day)        |

\*Either `media_buy_ids` or `buyer_refs` can be provided. If neither provided, returns all media buys in current session context.

## Response

Returns delivery report with aggregated totals and per-media-buy breakdowns:

| Field                  | Description                                                                                                                                                                                    |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `reporting_period`     | Date range for report (start/end timestamps)                                                                                                                                                   |
| `currency`             | ISO 4217 currency code (USD, EUR, GBP, etc.)                                                                                                                                                   |
| `attribution_window`   | Attribution methodology: `post_click` and `post_view` (duration objects), and `model` (last\_touch, first\_touch, linear, time\_decay, data\_driven)                                           |
| `aggregated_totals`    | Combined metrics across all media buys (impressions, spend, clicks, video\_completions, conversions, conversion\_value, roas, new\_to\_brand\_rate, cost\_per\_acquisition, media\_buy\_count) |
| `media_buy_deliveries` | Array of delivery data per media buy                                                                                                                                                           |

### Media Buy Delivery Object

| Field                | Description                                                                                                                              |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `media_buy_id`       | Media buy identifier                                                                                                                     |
| `buyer_ref`          | Buyer's reference identifier                                                                                                             |
| `buyer_campaign_ref` | Buyer campaign label echoed from `create_media_buy.buyer_campaign_ref` (when provided)                                                   |
| `status`             | Current status (`pending_activation`, `active`, `paused`, `completed`). In webhook context, may also be `reporting_delayed` or `failed`. |
| `totals`             | Aggregate metrics (impressions, spend, clicks, ctr, conversions, conversion\_value, roas, new\_to\_brand\_rate)                          |
| `by_package`         | Package-level breakdowns with delivery\_status, paused state, and pacing\_index                                                          |
| `daily_breakdown`    | Day-by-day delivery (date, impressions, spend, conversions, conversion\_value, roas, new\_to\_brand\_rate)                               |

See [schema](https://adcontextprotocol.org/schemas/v3/media-buy/get-media-buy-delivery-response.json) for complete field list.

## Common Scenarios

### Single Media Buy

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

  // Get single media buy delivery report
  const result = await testAgent.getMediaBuyDelivery({
    media_buy_ids: ['mb_12345'],
    start_date: '2024-02-01',
    end_date: '2024-02-07'
  });

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

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

  // Check for errors (discriminated union response)
  if ('errors' in validated && validated.errors) {
    throw new Error(`Query failed: ${JSON.stringify(validated.errors)}`);
  }

  console.log(`Delivered ${validated.aggregated_totals.impressions.toLocaleString()} impressions`);
  console.log(`Spend: $${validated.aggregated_totals.spend.toFixed(2)}`);
  if (validated.media_buy_deliveries.length > 0) {
    console.log(`CTR: ${(validated.media_buy_deliveries[0].totals.ctr * 100).toFixed(2)}%`);
  }
  ```

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

  async def main():
      # Get single media buy delivery report
      result = await test_agent.get_media_buy_delivery(
          GetMediaBuyDeliveryRequest(
              media_buy_ids=['mb_12345'],
              start_date='2024-02-01',
              end_date='2024-02-07'
          )
      )

      # Check for errors (discriminated union response)
      if hasattr(result, 'errors') and result.errors:
          raise Exception(f"Query failed: {result.errors}")

      print(f"Delivered {result.aggregated_totals.impressions:,} impressions")
      print(f"Spend: ${result.aggregated_totals.spend:.2f}")
      if result.media_buy_deliveries:
          print(f"CTR: {result.media_buy_deliveries[0].totals.ctr * 100:.2f}%")

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

### Multiple Media Buys

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

  // Get all active media buys from context
  const result = await testAgent.getMediaBuyDelivery({
    status_filter: 'active',
    start_date: '2024-02-01',
    end_date: '2024-02-07'
  });

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

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

  if ('errors' in validated && validated.errors) {
    throw new Error(`Query failed: ${JSON.stringify(validated.errors)}`);
  }

  console.log(`${validated.aggregated_totals.media_buy_count} active campaigns`);
  console.log(`Total impressions: ${validated.aggregated_totals.impressions.toLocaleString()}`);
  console.log(`Total spend: $${validated.aggregated_totals.spend.toFixed(2)}`);

  // Review each campaign
  validated.media_buy_deliveries.forEach(delivery => {
    console.log(`${delivery.media_buy_id}: ${delivery.totals.impressions.toLocaleString()} impressions, CTR ${(delivery.totals.ctr * 100).toFixed(2)}%`);
  });
  ```

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

  async def main():
      # Get all active media buys from context
      result = await test_agent.get_media_buy_delivery(
          GetMediaBuyDeliveryRequest(
              status_filter='active',
              start_date='2024-02-01',
              end_date='2024-02-07'
          )
      )

      if hasattr(result, 'errors') and result.errors:
          raise Exception(f"Query failed: {result.errors}")

      print(f"{result.aggregated_totals.media_buy_count} active campaigns")
      print(f"Total impressions: {result.aggregated_totals.impressions:,}")
      print(f"Total spend: ${result.aggregated_totals.spend:.2f}")

      # Review each campaign
      for delivery in result.media_buy_deliveries:
          print(f"{delivery.media_buy_id}: {delivery.totals.impressions:,} impressions, CTR {delivery.totals.ctr * 100:.2f}%")

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

### Date Range Reporting

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

  // Get month-to-date performance
  const now = new Date();
  const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
  const dateFormat = date => date.toISOString().split('T')[0];

  const result = await testAgent.getMediaBuyDelivery({
    media_buy_ids: ['mb_12345'],
    start_date: dateFormat(monthStart),
    end_date: dateFormat(now)
  });

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

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

  if ('errors' in validated && validated.errors) {
    throw new Error(`Query failed: ${JSON.stringify(validated.errors)}`);
  }

  if (validated.media_buy_deliveries.length > 0) {
    // Analyze daily breakdown
    const dailyBreakdown = validated.media_buy_deliveries[0].daily_breakdown;
    if (dailyBreakdown && dailyBreakdown.length > 0) {
      console.log(`Daily average: ${Math.round(validated.aggregated_totals.impressions / dailyBreakdown.length).toLocaleString()} impressions`);

      // Find peak day
      const peakDay = dailyBreakdown.reduce((max, day) =>
        day.impressions > max.impressions ? day : max
      );
      console.log(`Peak day: ${peakDay.date} with ${peakDay.impressions.toLocaleString()} impressions`);
    }
  }
  ```

  ```python Python test=false theme={null}
  import asyncio
  from adcp.testing import test_agent
  from adcp.types import GetMediaBuyDeliveryRequest
  from datetime import date

  async def main():
      # Get month-to-date performance
      today = date.today()
      month_start = date(today.year, today.month, 1)

      result = await test_agent.get_media_buy_delivery(
          GetMediaBuyDeliveryRequest(
              media_buy_ids=['mb_12345'],
              start_date=str(month_start),
              end_date=str(today)
          )
      )

      if hasattr(result, 'errors') and result.errors:
          raise Exception(f"Query failed: {result.errors}")

      if result.media_buy_deliveries:
          # Analyze daily breakdown
          daily_breakdown = result.media_buy_deliveries[0].daily_breakdown
          if daily_breakdown:
              daily_avg = result.aggregated_totals.impressions // len(daily_breakdown)
              print(f"Daily average: {daily_avg:,} impressions")

              # Find peak day
              peak_day = max(daily_breakdown, key=lambda d: d.impressions)
              print(f"Peak day: {peak_day.date} with {peak_day.impressions:,} impressions")

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

### Multi-Status Query

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

  // Get both active and paused campaigns
  const result = await testAgent.getMediaBuyDelivery({
    status_filter: ['active', 'paused'],
    start_date: '2024-02-01',
    end_date: '2024-02-07'
  });

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

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

  if ('errors' in validated && validated.errors) {
    throw new Error(`Query failed: ${JSON.stringify(validated.errors)}`);
  }

  // Group by status
  const byStatus = validated.media_buy_deliveries.reduce((acc, delivery) => {
    if (!acc[delivery.status]) acc[delivery.status] = [];
    acc[delivery.status].push(delivery);
    return acc;
  }, {});

  console.log(`Active campaigns: ${byStatus.active?.length || 0}`);
  console.log(`Paused campaigns: ${byStatus.paused?.length || 0}`);

  // Identify underperforming campaigns
  byStatus.paused?.forEach(delivery => {
    if (delivery.by_package && delivery.by_package.length > 0) {
      const avgPacing = delivery.by_package.reduce((sum, pkg) => sum + pkg.pacing_index, 0) / delivery.by_package.length;
      console.log(`${delivery.media_buy_id}: paused with ${(avgPacing * 100).toFixed(0)}% pacing`);
    }
  });
  ```

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

  async def main():
      # Get both active and paused campaigns
      result = await test_agent.get_media_buy_delivery(
          GetMediaBuyDeliveryRequest(
              status_filter=['active', 'paused'],
              start_date='2024-02-01',
              end_date='2024-02-07'
          )
      )

      if hasattr(result, 'errors') and result.errors:
          raise Exception(f"Query failed: {result.errors}")

      # Group by status
      by_status = defaultdict(list)
      for delivery in result.media_buy_deliveries:
          by_status[delivery.status].append(delivery)

      print(f"Active campaigns: {len(by_status['active'])}")
      print(f"Paused campaigns: {len(by_status['paused'])}")

      # Identify underperforming campaigns
      for delivery in by_status['paused']:
          if delivery.by_package:
              avg_pacing = sum(pkg.pacing_index for pkg in delivery.by_package) / len(delivery.by_package)
              print(f"{delivery.media_buy_id}: paused with {avg_pacing * 100:.0f}% pacing")

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

### Buyer Reference Query

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

  // Query by buyer reference instead of media buy ID
  const result = await testAgent.getMediaBuyDelivery({
    buyer_refs: ['acme_q1_campaign_2024', 'acme_q1_retargeting_2024']
  });

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

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

  if ('errors' in validated && validated.errors) {
    throw new Error(`Query failed: ${JSON.stringify(validated.errors)}`);
  }

  // Lifetime delivery data (no date range specified)
  console.log(`Total lifetime impressions: ${validated.aggregated_totals.impressions.toLocaleString()}`);
  console.log(`Total lifetime spend: $${validated.aggregated_totals.spend.toFixed(2)}`);

  // Compare campaigns
  validated.media_buy_deliveries.forEach(delivery => {
    if (delivery.totals.impressions > 0) {
      const cpm = (delivery.totals.spend / delivery.totals.impressions) * 1000;
      console.log(`${delivery.buyer_ref}: CPM $${cpm.toFixed(2)}, CTR ${(delivery.totals.ctr * 100).toFixed(2)}%`);
    }
  });
  ```

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

  async def main():
      # Query by buyer reference instead of media buy ID
      result = await test_agent.get_media_buy_delivery(
          GetMediaBuyDeliveryRequest(
              buyer_refs=['acme_q1_campaign_2024', 'acme_q1_retargeting_2024']
          )
      )

      if hasattr(result, 'errors') and result.errors:
          raise Exception(f"Query failed: {result.errors}")

      # Lifetime delivery data (no date range specified)
      print(f"Total lifetime impressions: {result.aggregated_totals.impressions:,}")
      print(f"Total lifetime spend: ${result.aggregated_totals.spend:.2f}")

      # Compare campaigns
      for delivery in result.media_buy_deliveries:
          if delivery.totals.impressions > 0:
              cpm = (delivery.totals.spend / delivery.totals.impressions) * 1000
              print(f"{delivery.buyer_ref}: CPM ${cpm:.2f}, CTR {delivery.totals.ctr * 100:.2f}%")

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

### Account-Scoped Query

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

  // Get delivery for a specific advertiser account
  const result = await testAgent.getMediaBuyDelivery({
    account: { account_id: 'acc_acme_pinnacle' },
    status_filter: 'active',
    start_date: '2024-02-01',
    end_date: '2024-02-07'
  });

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

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

  if ('errors' in validated && validated.errors) {
    throw new Error(`Query failed: ${JSON.stringify(validated.errors)}`);
  }

  console.log(`${validated.aggregated_totals.media_buy_count} campaigns for account`);
  console.log(`Total spend: $${validated.aggregated_totals.spend.toFixed(2)}`);
  ```

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

  async def main():
      # Get delivery for a specific advertiser account
      result = await test_agent.get_media_buy_delivery(
          GetMediaBuyDeliveryRequest(
              account={'account_id': 'acc_acme_pinnacle'},
              status_filter='active',
              start_date='2024-02-01',
              end_date='2024-02-07'
          )
      )

      if hasattr(result, 'errors') and result.errors:
          raise Exception(f"Query failed: {result.errors}")

      print(f"{result.aggregated_totals.media_buy_count} campaigns for account")
      print(f"Total spend: ${result.aggregated_totals.spend:.2f}")

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

## Metrics Definitions

| Metric                   | Definition                                                                       |
| ------------------------ | -------------------------------------------------------------------------------- |
| **Impressions**          | Number of times ads were displayed                                               |
| **Spend**                | Amount spent in specified currency                                               |
| **Clicks**               | Number of ad clicks (if available)                                               |
| **CTR**                  | Click-through rate (clicks/impressions)                                          |
| **Video Completions**    | Videos watched to completion                                                     |
| **Completion Rate**      | Video completions/video impressions                                              |
| **Conversions**          | Attributed conversions/orders                                                    |
| **Conversion Value**     | Total monetary value of attributed conversions                                   |
| **ROAS**                 | Return on ad spend (conversion\_value / spend)                                   |
| **New-to-Brand Rate**    | Fraction of conversions from first-time brand buyers (0-1)                       |
| **Cost per Acquisition** | Cost per conversion (spend / conversions)                                        |
| **Pacing Index**         | Actual vs. expected delivery rate (1.0 = on track, \<1.0 = behind, >1.0 = ahead) |
| **CPM**                  | Cost per thousand impressions (spend/impressions \* 1000)                        |

## Query Behavior

### Context-Based Queries

* If neither `media_buy_ids` nor `buyer_refs` provided, returns all media buys from current session context
* Context established by previous operations (e.g., `create_media_buy`)

### Status Filtering

* Defaults to `["active"]` if not specified
* Can be single string (`"active"`) or array (`["active", "paused"]`)
* Valid filter values are media-buy lifecycle statuses: `pending_activation`, `active`, `paused`, `completed`
* `reporting_delayed` and `failed` are delivery/reporting statuses returned in webhook contexts, not request filter values
* Some legacy integrations may emit `pending`; treat it as equivalent to `pending_activation`

### Date Ranges

* If dates not specified, returns campaign lifetime delivery data
* Both `start_date` and `end_date` must be provided together — partial date ranges are invalid
* Date format: `YYYY-MM-DD`
* **Start-inclusive, end-exclusive**: `start_date` is included, `end_date` is excluded. For example, `start_date: "2026-01-01"` and `end_date: "2026-01-02"` returns data for January 1st only.
* Products declare date range support in `reporting_capabilities.date_range_support`
* Products with `date_range_support: "lifetime_only"` reject requests that include `start_date`/`end_date` with a `DATE_RANGE_NOT_SUPPORTED` error
* Products with `date_range_support: "date_range"` accept date parameters and filter delivery data accordingly
* Daily breakdown may be truncated for long date ranges to reduce response size

### Metric Availability

* **Universal**: Impressions, spend (available on all platforms)
* **Format-dependent**: Clicks, video completions (depends on inventory type and platform capabilities)
* **Commerce attribution**: Conversions, conversion\_value, roas, new\_to\_brand\_rate (available on commerce media platforms)
* **Attribution window**: `attribution_window` describes the lookback windows and model used for conversion attribution (e.g., 14-day click, 1-day view, last\_touch)
* **Package-level**: All metrics broken down by package with pacing\_index

## Data Freshness

* Reporting data typically has 2-4 hour delay
* Real-time impression counts not available
* Use for periodic reporting and optimization decisions, not live monitoring

## Error Handling

| Error Code                 | Description                              | Resolution                                                                                          |
| -------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `AUTH_REQUIRED`            | Authentication needed                    | Provide credentials                                                                                 |
| `MEDIA_BUY_NOT_FOUND`      | Media buy doesn't exist                  | Verify media\_buy\_id                                                                               |
| `INVALID_DATE_RANGE`       | Invalid start/end dates                  | Use YYYY-MM-DD format, ensure start \< end                                                          |
| `DATE_RANGE_NOT_SUPPORTED` | Product only supports lifetime reporting | Omit `start_date` and `end_date`. Check `reporting_capabilities.date_range_support` on the product. |
| `CONTEXT_REQUIRED`         | No media buys in context                 | Provide media\_buy\_ids or buyer\_refs explicitly                                                   |
| `INVALID_STATUS_FILTER`    | Invalid status value                     | Use valid status: pending\_activation, active, paused, completed                                    |

## Package-Level Metrics

The `by_package` array provides per-package delivery details with these key fields:

**Buyer Control**:

* **`paused`**: Whether the package is currently paused by the buyer (true/false)

**System State**:

* **`delivery_status`**: System-reported operational state:
  * `delivering` - Package is actively delivering impressions
  * `completed` - Package finished successfully
  * `budget_exhausted` - Package ran out of budget
  * `flight_ended` - Package reached its end date
  * `goal_met` - Package achieved its impression/conversion goal

**Performance**:

* **`pacing_index`**: Delivery pace (1.0 = on track, below 1.0 = behind, above 1.0 = ahead)
* **`rate`**: Effective pricing rate (e.g., CPM)
* **`pricing_model`**: How the package is billed (cpm, cpcv, cpp, etc.)

**Key Distinction**: `paused` reflects buyer control, while `delivery_status` reflects system reality. A package can be not paused but have `delivery_status: "budget_exhausted"`.

## Creative-Level Metrics

When the seller supports creative-level reporting (`supports_creative_breakdown` in reporting capabilities), each package includes a `by_creative` array with per-creative delivery metrics.

Each creative entry includes:

* **`creative_id`**: Creative identifier matching the creative assignment
* **`weight`**: Delivery weight for this creative during the reporting period (0-100)
* All standard delivery metrics (impressions, spend, clicks, ctr, etc.)

```json theme={null}
{
  "by_package": [
    {
      "package_id": "pkg_001",
      "spend": 5000,
      "impressions": 100000,
      "pricing_model": "cpm",
      "rate": 50,
      "currency": "USD",
      "delivery_status": "delivering",
      "by_creative": [
        {
          "creative_id": "hero_video_30s",
          "weight": 60,
          "impressions": 60000,
          "spend": 3000,
          "clicks": 3000,
          "ctr": 0.05,
          "completion_rate": 0.72
        },
        {
          "creative_id": "hero_video_15s",
          "weight": 40,
          "impressions": 40000,
          "spend": 2000,
          "clicks": 1200,
          "ctr": 0.03,
          "completion_rate": 0.85
        }
      ]
    }
  ]
}
```

For deeper creative analytics including variant-level delivery data (asset combination optimization, generative creative), use [`get_creative_delivery`](/dist/docs/3.0.0-rc.2/creative/task-reference/get_creative_delivery). This is a Creative Protocol task — call it on any agent that implements the Creative Protocol, which may be the same sales agent if it declares `"creative"` in `supported_protocols`. See [Creative capabilities on sales agents](/dist/docs/3.0.0-rc.2/creative/sales-agent-creative-capabilities).

## Catalog-item reporting

For catalog-driven packages (packages with a `catalog` field), the seller can return per-catalog-item delivery in the `by_catalog_item` array within each package.

Each entry identifies the catalog item and includes standard delivery metrics:

| Field             | Description                                                                                |
| ----------------- | ------------------------------------------------------------------------------------------ |
| `content_id`      | The item identifier (SKU, GTIN, job ID, etc.)                                              |
| `content_id_type` | Identifier type (`sku`, `gtin`, `job_id`, etc.) matching the catalog's `content_id_type`   |
| Standard metrics  | `impressions`, `spend`, `clicks`, `ctr`, `conversions`, `roas`, and other delivery metrics |

This is optional. Sellers that support item-level reporting populate `by_catalog_item`; sellers that do not simply omit it.

```json theme={null}
{
  "by_package": [
    {
      "package_id": "pkg_001",
      "spend": 5000,
      "impressions": 100000,
      "pricing_model": "cpc",
      "rate": 1.20,
      "currency": "USD",
      "delivery_status": "delivering",
      "by_catalog_item": [
        {
          "content_id": "SKU-12345",
          "content_id_type": "sku",
          "impressions": 45000,
          "spend": 2250,
          "clicks": 1800,
          "ctr": 0.04,
          "conversions": 90,
          "roas": 4.2
        },
        {
          "content_id": "SKU-67890",
          "content_id_type": "sku",
          "impressions": 55000,
          "spend": 2750,
          "clicks": 2200,
          "ctr": 0.04,
          "conversions": 110,
          "roas": 3.8
        }
      ]
    }
  ]
}
```

## Dimension Breakdowns

When you include `reporting_dimensions` in the request, the response includes dimensional breakdown arrays within each `by_package` entry. Each breakdown entry inherits all fields from `delivery-metrics` plus dimension-specific identifiers.

### Requesting breakdowns

```json test=false theme={null}
{
  "media_buy_ids": ["mb_123"],
  "reporting_dimensions": {
    "geo": { "geo_level": "metro", "system": "nielsen_dma", "limit": 10 },
    "device_type": {},
    "placement": { "limit": 5, "sort_by": "roas" }
  }
}
```

Each dimension accepts optional `limit` (max rows; defaults to 25 for geo, audience, and placement) and `sort_by` (any value from the `sort-metric` enum, e.g., `spend`, `impressions`, `clicks`, `roas` — defaults to `spend` descending; falls back to `spend` if the seller does not report the requested metric). Geo requires `geo_level` (`country`, `region`, `metro`, `postal_area`) and `system` for metro/postal levels. Each request uses a single geo\_level — for multiple granularities (e.g., country and region), make separate requests. Unsupported dimensions are silently omitted from the response, but malformed requests (e.g., geo without `geo_level`) return a validation error. Breakdowns are per-dimension only — cross-dimensional intersections (e.g., device\_type × geo) are not supported.

### Available dimensions

| Dimension       | Breakdown field      | Required fields                                          | Capability flag                      |
| --------------- | -------------------- | -------------------------------------------------------- | ------------------------------------ |
| Geography       | `by_geo`             | `geo_level`, `geo_code`, `impressions`, `spend`          | `supports_geo_breakdown`             |
| Device type     | `by_device_type`     | `device_type`, `impressions`, `spend`                    | `supports_device_type_breakdown`     |
| Device platform | `by_device_platform` | `device_platform`, `impressions`, `spend`                | `supports_device_platform_breakdown` |
| Audience        | `by_audience`        | `audience_id`, `audience_source`, `impressions`, `spend` | `supports_audience_breakdown`        |
| Placement       | `by_placement`       | `placement_id`, `impressions`, `spend`                   | `supports_placement_breakdown`       |

Check `reporting_capabilities` on the product to discover which dimensions are available. Product-level capabilities are authoritative since different products from the same seller may support different breakdowns.

### Truncation

Each breakdown array has a sibling boolean flag (e.g., `by_geo_truncated`). When `true`, additional rows exist beyond the returned set. When `false`, the list is complete. Sellers MUST return the truncated flag whenever the corresponding breakdown array is present. Rows are sorted by the requested `sort_by` metric descending.

### Audience sources

The `audience_source` field indicates where the audience segment originated:

| Source        | Description                                     | Targetable?                                     |
| ------------- | ----------------------------------------------- | ----------------------------------------------- |
| `synced`      | Buyer's first-party data via `sync_audiences`   | Yes — use `audience_include`/`audience_exclude` |
| `platform`    | Seller's native segments (interest, behavioral) | No — informational                              |
| `third_party` | External data provider segments                 | No — informational                              |
| `lookalike`   | Platform-generated expansion from a seed        | No — informational                              |
| `retargeting` | Prior engagement via seller's pixel/tag         | No — informational                              |
| `unknown`     | Unclassified or unrecognized audience source    | No — informational                              |

## Best Practices

**1. Check Date Range Support**
Before requesting date-filtered delivery, check `reporting_capabilities.date_range_support` on the product. Products with `lifetime_only` support reject date range requests — omit `start_date` and `end_date` to get campaign lifetime data instead.

**2. Use Date Ranges for Analysis**
For products that support date ranges, specify dates for period-over-period comparisons and trend analysis.

**3. Monitor Pacing Index**
Aim for 0.95-1.05 pacing index. Values outside this range indicate delivery issues.

**4. Check Daily Breakdown**
Identify delivery patterns and weekend/weekday performance differences.

**5. Compare Package Performance**
Use `by_package` breakdowns to identify best-performing inventory. Check both `paused` state and `delivery_status` to understand why packages aren't delivering.

**6. Track Status Changes**
Use multi-status queries to understand why campaigns were paused or completed.

## Next Steps

After retrieving delivery data:

1. **Optimize Campaigns**: Use [`update_media_buy`](/dist/docs/3.0.0-rc.2/media-buy/task-reference/update_media_buy) to adjust budgets, pacing, or targeting
2. **Provide Feedback**: Use [`provide_performance_feedback`](/dist/docs/3.0.0-rc.2/media-buy/task-reference/provide_performance_feedback) to share results with seller
3. **Update Creatives**: Use [`sync_creatives`](/dist/docs/3.0.0-rc.2/creative/task-reference/sync_creatives) to refresh underperforming assets
4. **Create Follow-Up Campaigns**: Use [`create_media_buy`](/dist/docs/3.0.0-rc.2/media-buy/task-reference/create_media_buy) based on insights

## Learn More

* [Media Buy Lifecycle](/dist/docs/3.0.0-rc.2/media-buy/media-buys/) - Complete campaign workflow
* [Async Operations](/dist/docs/3.0.0-rc.2/building/implementation/async-operations) - Async patterns and status handling
* [Performance Optimization](/dist/docs/3.0.0-rc.2/media-buy/media-buys/optimization-reporting) - Using delivery data for optimization
