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

# Get reporting

> Get reporting metrics across all advertisers and campaigns. The response is hierarchical for view=summary, flat leaf-by-day rows for view=timeseries, or a signed CSV download descriptor when download=true.



## OpenAPI

````yaml /v2/buyer-api-v2.yaml get /reporting/metrics
openapi: 3.0.0
info:
  title: Scope3 Buyer API
  version: 2.0.0
  description: |-
    REST API for advertisers to manage advertisers, campaigns, and reporting.

    ## Authentication

    All endpoints require a Bearer token in the Authorization header:
    ```
    Authorization: Bearer your-api-key
    ```

    ## Base URL

    `https://api.interchange.io/api/v2/buyer`

    ## For AI Agents

    AI agents can use the MCP endpoint at `/mcp/v2/buyer` with three tools:
    - `initialize`: Start an MCP session
    - `api_call`: Make REST API calls
    - `ask_about_capability`: Learn about API features
servers:
  - url: https://api.interchange.io/api/v2/buyer
    description: Production server
security: []
tags:
  - name: Signup
    description: Request reviewed access to Interchange
  - name: Account
    description: Account management, service tokens, and preferences
  - name: Asks
    description: >-
      What you are waiting on Scope3 for — support, product, and supply asks in
      one list
  - name: Advertisers
    description: Manage advertisers
  - name: Product Discovery
    description: Discover and select products
  - name: Campaigns
    description: Manage advertising campaigns
  - name: Creatives
    description: Build, manage, and sync campaign creatives via AdCP Creative Protocol
  - name: Reporting
    description: Access performance metrics
  - name: Event Sources
    description: >-
      Manage event source configurations and log conversion/marketing events for
      attribution
  - name: Property Lists
    description: Validate property lists against AAO registry
  - name: Sales Agents
    description: View and connect sales agents
  - name: Measurement
    description: Measurement sources, records, context, and freshness
  - name: Syndication
    description: Syndicate resources to ADCP agents
  - name: Tasks
    description: Track async operation status
  - name: Buyer Billing
    description: >-
      Consolidated invoicing for buyers — invoices and pending invoice items
      issued by Scope3 across the buyer customer.
  - name: MCP
    description: Model Context Protocol endpoints for AI agents
paths:
  /reporting/metrics:
    get:
      tags:
        - Reporting
      summary: Get reporting
      description: >-
        Get reporting metrics across all advertisers and campaigns. The response
        is hierarchical for view=summary, flat leaf-by-day rows for
        view=timeseries, or a signed CSV download descriptor when download=true.
      operationId: getReportingMetrics
      parameters:
        - in: query
          name: advertiserId
          schema:
            description: Filter to campaigns on this advertiser
            type: string
          description: Filter to campaigns on this advertiser
        - in: query
          name: campaignId
          schema:
            description: >-
              Filter to a specific campaign. If advertiserId is also provided,
              the campaign must belong to that advertiser
            type: string
          description: >-
            Filter to a specific campaign. If advertiserId is also provided, the
            campaign must belong to that advertiser
        - in: query
          name: channelGroupId
          schema:
            description: >-
              Filter to media buys in one campaign channel group. May be
              combined with advertiserId or campaignId to assert the expected
              parent scope
            type: string
            minLength: 1
            maxLength: 128
          description: >-
            Filter to media buys in one campaign channel group. May be combined
            with advertiserId or campaignId to assert the expected parent scope
        - in: query
          name: mediaBuyId
          schema:
            description: >-
              Filter to a specific media buy owned by the authenticated buyer.
              May be combined with advertiserId or campaignId to assert the
              expected parent scope
            type: string
          description: >-
            Filter to a specific media buy owned by the authenticated buyer. May
            be combined with advertiserId or campaignId to assert the expected
            parent scope
        - in: query
          name: startDate
          schema:
            description: Start date in ISO format (YYYY-MM-DD)
            example: '2025-01-01'
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          description: Start date in ISO format (YYYY-MM-DD)
        - in: query
          name: endDate
          schema:
            description: End date in ISO format (YYYY-MM-DD)
            example: '2025-01-31'
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          description: End date in ISO format (YYYY-MM-DD)
        - in: query
          name: days
          schema:
            default: 7
            description: >-
              Number of days to include (default: 7, max: 90). Use 0 for the
              full campaign timeframe.
            example: 7
            type: integer
            minimum: 0
            maximum: 90
          description: >-
            Number of days to include (default: 7, max: 90). Use 0 for the full
            campaign timeframe.
        - in: query
          name: view
          schema:
            default: summary
            description: >-
              Response format: "summary" for hierarchical
              advertiser/campaign/media-buy/package breakdown, "timeseries" for
              flat rows with one entry per (advertiser → campaign → media buy →
              package) × day
            type: string
            enum:
              - summary
              - timeseries
          description: >-
            Response format: "summary" for hierarchical
            advertiser/campaign/media-buy/package breakdown, "timeseries" for
            flat rows with one entry per (advertiser → campaign → media buy →
            package) × day
        - in: query
          name: displayCurrency
          schema:
            description: >-
              ISO-4217 currency for the consolidated (FX-converted)
              cross-advertiser rollup. Defaults to the buyer home currency when
              the advertisers share one; must be a platform-supported currency.
              Summary view only. The converted figures are display estimates,
              never billing inputs
            example: EUR
            type: string
            pattern: ^[A-Za-z]{3}$
          description: >-
            ISO-4217 currency for the consolidated (FX-converted)
            cross-advertiser rollup. Defaults to the buyer home currency when
            the advertisers share one; must be a platform-supported currency.
            Summary view only. The converted figures are display estimates,
            never billing inputs
        - in: query
          name: download
          schema:
            description: >-
              When true, generates a CSV file and returns a signed download URL
              instead of JSON data
            default: false
            type: boolean
          description: >-
            When true, generates a CSV file and returns a signed download URL
            instead of JSON data
        - in: query
          name: demo
          schema:
            description: >-
              When true, returns auto-generated demo data instead of querying
              real data sources
            default: false
            type: boolean
          description: >-
            When true, returns auto-generated demo data instead of querying real
            data sources
      responses:
        '200':
          description: Get reporting
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/ReportingMetricsResponse'
                  - $ref: '#/components/schemas/ReportingMetricsTimeseriesResponse'
                  - $ref: '#/components/schemas/ReportingMetricsExportResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - bearerAuth: []
components:
  schemas:
    ReportingMetricsResponse:
      type: object
      properties:
        advertisers:
          type: array
          items:
            $ref: '#/components/schemas/AdvertiserReporting'
          description: Advertiser-level reporting data
        totals:
          description: >-
            Aggregated totals across all advertisers, exact and native. Money
            metrics are present only when every advertiser shares one currency
            (totalsCurrency); when currencies mix they are null — see the
            consolidated block for the converted rollup
          allOf:
            - $ref: '#/components/schemas/ReportingTotalsMetrics'
        totalsCurrency:
          nullable: true
          description: >-
            ISO-4217 currency the native totals are denominated in; null when
            the advertisers span multiple currencies (money metrics in totals
            are then null)
          type: string
        consolidated:
          description: >-
            FX-converted cross-advertiser rollup in the display currency
            (explicit displayCurrency, or the buyer home currency when
            resolvable). Omitted when no conversion applies (single-currency
            buyer viewing natively). Display estimate only — never a billing
            input
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ConsolidatedReporting'
        periodStart:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Start of the reporting period (YYYY-MM-DD)
        periodEnd:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: End of the reporting period (YYYY-MM-DD)
      required:
        - advertisers
        - totals
        - totalsCurrency
        - periodStart
        - periodEnd
      additionalProperties: false
      description: >-
        Hierarchical reporting response: advertiser → campaign → media buy →
        package
    ReportingMetricsTimeseriesResponse:
      type: object
      properties:
        timeseries:
          type: array
          items:
            $ref: '#/components/schemas/TimeseriesEntry'
          description: >-
            Flat rows: one entry per (advertiser → campaign → media buy →
            package) × day, sorted by date ascending
        totals:
          description: >-
            Aggregated totals across the entire period. Money metrics are null
            when the emitted rows span currencies
          allOf:
            - $ref: '#/components/schemas/ReportingTotalsMetrics'
        totalsCurrency:
          nullable: true
          description: >-
            ISO-4217 currency the returned-row totals are denominated in; null
            when there are no rows or emitted rows span multiple currencies
          type: string
        periodStart:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Start of the reporting period (YYYY-MM-DD)
        periodEnd:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: End of the reporting period (YYYY-MM-DD)
      required:
        - timeseries
        - totals
        - totalsCurrency
        - periodStart
        - periodEnd
      additionalProperties: false
      description: >-
        Time-series reporting response: flat leaf × day rows (same hierarchy
        fields as the summary view, plus date)
    ReportingMetricsExportResponse:
      type: object
      properties:
        downloadUrl:
          type: string
          format: uri
          description: Signed URL to download the CSV file (expires in 7 days)
        expiresAt:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          description: ISO 8601 timestamp when the download URL expires
        fileName:
          type: string
          description: Name of the generated CSV file
        rowCount:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Number of data rows in the CSV (excluding header)
      required:
        - downloadUrl
        - expiresAt
        - fileName
        - rowCount
      additionalProperties: false
      description: Response containing a signed URL to download the exported CSV
    ErrorResponse:
      type: object
      properties:
        data:
          type: string
          nullable: true
          enum:
            - null
        error:
          $ref: '#/components/schemas/ApiError'
      required:
        - data
        - error
      additionalProperties: false
      description: Standard error response
    AdvertiserReporting:
      type: object
      properties:
        advertiserId:
          type: string
          description: Advertiser identifier
        advertiserName:
          type: string
          description: Advertiser name
        currency:
          type: string
          description: >-
            ISO-4217 currency used for money under this advertiser (the
            advertiser's locked primary currency); source delivery spend is
            normalized to it when an applicable FX rate is available
        metrics:
          $ref: '#/components/schemas/ReportingMetrics'
        campaigns:
          type: array
          items:
            $ref: '#/components/schemas/CampaignReporting'
          description: Campaign-level breakdown
      required:
        - advertiserId
        - advertiserName
        - currency
        - metrics
        - campaigns
      additionalProperties: false
      description: Advertiser-level reporting metrics with campaign breakdown
    ReportingTotalsMetrics:
      type: object
      properties:
        impressions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total impressions
        spend:
          nullable: true
          description: >-
            Total spend (gross, fee-inclusive — the buyer denomination) in the
            currency named by totalsCurrency; null when the returned data spans
            currencies or has no denomination
          type: number
          minimum: 0
        clicks:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total clicks
        views:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Viewable impressions (the MRC-viewable subset of impressions, per
            AdCP). For viewability rate, divide by impressions.
        completedViews:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Video/audio completions (qualified by view_duration_seconds when set
            on the goal)
        conversions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total conversions
        leads:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total leads
        videoCompletions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total video completions
        conversionValue:
          nullable: true
          description: >-
            Total conversion value in the currency named by totalsCurrency; null
            when the returned data spans currencies or has no denomination
          type: number
          minimum: 0
        ecpm:
          nullable: true
          description: >-
            Effective CPM: (spend * 1000) / impressions, derived from spend in
            this surface's denomination (gross fee-inclusive on buyer surfaces);
            null when impressions is 0
          type: number
        cpc:
          nullable: true
          description: >-
            Cost per click: spend / clicks, derived from spend in this surface's
            denomination (gross fee-inclusive on buyer surfaces); null when
            clicks is 0
          type: number
        ctr:
          nullable: true
          description: 'Click-through rate: clicks / impressions'
          type: number
        completionRate:
          nullable: true
          description: >-
            Completion rate: completedViews / impressions (completions per paid
            impression; impressions is the paid unit for CPM video)
          type: number
        cpa:
          nullable: true
          description: >-
            Cost per acquisition: spend / conversions, derived from spend in
            this surface's denomination (gross fee-inclusive on buyer surfaces);
            null when conversions is 0
          type: number
        roas:
          nullable: true
          description: >-
            Return on ad spend: conversionValue / spend; null when spend is 0,
            or when there is no conversion signal at all (conversionValue and
            conversions are both 0). Reports a true 0 when conversions are real
            but attributed value is zero. conversionValue carries no platform
            fee while spend is gross fee-inclusive on buyer surfaces, so buyer
            ROAS reads lower than storefront ROAS for identical delivery — the
            same denomination difference that already separates buyer and
            storefront cpc/ecpm.
          type: number
      required:
        - impressions
        - spend
        - clicks
        - views
        - completedViews
        - conversions
        - leads
        - videoCompletions
        - conversionValue
        - ecpm
        - cpc
        - ctr
        - completionRate
        - cpa
        - roas
      additionalProperties: false
      description: >-
        Reporting totals; money metrics are null when returned denominations mix
        or no denomination is available
    ConsolidatedReporting:
      type: object
      properties:
        totals:
          description: >-
            Cross-advertiser totals in the display currency: counts summed
            natively, money converted per advertiser then summed; money-derived
            metrics are null when any advertiser could not be converted
          allOf:
            - $ref: '#/components/schemas/ReportingTotalsMetrics'
        byAdvertiser:
          type: array
          items:
            type: object
            properties:
              advertiserId:
                type: string
              currency:
                type: string
                description: The advertiser native currency this row converted from
              spend:
                nullable: true
                description: >-
                  This advertiser spend converted to the display currency; null
                  when its pair had no rate
                type: number
            required:
              - advertiserId
              - currency
              - spend
            additionalProperties: false
          description: >-
            Per-advertiser converted spend so the consolidated total is
            auditable row by row
        conversionInfo:
          $ref: '#/components/schemas/ReportingConversionInfo'
      required:
        - totals
        - byAdvertiser
        - conversionInfo
      additionalProperties: false
      description: >-
        FX-converted cross-advertiser rollup (display estimate only — never
        billing)
    TimeseriesEntry:
      type: object
      properties:
        date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Reporting date (YYYY-MM-DD)
          example: '2025-01-15'
        advertiserId:
          type: string
          description: Advertiser identifier
        advertiserName:
          type: string
          description: Advertiser name
        currency:
          type: string
          description: >-
            ISO-4217 currency that actually denominates the row's spend, eCPM,
            and CPC; normally the advertiser's locked primary currency, or the
            reported source currency when FX conversion is unavailable
        campaignId:
          type: string
          description: Campaign identifier
        campaignName:
          type: string
          description: Campaign name
        management:
          description: >-
            Management state of the row's campaign: "tracked" (mirrored
            read-only from a connected provider account) or "managed" (authored
            or adopted through the platform). Rows without a campaign are
            managed.
          allOf:
            - $ref: '#/components/schemas/CampaignManagement'
        mediaBuyId:
          type: string
          description: Media buy identifier
        mediaBuyName:
          type: string
          description: Media buy name
        channelGroupId:
          description: Campaign channel group identifier, or null when ungrouped.
          nullable: true
          type: string
        channelGroupName:
          description: Campaign channel group name, or null when ungrouped.
          nullable: true
          type: string
        mediaBuyStatus:
          type: string
          description: Media buy status
        packageId:
          type: string
          description: Package identifier. Empty string when the media buy has no packages.
        productId:
          type: string
          description: Product identifier for this package. Empty string when no package.
        productName:
          type: string
          description: >-
            Human-readable product name for this package. Empty string when no
            package.
        metrics:
          $ref: '#/components/schemas/ReportingMetrics'
      required:
        - date
        - advertiserId
        - advertiserName
        - currency
        - campaignId
        - campaignName
        - management
        - mediaBuyId
        - mediaBuyName
        - mediaBuyStatus
        - packageId
        - productId
        - productName
        - metrics
      additionalProperties: false
      description: >-
        One row of metrics for a single (advertiser → campaign → media buy →
        package) leaf on a single day
    ApiError:
      type: object
      properties:
        code:
          type: string
          description: Machine-readable error code
        message:
          type: string
          description: Human-readable error message
        field:
          description: Field path associated with the error
          type: string
        details:
          description: Additional error context
          type: object
          additionalProperties: {}
      required:
        - code
        - message
      additionalProperties: false
      description: Structured error object
    ReportingMetrics:
      type: object
      properties:
        impressions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total impressions
        spend:
          type: number
          minimum: 0
          description: >-
            Total spend, denominated in the advertiser's primary currency (every
            campaign and buy is stamped in that currency; USD only for USD
            advertisers). On BUYER surfaces spend is GROSS (fee-inclusive):
            seller-reported net delivered spend is grossed up at read time at
            each buy's own pinned terms (a buy without pinned terms reports net
            as stored). On STOREFRONT surfaces spend stays NET as the seller
            reported it.
        clicks:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total clicks
        views:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Viewable impressions (the MRC-viewable subset of impressions, per
            AdCP). For viewability rate, divide by impressions.
        completedViews:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Video/audio completions (qualified by view_duration_seconds when set
            on the goal)
        conversions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total conversions
        leads:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total leads
        videoCompletions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Total video completions
        conversionValue:
          type: number
          minimum: 0
          description: >-
            Total conversion value (advertiser-attributed revenue from
            conversions), denominated the same as spend. Unlike spend,
            conversion value is never grossed up on buyer surfaces — it is
            advertiser revenue, not marketplace spend, so it carries no platform
            fee.
        ecpm:
          nullable: true
          description: >-
            Effective CPM: (spend * 1000) / impressions, derived from spend in
            this surface's denomination (gross fee-inclusive on buyer surfaces);
            null when impressions is 0
          type: number
        cpc:
          nullable: true
          description: >-
            Cost per click: spend / clicks, derived from spend in this surface's
            denomination (gross fee-inclusive on buyer surfaces); null when
            clicks is 0
          type: number
        ctr:
          nullable: true
          description: 'Click-through rate: clicks / impressions'
          type: number
        completionRate:
          nullable: true
          description: >-
            Completion rate: completedViews / impressions (completions per paid
            impression; impressions is the paid unit for CPM video)
          type: number
        cpa:
          nullable: true
          description: >-
            Cost per acquisition: spend / conversions, derived from spend in
            this surface's denomination (gross fee-inclusive on buyer surfaces);
            null when conversions is 0
          type: number
        roas:
          nullable: true
          description: >-
            Return on ad spend: conversionValue / spend; null when spend is 0,
            or when there is no conversion signal at all (conversionValue and
            conversions are both 0). Reports a true 0 when conversions are real
            but attributed value is zero. conversionValue carries no platform
            fee while spend is gross fee-inclusive on buyer surfaces, so buyer
            ROAS reads lower than storefront ROAS for identical delivery — the
            same denomination difference that already separates buyer and
            storefront cpc/ecpm.
          type: number
      required:
        - impressions
        - spend
        - clicks
        - views
        - completedViews
        - conversions
        - leads
        - videoCompletions
        - conversionValue
        - ecpm
        - cpc
        - ctr
        - completionRate
        - cpa
        - roas
      additionalProperties: false
      description: Raw and calculated reporting metrics
    CampaignReporting:
      type: object
      properties:
        campaignId:
          type: string
          description: Campaign identifier
        campaignName:
          type: string
          description: Campaign name
        management:
          description: >-
            Management state of this campaign: "tracked" (a campaign the
            platform did not set up, mirrored read-only from a connected
            provider account) or "managed" (authored or adopted through the
            platform). Buyer reporting currently includes managed campaigns only
            — tracked mirror delivery is excluded from this surface — so
            aggregates never silently mix the two states.
          allOf:
            - $ref: '#/components/schemas/CampaignManagement'
        metrics:
          $ref: '#/components/schemas/ReportingMetrics'
        mediaBuys:
          type: array
          items:
            $ref: '#/components/schemas/MediaBuyReporting'
          description: Media buy-level breakdown
      required:
        - campaignId
        - campaignName
        - management
        - metrics
        - mediaBuys
      additionalProperties: false
      description: Campaign-level reporting metrics with media buy breakdown
    ReportingConversionInfo:
      type: object
      properties:
        displayCurrency:
          type: string
          description: ISO-4217 currency the consolidated block is expressed in
        asOf:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: >-
            UTC calendar day whose locked rate-of-the-day was applied (one rate
            across the whole window)
        rateSource:
          type: string
          enum:
            - fx_rate_snapshots
          description: Where the rates came from (the platform rate-of-day table)
        rateBasis:
          type: string
          enum:
            - as-of
          description: >-
            Conversion basis: 'as-of' applies one current rate-of-the-day to the
            whole window (an estimate; a booked-rate basis is a later phase)
        rates:
          type: array
          items:
            type: object
            properties:
              pair:
                type: string
                description: BASEQUOTE pair, e.g. USDZAR = ZAR per USD
              rate:
                type: number
                description: QUOTE units per 1 BASE
            required:
              - pair
              - rate
            additionalProperties: false
          description: Every rate applied in this conversion
        unconverted:
          type: array
          items:
            type: string
          description: >-
            Native currencies that could NOT be converted (no rate available);
            their spend is excluded from the consolidated money totals rather
            than guessed
        estimate:
          type: boolean
          enum:
            - true
          description: >-
            Always true: the consolidated figures are display estimates, never
            billing or settlement inputs
      required:
        - displayCurrency
        - asOf
        - rateSource
        - rateBasis
        - rates
        - unconverted
        - estimate
      additionalProperties: false
      description: How the consolidated (FX-converted) figures were produced
    CampaignManagement:
      type: string
      enum:
        - tracked
        - managed
      description: >-
        Whether the platform acts on this campaign. "tracked" = a campaign the
        platform did not set up, mirrored from a connected provider account: the
        shell is derived from the buys underneath, read-only, and updates
        automatically as the upstream campaign changes. "managed" = a campaign
        authored or adopted through the platform (get_products →
        create_media_buy → update_media_buy) — the platform sends instructions
        down. In both states the execution system remains the source of truth.
    MediaBuyReporting:
      type: object
      properties:
        mediaBuyId:
          type: string
          description: Media buy identifier
        name:
          type: string
          description: Media buy name
        channelGroup:
          description: >-
            Campaign channel group that compiled into this media buy, or null
            for a legacy or ungrouped buy.
          nullable: true
          type: object
          properties:
            channelGroupId:
              type: string
            name:
              type: string
          required:
            - channelGroupId
            - name
          additionalProperties: false
        status:
          type: string
          description: Media buy status
        budget:
          nullable: true
          description: >-
            Total allocated budget for this media buy (sum of product budgets),
            GROSS (fee-inclusive — stored budgets are the buyer denomination
            since the gross-budgets flip). Legacy media buys created before fee
            terms were locked report their stored legacy (net) amount instead.
            Null if no budget set
          type: number
        metrics:
          $ref: '#/components/schemas/ReportingMetrics'
        deliveryFxConversion:
          description: >-
            FX conversion applied to delivery spend when the source reported in
            a different currency from the advertiser primary currency. Null when
            no conversion was needed.
          nullable: true
          type: object
          properties:
            fromCurrency:
              type: string
              description: >-
                ISO-4217 currency the delivery spend was denominated in: the
                currency the source reported, or — when the reported label
                contradicts an FX lock or booked spread-ledger leg — the
                currency the source settles in
            rate:
              type: number
              description: >-
                Multiplier applied to source spend to produce
                advertiser-currency spend (QUOTE per BASE, e.g. ZAR per USD)
            asOfDate:
              nullable: true
              description: >-
                UTC calendar date of the FX rate used. Null when source is
                settlement: identity denomination looks up no rate, so there is
                no rate date
              type: string
              pattern: ^\d{4}-\d{2}-\d{2}$
            source:
              type: string
              enum:
                - booked
                - snapshot
                - settlement
              description: >-
                booked: rate locked in the spread ledger at buy time; snapshot:
                fx_rate_snapshots fallback on buy creation date; settlement: the
                source reported a currency it is not paid in, so the spend is
                denominated by its settlement currency (rate is always 1)
          required:
            - fromCurrency
            - rate
            - asOfDate
            - source
          additionalProperties: false
        packages:
          type: array
          items:
            $ref: '#/components/schemas/PackageReporting'
          description: Package-level breakdown
      required:
        - mediaBuyId
        - name
        - status
        - budget
        - metrics
        - packages
      additionalProperties: false
      description: Media buy-level reporting metrics with package breakdown
    PackageReporting:
      type: object
      properties:
        packageId:
          type: string
          description: Package identifier
        productId:
          nullable: true
          description: Product identifier for this package
          type: string
        productName:
          nullable: true
          description: Human-readable product name for this package
          type: string
        metrics:
          $ref: '#/components/schemas/ReportingMetrics'
      required:
        - packageId
        - productId
        - productName
        - metrics
      additionalProperties: false
      description: Package-level reporting metrics
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key or access token

````