Module adcp.types.media_buy

AdCP media buy types — curated partial surface.

Media-buy lifecycle types — create / update / get media buys, packages, delivery, pacing, budget, targeting overlays, and media-buy status.

A stable, narrow alternative to importing the whole :mod:adcp.types namespace. Every name here is also exported from :mod:adcp.types; this module simply groups the ones a media buy integration reaches for, and never exposes the internal generated layer.

This module is for curation and discoverability, not a separate performance tier: importing it is cheap, but the first access to any AdCP type (here or via :mod:adcp.types / :mod:adcp) realizes the full generated Pydantic graph — there is no per-domain graph. Use it for a smaller, focused import surface.

from adcp.types.media_buy import CreateMediaBuyRequest

Classes

class AggregatedTotals (**data: Any)
Expand source code
class AggregatedTotals(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    impressions: Annotated[
        float, Field(description='Total impressions delivered across all media buys', ge=0.0)
    ]
    spend: Annotated[float, Field(description='Total amount spent across all media buys', ge=0.0)]
    clicks: Annotated[
        float | None,
        Field(description='Total clicks across all media buys (if applicable)', ge=0.0),
    ] = None
    completed_views: Annotated[
        float | None,
        Field(
            description='Total audio/video completions across all media buys (if applicable)',
            ge=0.0,
        ),
    ] = None
    views: Annotated[
        float | None, Field(description='Total views across all media buys (if applicable)', ge=0.0)
    ] = None
    conversions: Annotated[
        float | None,
        Field(description='Total conversions across all media buys (if applicable)', ge=0.0),
    ] = None
    conversion_value: Annotated[
        float | None,
        Field(description='Total conversion value across all media buys (if applicable)', ge=0.0),
    ] = None
    roas: Annotated[
        float | None,
        Field(
            description='Aggregate return on ad spend across all media buys (total conversion_value / total spend)',
            ge=0.0,
        ),
    ] = None
    new_to_brand_rate: Annotated[
        float | None,
        Field(
            description='Fraction of total conversions across all media buys from first-time brand buyers (weighted by conversion volume, not a simple average of per-buy rates)',
            ge=0.0,
            le=1.0,
        ),
    ] = None
    cost_per_acquisition: Annotated[
        float | None,
        Field(
            description='Aggregate cost per conversion across all media buys (total spend / total conversions)',
            ge=0.0,
        ),
    ] = None
    completion_rate: Annotated[
        float | None,
        Field(
            description='Aggregate completion rate across all media buys (weighted by impressions, not a simple average of per-buy rates)',
            ge=0.0,
            le=1.0,
        ),
    ] = None
    reach: Annotated[
        float | None,
        Field(
            description='Deduplicated reach across all media buys (if the seller can deduplicate across buys; otherwise sum of per-buy reach). Only present when all media buys share the same reach_unit. Omitted when reach units are heterogeneous — use per-buy reach values instead.',
            ge=0.0,
        ),
    ] = None
    reach_unit: Annotated[
        reach_unit_1.ReachUnit | None,
        Field(
            description='Unit of measurement for reach. Only present when all aggregated media buys use the same reach_unit.'
        ),
    ] = None
    frequency: Annotated[
        float | None,
        Field(
            description='Average frequency per reach unit across all media buys (impressions / reach when cross-buy deduplication is available). Only present when reach is present.',
            ge=0.0,
        ),
    ] = None
    media_buy_count: Annotated[
        int, Field(description='Number of media buys included in the response', ge=0)
    ]
    metric_aggregates: Annotated[
        list[delivery_metric_aggregate.DeliveryMetricAggregate] | None,
        Field(
            description="Cross-buy delivery aggregates partitioned by qualifier. Row-symmetric with `package.committed_metrics` and `by_package[].missing_metrics` — same atomic unit `(scope, metric_id, qualifier)` — so reconciliation collapses to a row-level join on the tuple. Granularity rule: one row per `(metric_id, full-qualifier-set)`, reported at the finest available granularity; buyers re-aggregate up if they want a coarser view. Used only for metrics with non-empty qualifier sets — unqualified metrics (`impressions`, `spend`, `media_buy_count`, etc.) remain at the top of `aggregated_totals`. **Mutual exclusion MUST**: for any `metric_id` appearing in `metric_aggregates`, the corresponding top-level scalar in `aggregated_totals` MUST be omitted (not zeroed) — avoids duplicate sources of truth. The qualifier vocabulary on this delivery surface is closed today (`additionalProperties: false`, same content as `committed_metrics.qualifier`) but is expected to **diverge from contract qualifier in future minors** as transparency disclosures buyers don't commit to ship delivery-only (e.g., `tracker_firing` pending #3832 resolution). Each row carries a `value` plus inlined per-metric component fields (e.g., `measurable_impressions` and `viewable_impressions` for `viewable_rate`; `spend` and `conversions` for `cost_per_acquisition`). Per-buy `totals` keeps its flat shape — each buy is single-qualifier by definition; only the aggregate spans qualifiers. **Qualifier-set drift across reports**: when a campaign gains a new qualifier mid-flight (e.g., adds `tracker_firing` partitioning in week 2), prior periods' rows remain valid at their original granularity; buyers SHOULD NOT retroactively repartition.",
            examples=[
                [
                    {
                        'scope': 'standard',
                        'metric_id': 'viewable_rate',
                        'qualifier': {'viewability_standard': 'mrc'},
                        'value': 0.7286,
                        'measurable_impressions': 700000,
                        'viewable_impressions': 510000,
                    },
                    {
                        'scope': 'standard',
                        'metric_id': 'viewable_rate',
                        'qualifier': {'viewability_standard': 'groupm'},
                        'value': 0.55,
                        'measurable_impressions': 180000,
                        'viewable_impressions': 99000,
                    },
                    {
                        'scope': 'vendor',
                        'vendor': {'domain': 'attentionvendor.example'},
                        'metric_id': 'attention_units',
                        'qualifier': {},
                        'value': 4.2,
                        'measurable_impressions': 800000,
                    },
                ]
            ],
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var clicks : float | None
var completed_views : float | None
var completion_rate : float | None
var conversion_value : float | None
var conversions : float | None
var cost_per_acquisition : float | None
var frequency : float | None
var impressions : float
var media_buy_count : int
var metric_aggregates : list[adcp.types.generated_poc.core.delivery_metric_aggregate.DeliveryMetricAggregate] | None
var model_config
var new_to_brand_rate : float | None
var reach : float | None
var reach_unit : adcp.types.generated_poc.enums.reach_unit.ReachUnit | None
var roas : float | None
var spend : float
var views : float | None

Inherited members

class AssignedPackage (**data: Any)
Expand source code
class AssignedPackage(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    package_id: Annotated[str, Field(description='Package identifier')]
    assigned_date: Annotated[AwareDatetime, Field(description='When this assignment was created')]

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var assigned_date : pydantic.types.AwareDatetime
var model_config
var package_id : str

Inherited members

class ByPackageItem (**data: Any)
Expand source code
class ByPackageItem(DeliveryMetrics):
    package_id: Annotated[str, Field(description="Seller's package identifier")]
    pacing_index: Annotated[
        float | None,
        Field(description='Delivery pace (1.0 = on track, <1.0 = behind, >1.0 = ahead)', ge=0.0),
    ] = None
    pricing_model: Annotated[
        pricing_model_1.PricingModel,
        Field(
            description='The pricing model used for this package (e.g., cpm, cpcv, cpp). Indicates how the package is billed and which metrics are most relevant for optimization.'
        ),
    ]
    rate: Annotated[
        float,
        Field(
            description='The pricing rate for this package in the specified currency. For fixed-rate pricing, this is the agreed rate (e.g., CPM rate of 12.50 means $12.50 per 1,000 impressions). For auction-based pricing, this represents the effective rate based on actual delivery.',
            ge=0.0,
        ),
    ]
    currency: Annotated[
        str,
        Field(
            description="ISO 4217 currency code (e.g., USD, EUR, GBP) for this package's pricing. Indicates the currency in which the rate and spend values are denominated. Different packages can use different currencies when supported by the publisher.",
            pattern='^[A-Z]{3}$',
        ),
    ]
    delivery_status: Annotated[
        DeliveryStatus | None,
        Field(
            description='System-reported operational state of this package. Reflects actual delivery state independent of buyer pause control.'
        ),
    ] = None
    paused: Annotated[
        bool | None, Field(description='Whether this package is currently paused by the buyer')
    ] = None
    is_final: Annotated[
        bool | None,
        Field(
            description="Whether this delivery data is final for the reporting period. When false, the data may be updated as measurement matures (e.g., broadcast C7 window accumulating DVR playback) or as processing completes (e.g., IVT filtering, deduplication). When true, the seller considers this data closed — no further updates for this period — and is willing to invoice on it subject to the buy's `measurement_terms.billing_measurement`. Absent means the seller does not distinguish provisional from final data."
        ),
    ] = None
    finalized_at: Annotated[
        AwareDatetime | None,
        Field(
            description="ISO 8601 timestamp at which this package's data became final. Present only when `is_final: true`. Anchors reconciliation and (when later defined) dispute-window clocks against the buy's `measurement_terms.billing_measurement.measurement_window`."
        ),
    ] = None
    measurement_window: Annotated[
        str | None,
        Field(
            description="Which measurement window this data represents, referencing a window_id from the product's reporting_capabilities.measurement_windows. For broadcast: 'live', 'c3', 'c7'. When absent, the data is not windowed (standard digital reporting). When present with is_final: false, a later report for the same period will provide a wider window or more complete data.",
            examples=['live', 'c3', 'c7'],
            max_length=50,
        ),
    ] = None
    supersedes_window: Annotated[
        str | None,
        Field(
            description="Which measurement window this data replaces. Present on window_update notifications to indicate progression (e.g., 'live' when reporting C3 data that supersedes live-only numbers). Absent on the first report for a period. Buyers should replace stored data for the superseded window with this report's data.",
            examples=['live', 'c3'],
            max_length=50,
        ),
    ] = None
    missing_metrics: Annotated[
        list[missing_metric.MissingMetric] | None,
        Field(
            description="Metrics that the binding reporting contract declared but that are NOT populated in this report. Reconciliation source: when `package.committed_metrics` is present, `missing_metrics` is computed against entries where `committed_at < reporting_period.end` — independent of subsequent product mutations and respecting the commitment timestamp on each entry (a metric committed mid-flight is only flagged missing in reports for periods after its commitment). When `package.committed_metrics` is absent, fall back to the product's current `reporting_capabilities.available_metrics` (no timestamp filter). Empty array (or absent) indicates clean delivery against the contract. Non-empty signals an accountability breach — the seller committed to the metric but did not produce the value here. Sellers MUST exclude metrics that are not yet measurable for the current `measurement_window` (e.g., post-IVT counts during the live window) — those will appear (or not) when a wider window supersedes this report via `supersedes_window`. Each entry uses an explicit `scope` discriminator: `standard` for entries from the closed `available-metric.json` enum, `vendor` for vendor-defined metrics anchored on a BrandRef. Symmetric with `committed_metrics`.",
            examples=[
                [],
                [{'scope': 'standard', 'metric_id': 'completed_views'}],
                [
                    {'scope': 'standard', 'metric_id': 'completed_views'},
                    {
                        'scope': 'vendor',
                        'vendor': {'domain': 'attentionvendor.example'},
                        'metric_id': 'attention_units',
                    },
                ],
            ],
        ),
    ] = None
    by_catalog_item: Annotated[
        list[catalog_item_delivery_metrics.CatalogItemDeliveryMetrics] | None,
        Field(
            description='Delivery by catalog item within this package. Available for catalog-driven packages when the seller supports item-level reporting.'
        ),
    ] = None
    by_creative: Annotated[
        list[creative_delivery_metrics.CreativeDeliveryMetrics] | None,
        Field(
            description='Metrics broken down by creative within this package. Available when the seller supports creative-level reporting.'
        ),
    ] = None
    by_keyword: Annotated[
        list[keyword_delivery_metrics.KeywordDeliveryMetrics] | None,
        Field(
            description='Metrics broken down by keyword within this package. One row per (keyword, match_type) pair — the same keyword with different match types appears as separate rows. Keyword-grain only: rows reflect aggregate performance of each targeted keyword, not individual search queries. Rows may not sum to package totals when a single impression is attributed to the triggering keyword only. Available for search and retail media packages when the seller supports keyword-level reporting.'
        ),
    ] = None
    by_geo: Annotated[
        list[geo_delivery_metrics.GeoDeliveryMetrics] | None,
        Field(
            description="Delivery by geographic area within this package. Available when the buyer requests geo breakdown via reporting_dimensions and the seller supports it. Each dimension's rows are independent slices that should sum to the package total."
        ),
    ] = None
    by_geo_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_geo was truncated due to the requested limit or a seller-imposed maximum. Sellers MUST return this flag whenever by_geo is present (false means the list is complete).'
        ),
    ] = None
    by_device_type: Annotated[
        list[ByDeviceTypeItem] | None,
        Field(
            description='Delivery by device form factor within this package. Available when the buyer requests device_type breakdown via reporting_dimensions and the seller supports it.'
        ),
    ] = None
    by_device_type_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_device_type was truncated. Sellers MUST return this flag whenever by_device_type is present (false means the list is complete).'
        ),
    ] = None
    by_device_platform: Annotated[
        list[ByDevicePlatformItem] | None,
        Field(
            description='Delivery by operating system within this package. Available when the buyer requests device_platform breakdown via reporting_dimensions and the seller supports it. Useful for CTV campaigns where tvOS vs Roku OS vs Fire OS matters.'
        ),
    ] = None
    by_device_platform_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_device_platform was truncated. Sellers MUST return this flag whenever by_device_platform is present (false means the list is complete).'
        ),
    ] = None
    by_audience: Annotated[
        list[ByAudienceItem] | None,
        Field(
            description="Delivery by audience segment within this package. Available when the buyer requests audience breakdown via reporting_dimensions and the seller supports it. Only 'synced' audiences are directly targetable via the targeting overlay; other sources are informational."
        ),
    ] = None
    by_audience_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_audience was truncated. Sellers MUST return this flag whenever by_audience is present (false means the list is complete).'
        ),
    ] = None
    by_placement: Annotated[
        list[ByPlacementItem] | None,
        Field(
            description="Delivery by placement within this package. Available when the buyer requests placement breakdown via reporting_dimensions and the seller supports it. Placement IDs reference the product's placements array."
        ),
    ] = None
    by_placement_truncated: Annotated[
        bool | None,
        Field(
            description='Whether by_placement was truncated. Sellers MUST return this flag whenever by_placement is present (false means the list is complete).'
        ),
    ] = None
    daily_breakdown: Annotated[
        list[DailyBreakdownItem] | None,
        Field(
            description='Day-by-day delivery for this package. Only present when include_package_daily_breakdown is true in the request. Enables per-package pacing analysis and line-item monitoring.'
        ),
    ] = None
    spend: Any

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.delivery_metrics.DeliveryMetrics
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var by_audience : list[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByAudienceItem] | None
var by_audience_truncated : bool | None
var by_catalog_item : list[adcp.types.generated_poc.core.catalog_item_delivery_metrics.CatalogItemDeliveryMetrics] | None
var by_creative : list[adcp.types.generated_poc.core.creative_delivery_metrics.CreativeDeliveryMetrics] | None
var by_device_platform : list[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByDevicePlatformItem] | None
var by_device_platform_truncated : bool | None
var by_device_type : list[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByDeviceTypeItem] | None
var by_device_type_truncated : bool | None
var by_geo : list[adcp.types.generated_poc.core.geo_delivery_metrics.GeoDeliveryMetrics] | None
var by_geo_truncated : bool | None
var by_keyword : list[adcp.types.generated_poc.core.keyword_delivery_metrics.KeywordDeliveryMetrics] | None
var by_placement : list[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByPlacementItem] | None
var by_placement_truncated : bool | None
var currency : str
var daily_breakdown : list[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.DailyBreakdownItem] | None
var delivery_status : adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.DeliveryStatus | None
var finalized_at : pydantic.types.AwareDatetime | None
var is_final : bool | None
var measurement_window : str | None
var missing_metrics : list[adcp.types.generated_poc.core.missing_metric.MissingMetric] | None
var model_config
var pacing_index : float | None
var package_id : str
var paused : bool | None
var pricing_model : adcp.types.generated_poc.enums.pricing_model.PricingModel
var rate : float
var spend : Any
var supersedes_window : str | None

Inherited members

class CreateMediaBuyRequest (**data: Any)
Expand source code
class CreateMediaBuyRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated unique key for this request. If a request with the same idempotency_key and account has already been processed, the seller returns the existing media buy rather than creating a duplicate. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ]
    plan_id: Annotated[
        str | None,
        Field(
            description='Campaign governance plan identifier. Required when the account has governance_agents. The seller includes this in the committed check_governance request so the governance agent can validate against the correct plan.'
        ),
    ] = None
    account: Annotated[
        account_ref.AccountReference,
        Field(
            description='Account to bill for this media buy. Pass a natural key (brand, operator, optional sandbox) or a seller-assigned account_id from list_accounts.'
        ),
    ]
    proposal_id: Annotated[
        str | None,
        Field(
            description="ID of a committed proposal from get_products to execute. When provided with total_budget, the publisher converts the proposal's allocation percentages into packages automatically. Alternative to providing packages array. If the referenced proposal has proposal_status: 'draft', the seller MUST reject with PROPOSAL_NOT_COMMITTED; the buyer finalizes first via get_products refine action 'finalize'."
        ),
    ] = None
    total_budget: Annotated[
        TotalBudget | None,
        Field(
            description="Total budget for the media buy when executing a proposal. The publisher applies the proposal's allocation percentages to this amount to derive package budgets."
        ),
    ] = None
    packages: Annotated[
        Sequence[package_request.PackageRequest] | None,
        Field(
            description="Array of package configurations. Required when not using proposal_id. When executing a proposal, this can be omitted and packages will be derived from the proposal's allocations.",
            min_length=1,
        ),
    ] = None
    brand: Annotated[
        brand_ref.BrandReference,
        Field(
            description='Brand reference for this media buy. Resolved to full brand identity at execution time from brand.json or the registry.'
        ),
    ]
    advertiser_industry: Annotated[
        advertiser_industry_1.AdvertiserIndustry | None,
        Field(
            description="Industry classification for this specific campaign. A brand may operate across multiple industries (brand.json industries field), but each media buy targets one. For example, a consumer health company running a wellness campaign sends 'healthcare.wellness', not 'cpg'. Sellers map this to platform-native codes (e.g., Spotify ADV categories, LinkedIn industry IDs). When omitted, sellers may infer from the brand manifest's industries field."
        ),
    ] = None
    invoice_recipient: Annotated[
        business_entity.BusinessEntity | None,
        Field(
            description="Override the account's default billing entity for this specific buy. When provided, the seller invoices this entity instead. The seller MUST validate the invoice recipient is authorized for this account. When governance_agents are configured, the seller MUST include invoice_recipient in the check_governance request."
        ),
    ] = None
    io_acceptance: Annotated[
        IoAcceptance | None,
        Field(
            description="Acceptance of an insertion order from a committed proposal. Required when the proposal's insertion_order has requires_signature: true. References the io_id from the proposal's insertion_order."
        ),
    ] = None
    po_number: Annotated[str | None, Field(description='Purchase order number for tracking')] = None
    agency_estimate_number: Annotated[
        str | None,
        Field(
            description="Agency estimate or authorization number. Primary financial reference for broadcast buys — links the order to the agency's media plan and billing system. Travels with the order and creative traffic identifiers through the transaction lifecycle.",
            max_length=100,
        ),
    ] = None
    start_time: start_timing.StartTiming
    end_time: Annotated[
        AwareDatetime, Field(description='Campaign end date/time in ISO 8601 format')
    ]
    paused: Annotated[
        bool | None,
        Field(
            description="Create the media buy in a paused delivery state. When true, and the buy would otherwise be active because creatives are assigned and the flight has started, the seller returns media_buy_status 'paused'. Setup blockers still take precedence: a buy with no creatives remains 'pending_creatives', and a future-dated buy remains 'pending_start' until its flight can start. Defaults to false."
        ),
    ] = False
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Optional webhook configuration for async task status notifications. Publisher will send webhooks when status changes (working, input-required, completed, failed, canceled). Buyers SHOULD supply `push_notification_config_1.operation_id` as the canonical correlation value; publishers echo that field back verbatim in webhook payloads and MUST NOT parse the URL to derive it.'
        ),
    ] = None
    reporting_webhook: Annotated[
        reporting_webhook_1.ReportingWebhook | None,
        Field(description='Optional webhook configuration for automated reporting delivery'),
    ] = None
    artifact_webhook: Annotated[
        ArtifactWebhook | None,
        Field(
            description='Optional webhook configuration for content artifact delivery. Used by governance agents to validate content adjacency. Seller pushes artifacts to this endpoint; orchestrator forwards to governance agent for validation.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var account : adcp.types.generated_poc.core.account_ref.AccountReference
var advertiser_industry : adcp.types.generated_poc.enums.advertiser_industry.AdvertiserIndustry | None
var agency_estimate_number : str | None
var artifact_webhook : adcp.types.generated_poc.media_buy.create_media_buy_request.ArtifactWebhook | None
var brand : adcp.types.generated_poc.core.brand_ref.BrandReference
var context : adcp.types.generated_poc.core.context.ContextObject | None
var end_time : pydantic.types.AwareDatetime
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var idempotency_key : str
var invoice_recipient : adcp.types.generated_poc.core.business_entity.BusinessEntity | None
var io_acceptance : adcp.types.generated_poc.media_buy.create_media_buy_request.IoAcceptance | None
var model_config
var packages : collections.abc.Sequence[adcp.types.generated_poc.media_buy.package_request.PackageRequest] | None
var paused : bool | None
var plan_id : str | None
var po_number : str | None
var proposal_id : str | None
var push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | None
var reporting_webhook : adcp.types.generated_poc.core.reporting_webhook.ReportingWebhook | None
var start_time : adcp.types.generated_poc.core.start_timing.StartTiming
var total_budget : adcp.types.generated_poc.media_buy.create_media_buy_request.TotalBudget | None

Inherited members

class CreateMediaBuySuccessResponse (**data: Any)
Expand source code
class CreateMediaBuyResponse1(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    media_buy_id: str
    account: account_1.Account | None = None
    invoice_recipient: business_entity_1.BusinessEntity | None = None
    media_buy_status: media_buy_status_1.MediaBuyStatus | None = None
    status: Literal['completed']
    confirmed_at: AwareDatetime
    creative_deadline: AwareDatetime | None = None
    revision: Annotated[int, Field(ge=1)]
    currency: Annotated[str, StringConstraints(pattern='^[A-Z]{3}$')] | None = None
    total_budget: Annotated[float, Field(ge=0)] | None = None
    valid_actions: list[media_buy_valid_action_1.MediaBuyValidAction] | None = None
    available_actions: list[media_buy_available_action_1.MediaBuyAvailableAction] | None = None
    packages: list[package_1.Package]
    planned_delivery: planned_delivery_1.PlannedDelivery | None = None
    sandbox: bool | None = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

    @model_validator(mode='before')
    @classmethod
    def _normalize_legacy_status(cls, data: Any) -> Any:
        if not isinstance(data, dict):
            return data
        raw_status = unwrap_enum_value(data.get('status'))
        media_buy_status = unwrap_enum_value(data.get('media_buy_status'))
        if raw_status is None:
            data = dict(data)
            data['status'] = 'completed'
        elif raw_status == 'completed':
            data = dict(data)
            data['status'] = 'completed'
        elif media_buy_status is None and raw_status in MEDIA_BUY_LEGACY_STATUS_VALUES:
            data = dict(data)
            data['media_buy_status'] = raw_status
            data['status'] = 'completed'
        elif media_buy_status is not None and raw_status == media_buy_status:
            data = dict(data)
            data['status'] = 'completed'
        return data

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var account : adcp.types.generated_poc.core.account.Account | None
var available_actions : list[adcp.types.generated_poc.core.media_buy_available_action.MediaBuyAvailableAction] | None
var confirmed_at : pydantic.types.AwareDatetime
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_deadline : pydantic.types.AwareDatetime | None
var currency : str | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var invoice_recipient : adcp.types.generated_poc.core.business_entity.BusinessEntity | None
var media_buy_id : str
var media_buy_status : adcp.types.generated_poc.enums.media_buy_status.MediaBuyStatus | None
var model_config
var packages : list[adcp.types.generated_poc.core.package.Package]
var planned_delivery : adcp.types.generated_poc.core.planned_delivery.PlannedDelivery | None
var revision : int
var sandbox : bool | None
var status : Literal['completed']
var total_budget : float | None
var valid_actions : list[adcp.types.generated_poc.enums.media_buy_valid_action.MediaBuyValidAction] | None

Inherited members

class CreateMediaBuyErrorResponse (**data: Any)
Expand source code
class CreateMediaBuyResponse2(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    errors: Annotated[list[error_1.Error], Field(min_length=1)]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var errors : list[adcp.types.generated_poc.core.error.Error]
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var model_config

Inherited members

class CreateMediaBuySubmittedResponse (**data: Any)
Expand source code
class CreateMediaBuyResponse3(AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(extra='allow', validate_default=True)
    status: Literal[task_status_1.TaskStatus.submitted] = task_status_1.TaskStatus.submitted
    task_id: str
    message: Annotated[str, StringConstraints(max_length=2000)] | None = None
    errors: list[error_1.Error] | None = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • adcp.types.generated_poc.core.protocol_envelope.ProtocolEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var errors : list[adcp.types.generated_poc.core.error.Error] | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var message : str | None
var model_config
var status : Literal[]
var task_id : str

Inherited members

class DailyBreakdownItem (**data: Any)
Expand source code
class DailyBreakdownItem(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    date: Annotated[str, Field(description='Date (YYYY-MM-DD)', pattern='^\\d{4}-\\d{2}-\\d{2}$')]
    impressions: Annotated[float, Field(description='Daily impressions for this package', ge=0.0)]
    spend: Annotated[float, Field(description='Daily spend for this package', ge=0.0)]
    conversions: Annotated[
        float | None, Field(description='Daily conversions for this package', ge=0.0)
    ] = None
    conversion_value: Annotated[
        float | None, Field(description='Daily conversion value for this package', ge=0.0)
    ] = None
    roas: Annotated[
        float | None,
        Field(description='Daily return on ad spend (conversion_value / spend)', ge=0.0),
    ] = None
    new_to_brand_rate: Annotated[
        float | None,
        Field(
            description='Daily fraction of conversions from first-time brand buyers (0 = none, 1 = all)',
            ge=0.0,
            le=1.0,
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var conversion_value : float | None
var conversions : float | None
var date : str
var impressions : float
var model_config
var new_to_brand_rate : float | None
var roas : float | None
var spend : float

Inherited members

class DaypartTarget (**data: Any)
Expand source code
class DaypartTarget(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    days: Annotated[
        list[day_of_week.DayOfWeek],
        Field(
            description='Days of week this window applies to. Use multiple days for compact targeting (e.g., monday-friday in one object).',
            min_length=1,
        ),
    ]
    start_hour: Annotated[
        int,
        Field(
            description='Start hour (inclusive), 0-23 in 24-hour format. 0 = midnight, 6 = 6:00am, 18 = 6:00pm.',
            ge=0,
            le=23,
        ),
    ]
    end_hour: Annotated[
        int,
        Field(
            description='End hour (exclusive), 1-24 in 24-hour format. 10 = 10:00am, 24 = midnight. Must be greater than start_hour.',
            ge=1,
            le=24,
        ),
    ]
    label: Annotated[
        str | None,
        Field(
            description="Optional human-readable name for this time window (e.g., 'Morning Drive', 'Prime Time')"
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var days : list[adcp.types.generated_poc.enums.day_of_week.DayOfWeek]
var end_hour : int
var label : str | None
var model_config
var start_hour : int

Inherited members

class DeliveryMetrics (**data: Any)
Expand source code
class DeliveryMetrics(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    impressions: Annotated[float | None, Field(description='Impressions delivered', ge=0.0)] = None
    spend: Annotated[float | None, Field(description='Amount spent', ge=0.0)] = None
    clicks: Annotated[float | None, Field(description='Total clicks', ge=0.0)] = None
    ctr: Annotated[
        float | None, Field(description='Click-through rate (clicks/impressions)', ge=0.0, le=1.0)
    ] = None
    views: Annotated[
        float | None,
        Field(
            description="Content engagements counted toward the billable view threshold. For video this is a platform-defined view event (e.g., 30 seconds or video midpoint); for audio/podcast it is a stream start; for other formats it follows the pricing model's view definition. When the package uses CPV pricing, spend = views × rate.",
            ge=0.0,
        ),
    ] = None
    completed_views: Annotated[
        float | None,
        Field(
            description='Video/audio completions. When the package has a completed_views optimization goal with view_duration_seconds, completions are counted at that threshold rather than 100% completion.',
            ge=0.0,
        ),
    ] = None
    completion_rate: Annotated[
        float | None,
        Field(description='Completion rate (completed_views/impressions)', ge=0.0, le=1.0),
    ] = None
    conversions: Annotated[
        float | None,
        Field(
            description='Total conversions attributed to this delivery. When by_event_type is present, this equals the sum of all by_event_type[].count entries.',
            ge=0.0,
        ),
    ] = None
    conversion_value: Annotated[
        float | None,
        Field(
            description='Total monetary value of attributed conversions (in the reporting currency)',
            ge=0.0,
        ),
    ] = None
    roas: Annotated[
        float | None, Field(description='Return on ad spend (conversion_value / spend)', ge=0.0)
    ] = None
    cost_per_acquisition: Annotated[
        float | None, Field(description='Cost per conversion (spend / conversions)', ge=0.0)
    ] = None
    new_to_brand_rate: Annotated[
        float | None,
        Field(
            description='Fraction of `conversions` (transactions) from first-time brand buyers, 0 = none, 1 = all. For retail-media unit-volume tracking of first-time buyers, see `new_to_brand_units` (count, not rate).',
            ge=0.0,
            le=1.0,
        ),
    ] = None
    leads: Annotated[
        float | None,
        Field(
            description="Leads generated (convenience alias for by_event_type where event_type='lead')",
            ge=0.0,
        ),
    ] = None
    incremental_sales_lift: Annotated[
        float | None,
        Field(
            description="Incremental sales lift attributed to the campaign — sales above the control/holdout baseline. Reported as a fraction (0.15 = 15% lift) or as an absolute value depending on seller convention. The seller's `attribution_methodology` qualifier (typically `deterministic_purchase` or `modeled`) and `attribution_window` qualifier on the matching `committed_metrics` entry disambiguate the methodology and window.",
            ge=0.0,
        ),
    ] = None
    brand_lift: Annotated[
        float | None,
        Field(
            description="Brand lift — measured change in a brand metric (awareness, consideration, favorability, purchase intent, or ad recall) attributed to the campaign. Typically panel-based or survey-based. Reported as a fraction (0.05 = 5% lift). **Multidimensional in production** — Kantar, Upwave, Cint, DV all report each dimension separately with its own sample size and confidence interval. The dimension flows through `qualifier.lift_dimension` on `committed_metrics` / `metric_aggregates` (`awareness` | `consideration` | `favorability` | `purchase_intent` | `ad_recall`); rows under different dimensions are different surveyed outcomes and must not be combined. Use `attribution_methodology: 'panel_based'` qualifier when the underlying methodology is a panel.",
            ge=0.0,
        ),
    ] = None
    foot_traffic: Annotated[
        float | None,
        Field(
            description="Store visits attributed to ad exposure. Count of incremental visits over baseline. Typically uses location-data panel methodology (`attribution_methodology: 'panel_based'`) or deterministic loyalty-card match (`attribution_methodology: 'deterministic_purchase'`).",
            ge=0.0,
        ),
    ] = None
    conversion_lift: Annotated[
        float | None,
        Field(
            description='Incremental conversions attributed to the campaign — conversions above the control/holdout baseline. Reported as a fraction (0.10 = 10% lift) or as an absolute count depending on seller convention. Distinct from `conversions` (raw count of attributed conversions); conversion_lift requires a control group and an incrementality methodology.',
            ge=0.0,
        ),
    ] = None
    brand_search_lift: Annotated[
        float | None,
        Field(
            description='Lift in brand search query volume attributed to the campaign — measured via search-data partnerships (Google, Microsoft) or survey methodology. Reported as a fraction (0.20 = 20% lift in branded search).',
            ge=0.0,
        ),
    ] = None
    plays: Annotated[
        float | None,
        Field(
            description="Number of times the ad creative was displayed on a DOOH screen or played in a loop. Raw play count before any impression multiplier is applied. Mirrors `forecastable-metric.json`'s `plays` token for forecast↔delivery reconciliation. Distinct from `dooh_metrics.loop_plays` (per-screen rotation count) and from `impressions` (multiplied audience figure). Used for DOOH and broadcast inventory where buyers reconcile against forecast `plays`.",
            ge=0.0,
        ),
    ] = None
    by_event_type: Annotated[
        list[ByEventTypeItem] | None,
        Field(
            description='Conversion metrics broken down by event type. Spend-derived metrics (ROAS, CPA) are only available at the package/totals level since spend cannot be attributed to individual event types.'
        ),
    ] = None
    grps: Annotated[
        float | None, Field(description='Gross Rating Points delivered (for CPP)', ge=0.0)
    ] = None
    reach: Annotated[
        float | None,
        Field(
            description='Unique reach in the units specified by reach_unit. When reach_unit is omitted, units are unspecified — do not compare reach values across packages or media buys without a common reach_unit. The measurement window for this value is declared in `reach_window`; when `reach_window` is omitted, the window is unspecified and buyers MUST NOT sum reach across reports (the value MAY be a daily snapshot, a cumulative total, or something else).',
            ge=0.0,
        ),
    ] = None
    reach_unit: Annotated[
        reach_unit_1.ReachUnit | None,
        Field(
            description='Unit of measurement for the reach field. Aligns with the reach_unit declared on optimization goals and delivery forecasts. Required when reach is present to enable cross-platform comparison.'
        ),
    ] = None
    reach_window: Annotated[
        ReachWindow | None,
        Field(
            description='Measurement window for the reported `reach` and `frequency` values in this row. Declares whether the values are a per-period snapshot, a trailing rolling window, or cumulative-to-date — without this declaration, buyers summing `reach` across rows (e.g., daily delivery reports) can silently double-count audiences. Sellers SHOULD populate this whenever `reach` is present.'
        ),
    ] = None
    frequency: Annotated[
        float | None,
        Field(
            description="Average frequency per reach unit, measured over the window declared in `reach_window`. When `reach_unit` is 'households', this is average exposures per household; when 'accounts', per logged-in account; etc. When `reach_window` is omitted, the window is unspecified — buyers MUST NOT compare or average frequency values across rows.",
            ge=0.0,
        ),
    ] = None
    quartile_data: Annotated[
        QuartileData | None, Field(description='Audio/video quartile completion data')
    ] = None
    dooh_metrics: Annotated[
        DoohMetrics | None,
        Field(description='DOOH-specific metrics (only included for DOOH campaigns)'),
    ] = None
    viewability: Annotated[
        Viewability | None,
        Field(
            description='Viewability metrics. Viewable rate should be calculated as viewable_impressions / measurable_impressions (not total impressions), since some environments cannot measure viewability. Includes `viewed_seconds` — average in-view duration — since duration is governed by the same viewability threshold (`standard`) and shares the same `measurable_impressions` denominator. Sellers SHOULD include `standard` whenever measured viewability values are reported because MRC and GroupM rows are not interchangeable.'
        ),
    ] = None
    engagements: Annotated[
        float | None,
        Field(
            description="Total engagements — direct interactions with the ad beyond viewing. Includes social reactions/comments/shares, story/unit opens, interactive overlay taps on CTV, companion banner interactions on audio. Platform-specific; corresponds to the 'engagements' optimization metric. Maps to DBCFM KPI_INTERACTIONS (Interaktionen) in the Reporting/Performance block.",
            ge=0.0,
        ),
    ] = None
    follows: Annotated[
        float | None,
        Field(
            description='New followers, page likes, artist/podcast/channel follows, or free channel/feed subscribes attributed to this delivery. Paid subscriptions are conversion events with `event_type: subscribe`, not `follows`.',
            ge=0.0,
        ),
    ] = None
    saves: Annotated[
        float | None,
        Field(
            description='Saves, bookmarks, playlist adds, pins attributed to this delivery.', ge=0.0
        ),
    ] = None
    profile_visits: Annotated[
        float | None,
        Field(
            description="Visits to the brand's in-platform page (profile, artist page, channel, or storefront) attributed to this delivery. Does not include external website clicks.",
            ge=0.0,
        ),
    ] = None
    engagement_rate: Annotated[
        float | None,
        Field(
            description='Platform-specific engagement rate (0.0 to 1.0). Typically engagements/impressions, but definition varies by platform.',
            ge=0.0,
            le=1.0,
        ),
    ] = None
    cost_per_click: Annotated[
        float | None, Field(description='Cost per click (spend / clicks)', ge=0.0)
    ] = None
    cost_per_completed_view: Annotated[
        float | None,
        Field(
            description="Cost per completed view (spend / completed_views). Primary CPCV pricing scalar for video/audio inventory; the package's `pricing_model` is `cpcv` when this field is the billing basis.",
            ge=0.0,
        ),
    ] = None
    cpm: Annotated[
        float | None,
        Field(
            description="Cost per thousand impressions, computed as (spend / impressions) × 1000. Universal pricing scalar across CTV, display, mobile/web video, native, audio, and DOOH inventory; the package's `pricing_model` is `cpm` when this field is the billing basis. Field name aligns with the canonical `cpm` token in `enums/pricing-model.json` and `pricing-options/cpm-option.json` so buyers cross-walk pricing model → reported scalar without a translation table.",
            ge=0.0,
        ),
    ] = None
    downloads: Annotated[
        float | None,
        Field(
            description="Audio/podcast downloads (IAB Podcast Measurement Technical Guidelines 2.x methodology). Distinct from `views` — for podcast inventory this is the count of podcast episode downloads; for streaming audio it is the count of stream starts that meet the platform's download threshold. Prefer this over `views` for audio inventory.",
            ge=0.0,
        ),
    ] = None
    units_sold: Annotated[
        float | None,
        Field(
            description='Items sold attributed to this delivery. Retail-media scalar distinct from `conversions` — a single conversion (transaction) may carry multiple `units_sold`. Used by retail media platforms where the buyer optimizes against unit movement, not transaction count. Attribution lookback windows are platform-specific (commonly 7/14/30 days, view-through and click-through variants); sellers SHOULD declare the window via `reporting_capabilities.measurement_windows` or `measurement_terms` rather than encoding it in this scalar.',
            ge=0.0,
        ),
    ] = None
    new_to_brand_units: Annotated[
        float | None,
        Field(
            description='Units sold to first-time brand buyers (count, not rate). Retail-media scalar — the unit-volume parallel to the conversion-fraction `new_to_brand_rate`. Used by retail media platforms where new-customer acquisition unit volume is a primary KPI. Same attribution-window note as `units_sold` applies.',
            ge=0.0,
        ),
    ] = None
    by_action_source: Annotated[
        list[ByActionSourceItem] | None,
        Field(
            description='Conversion metrics broken down by action source (website, app, in_store, etc.). Useful for omnichannel sellers where conversions occur across digital and physical channels.'
        ),
    ] = None
    vendor_metric_values: Annotated[
        list[vendor_metric_value.VendorMetricValue] | None,
        Field(
            description="Reported values for vendor-defined metrics that the product's `reporting_capabilities.vendor_metrics` declared. Each entry carries the vendor (BrandRef), the metric identifier within the vendor's vocabulary, the value, optional unit, and `measurable_impressions` as the coverage denominator — vendor measurement is rarely 100% of delivered impressions, since vendors only score impressions where their SDK fires or their panel matches. When a declared vendor metric is omitted from this array, buyers infer no measurement happened (no integration). One row per `(vendor.domain, vendor.brand_id, metric_id)` per reporting period — sellers MUST de-duplicate before emission and MUST NOT emit the same vendor metric twice; buyers MAY treat duplicate rows as a seller-side conformance bug. The structured `vendor_metric_values` array is the recommended path for vendor metrics; `additionalProperties: true` on this parent object is preserved so existing free-form vendor emissions remain conformant during migration."
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Subclasses

  • adcp.types.generated_poc.core.catalog_item_delivery_metrics.CatalogItemDeliveryMetrics
  • adcp.types.generated_poc.core.creative_delivery_metrics.CreativeDeliveryMetrics
  • adcp.types.generated_poc.core.creative_variant.CreativeVariant
  • adcp.types.generated_poc.core.geo_delivery_metrics.GeoDeliveryMetrics
  • adcp.types.generated_poc.core.keyword_delivery_metrics.KeywordDeliveryMetrics
  • adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByAudienceItem
  • adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByDevicePlatformItem
  • adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByDeviceTypeItem
  • adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByPackageItem
  • adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByPackageItem1
  • adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByPlacementItem
  • adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.Totals
  • adcp.types.generated_poc.media_buy.media_buy_delivery_webhook_result.ByPackageItem
  • adcp.types.generated_poc.media_buy.media_buy_delivery_webhook_result.Totals

Class variables

var brand_lift : float | None
var brand_search_lift : float | None
var by_action_source : list[adcp.types.generated_poc.core.delivery_metrics.ByActionSourceItem] | None
var by_event_type : list[adcp.types.generated_poc.core.delivery_metrics.ByEventTypeItem] | None
var clicks : float | None
var completed_views : float | None
var completion_rate : float | None
var conversion_lift : float | None
var conversion_value : float | None
var conversions : float | None
var cost_per_acquisition : float | None
var cost_per_click : float | None
var cost_per_completed_view : float | None
var cpm : float | None
var ctr : float | None
var dooh_metrics : adcp.types.generated_poc.core.delivery_metrics.DoohMetrics | None
var downloads : float | None
var engagement_rate : float | None
var engagements : float | None
var follows : float | None
var foot_traffic : float | None
var frequency : float | None
var grps : float | None
var impressions : float | None
var incremental_sales_lift : float | None
var leads : float | None
var model_config
var new_to_brand_rate : float | None
var new_to_brand_units : float | None
var plays : float | None
var profile_visits : float | None
var quartile_data : adcp.types.generated_poc.core.delivery_metrics.QuartileData | None
var reach : float | None
var reach_unit : adcp.types.generated_poc.enums.reach_unit.ReachUnit | None
var reach_window : adcp.types.generated_poc.core.delivery_metrics.ReachWindow | None
var roas : float | None
var saves : float | None
var spend : float | None
var units_sold : float | None
var vendor_metric_values : list[adcp.types.generated_poc.core.vendor_metric_value.VendorMetricValue] | None
var viewability : adcp.types.generated_poc.core.delivery_metrics.Viewability | None
var views : float | None

Inherited members

class DeliveryStatus (*args, **kwds)
Expand source code
class DeliveryStatus(StrEnum):
    delivering = 'delivering'
    not_delivering = 'not_delivering'
    completed = 'completed'
    budget_exhausted = 'budget_exhausted'
    flight_ended = 'flight_ended'
    goal_met = 'goal_met'

Enum where members are also (and must be) strings

Ancestors

  • enum.StrEnum
  • builtins.str
  • enum.ReprEnum
  • enum.Enum

Class variables

var budget_exhausted
var completed
var delivering
var flight_ended
var goal_met
var not_delivering
class DeliveryType (*args, **kwds)
Expand source code
class DeliveryType(StrEnum):
    guaranteed = 'guaranteed'
    non_guaranteed = 'non_guaranteed'

Enum where members are also (and must be) strings

Ancestors

  • enum.StrEnum
  • builtins.str
  • enum.ReprEnum
  • enum.Enum

Class variables

var guaranteed
var non_guaranteed
class FrequencyCap (**data: Any)
Expand source code
class FrequencyCap(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    suppress: Annotated[
        duration.Duration | None,
        Field(
            description='Cooldown period between consecutive exposures to the same entity. Prevents back-to-back ad delivery (e.g. {"interval": 60, "unit": "minutes"} for a 1-hour cooldown). Preferred over suppress_minutes.'
        ),
    ] = None
    suppress_minutes: Annotated[
        float | None,
        Field(
            description='Deprecated — use suppress instead. Cooldown period in minutes between consecutive exposures to the same entity (e.g. 60 for a 1-hour cooldown).',
            ge=0.0,
        ),
    ] = None
    max_impressions: Annotated[
        int | None,
        Field(
            description="Maximum number of impressions per entity per window. For duration windows, implementations typically use a rolling window; 'campaign' applies a fixed cap across the full flight.",
            ge=1,
        ),
    ] = None
    per: Annotated[
        reach_unit.ReachUnit | None,
        Field(
            description='Entity granularity for impression counting. Required when max_impressions is set.'
        ),
    ] = None
    window: Annotated[
        duration.Duration | None,
        Field(
            description='Time window for the max_impressions cap (e.g. {"interval": 7, "unit": "days"} or {"interval": 1, "unit": "campaign"} for the full flight). Required when max_impressions is set.'
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var max_impressions : int | None
var model_config
var per : adcp.types.generated_poc.enums.reach_unit.ReachUnit | None
var suppress : adcp.types.generated_poc.core.duration.Duration | None
var suppress_minutes : float | None
var window : adcp.types.generated_poc.core.duration.Duration | None

Inherited members

class FrequencyCapScope (root: RootModelRootType = PydanticUndefined, **data)
Expand source code
class FrequencyCapScope(RootModel[Literal['package']]):
    root: Annotated[
        Literal['package'],
        Field(description='Scope for frequency cap application', title='Frequency Cap Scope'),
    ] = 'package'

Usage Documentation

RootModel and Custom Root Types

A Pydantic BaseModel for the root object of the model.

Attributes

root
The root object of the model.
__pydantic_root_model__
Whether the model is a RootModel.
__pydantic_private__
Private fields in the model.
__pydantic_extra__
Extra fields in the model.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • pydantic.root_model.RootModel[Literal['package']]
  • pydantic.root_model.RootModel
  • pydantic.main.BaseModel
  • typing.Generic

Class variables

var model_config
var root : Literal['package']
class GetMediaBuyArtifactsRequest (**data: Any)
Expand source code
class GetMediaBuyArtifactsRequest(AdcpVersionEnvelope):
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description='Filter artifacts to a specific account. When omitted, returns artifacts across all accessible accounts.'
        ),
    ] = None
    media_buy_id: Annotated[str, Field(description='Media buy to get artifacts from')]
    package_ids: Annotated[
        list[str] | None,
        Field(description='Filter to specific packages within the media buy', min_length=1),
    ] = None
    failures_only: Annotated[
        bool | None,
        Field(
            description="When true, only return artifacts where the seller's local model returned local_verdict: 'fail'. Useful for auditing false positives. Not useful when the seller does not run a local evaluation model (all verdicts are 'unevaluated')."
        ),
    ] = False
    time_range: Annotated[TimeRange | None, Field(description='Filter to specific time period')] = (
        None
    )
    pagination: Annotated[
        Pagination | None,
        Field(
            description='Pagination parameters. Uses higher limits than standard pagination because artifact result sets can be very large.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var account : adcp.types.generated_poc.core.account_ref.AccountReference | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var failures_only : bool | None
var media_buy_id : str
var model_config
var package_ids : list[str] | None
var pagination : adcp.types.generated_poc.content_standards.get_media_buy_artifacts_request.Pagination | None
var time_range : adcp.types.generated_poc.content_standards.get_media_buy_artifacts_request.TimeRange | None

Inherited members

class GetMediaBuyDeliveryRequest (**data: Any)
Expand source code
class GetMediaBuyDeliveryRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description='Filter delivery data to a specific account. When omitted, returns data across all accessible accounts.'
        ),
    ] = None
    media_buy_ids: Annotated[
        list[str] | None,
        Field(description='Array of media buy IDs to get delivery data for', min_length=1),
    ] = None
    status_filter: Annotated[
        media_buy_status.MediaBuyStatus | StatusFilter | None,
        Field(description='Filter by status. Can be a single status or array of statuses'),
    ] = None
    start_date: Annotated[
        str | None,
        Field(
            description="Start date for reporting period (YYYY-MM-DD). When omitted along with end_date, returns campaign lifetime data. Only accepted when the product's reporting_capabilities.date_range_support is 'date_range'.",
            pattern='^\\d{4}-\\d{2}-\\d{2}$',
        ),
    ] = None
    end_date: Annotated[
        str | None,
        Field(
            description="End date for reporting period (YYYY-MM-DD). When omitted along with start_date, returns campaign lifetime data. Only accepted when the product's reporting_capabilities.date_range_support is 'date_range'.",
            pattern='^\\d{4}-\\d{2}-\\d{2}$',
        ),
    ] = None
    include_package_daily_breakdown: Annotated[
        bool | None,
        Field(
            description='When true, include daily_breakdown arrays within each package in by_package. Useful for per-package pacing analysis and line-item monitoring. Omit or set false to reduce response size — package daily data can be large for multi-package buys over long flights.'
        ),
    ] = False
    time_granularity: Annotated[
        reporting_frequency.ReportingFrequency | None,
        Field(
            description="Per-window slice granularity for the pull, using the same vocabulary as reporting_webhook.reporting_frequency. When set, the seller returns per-window delivery slices over the date range — useful for reconstructing data a buyer's webhook receiver missed, since the slice payload is shape-aligned with what reporting_webhook would have delivered for the same window. Capability-scoped: the value MUST be one of the seller's declared reporting_capabilities.windowed_pull_granularities; otherwise the seller MUST return UNSUPPORTED_GRANULARITY. When omitted, behavior is unchanged (cumulative aggregates plus optional daily breakdowns per existing fields)."
        ),
    ] = None
    include_window_breakdown: Annotated[
        bool | None,
        Field(
            description="When true, the response includes media_buy_deliveries[].windows[] — an array of per-window delivery slices over the date range at the requested time_granularity. Ignored when time_granularity is omitted. Each window's payload mirrors what reporting_webhook would have delivered for the same window, enabling lossless GET-path recovery for buyers who missed webhook fires. Omit or set false to reduce response size when only cumulative aggregates are needed."
        ),
    ] = False
    attribution_window: Annotated[
        AttributionWindow | None,
        Field(
            description='Attribution window to apply for conversion metrics. When provided, the seller returns conversion data using the requested lookback windows instead of their platform default. The seller echoes the applied window in the response. Sellers that do not support configurable windows ignore this field and return their default. Check get_adcp_capabilities conversion_tracking.attribution_windows for available options.'
        ),
    ] = None
    reporting_dimensions: Annotated[
        ReportingDimensions | None,
        Field(
            description='Request dimensional breakdowns in delivery reporting. Each key enables a specific breakdown dimension within by_package — include as an empty object (e.g., "device_type": {}) to activate with defaults. Omit entirely for no breakdowns (backward compatible). Unsupported dimensions are silently omitted from the response. Note: keyword, catalog_item, and creative breakdowns are returned automatically when the seller supports them and are not controlled by this object.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var account : adcp.types.generated_poc.core.account_ref.AccountReference | None
var attribution_window : adcp.types.generated_poc.media_buy.get_media_buy_delivery_request.AttributionWindow | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var end_date : str | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var include_package_daily_breakdown : bool | None
var include_window_breakdown : bool | None
var media_buy_ids : list[str] | None
var model_config
var reporting_dimensions : adcp.types.generated_poc.media_buy.get_media_buy_delivery_request.ReportingDimensions | None
var start_date : str | None
var status_filter : adcp.types.generated_poc.enums.media_buy_status.MediaBuyStatus | adcp.types.generated_poc.media_buy.get_media_buy_delivery_request.StatusFilter | None
var time_granularity : adcp.types.generated_poc.enums.reporting_frequency.ReportingFrequency | None

Inherited members

class GetMediaBuyDeliveryResponse (**data: Any)
Expand source code
class GetMediaBuyDeliveryResponse(AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    notification_type: Annotated[
        NotificationType | None,
        Field(
            description='Type of webhook notification (only present in webhook deliveries): scheduled = regular periodic update, final = campaign completed, delayed = data not yet available, adjusted = resending period with corrected data (same window), window_update = resending period with a wider measurement window (e.g., C3 superseding live, C7 superseding C3)'
        ),
    ] = None
    partial_data: Annotated[
        bool | None,
        Field(
            description='Indicates if any media buys in this webhook have missing/delayed data (only present in webhook deliveries)'
        ),
    ] = None
    unavailable_count: Annotated[
        int | None,
        Field(
            description='Number of media buys with reporting_delayed or failed status (only present in webhook deliveries when partial_data is true)',
            ge=0,
        ),
    ] = None
    sequence_number: Annotated[
        int | None,
        Field(
            description='Sequential notification number (only present in webhook deliveries, starts at 1)',
            ge=1,
        ),
    ] = None
    next_expected_at: Annotated[
        AwareDatetime | None,
        Field(
            description="ISO 8601 timestamp for next expected notification (only present in webhook deliveries when notification_type is not 'final')"
        ),
    ] = None
    reporting_period: Annotated[
        ReportingPeriod,
        Field(description='Date range for the report. All periods use UTC timezone.'),
    ]
    currency: Annotated[str, Field(description='ISO 4217 currency code', pattern='^[A-Z]{3}$')]
    attribution_window: Annotated[
        attribution_window_1.AttributionWindow | None,
        Field(
            description='Attribution methodology and lookback windows used for conversion metrics in this response. All media buys from a single seller share the same attribution methodology. Enables cross-platform comparison (e.g., Amazon 14-day click vs. Criteo 30-day click).'
        ),
    ] = None
    aggregated_totals: Annotated[
        AggregatedTotals | None,
        Field(
            description='Combined metrics across all returned media buys. Only included in API responses (get_media_buy_delivery), not in webhook notifications.'
        ),
    ] = None
    media_buy_deliveries: Annotated[
        Sequence[MediaBuyDelivery],
        Field(
            description='Array of delivery data for media buys. When used in webhook notifications, may contain multiple media buys aggregated by publisher. When used in get_media_buy_delivery API responses, typically contains requested media buys.'
        ),
    ]
    errors: Annotated[
        list[error.Error] | None,
        Field(
            description='Task-specific errors and warnings (e.g., missing delivery data, reporting platform issues)'
        ),
    ] = None
    sandbox: Annotated[
        bool | None,
        Field(description='When true, this response contains simulated data from sandbox mode.'),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • adcp.types.generated_poc.core.protocol_envelope.ProtocolEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var aggregated_totals : adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.AggregatedTotals | None
var attribution_window : adcp.types.generated_poc.core.attribution_window.AttributionWindow | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var currency : str
var errors : list[adcp.types.generated_poc.core.error.Error] | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var media_buy_deliveries : Sequence[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.MediaBuyDelivery]
var model_config
var next_expected_at : pydantic.types.AwareDatetime | None
var notification_type : adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.NotificationType | None
var partial_data : bool | None
var reporting_period : adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ReportingPeriod
var sandbox : bool | None
var sequence_number : int | None
var status : adcp.types.generated_poc.enums.task_status.TaskStatus | None
var unavailable_count : int | None
class Results (**data: Any)
Expand source code
class GetMediaBuyDeliveryResponse(AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    notification_type: Annotated[
        NotificationType | None,
        Field(
            description='Type of webhook notification (only present in webhook deliveries): scheduled = regular periodic update, final = campaign completed, delayed = data not yet available, adjusted = resending period with corrected data (same window), window_update = resending period with a wider measurement window (e.g., C3 superseding live, C7 superseding C3)'
        ),
    ] = None
    partial_data: Annotated[
        bool | None,
        Field(
            description='Indicates if any media buys in this webhook have missing/delayed data (only present in webhook deliveries)'
        ),
    ] = None
    unavailable_count: Annotated[
        int | None,
        Field(
            description='Number of media buys with reporting_delayed or failed status (only present in webhook deliveries when partial_data is true)',
            ge=0,
        ),
    ] = None
    sequence_number: Annotated[
        int | None,
        Field(
            description='Sequential notification number (only present in webhook deliveries, starts at 1)',
            ge=1,
        ),
    ] = None
    next_expected_at: Annotated[
        AwareDatetime | None,
        Field(
            description="ISO 8601 timestamp for next expected notification (only present in webhook deliveries when notification_type is not 'final')"
        ),
    ] = None
    reporting_period: Annotated[
        ReportingPeriod,
        Field(description='Date range for the report. All periods use UTC timezone.'),
    ]
    currency: Annotated[str, Field(description='ISO 4217 currency code', pattern='^[A-Z]{3}$')]
    attribution_window: Annotated[
        attribution_window_1.AttributionWindow | None,
        Field(
            description='Attribution methodology and lookback windows used for conversion metrics in this response. All media buys from a single seller share the same attribution methodology. Enables cross-platform comparison (e.g., Amazon 14-day click vs. Criteo 30-day click).'
        ),
    ] = None
    aggregated_totals: Annotated[
        AggregatedTotals | None,
        Field(
            description='Combined metrics across all returned media buys. Only included in API responses (get_media_buy_delivery), not in webhook notifications.'
        ),
    ] = None
    media_buy_deliveries: Annotated[
        Sequence[MediaBuyDelivery],
        Field(
            description='Array of delivery data for media buys. When used in webhook notifications, may contain multiple media buys aggregated by publisher. When used in get_media_buy_delivery API responses, typically contains requested media buys.'
        ),
    ]
    errors: Annotated[
        list[error.Error] | None,
        Field(
            description='Task-specific errors and warnings (e.g., missing delivery data, reporting platform issues)'
        ),
    ] = None
    sandbox: Annotated[
        bool | None,
        Field(description='When true, this response contains simulated data from sandbox mode.'),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • adcp.types.generated_poc.core.protocol_envelope.ProtocolEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var aggregated_totals : adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.AggregatedTotals | None
var attribution_window : adcp.types.generated_poc.core.attribution_window.AttributionWindow | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var currency : str
var errors : list[adcp.types.generated_poc.core.error.Error] | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var media_buy_deliveries : Sequence[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.MediaBuyDelivery]
var model_config
var next_expected_at : pydantic.types.AwareDatetime | None
var notification_type : adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.NotificationType | None
var partial_data : bool | None
var reporting_period : adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ReportingPeriod
var sandbox : bool | None
var sequence_number : int | None
var status : adcp.types.generated_poc.enums.task_status.TaskStatus | None
var unavailable_count : int | None

Inherited members

class GetMediaBuysRequest (**data: Any)
Expand source code
class GetMediaBuysRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description='Account to retrieve media buys for. When omitted, returns data across all accessible accounts.'
        ),
    ] = None
    media_buy_ids: Annotated[
        list[str] | None,
        Field(
            description='Array of media buy IDs to retrieve. When omitted, returns a paginated set of accessible media buys matching status_filter.',
            min_length=1,
        ),
    ] = None
    status_filter: Annotated[
        media_buy_status.MediaBuyStatus | StatusFilter | None,
        Field(
            description='Filter by status. Can be a single status or array of statuses. Defaults to ["active"] when media_buy_ids is omitted. When media_buy_ids is provided, no implicit status filter is applied.'
        ),
    ] = None
    include_snapshot: Annotated[
        bool | None,
        Field(
            description='When true, include a near-real-time delivery snapshot for each package. Snapshots reflect the latest available entity-level stats from the platform (e.g., updated every ~15 minutes on GAM, ~1 hour on batch-only platforms). The staleness_seconds field on each snapshot indicates data freshness. If a snapshot cannot be returned, package.snapshot_unavailable_reason explains why. Defaults to false.'
        ),
    ] = False
    include_history: Annotated[
        int | None,
        Field(
            description='When present, include the last N revision history entries for each media buy (returns min(N, available entries)). Each entry contains revision number, timestamp, actor, and a summary of what changed. Omit or set to 0 to exclude history (default). Recommended: 5-10 for monitoring, 50+ for audit.',
            ge=0,
            le=1000,
        ),
    ] = 0
    include_webhook_activity: Annotated[
        bool | None,
        Field(
            description="When true, each returned media buy includes a `webhook_activity` array describing recent delivery-report webhook fires for the calling principal. Used by buyer agents to verify whether a publisher actually fired against the buyer's registered endpoint and what the endpoint returned — closes the operator-ticket loop for webhook debugging. Scoped to the calling principal: a buyer sees only fires targeting its own endpoint, even when multiple principals share visibility into the same media buy. Defaults to false. See `webhook_activity_limit` for the per-buy cap."
        ),
    ] = False
    webhook_activity_limit: Annotated[
        int | None,
        Field(
            description="Maximum number of webhook delivery records to return per media buy, ordered most-recent first. Ignored when `include_webhook_activity` is false. Sellers that surface webhook activity MUST retain records for at least 30 days from each record's `completed_at` (see `webhook_activity` description in the response schema for the `pending`-status carve-out); sellers unable to honor that floor MUST omit the field entirely rather than truncate. When a buy has more historical fires than the limit, only the most recent are returned — there is no cursor for older fires; this surface is a debug aid, not a full audit log.",
            ge=1,
            le=200,
        ),
    ] = 50
    pagination: Annotated[
        pagination_request.PaginationRequest | None,
        Field(
            description='Cursor-based pagination controls. Strongly recommended when querying broad scopes (for example, all active media buys in an account).'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var account : adcp.types.generated_poc.core.account_ref.AccountReference | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var include_history : int | None
var include_snapshot : bool | None
var include_webhook_activity : bool | None
var media_buy_ids : list[str] | None
var model_config
var pagination : adcp.types.generated_poc.core.pagination_request.PaginationRequest | None
var status_filter : adcp.types.generated_poc.enums.media_buy_status.MediaBuyStatus | adcp.types.generated_poc.media_buy.get_media_buys_request.StatusFilter | None
var webhook_activity_limit : int | None

Inherited members

class GetMediaBuysResponse (**data: Any)
Expand source code
class GetMediaBuysResponse(AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    media_buys: Annotated[
        Sequence[MediaBuy],
        Field(
            description='Array of media buys with status, creative approval state, and optional delivery snapshots'
        ),
    ]
    errors: Annotated[
        list[error.Error] | None,
        Field(description='Task-specific errors (e.g., media buy not found)'),
    ] = None
    pagination: Annotated[
        pagination_response.PaginationResponse | None,
        Field(description='Pagination metadata for the media_buys array.'),
    ] = None
    sandbox: Annotated[
        bool | None,
        Field(description='When true, this response contains simulated data from sandbox mode.'),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • adcp.types.generated_poc.core.protocol_envelope.ProtocolEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var errors : list[adcp.types.generated_poc.core.error.Error] | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var media_buys : Sequence[adcp.types.generated_poc.media_buy.get_media_buys_response.MediaBuy]
var model_config
var pagination : adcp.types.generated_poc.core.pagination_response.PaginationResponse | None
var sandbox : bool | None

Inherited members

class MediaBuy (**data: Any)
Expand source code
class MediaBuy(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    media_buy_id: Annotated[str, Field(description="Seller's unique identifier for the media buy")]
    account: Annotated[
        account_1.Account | None, Field(description='Account billed for this media buy')
    ] = None
    status: media_buy_status.MediaBuyStatus
    health: Annotated[
        media_buy_health.MediaBuyHealth | None,
        Field(
            description="Aggregate health based on open impairments[]. Orthogonal to status — a paused, pending, or active buy can each be impaired. Defaults to 'ok' when impairments[] is empty."
        ),
    ] = media_buy_health.MediaBuyHealth.ok
    impairments: Annotated[
        list[impairment.Impairment] | None,
        Field(
            description="Open impairments — upstream dependency state changes that affect delivery for at least one package on this buy. Empty when health is 'ok'. Sellers MUST add an entry on next sync/poll response after a referenced resource transitions to an offline state, and MUST remove the entry (flipping health to 'ok' when the array empties) when the resource returns to a serviceable state. Staleness budget: the snapshot MUST reflect the impairment within 5 minutes of impairment.observed_at regardless of buyer poll cadence — sellers cannot rely on rare buyer polls to defer write propagation. See impairment.coherence assertion for the cross-resource invariant."
        ),
    ] = None
    rejection_reason: Annotated[
        str | None,
        Field(
            description="Reason provided by the seller when status is 'rejected'. Present only when status is 'rejected'."
        ),
    ] = None
    confirmed_at: Annotated[
        AwareDatetime | None,
        Field(
            description='ISO 8601 timestamp when the seller committed to this media buy. May be null until seller commitment occurs in deferred/manual approval flows. Once populated, remains stable through later pause, resume, activation, completion, cancellation, and reporting transitions.'
        ),
    ]
    cancellation: Annotated[
        Cancellation | None,
        Field(description="Cancellation metadata. Present only when status is 'canceled'."),
    ] = None
    total_budget: Annotated[float, Field(description='Total budget amount', ge=0.0)]
    packages: Annotated[
        list[package.Package], Field(description='Array of packages within this media buy')
    ]
    context: Annotated[
        context_1.ContextObject | None,
        Field(
            description='Opaque media-buy-level correlation data echoed unchanged from the create_media_buy request. Sellers MUST include persisted context on read surfaces such as get_media_buys when the media buy was created through AdCP with context, so buyers can reconcile seller-assigned media_buy_id values with their own tracking state. Sellers MAY omit context for media buys created outside AdCP or created without context. Sellers MUST NOT parse this object for business logic.'
        ),
    ] = None
    invoice_recipient: Annotated[
        business_entity.BusinessEntity | None,
        Field(
            description="Per-buy override for who receives the invoice. When provided, the seller invoices this entity instead of the account's default billing_entity. The seller MUST validate the invoice recipient is authorized for this account. When governance_agents are configured, the seller MUST include invoice_recipient in the check_governance request."
        ),
    ] = None
    creative_deadline: Annotated[
        AwareDatetime | None, Field(description='ISO 8601 timestamp for creative upload deadline')
    ] = None
    revision: Annotated[
        int,
        Field(
            description='Monotonically increasing optimistic concurrency token. Incremented on every mutating state change or update; reads, validation-only calls, and exact idempotency replays do not increment it. Callers SHOULD include this in update_media_buy requests intended to change state — when provided, sellers MUST reject with CONFLICT if the revision does not match the current value, and MUST enforce that comparison atomically with the write.',
            ge=1,
        ),
    ]
    created_at: Annotated[AwareDatetime | None, Field(description='Creation timestamp')] = None
    updated_at: Annotated[AwareDatetime | None, Field(description='Last update timestamp')] = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var account : adcp.types.generated_poc.core.account.Account | None
var cancellation : adcp.types.generated_poc.core.media_buy.Cancellation | None
var confirmed_at : pydantic.types.AwareDatetime | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var created_at : pydantic.types.AwareDatetime | None
var creative_deadline : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var health : adcp.types.generated_poc.enums.media_buy_health.MediaBuyHealth | None
var impairments : list[adcp.types.generated_poc.core.impairment.Impairment] | None
var invoice_recipient : adcp.types.generated_poc.core.business_entity.BusinessEntity | None
var media_buy_id : str
var model_config
var packages : list[adcp.types.generated_poc.core.package.Package]
var rejection_reason : str | None
var revision : int
var status : adcp.types.generated_poc.enums.media_buy_status.MediaBuyStatus
var total_budget : float
var updated_at : pydantic.types.AwareDatetime | None

Inherited members

class MediaBuyDelivery (**data: Any)
Expand source code
class MediaBuyDelivery(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    media_buy_id: Annotated[str, Field(description="Seller's media buy identifier")]
    status: Annotated[
        Status,
        Field(
            description='Current media buy status. Lifecycle states use the same taxonomy as media-buy-status (`pending_creatives`, `pending_start`, `active`, `paused`, `completed`, `rejected`, `canceled`). In webhook context, reporting_delayed indicates data temporarily unavailable. `pending` is accepted as a legacy alias for pending_start.'
        ),
    ]
    expected_availability: Annotated[
        AwareDatetime | None,
        Field(
            description='When delayed data is expected to be available (only present when status is reporting_delayed)'
        ),
    ] = None
    is_adjusted: Annotated[
        bool | None,
        Field(
            description='Indicates this delivery contains updated data for a previously reported period. Buyer should replace previous period data with these totals.'
        ),
    ] = None
    is_final: Annotated[
        bool | None,
        Field(
            description="Whether this row's delivery data is final for the reporting period. The row does not carry its own `measurement_window` — that lives on each `by_package[*]` entry. Reconciliation joins on per-package `measurement_window`; this row-level flag is a convenience roll-up. Sellers MUST NOT emit `is_final: true` at the row level unless every entry in `by_package` has `is_final: true` for the same `measurement_window` as the buy's `measurement_terms.billing_measurement.measurement_window` (or for the row's natural window when no `billing_measurement.measurement_window` is set). On any disagreement between row-level and package-level finality, package-level is authoritative. When true, the seller considers these numbers closed and is willing to invoice on them subject to `measurement_terms.billing_measurement`. When false, numbers may still move as measurement matures (broadcast C3 → C7) or processing completes (IVT scrubbing, dedup). When absent, the seller does not distinguish provisional from final at the row level — consult per-package `is_final`."
        ),
    ] = None
    finalized_at: Annotated[
        AwareDatetime | None,
        Field(
            description="ISO 8601 timestamp at which this row became final. Present only when `is_final: true`. Anchors the buyer's reconciliation and (when later defined) dispute-window clocks against the buy's `measurement_terms.billing_measurement`. Computed as the latest `finalized_at` across the row's packages for the reconciliation window."
        ),
    ] = None
    pricing_model: Annotated[
        pricing_model_1.PricingModel | None,
        Field(description='Pricing model used for this media buy'),
    ] = None
    totals: Totals
    by_package: Annotated[list[ByPackageItem], Field(description='Metrics broken down by package')]
    windows: Annotated[
        list[Window] | None,
        Field(
            description="Per-window delivery slices over the reporting period at the requested time_granularity. Only present when the request set time_granularity and include_window_breakdown: true. Each slice mirrors what reporting_webhook would have delivered for the same window — buyers who missed webhook fires can reconstruct identical data by reading this array. Slice rows are ordered by window_start ascending; consecutive rows are contiguous (each row's window_end equals the next row's window_start) and partition the requested date range at the chosen granularity. Sellers MUST exclude this field when time_granularity is omitted; when set, sellers MUST honor pulls at any granularity in reporting_capabilities.windowed_pull_granularities (otherwise return UNSUPPORTED_GRANULARITY). See snapshot-and-log Rule 4 for the two-paths-parity contract this surface anchors."
        ),
    ] = None
    daily_breakdown: Annotated[
        list[DailyBreakdownItem1] | None, Field(description='Day-by-day delivery')
    ] = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var by_package : list[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.ByPackageItem]
var daily_breakdown : list[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.DailyBreakdownItem1] | None
var expected_availability : pydantic.types.AwareDatetime | None
var finalized_at : pydantic.types.AwareDatetime | None
var is_adjusted : bool | None
var is_final : bool | None
var media_buy_id : str
var model_config
var pricing_model : adcp.types.generated_poc.enums.pricing_model.PricingModel | None
var status : adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.Status
var totals : adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.Totals
var windows : list[adcp.types.generated_poc.media_buy.get_media_buy_delivery_response.Window] | None

Inherited members

class MediaBuyFeatures (**data: Any)
Expand source code
class MediaBuyFeatures(AdCPBaseModel):
    inline_creative_management: Annotated[
        bool | None,
        Field(
            description='Supports creatives provided inline in create_media_buy and update_media_buy package payloads. This flag does not imply a creative library: an inline-only seller can accept packages[].creatives without advertising sync_creatives, list_creatives, or reusable creative IDs.'
        ),
    ] = None
    property_list_filtering: Annotated[
        bool | None,
        Field(
            description='Honors property_list parameter in get_products to filter results to buyer-approved properties'
        ),
    ] = None
    catalog_management: Annotated[
        bool | None,
        Field(
            description='Supports sync_catalogs task for catalog feed management with platform review and approval'
        ),
    ] = None
    committed_metrics_supported: Annotated[
        bool | None,
        Field(
            description="Seller has per-package snapshot infrastructure for the reporting contract. When true, the seller MUST populate `package.committed_metrics` on committed `create_media_buy` responses where `confirmed_at` is non-null, MUST omit `package.committed_metrics` while `confirmed_at` is null for a provisional buy, and MUST honor append-only mid-flight metric additions via `update_media_buy`. The unified `committed_metrics` array (per the metric-accountability design) covers both standard and vendor-defined metric entries, so a single flag is load-bearing. Buyers filtering on this flag are detecting 'this seller can stamp the reporting contract,' which closes the audit gap from PR #3510 where absence of `committed_metrics` was indistinguishable between 'didn't snapshot' and 'snapshot infrastructure not implemented.'"
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var catalog_management : bool | None
var committed_metrics_supported : bool | None
var inline_creative_management : bool | None
var model_config
var property_list_filtering : bool | None

Inherited members

class MediaBuyStatus (*args, **kwds)
Expand source code
class MediaBuyStatus(StrEnum):
    pending_creatives = 'pending_creatives'
    pending_start = 'pending_start'
    active = 'active'
    paused = 'paused'
    completed = 'completed'
    rejected = 'rejected'
    canceled = 'canceled'

Enum where members are also (and must be) strings

Ancestors

  • enum.StrEnum
  • builtins.str
  • enum.ReprEnum
  • enum.Enum

Class variables

var active
var canceled
var completed
var paused
var pending_creatives
var pending_start
var rejected
class OptimizationGoal (root: RootModelRootType = PydanticUndefined, **data)
Expand source code
class OptimizationGoal(RootModel[OptimizationGoal1 | OptimizationGoal2 | OptimizationGoal3]):
    root: Annotated[
        OptimizationGoal1 | OptimizationGoal2 | OptimizationGoal3,
        Field(
            description='A single optimization target for a package. Packages accept an array of optimization_goals. When multiple goals are present, priority determines which the seller focuses on — 1 is highest priority (primary goal); higher numbers are secondary. When priorities are present but no goal is priority 1, the goal with the lowest priority value is primary (e.g., priorities of 2 and 3 mean 2 is primary). Duplicate priority values result in undefined seller behavior.',
            discriminator='kind',
            title='Optimization Goal',
        ),
    ]
    def __getattr__(self, name: str) -> Any:
        """Proxy attribute access to the wrapped type."""
        if name.startswith('_'):
            raise AttributeError(name)
        return getattr(self.root, name)

Usage Documentation

RootModel and Custom Root Types

A Pydantic BaseModel for the root object of the model.

Attributes

root
The root object of the model.
__pydantic_root_model__
Whether the model is a RootModel.
__pydantic_private__
Private fields in the model.
__pydantic_extra__
Extra fields in the model.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • pydantic.root_model.RootModel[Union[OptimizationGoal1, OptimizationGoal2, OptimizationGoal3]]
  • pydantic.root_model.RootModel
  • pydantic.main.BaseModel
  • typing.Generic

Class variables

var model_config
var root : adcp.types.generated_poc.core.optimization_goal.OptimizationGoal1 | adcp.types.generated_poc.core.optimization_goal.OptimizationGoal2 | adcp.types.generated_poc.core.optimization_goal.OptimizationGoal3
class Overlay (**data: Any)
Expand source code
class Overlay(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    id: Annotated[
        str,
        Field(
            description="Identifier for this overlay (e.g., 'play_pause', 'volume', 'publisher_logo', 'carousel_prev', 'carousel_next')"
        ),
    ]
    description: Annotated[
        str | None,
        Field(
            description='Human-readable explanation of what this overlay is and how buyers should account for it'
        ),
    ] = None
    visual: Annotated[
        Visual | None,
        Field(
            description='Optional visual reference for this overlay element. Useful for creative agents compositing previews and for buyers understanding what will appear over their content. Must include at least one of: url, light, or dark.'
        ),
    ] = None
    bounds: Annotated[
        Bounds,
        Field(
            description="Position and size of the overlay relative to the asset's own top-left corner. See 'unit' for coordinate interpretation."
        ),
    ]

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var bounds : adcp.types.generated_poc.core.overlay.Bounds
var description : str | None
var id : str
var model_config
var visual : adcp.types.generated_poc.core.overlay.Visual | None

Inherited members

class Pacing (*args, **kwds)
Expand source code
class Pacing(StrEnum):
    even = 'even'
    asap = 'asap'
    front_loaded = 'front_loaded'

Enum where members are also (and must be) strings

Ancestors

  • enum.StrEnum
  • builtins.str
  • enum.ReprEnum
  • enum.Enum

Class variables

var asap
var even
var front_loaded
class MediaBuyPackage (**data: Any)
Expand source code
class Package(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    package_id: Annotated[str, Field(description="Seller's package identifier")]
    product_id: Annotated[
        str | None,
        Field(
            description="Product identifier this package is purchased from. For packages created from an explicit create_media_buy package request, sellers MUST echo the request package's product_id on every response package object that represents that requested package."
        ),
    ] = None
    budget: Annotated[
        float | None,
        Field(
            description='Package budget amount, denominated in package.currency when present, otherwise media_buy.currency',
            ge=0.0,
        ),
    ] = None
    currency: Annotated[
        str | None,
        Field(
            description='ISO 4217 currency code for monetary values at this package level (budget, bid_price, snapshot.spend). When absent, inherit media_buy.currency.',
            pattern='^[A-Z]{3}$',
        ),
    ] = None
    bid_price: Annotated[
        float | None,
        Field(
            description='Current bid price for auction-based packages. Denominated in package.currency when present, otherwise media_buy.currency. Relevant for automated price optimization loops.',
            ge=0.0,
        ),
    ] = None
    format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            description='Legacy named-format IDs supplied for this package on create_media_buy. Sellers SHOULD echo this field whenever the request included it, including dual-emission cases where another selector won precedence.',
            min_length=1,
        ),
    ] = None
    format_option_refs: Annotated[
        list[format_option_ref.FormatOptionReference] | None,
        Field(
            description='Structured 3.1+ format option references supplied for this package on create_media_buy. Sellers SHOULD echo this field whenever the request included it.',
            min_length=1,
        ),
    ] = None
    format_kind: Annotated[
        canonical_format_kind.CanonicalFormatKind | None,
        Field(
            description='Direct canonical selector supplied for this package on create_media_buy. Sellers SHOULD echo this field whenever the request included it, including informational-echo cases where another selector won precedence.'
        ),
    ] = None
    params: Annotated[
        dict[str, Any] | None,
        Field(
            description='Parameters for the direct canonical selector in `format_kind`, echoed from the create_media_buy request whenever the request included it. Requires `format_kind`.'
        ),
    ] = None
    impressions: Annotated[
        float | None,
        Field(description='Goal impression count for impression-based packages', ge=0.0),
    ] = None
    targeting_overlay: Annotated[
        targeting.TargetingOverlay | None,
        Field(
            description='Targeting overlay applied to this package, echoed from the most recent create_media_buy or update_media_buy. Sellers SHOULD echo any persisted targeting so buyers can verify what was stored without replaying their own request. Sellers claiming the property-lists or collection-lists specialisms MUST include, within this targeting_overlay, the PropertyListReference / CollectionListReference they persisted.'
        ),
    ] = None
    start_time: Annotated[
        AwareDatetime | None,
        Field(
            description='ISO 8601 flight start time for this package. Use to determine whether the package is within its scheduled flight before interpreting delivery status.'
        ),
    ] = None
    end_time: Annotated[
        AwareDatetime | None, Field(description='ISO 8601 flight end time for this package')
    ] = None
    paused: Annotated[
        bool | None, Field(description='Whether this package is currently paused by the buyer')
    ] = None
    canceled: Annotated[
        bool | None,
        Field(
            description='Whether this package has been canceled. Canceled packages stop delivery and cannot be reactivated.'
        ),
    ] = None
    cancellation: Annotated[
        Cancellation1 | None,
        Field(description='Cancellation metadata. Present only when canceled is true.'),
    ] = None
    creative_deadline: Annotated[
        AwareDatetime | None,
        Field(
            description="ISO 8601 timestamp for creative upload or change deadline for this package. After this deadline, creative changes are rejected. When absent, the media buy's creative_deadline applies."
        ),
    ] = None
    context: Annotated[
        context_1.ContextObject | None,
        Field(
            description='Opaque package-level correlation data echoed unchanged from the create_media_buy package request. Sellers MUST include persisted package context on read surfaces when the package was created through AdCP with context, so buyers can reconcile seller-assigned package_id values with their own line items; this is the legacy-safe fallback when an older seller did not echo product_id on the create response. Sellers MAY omit context for packages created outside AdCP or created without context. Sellers MUST NOT parse this object for business logic.'
        ),
    ] = None
    creative_approvals: Annotated[
        list[CreativeApproval] | None,
        Field(
            description='Approval status for each creative assigned to this package. Absent when no creatives have been assigned.'
        ),
    ] = None
    format_ids_pending: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            description='Format IDs from the original create_media_buy format_ids_to_provide that have not yet been uploaded via sync_creatives. When empty or absent, all required formats have been provided.'
        ),
    ] = None
    snapshot_unavailable_reason: Annotated[
        snapshot_unavailable_reason_1.SnapshotUnavailableReason | None,
        Field(
            description='Machine-readable reason the snapshot is omitted. Present only when include_snapshot was true and snapshot is unavailable for this package.'
        ),
    ] = None
    snapshot: Annotated[
        Snapshot | None,
        Field(
            description='Near-real-time delivery snapshot for this package. Only present when include_snapshot was true in the request. Represents the latest available entity-level stats from the platform — not billing-grade data.'
        ),
    ] = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var bid_price : float | None
var budget : float | None
var canceled : bool | None
var cancellation : adcp.types.generated_poc.media_buy.get_media_buys_response.Cancellation1 | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_approvals : list[adcp.types.generated_poc.media_buy.get_media_buys_response.CreativeApproval] | None
var creative_deadline : pydantic.types.AwareDatetime | None
var currency : str | None
var end_time : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var format_ids_pending : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var format_kind : adcp.types.generated_poc.core.canonical_format_kind.CanonicalFormatKind | None
var format_option_refs : list[adcp.types.generated_poc.core.format_option_ref.FormatOptionReference] | None
var impressions : float | None
var model_config
var package_id : str
var params : dict[str, typing.Any] | None
var paused : bool | None
var product_id : str | None
var snapshot : adcp.types.generated_poc.media_buy.get_media_buys_response.Snapshot | None
var snapshot_unavailable_reason : adcp.types.generated_poc.enums.snapshot_unavailable_reason.SnapshotUnavailableReason | None
var start_time : pydantic.types.AwareDatetime | None
var targeting_overlay : adcp.types.generated_poc.core.targeting.TargetingOverlay | None
class Package (**data: Any)
Expand source code
class Package(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    package_id: Annotated[str, Field(description="Seller's unique identifier for the package")]
    product_id: Annotated[
        str | None,
        Field(
            description="ID of the product this package is based on. For packages created from an explicit create_media_buy package request, sellers MUST echo the request package's product_id on every response package object that represents that requested package."
        ),
    ] = None
    budget: Annotated[
        float | None,
        Field(
            description='Budget allocation for this package in the currency specified by the pricing option',
            ge=0.0,
        ),
    ] = None
    pacing: pacing_1.Pacing | None = None
    pricing_option_id: Annotated[
        str | None,
        Field(
            description="ID of the selected pricing option from the product's pricing_options array"
        ),
    ] = None
    bid_price: Annotated[
        float | None,
        Field(
            description="Bid price for auction-based pricing. This is the exact bid/price to honor unless the selected pricing option has max_bid=true, in which case bid_price is the buyer's maximum willingness to pay (ceiling).",
            ge=0.0,
        ),
    ] = None
    price_breakdown: Annotated[
        price_breakdown_1.PriceBreakdown | None,
        Field(
            description="Breakdown of the effective price for this package. On fixed-price packages, echoes the pricing option's breakdown. On auction packages, shows the clearing price breakdown including any commission or settlement terms."
        ),
    ] = None
    impressions: Annotated[
        float | None, Field(description='Impression goal for this package', ge=0.0)
    ] = None
    catalogs: Annotated[
        list[catalog.Catalog] | None,
        Field(
            description='Catalogs this package promotes. Each catalog MUST have a distinct type (e.g., one product catalog, one store catalog). This constraint is enforced at the application level — sellers MUST reject requests containing multiple catalogs of the same type with a validation_error. Echoed from the create_media_buy request.'
        ),
    ] = None
    format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            description='Legacy named-format IDs supplied for this package on create_media_buy. Sellers SHOULD echo this field whenever the request included it, including dual-emission cases where `format_option_refs` was the winning selector, so read surfaces preserve the original wire contract. Omitted means the request did not carry legacy format_ids unless the seller cannot reconstruct legacy requests created before this field was persisted.'
        ),
    ] = None
    format_option_refs: Annotated[
        list[format_option_ref.FormatOptionReference] | None,
        Field(
            description='Structured 3.1+ format option references supplied for this package on create_media_buy. Sellers SHOULD echo this field whenever the request included it. Publisher-catalog-backed options are identified by `{ scope: "publisher", publisher_domain, format_option_id }`; product-local options are identified by `{ scope: "product", format_option_id }` and resolve only against this package\'s target product. Omitted means the request did not carry format_option_refs unless the seller cannot reconstruct legacy requests created before this field was persisted.',
            min_length=1,
        ),
    ] = None
    format_kind: Annotated[
        canonical_format_kind.CanonicalFormatKind | None,
        Field(
            description='Direct canonical selector supplied for this package on create_media_buy. Sellers SHOULD echo this field whenever the request included it, including informational-echo cases where `format_ids` was the winning selector, so read surfaces preserve the original wire contract.'
        ),
    ] = None
    params: Annotated[
        dict[str, Any] | None,
        Field(
            description='Parameters for the direct canonical selector in `format_kind`, echoed from the create_media_buy request whenever the request included it. Requires `format_kind`; omitted only when the request did not carry direct canonical params or when the seller cannot reconstruct legacy requests created before this field was persisted.'
        ),
    ] = None
    targeting_overlay: targeting.TargetingOverlay | None = None
    measurement_terms: Annotated[
        measurement_terms_1.MeasurementTerms | None,
        Field(
            description="Agreed billing measurement and makegood terms for this package. Reflects what was negotiated — may differ from the buyer's proposal or the product's defaults. When present, these terms are binding for the package's duration."
        ),
    ] = None
    performance_standards: Annotated[
        list[performance_standard.PerformanceStandard] | None,
        Field(
            description='Agreed performance standards for this package. When any entry specifies a vendor, creatives assigned to this package MUST include corresponding tracker_script or tracker_pixel assets from that vendor.',
            min_length=1,
        ),
    ] = None
    committed_metrics: Annotated[
        list[committed_metric.CommittedMetric] | None,
        Field(
            description="The binding reporting contract for this package — what the seller has agreed to populate in delivery reports. Each entry carries an explicit `committed_at` timestamp, so the array also serves as the contract amendment ledger: day-1 commitments share `committed_at = create_media_buy.confirmed_at`; mid-flight additions carry their own timestamps. When `create_media_buy.confirmed_at` is null for a provisional buy, sellers MUST omit `committed_metrics` until commitment. The first response that sets `confirmed_at` MAY include the initial committed-metrics set, and each such entry's `committed_at` MUST equal `confirmed_at`. The `missing_metrics` field on `get_media_buy_delivery` reconciles against this list, filtering to entries where `committed_at < reporting_period.end` (a metric committed mid-flight is only audited from its commitment timestamp forward). Sellers stamp the day-1 set on the `create_media_buy` response; mid-flight additions are appended via `update_media_buy` (append-only — sellers MUST reject attempts to modify or remove existing entries with `validation_error`, suggested code: `IMMUTABLE_FIELD`). Optional in v1; absence means the seller does not provide an audit-grade contract and `missing_metrics` falls back to the product's live `available_metrics` (a known audit gap — buyers SHOULD treat absence as 'no audit-grade contract' rather than 'clean delivery'). Each entry uses an explicit `scope` discriminator: `standard` for entries from the closed `available-metric.json` enum, `vendor` for vendor-defined metrics anchored on a BrandRef. The unified shape is symmetric with `missing_metrics` and `aggregated_totals.metric_aggregates` — same atomic unit `(scope, metric_id, qualifier)` across contract, diff, and delivery, so reconciliation collapses to a row-level join on the tuple. Replaces the parallel-array design that shipped briefly in #3510.",
            examples=[
                [
                    {
                        'scope': 'standard',
                        'metric_id': 'impressions',
                        'committed_at': '2026-04-29T10:53:00Z',
                    },
                    {
                        'scope': 'standard',
                        'metric_id': 'spend',
                        'committed_at': '2026-04-29T10:53:00Z',
                    },
                    {
                        'scope': 'standard',
                        'metric_id': 'completed_views',
                        'committed_at': '2026-04-29T10:53:00Z',
                    },
                    {
                        'scope': 'vendor',
                        'vendor': {'domain': 'attentionvendor.example'},
                        'metric_id': 'attention_units',
                        'committed_at': '2026-04-29T10:53:00Z',
                    },
                    {
                        'scope': 'standard',
                        'metric_id': 'viewable_rate',
                        'qualifier': {'viewability_standard': 'mrc'},
                        'committed_at': '2026-05-30T14:22:00Z',
                    },
                ]
            ],
            min_length=1,
        ),
    ] = None
    creative_assignments: Annotated[
        list[creative_assignment.CreativeAssignment] | None,
        Field(description='Creative assets assigned to this package'),
    ] = None
    format_ids_to_provide: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(description='Format IDs that creative assets will be provided for this package'),
    ] = None
    optimization_goals: Annotated[
        list[optimization_goal.OptimizationGoal] | None,
        Field(
            description='Optimization targets for this package. The seller optimizes delivery toward these goals in priority order. Common pattern: event goals (purchase, install) as primary targets at priority 1; metric goals (clicks, views) as secondary proxy signals at priority 2+.',
            min_length=1,
        ),
    ] = None
    start_time: Annotated[
        AwareDatetime | None,
        Field(
            description="Flight start date/time for this package in ISO 8601 format. When omitted, the package inherits the media buy's start_time. Sellers SHOULD always include the resolved value in responses, even when inherited."
        ),
    ] = None
    end_time: Annotated[
        AwareDatetime | None,
        Field(
            description="Flight end date/time for this package in ISO 8601 format. When omitted, the package inherits the media buy's end_time. Sellers SHOULD always include the resolved value in responses, even when inherited."
        ),
    ] = None
    paused: Annotated[
        bool | None,
        Field(
            description='Whether this package is paused by the buyer. Paused packages do not deliver impressions. Defaults to false.'
        ),
    ] = False
    canceled: Annotated[
        bool | None,
        Field(
            description='Whether this package has been canceled. Canceled packages stop delivery and cannot be reactivated. Defaults to false.'
        ),
    ] = False
    cancellation: Annotated[
        Cancellation | None,
        Field(description='Cancellation metadata. Present only when canceled is true.'),
    ] = None
    agency_estimate_number: Annotated[
        str | None,
        Field(
            description="Agency estimate or authorization number for this package. Echoed from the buyer's request. When present on the package, takes precedence over the media buy-level estimate number.",
            max_length=100,
        ),
    ] = None
    creative_deadline: Annotated[
        AwareDatetime | None,
        Field(
            description="ISO 8601 timestamp for creative upload or change deadline for this package. After this deadline, creative changes are rejected. When absent, the media buy's creative_deadline applies."
        ),
    ] = None
    context: Annotated[
        context_1.ContextObject | None,
        Field(
            description='Opaque package-level correlation data echoed unchanged in responses, webhooks, and read surfaces. Buyers targeting mixed seller populations SHOULD include a per-package correlation value here, commonly context.buyer_ref, so responses from legacy sellers that do not echo product_id can still be mapped back to the requested product or line item. Sellers MUST preserve this object unchanged and MUST NOT parse it for business logic.'
        ),
    ] = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var agency_estimate_number : str | None
var bid_price : float | None
var budget : float | None
var canceled : bool | None
var cancellation : adcp.types.generated_poc.core.package.Cancellation | None
var catalogs : list[adcp.types.generated_poc.core.catalog.Catalog] | None
var committed_metrics : list[adcp.types.generated_poc.core.committed_metric.CommittedMetric] | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_assignments : list[adcp.types.generated_poc.core.creative_assignment.CreativeAssignment] | None
var creative_deadline : pydantic.types.AwareDatetime | None
var end_time : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var format_ids_to_provide : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var format_kind : adcp.types.generated_poc.core.canonical_format_kind.CanonicalFormatKind | None
var format_option_refs : list[adcp.types.generated_poc.core.format_option_ref.FormatOptionReference] | None
var impressions : float | None
var measurement_terms : adcp.types.generated_poc.core.measurement_terms.MeasurementTerms | None
var model_config
var optimization_goals : list[adcp.types.generated_poc.core.optimization_goal.OptimizationGoal] | None
var pacing : adcp.types.generated_poc.enums.pacing.Pacing | None
var package_id : str
var params : dict[str, typing.Any] | None
var paused : bool | None
var performance_standards : list[adcp.types.generated_poc.core.performance_standard.PerformanceStandard] | None
var price_breakdown : adcp.types.generated_poc.pricing_options.price_breakdown.PriceBreakdown | None
var pricing_option_id : str | None
var product_id : str | None
var start_time : pydantic.types.AwareDatetime | None
var targeting_overlay : adcp.types.generated_poc.core.targeting.TargetingOverlay | None

Inherited members

class PackageRequest (**data: Any)
Expand source code
class PackageRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    product_id: Annotated[
        str,
        Field(
            description='Product ID for this package. Sellers MUST echo this value on every response package object that represents this requested package.'
        ),
    ]
    format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            description="Legacy named-format selector. Array of format IDs that will be used for this package - must be supported by the product. If omitted (and no 3.1+ format-option selector or direct canonical selector is present), defaults to all formats supported by the product.\n\nSellers comparing this selector to a product's `format_options[]` MUST first normalize each legacy `format_id` through the canonical mapping path (`canonical`, `v1_format_ref`, or registry projection). Exact `(agent_url, id)` comparison after projection is insufficient: a legacy fixed-size display ID can satisfy a canonical `image` product declaration with matching `width`/`height`. Product gating remains directional: if the product declares fixed dimensions or duration, the selected format must declare and match those constraints; an under-specified canonical request is not a wildcard for a fixed-size or fixed-duration product. Range constraints use containment, not overlap: a range-based request satisfies the product only when every value it permits falls within the product's accepted range.",
            min_length=1,
        ),
    ] = None
    format_option_refs: Annotated[
        list[format_option_ref.FormatOptionReference] | None,
        Field(
            description='3.1+ format-option selector. Array of structured format option references, each matching one of the target product\'s `format_options[]` entries. Publisher-catalog-backed options match by `{ scope: "publisher", publisher_domain, format_option_id }`; product-local options match by `{ scope: "product", format_option_id }`. If omitted along with `format_ids` and direct `format_kind`, all product formats are active.\n\n**Resolution rules (normative).**\n- **Both `format_option_refs` and `format_ids` present.** `format_option_refs` wins; the seller routes by structured references and MUST NOT validate `format_ids` for consistency with the resolved declarations. The `format_ids` value is a legacy-compat hint for intermediaries on the wire path; the resolving seller ignores it.\n- **`format_option_refs` only.** Seller looks up each entry against the package\'s target product `format_options[]` and uses the matching declaration (and that declaration\'s `v1_format_ref[]` when projecting to legacy named-format surfaces). This is the 3.1+ format-option authoring path. `scope: "product"` is scoped only by this target product; it is not a seller-wide identifier.\n- **`format_ids` only.** Existing named-format behavior; unchanged.\n- **`format_kind` only.** Direct canonical selector behavior; seller compares `{ format_kind, params }` against the product\'s `format_options[]` declarations using directional product satisfaction.\n- **None of `format_option_refs`, `format_ids`, or `format_kind`.** Default — all formats supported by the product are active.\n\n**Failure modes (normative).** Sellers MUST reject with `UNSUPPORTED_FEATURE` (with `field` pointing at the failing package and entry, e.g. `packages[0].format_option_refs[1]`) when:\n- Any entry references a format option not present in the target product\'s `format_options[]`, OR\n- The target product carries `format_ids` but no `format_options[]` (legacy-format-only product — there is no closed set to resolve against), OR\n- The target product carries `format_options[]` but none of the entries publish selectable `format_option_id` values. Sellers SHOULD set `error.details.reason` to `format_option_refs_not_published` in this case so buyers can distinguish it from an outright mismatch and fall back to `format_ids[]`.\n\n**Seller obligation.** For buyers to use the 3.1+ format-option path against a product, the seller MUST publish a selectable `format_option_id` on each `format_options[]` entry it expects buyers to select; if the option is publisher-catalog backed, include `publisher_domain` on the product declaration and require buyers to use `scope: "publisher"` in `FormatOptionRef`.\n\n**No legacy capability selector.** `capability_ids` was removed before GA; schemas reject it instead of treating it as an extension.\n\n**Dual emission.** Format-option-aware buyer SDKs targeting a heterogeneous seller population SHOULD emit `format_ids` alongside `format_option_refs` so legacy-format-only sellers — which ignore unknown fields per `additionalProperties: true` — still receive an explicit format set rather than silently defaulting to all formats supported by the product.',
            min_length=1,
        ),
    ] = None
    format_kind: Annotated[
        canonical_format_kind.CanonicalFormatKind | None,
        Field(
            description='3.1+ direct canonical selector. Names the canonical format shape this package targets when the buyer is authoring by canonical kind rather than by a product-local `format_option_ref` or legacy `format_id`. Pair with `params` when the product declaration requires dimensions, duration, sizes, codecs, or other canonical parameters. If `format_option_refs` is present, it wins over this direct selector. If `format_ids` is present without `format_option_refs`, sellers MUST normalize and validate the legacy selector; buyers SHOULD NOT also send `format_kind` unless it is an informational echo of the same normalized shape.\n\nProduct satisfaction is directional: a broad selector such as `{ format_kind: "image" }` does not satisfy a product whose `format_options[]` fixes `params.width` and `params.height`. Sellers MUST reject under-specified direct selectors with `UNSUPPORTED_FEATURE` or an equivalent format-selector validation error.'
        ),
    ] = None
    params: Annotated[
        dict[str, Any] | None,
        Field(
            description="Parameters for the direct canonical selector in `format_kind`. Shape follows the selected canonical's parameter vocabulary: dimensions (`width`, `height`, `sizes`), duration (`duration_ms_exact`, `duration_ms_range`), codecs, asset-source and slot narrowing, or other canonical-specific constraints. Omit when selecting by `format_option_refs` or `format_ids`; those selectors resolve their parameters from the product declaration or legacy catalog projection."
        ),
    ] = None
    budget: Annotated[
        float,
        Field(description="Budget allocation for this package in the media buy's currency", ge=0.0),
    ]
    pacing: pacing_1.Pacing | None = None
    pricing_option_id: Annotated[
        str,
        Field(
            description="ID of the selected pricing option from the product's pricing_options array"
        ),
    ]
    bid_price: Annotated[
        float | None,
        Field(
            description="Bid price for auction-based pricing options. This is the exact bid/price to honor unless selected pricing_option has max_bid=true, in which case bid_price is the buyer's maximum willingness to pay (ceiling).",
            ge=0.0,
        ),
    ] = None
    impressions: Annotated[
        float | None, Field(description='Impression goal for this package', ge=0.0)
    ] = None
    start_time: Annotated[
        AwareDatetime | None,
        Field(
            description="Flight start date/time for this package in ISO 8601 format. When omitted, the package inherits the media buy's start_time. Must fall within the media buy's date range."
        ),
    ] = None
    end_time: Annotated[
        AwareDatetime | None,
        Field(
            description="Flight end date/time for this package in ISO 8601 format. When omitted, the package inherits the media buy's end_time. Must fall within the media buy's date range."
        ),
    ] = None
    paused: Annotated[
        bool | None,
        Field(
            description='Whether this package should be created in a paused state. Paused packages do not deliver impressions. Defaults to false.'
        ),
    ] = False
    catalogs: Annotated[
        list[catalog.Catalog] | None,
        Field(
            description='Catalogs this package promotes. Each catalog MUST have a distinct type (e.g., one product catalog, one store catalog). This constraint is enforced at the application level — sellers MUST reject requests containing multiple catalogs of the same type with a validation_error. Makes the package catalog-driven: one budget envelope, platform optimizes across items.'
        ),
    ] = None
    optimization_goals: Annotated[
        list[optimization_goal.OptimizationGoal] | None,
        Field(
            description='Optimization targets for this package. The seller optimizes delivery toward these goals in priority order. Common pattern: event goals (purchase, install) as primary targets at priority 1; metric goals (clicks, views) as secondary proxy signals at priority 2+.',
            min_length=1,
        ),
    ] = None
    targeting_overlay: targeting.TargetingOverlay | None = None
    measurement_terms: Annotated[
        measurement_terms_1.MeasurementTerms | None,
        Field(
            description="Buyer's proposed billing measurement and makegood terms. Overrides product defaults. Seller accepts (echoed on confirmed package), rejects with TERMS_REJECTED, or adjusts. When absent, product's measurement_terms apply."
        ),
    ] = None
    performance_standards: Annotated[
        list[performance_standard.PerformanceStandard] | None,
        Field(
            description="Buyer's proposed performance standards for this package. Overrides product defaults. Seller accepts, rejects with TERMS_REJECTED, or adjusts. When absent, product's performance_standards apply.",
            min_length=1,
        ),
    ] = None
    committed_metrics: Annotated[
        list[CommittedMetrics6] | None,
        Field(
            description="Buyer's proposed reporting contract for this package — the metrics the buyer wants the seller to commit to populating in delivery reports. Same negotiation pattern as `measurement_terms` and `performance_standards`: seller accepts (echoes on confirmed package with `committed_at` stamped), rejects with `TERMS_REJECTED` (with explanation of which entries were unworkable), or normalizes (echoes a different but compatible list — buyer can accept by retrying with the normalized terms). When absent, the seller decides what to commit based on the product's `available_metrics` and the buyer's `required_metrics` filter on `get_products`. Each entry uses an explicit `scope` discriminator (`standard` or `vendor`) and identifies the metric — request-side entries do NOT carry `committed_at`; that timestamp is stamped by the seller on accept. Constraints on what the buyer MAY propose: each `scope: standard` entry's `metric_id` MUST be in the product's `available_metrics`, and each `scope: vendor` entry's `(vendor, metric_id)` MUST appear in the product's `vendor_metrics` — sellers SHOULD reject with `TERMS_REJECTED` and reference the offending entry when the proposal exceeds product capability.",
            min_length=1,
        ),
    ] = None
    creative_assignments: Annotated[
        list[creative_assignment.CreativeAssignment] | None,
        Field(
            description='Assign existing library creatives to this package with optional weights and placement targeting',
            min_length=1,
        ),
    ] = None
    creatives: Annotated[
        Sequence[creative_asset.CreativeAsset] | None,
        Field(
            description="Upload creative assets inline and assign to this package. When the seller also advertises creative.has_creative_library: true, these creatives enter the seller's creative library and can be reused by creative_id while retained; inline-only sellers may store them as package-scoped assets. Use creative_assignments instead for existing library creatives.",
            max_length=100,
            min_length=1,
        ),
    ] = None
    agency_estimate_number: Annotated[
        str | None,
        Field(
            description='Agency estimate or authorization number for this package. Overrides the media buy-level estimate number when different packages correspond to different agency estimates (e.g., different stations or flights within the same buy).',
            max_length=100,
        ),
    ] = None
    context: Annotated[
        context_1.ContextObject | None,
        Field(
            description='Opaque package-level correlation data echoed unchanged in the package response, webhooks, and read surfaces. Buyers targeting mixed seller populations SHOULD include a per-package correlation value here, commonly context_1.buyer_ref, so responses from legacy sellers that do not echo product_id can still be mapped back to the requested product or line item. Do not use deprecated top-level buyer_ref for v3 correlation.'
        ),
    ] = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var agency_estimate_number : str | None
var bid_price : float | None
var budget : float
var catalogs : list[adcp.types.generated_poc.core.catalog.Catalog] | None
var committed_metrics : list[adcp.types.generated_poc.media_buy.package_request.CommittedMetrics6] | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_assignments : list[adcp.types.generated_poc.core.creative_assignment.CreativeAssignment] | None
var creatives : collections.abc.Sequence[adcp.types.generated_poc.core.creative_asset.CreativeAsset] | None
var end_time : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var format_kind : adcp.types.generated_poc.core.canonical_format_kind.CanonicalFormatKind | None
var format_option_refs : list[adcp.types.generated_poc.core.format_option_ref.FormatOptionReference] | None
var impressions : float | None
var measurement_terms : adcp.types.generated_poc.core.measurement_terms.MeasurementTerms | None
var model_config
var optimization_goals : list[adcp.types.generated_poc.core.optimization_goal.OptimizationGoal] | None
var pacing : adcp.types.generated_poc.enums.pacing.Pacing | None
var params : dict[str, typing.Any] | None
var paused : bool | None
var performance_standards : list[adcp.types.generated_poc.core.performance_standard.PerformanceStandard] | None
var pricing_option_id : str
var product_id : str
var start_time : pydantic.types.AwareDatetime | None
var targeting_overlay : adcp.types.generated_poc.core.targeting.TargetingOverlay | None

Inherited members

class PackageUpdate (**data: Any)
Expand source code
class PackageUpdate(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    package_id: Annotated[str, Field(description="Seller's ID of package to update")]
    budget: Annotated[
        float | None,
        Field(
            description='Updated budget allocation for this package in the currency specified by the pricing option',
            ge=0.0,
        ),
    ] = None
    pacing: pacing_1.Pacing | None = None
    bid_price: Annotated[
        float | None,
        Field(
            description="Updated bid price for auction-based pricing options. This is the exact bid/price to honor unless selected pricing_option has max_bid=true, in which case bid_price is the buyer's maximum willingness to pay (ceiling).",
            ge=0.0,
        ),
    ] = None
    impressions: Annotated[
        float | None, Field(description='Updated impression goal for this package', ge=0.0)
    ] = None
    start_time: Annotated[
        AwareDatetime | None,
        Field(
            description="Updated flight start date/time for this package in ISO 8601 format. Must fall within the media buy's date range."
        ),
    ] = None
    end_time: Annotated[
        AwareDatetime | None,
        Field(
            description="Updated flight end date/time for this package in ISO 8601 format. Must fall within the media buy's date range."
        ),
    ] = None
    paused: Annotated[
        bool | None,
        Field(description='Pause/resume specific package (true = paused, false = active)'),
    ] = None
    canceled: Annotated[
        Literal[True] | None,
        Field(
            description='Cancel this specific package. Cancellation is irreversible — canceled packages stop delivery and cannot be reactivated. Sellers MAY reject with NOT_CANCELLABLE.'
        ),
    ] = None
    cancellation_reason: Annotated[
        str | None, Field(description='Reason for canceling this package.', max_length=500)
    ] = None
    catalogs: Annotated[
        list[catalog.Catalog] | None,
        Field(
            description='Replace the catalogs this package promotes. Uses replacement semantics — the provided array replaces the current list. Omit to leave catalogs unchanged.',
            min_length=1,
        ),
    ] = None
    optimization_goals: Annotated[
        list[optimization_goal.OptimizationGoal] | None,
        Field(
            description='Replace all optimization goals for this package. Uses replacement semantics — omit to leave goals unchanged.',
            min_length=1,
        ),
    ] = None
    targeting_overlay: Annotated[
        targeting.TargetingOverlay | None,
        Field(
            description="Targeting overlay to apply to this package. Uses replacement semantics — the full overlay replaces the previous one. Omit to leave targeting unchanged. For keyword and negative keyword updates, prefer the incremental operations (keyword_targets_add, keyword_targets_remove, negative_keywords_add, negative_keywords_remove) which avoid replacing the full overlay. Sellers SHOULD return a validation error if targeting_overlay.keyword_targets is present in the same request as keyword_targets_add or keyword_targets_remove, and likewise for negative_keywords. If the replacement changes signal_targeting_groups, sellers MAY require a new quote or reject with REQUOTE_REQUIRED when the selected signal, group expression, or pricing_option_id changes the package's priced envelope."
        ),
    ] = None
    keyword_targets_add: Annotated[
        list[KeywordTargetsAddItem] | None,
        Field(
            description='Keyword targets to add or update on this package. Upserts by (keyword, match_type) identity: if the pair already exists, its bid_price is updated; if not, a new keyword target is added. Use targeting_overlay.keyword_targets in create_media_buy to set the initial list.',
            min_length=1,
        ),
    ] = None
    keyword_targets_remove: Annotated[
        list[KeywordTargetsRemoveItem] | None,
        Field(
            description='Keyword targets to remove from this package. Removes matching (keyword, match_type) pairs. If a specified pair is not present, sellers SHOULD treat it as a no-op for that entry.',
            min_length=1,
        ),
    ] = None
    negative_keywords_add: Annotated[
        list[NegativeKeywordsAddItem] | None,
        Field(
            description='Negative keywords to add to this package. Appends to the existing negative keyword list — does not replace it. If a keyword+match_type pair already exists, sellers SHOULD treat it as a no-op for that entry. Use targeting_overlay.negative_keywords in create_media_buy to set the initial list.',
            min_length=1,
        ),
    ] = None
    negative_keywords_remove: Annotated[
        list[NegativeKeywordsRemoveItem] | None,
        Field(
            description='Negative keywords to remove from this package. Removes matching keyword+match_type pairs from the existing list. If a specified pair is not present, sellers SHOULD treat it as a no-op for that entry.',
            min_length=1,
        ),
    ] = None
    creative_assignments: Annotated[
        list[creative_assignment.CreativeAssignment] | None,
        Field(
            description='Replace creative assignments for this package with optional weights and placement targeting. Uses replacement semantics - omit to leave assignments unchanged.'
        ),
    ] = None
    creatives: Annotated[
        list[creative_asset.CreativeAsset] | None,
        Field(
            description="Replace this package's inline creative assets. When the seller also advertises creative.has_creative_library: true, new inline creatives enter the seller's creative library and can be reused by creative_id while retained; inline-only sellers may store them as package-scoped assets. Use creative_assignments instead for existing library creatives.",
            max_length=100,
            min_length=1,
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var bid_price : float | None
var budget : float | None
var canceled : Literal[True] | None
var cancellation_reason : str | None
var catalogs : list[adcp.types.generated_poc.core.catalog.Catalog] | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_assignments : list[adcp.types.generated_poc.core.creative_assignment.CreativeAssignment] | None
var creatives : list[adcp.types.generated_poc.core.creative_asset.CreativeAsset] | None
var end_time : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var impressions : float | None
var keyword_targets_add : list[adcp.types.generated_poc.media_buy.package_update.KeywordTargetsAddItem] | None
var keyword_targets_remove : list[adcp.types.generated_poc.media_buy.package_update.KeywordTargetsRemoveItem] | None
var model_config
var negative_keywords_add : list[adcp.types.generated_poc.media_buy.package_update.NegativeKeywordsAddItem] | None
var negative_keywords_remove : list[adcp.types.generated_poc.media_buy.package_update.NegativeKeywordsRemoveItem] | None
var optimization_goals : list[adcp.types.generated_poc.core.optimization_goal.OptimizationGoal] | None
var pacing : adcp.types.generated_poc.enums.pacing.Pacing | None
var package_id : str
var paused : bool | None
var start_time : pydantic.types.AwareDatetime | None
var targeting_overlay : adcp.types.generated_poc.core.targeting.TargetingOverlay | None

Inherited members

class Proposal (**data: Any)
Expand source code
class Proposal(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    proposal_id: Annotated[
        str,
        Field(
            description='Unique identifier for this proposal. Used to finalize a draft proposal and to execute a committed proposal via create_media_buy.',
            max_length=255,
        ),
    ]
    name: Annotated[
        str, Field(description='Human-readable name for this media plan proposal', max_length=500)
    ]
    description: Annotated[
        str | None,
        Field(
            description='Explanation of the proposal strategy and what it achieves', max_length=2000
        ),
    ] = None
    allocations: Annotated[
        list[product_allocation.ProductAllocation],
        Field(
            description='Budget allocations across products. Allocation percentages MUST sum to 100. Publishers are responsible for ensuring the sum equals 100; buyers SHOULD validate this before execution.',
            min_length=1,
        ),
    ]
    proposal_status: Annotated[
        proposal_status_1.ProposalStatus | None,
        Field(
            description="Lifecycle status of this proposal and the per-proposal source of truth for whether finalization is required before create_media_buy. When absent, the proposal is ready to buy (backward compatible). 'draft' means indicative pricing — finalize via refine before purchasing. 'committed' means firm pricing with inventory reserved until expires_at and executable via create_media_buy."
        ),
    ] = None
    expires_at: Annotated[
        AwareDatetime | None,
        Field(
            description='When this proposal expires and can no longer be executed. For draft proposals, indicates when indicative pricing becomes stale. For committed proposals, indicates when the inventory hold lapses — the buyer must call create_media_buy before this time.'
        ),
    ] = None
    insertion_order: Annotated[
        insertion_order_1.InsertionOrder | None,
        Field(
            description='Formal insertion order attached to a committed proposal. Present when the seller requires a signed agreement before the media buy can proceed. The buyer references the io_id in io_acceptance on create_media_buy.'
        ),
    ] = None
    total_budget_guidance: Annotated[
        TotalBudgetGuidance | None, Field(description='Optional budget guidance for this proposal')
    ] = None
    brief_alignment: Annotated[
        str | None,
        Field(
            description='Explanation of how this proposal aligns with the campaign brief',
            max_length=2000,
        ),
    ] = None
    forecast: Annotated[
        delivery_forecast.DeliveryForecast | None,
        Field(
            description='Aggregate forecasted delivery metrics for the entire proposal. When both proposal-level and allocation-level forecasts are present, the proposal-level forecast is authoritative for total delivery estimation.'
        ),
    ] = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var allocations : list[adcp.types.generated_poc.core.product_allocation.ProductAllocation]
var brief_alignment : str | None
var description : str | None
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var forecast : adcp.types.generated_poc.core.delivery_forecast.DeliveryForecast | None
var insertion_order : adcp.types.generated_poc.core.insertion_order.InsertionOrder | None
var model_config
var name : str
var proposal_id : str
var proposal_status : adcp.types.generated_poc.enums.proposal_status.ProposalStatus | None
var total_budget_guidance : adcp.types.generated_poc.core.proposal.TotalBudgetGuidance | None

Inherited members

class MediaBuyDeliveryStatus (*args, **kwds)
Expand source code
class Status(StrEnum):
    pending_creatives = 'pending_creatives'
    pending_start = 'pending_start'
    pending = 'pending'
    active = 'active'
    paused = 'paused'
    completed = 'completed'
    rejected = 'rejected'
    canceled = 'canceled'
    failed = 'failed'
    reporting_delayed = 'reporting_delayed'

Enum where members are also (and must be) strings

Ancestors

  • enum.StrEnum
  • builtins.str
  • enum.ReprEnum
  • enum.Enum

Class variables

var active
var canceled
var completed
var failed
var paused
var pending
var pending_creatives
var pending_start
var rejected
var reporting_delayed
class TargetingOverlay (**data: Any)
Expand source code
class TargetingOverlay(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    geo_countries: Annotated[
        list[GeoCountry] | None,
        Field(
            description="Restrict delivery to specific countries. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').",
            min_length=1,
        ),
    ] = None
    geo_countries_exclude: Annotated[
        Sequence[GeoCountriesExcludeItem] | None,
        Field(
            description="Exclude specific countries from delivery. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').",
            min_length=1,
        ),
    ] = None
    geo_regions: Annotated[
        list[GeoRegion] | None,
        Field(
            description="Restrict delivery to specific regions/states. ISO 3166-2 subdivision codes (e.g., 'US-CA', 'GB-SCT').",
            min_length=1,
        ),
    ] = None
    geo_regions_exclude: Annotated[
        Sequence[GeoRegionsExcludeItem] | None,
        Field(
            description="Exclude specific regions/states from delivery. ISO 3166-2 subdivision codes (e.g., 'US-CA', 'GB-SCT').",
            min_length=1,
        ),
    ] = None
    geo_metros: Annotated[
        list[GeoMetro] | None,
        Field(
            description='Restrict delivery to specific metro areas. Each entry specifies the classification system and target values. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    geo_metros_exclude: Annotated[
        Sequence[GeoMetrosExcludeItem] | None,
        Field(
            description='Exclude specific metro areas from delivery. Each entry specifies the classification system and excluded values. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    geo_postal_areas: Annotated[
        list[postal_area.PostalArea] | None,
        Field(
            description='Restrict delivery to specific postal areas. Prefer the native country + postal system form. The deprecated legacy country-fused postal-system tokens remain accepted for compatibility. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    geo_postal_areas_exclude: Annotated[
        Sequence[postal_area.PostalArea] | None,
        Field(
            description='Exclude specific postal areas from delivery. Prefer the native country + postal system form. The deprecated legacy country-fused postal-system tokens remain accepted for compatibility. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    daypart_targets: Annotated[
        list[daypart_target.DaypartTarget] | None,
        Field(
            description='Restrict delivery to specific time windows. Each entry specifies days of week and an hour range.',
            min_length=1,
        ),
    ] = None
    axe_include_segment: Annotated[
        str | None,
        Field(
            deprecated=True,
            description='Deprecated: Use TMP provider fields instead. AXE segment ID to include for targeting.',
        ),
    ] = None
    axe_exclude_segment: Annotated[
        str | None,
        Field(
            deprecated=True,
            description='Deprecated: Use TMP provider fields instead. AXE segment ID to exclude from targeting.',
        ),
    ] = None
    audience_include: Annotated[
        list[str] | None,
        Field(
            description='Restrict delivery to members of these first-party CRM audiences. Only users present in the uploaded lists are eligible. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Not for lookalike expansion — express that intent in the campaign brief. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    audience_exclude: Annotated[
        list[str] | None,
        Field(
            description='Suppress delivery to members of these first-party CRM audiences. Matched users are excluded regardless of other targeting. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    signal_targeting_groups: Annotated[
        package_signal_targeting_groups.PackageSignalTargetingGroups | None,
        Field(
            description="Basic Boolean grouping for seller-offered signals. v1 supports a required top-level operator 'all' and child groups with operator 'any' for include groups or 'none' for exclusion groups. Example semantics: group 1 any(A, B) plus group 2 none(C, D) means (A OR B) AND NOT (C OR D). Signal entries reference named signal definitions with signal_ref scope 'product' for product-local signal options or scope 'data_provider' for external signals published in adagents.json signals[]. For simple include-only targeting, send one child group with operator 'any'. Sellers SHOULD reject entries that are not available for the product through inline signal_targeting_options or get_signals, are not active for the account, or exceed the product's signal_targeting_allowed/signal_targeting_rules/product terms. Signal targeting limits are product-scoped, not declared in get_adcp_capabilities, because products may be backed by different ad servers. Sellers MUST echo applied signal_targeting_groups on the resulting package state, including fixed/default selections. On update_media_buy, sellers MAY reject changes that require repricing with REQUOTE_REQUIRED."
        ),
    ] = None
    signal_targeting: Annotated[
        list[signal_targeting_1.SignalTargeting] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use signal_targeting_groups for package-level signal targeting. Legacy flat signal_targeting remains accepted during the SignalRef migration window but cannot express grouped include/exclude composition or product-scoped pricing.',
            min_length=1,
        ),
    ] = None
    frequency_cap: frequency_cap_1.FrequencyCap | None = None
    property_list: Annotated[
        property_list_ref.PropertyListReference | None,
        Field(
            description="Reference to a property list for targeting specific properties within this product. The package runs on the intersection of the product's publisher_properties and this list. Sellers SHOULD return a validation error if the product has property_targeting_allowed: false."
        ),
    ] = None
    collection_list: Annotated[
        collection_list_ref.CollectionListReference | None,
        Field(
            description='Reference to a collection list for including specific collections (programs, shows) within this product. The package runs on the intersection of matched collections and this list. Use for inclusion-based collection targeting. Seller must declare support in get_adcp_capabilities.'
        ),
    ] = None
    collection_list_exclude: Annotated[
        collection_list_ref.CollectionListReference | None,
        Field(
            description="Reference to a collection list for excluding specific collections (programs, shows) from this product. Matched collections must not carry the buyer's ads. Use for brand safety do-not-air lists. Seller must declare support in get_adcp_capabilities."
        ),
    ] = None
    age_restriction: Annotated[
        AgeRestriction | None,
        Field(
            description='Age restriction for compliance. Use for legal requirements (alcohol, gambling), not audience targeting.'
        ),
    ] = None
    device_platform: Annotated[
        list[device_platform_1.DevicePlatform] | None,
        Field(
            description='Restrict to specific platforms. Use for technical compatibility (app only works on iOS). Values from Sec-CH-UA-Platform standard, extended for CTV.',
            min_length=1,
        ),
    ] = None
    device_type: Annotated[
        list[device_type_1.DeviceType] | None,
        Field(
            description='Restrict to specific device form factors. Use for campaigns targeting hardware categories rather than operating systems (e.g., mobile-only promotions, CTV campaigns).',
            min_length=1,
        ),
    ] = None
    device_type_exclude: Annotated[
        list[device_type_1.DeviceType] | None,
        Field(
            description='Exclude specific device form factors from delivery (e.g., exclude CTV for app-install campaigns).',
            min_length=1,
        ),
    ] = None
    store_catchments: Annotated[
        list[StoreCatchment] | None,
        Field(
            description='Target users within store catchment areas from a synced store catalog. Each entry references a store-type catalog and optionally narrows to specific stores or catchment zones.',
            min_length=1,
        ),
    ] = None
    geo_proximity: Annotated[
        list[GeoProximityItem] | None,
        Field(
            description='Target users within travel time, distance, or a custom boundary around arbitrary geographic points. Multiple entries use OR semantics — a user within range of any listed point is eligible. For campaigns targeting 10+ locations, consider using store_catchments with a location catalog instead. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    language: Annotated[
        list[LanguageItem] | None,
        Field(
            description="Restrict to users with specific language preferences. ISO 639-1 codes (e.g., 'en', 'es', 'fr').",
            min_length=1,
        ),
    ] = None
    keyword_targets: Annotated[
        list[KeywordTarget] | None,
        Field(
            description='Keyword targeting for search and retail media platforms. Restricts delivery to queries matching the specified keywords. Each keyword is identified by the tuple (keyword, match_type) — the same keyword string with different match types are distinct targets. Sellers SHOULD reject duplicate (keyword, match_type) pairs within a single request. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    negative_keywords: Annotated[
        list[NegativeKeyword] | None,
        Field(
            description='Keywords to exclude from delivery. Queries matching these keywords will not trigger the ad. Each negative keyword is identified by the tuple (keyword, match_type). Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Class variables

var age_restriction : adcp.types.generated_poc.core.targeting.AgeRestriction | None
var audience_exclude : list[str] | None
var audience_include : list[str] | None
var axe_exclude_segment : str | None
var axe_include_segment : str | None
var collection_list : adcp.types.generated_poc.core.collection_list_ref.CollectionListReference | None
var collection_list_exclude : adcp.types.generated_poc.core.collection_list_ref.CollectionListReference | None
var daypart_targets : list[adcp.types.generated_poc.core.daypart_target.DaypartTarget] | None
var device_platform : list[adcp.types.generated_poc.enums.device_platform.DevicePlatform] | None
var device_type : list[adcp.types.generated_poc.enums.device_type.DeviceType] | None
var device_type_exclude : list[adcp.types.generated_poc.enums.device_type.DeviceType] | None
var frequency_cap : adcp.types.generated_poc.core.frequency_cap.FrequencyCap | None
var geo_countries : list[adcp.types.generated_poc.core.targeting.GeoCountry] | None
var geo_countries_exclude : collections.abc.Sequence[adcp.types.generated_poc.core.targeting.GeoCountriesExcludeItem] | None
var geo_metros : list[adcp.types.generated_poc.core.targeting.GeoMetro] | None
var geo_metros_exclude : collections.abc.Sequence[adcp.types.generated_poc.core.targeting.GeoMetrosExcludeItem] | None
var geo_postal_areas : list[adcp.types.generated_poc.core.postal_area.PostalArea] | None
var geo_postal_areas_exclude : collections.abc.Sequence[adcp.types.generated_poc.core.postal_area.PostalArea] | None
var geo_proximity : list[adcp.types.generated_poc.core.targeting.GeoProximityItem] | None
var geo_regions : list[adcp.types.generated_poc.core.targeting.GeoRegion] | None
var geo_regions_exclude : collections.abc.Sequence[adcp.types.generated_poc.core.targeting.GeoRegionsExcludeItem] | None
var keyword_targets : list[adcp.types.generated_poc.core.targeting.KeywordTarget] | None
var language : list[adcp.types.generated_poc.core.targeting.LanguageItem] | None
var model_config
var negative_keywords : list[adcp.types.generated_poc.core.targeting.NegativeKeyword] | None
var property_list : adcp.types.generated_poc.core.property_list_ref.PropertyListReference | None
var signal_targeting : list[adcp.types.generated_poc.core.signal_targeting.SignalTargeting] | None
var signal_targeting_groups : adcp.types.generated_poc.core.package_signal_targeting_groups.PackageSignalTargetingGroups | None
var store_catchments : list[adcp.types.generated_poc.core.targeting.StoreCatchment] | None

Inherited members

class Totals (**data: Any)
Expand source code
class Totals(DeliveryMetrics):
    effective_rate: Annotated[
        float | None,
        Field(
            description="Effective rate paid per unit based on pricing_model (e.g., actual CPM for 'cpm', actual cost per completed view for 'cpcv', actual cost per point for 'cpp')",
            ge=0.0,
        ),
    ] = None
    spend: Any

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.delivery_metrics.DeliveryMetrics
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var effective_rate : float | None
var model_config
var spend : Any

Inherited members

class UpdateMediaBuyRequest (**data: Any)
Expand source code
class UpdateMediaBuyRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference,
        Field(
            description='Account that owns this media buy. Pass a natural key (brand, operator, optional sandbox) or a seller-assigned account_id from list_accounts. Required for governance checks and account resolution.'
        ),
    ]
    media_buy_id: Annotated[str, Field(description="Seller's ID of the media buy to update")]
    revision: Annotated[
        int | None,
        Field(
            description="Expected current revision for optimistic concurrency. Optional for backward compatibility. When provided, sellers MUST reject the update with CONFLICT if the media buy's current revision does not match, and MUST enforce that comparison atomically with the write. Obtain from get_media_buys or the most recent create/update response.",
            ge=1,
        ),
    ] = None
    paused: Annotated[
        bool | None,
        Field(description='Pause/resume the entire media buy (true = paused, false = active)'),
    ] = None
    canceled: Annotated[
        Literal[True] | None,
        Field(
            description='Cancel the entire media buy. Cancellation is irreversible — canceled media buys cannot be reactivated. Sellers MAY reject with NOT_CANCELLABLE if the media buy cannot be canceled in its current state.'
        ),
    ] = None
    cancellation_reason: Annotated[
        str | None,
        Field(
            description='Reason for cancellation. Sellers SHOULD store this and return it in subsequent get_media_buys responses.',
            max_length=500,
        ),
    ] = None
    start_time: start_timing.StartTiming | None = None
    end_time: Annotated[
        AwareDatetime | None, Field(description='New end date/time in ISO 8601 format')
    ] = None
    packages: Annotated[
        Sequence[package_update.PackageUpdate] | None,
        Field(description='Package-specific updates for existing packages', min_length=1),
    ] = None
    invoice_recipient: Annotated[
        business_entity.BusinessEntity | None,
        Field(
            description="Update who receives the invoice for this buy. When provided, the seller invoices this entity instead of the account's default billing_entity. The seller MUST validate the invoice recipient is authorized for this account. When governance_agents are configured, the seller MUST include invoice_recipient in the check_governance request."
        ),
    ] = None
    new_packages: Annotated[
        list[package_request.PackageRequest] | None,
        Field(
            description='New packages to add to this media buy. Uses the same schema as create_media_buy packages. Sellers that support mid-flight package additions advertise `add_packages` in both `valid_actions[]` (deprecated) and as an entry in `available_actions[]` (authoritative). Sellers that do not support this MUST reject with ACTION_NOT_ALLOWED (preferred) or UNSUPPORTED_FEATURE (legacy).',
            min_length=1,
        ),
    ] = None
    reporting_webhook: Annotated[
        reporting_webhook_1.ReportingWebhook | None,
        Field(
            description='Optional webhook configuration for automated reporting delivery. Updates the reporting configuration for this media buy.'
        ),
    ] = None
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time. This is separate from reporting_webhook which configures ongoing campaign reporting.'
        ),
    ] = None
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated idempotency key for safe retries. If an update fails without a response, resending with the same idempotency_key guarantees the update is applied at most once. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var account : adcp.types.generated_poc.core.account_ref.AccountReference
var canceled : Literal[True] | None
var cancellation_reason : str | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var end_time : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var idempotency_key : str
var invoice_recipient : adcp.types.generated_poc.core.business_entity.BusinessEntity | None
var media_buy_id : str
var model_config
var new_packages : list[adcp.types.generated_poc.media_buy.package_request.PackageRequest] | None
var packages : collections.abc.Sequence[adcp.types.generated_poc.media_buy.package_update.PackageUpdate] | None
var paused : bool | None
var push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | None
var reporting_webhook : adcp.types.generated_poc.core.reporting_webhook.ReportingWebhook | None
var revision : int | None
var start_time : adcp.types.generated_poc.core.start_timing.StartTiming | None
class UpdateMediaBuyPackagesRequest (**data: Any)
Expand source code
class UpdateMediaBuyRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference,
        Field(
            description='Account that owns this media buy. Pass a natural key (brand, operator, optional sandbox) or a seller-assigned account_id from list_accounts. Required for governance checks and account resolution.'
        ),
    ]
    media_buy_id: Annotated[str, Field(description="Seller's ID of the media buy to update")]
    revision: Annotated[
        int | None,
        Field(
            description="Expected current revision for optimistic concurrency. Optional for backward compatibility. When provided, sellers MUST reject the update with CONFLICT if the media buy's current revision does not match, and MUST enforce that comparison atomically with the write. Obtain from get_media_buys or the most recent create/update response.",
            ge=1,
        ),
    ] = None
    paused: Annotated[
        bool | None,
        Field(description='Pause/resume the entire media buy (true = paused, false = active)'),
    ] = None
    canceled: Annotated[
        Literal[True] | None,
        Field(
            description='Cancel the entire media buy. Cancellation is irreversible — canceled media buys cannot be reactivated. Sellers MAY reject with NOT_CANCELLABLE if the media buy cannot be canceled in its current state.'
        ),
    ] = None
    cancellation_reason: Annotated[
        str | None,
        Field(
            description='Reason for cancellation. Sellers SHOULD store this and return it in subsequent get_media_buys responses.',
            max_length=500,
        ),
    ] = None
    start_time: start_timing.StartTiming | None = None
    end_time: Annotated[
        AwareDatetime | None, Field(description='New end date/time in ISO 8601 format')
    ] = None
    packages: Annotated[
        Sequence[package_update.PackageUpdate] | None,
        Field(description='Package-specific updates for existing packages', min_length=1),
    ] = None
    invoice_recipient: Annotated[
        business_entity.BusinessEntity | None,
        Field(
            description="Update who receives the invoice for this buy. When provided, the seller invoices this entity instead of the account's default billing_entity. The seller MUST validate the invoice recipient is authorized for this account. When governance_agents are configured, the seller MUST include invoice_recipient in the check_governance request."
        ),
    ] = None
    new_packages: Annotated[
        list[package_request.PackageRequest] | None,
        Field(
            description='New packages to add to this media buy. Uses the same schema as create_media_buy packages. Sellers that support mid-flight package additions advertise `add_packages` in both `valid_actions[]` (deprecated) and as an entry in `available_actions[]` (authoritative). Sellers that do not support this MUST reject with ACTION_NOT_ALLOWED (preferred) or UNSUPPORTED_FEATURE (legacy).',
            min_length=1,
        ),
    ] = None
    reporting_webhook: Annotated[
        reporting_webhook_1.ReportingWebhook | None,
        Field(
            description='Optional webhook configuration for automated reporting delivery. Updates the reporting configuration for this media buy.'
        ),
    ] = None
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time. This is separate from reporting_webhook which configures ongoing campaign reporting.'
        ),
    ] = None
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated idempotency key for safe retries. If an update fails without a response, resending with the same idempotency_key guarantees the update is applied at most once. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var account : adcp.types.generated_poc.core.account_ref.AccountReference
var canceled : Literal[True] | None
var cancellation_reason : str | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var end_time : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var idempotency_key : str
var invoice_recipient : adcp.types.generated_poc.core.business_entity.BusinessEntity | None
var media_buy_id : str
var model_config
var new_packages : list[adcp.types.generated_poc.media_buy.package_request.PackageRequest] | None
var packages : collections.abc.Sequence[adcp.types.generated_poc.media_buy.package_update.PackageUpdate] | None
var paused : bool | None
var push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | None
var reporting_webhook : adcp.types.generated_poc.core.reporting_webhook.ReportingWebhook | None
var revision : int | None
var start_time : adcp.types.generated_poc.core.start_timing.StartTiming | None
class UpdateMediaBuyPropertiesRequest (**data: Any)
Expand source code
class UpdateMediaBuyRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference,
        Field(
            description='Account that owns this media buy. Pass a natural key (brand, operator, optional sandbox) or a seller-assigned account_id from list_accounts. Required for governance checks and account resolution.'
        ),
    ]
    media_buy_id: Annotated[str, Field(description="Seller's ID of the media buy to update")]
    revision: Annotated[
        int | None,
        Field(
            description="Expected current revision for optimistic concurrency. Optional for backward compatibility. When provided, sellers MUST reject the update with CONFLICT if the media buy's current revision does not match, and MUST enforce that comparison atomically with the write. Obtain from get_media_buys or the most recent create/update response.",
            ge=1,
        ),
    ] = None
    paused: Annotated[
        bool | None,
        Field(description='Pause/resume the entire media buy (true = paused, false = active)'),
    ] = None
    canceled: Annotated[
        Literal[True] | None,
        Field(
            description='Cancel the entire media buy. Cancellation is irreversible — canceled media buys cannot be reactivated. Sellers MAY reject with NOT_CANCELLABLE if the media buy cannot be canceled in its current state.'
        ),
    ] = None
    cancellation_reason: Annotated[
        str | None,
        Field(
            description='Reason for cancellation. Sellers SHOULD store this and return it in subsequent get_media_buys responses.',
            max_length=500,
        ),
    ] = None
    start_time: start_timing.StartTiming | None = None
    end_time: Annotated[
        AwareDatetime | None, Field(description='New end date/time in ISO 8601 format')
    ] = None
    packages: Annotated[
        Sequence[package_update.PackageUpdate] | None,
        Field(description='Package-specific updates for existing packages', min_length=1),
    ] = None
    invoice_recipient: Annotated[
        business_entity.BusinessEntity | None,
        Field(
            description="Update who receives the invoice for this buy. When provided, the seller invoices this entity instead of the account's default billing_entity. The seller MUST validate the invoice recipient is authorized for this account. When governance_agents are configured, the seller MUST include invoice_recipient in the check_governance request."
        ),
    ] = None
    new_packages: Annotated[
        list[package_request.PackageRequest] | None,
        Field(
            description='New packages to add to this media buy. Uses the same schema as create_media_buy packages. Sellers that support mid-flight package additions advertise `add_packages` in both `valid_actions[]` (deprecated) and as an entry in `available_actions[]` (authoritative). Sellers that do not support this MUST reject with ACTION_NOT_ALLOWED (preferred) or UNSUPPORTED_FEATURE (legacy).',
            min_length=1,
        ),
    ] = None
    reporting_webhook: Annotated[
        reporting_webhook_1.ReportingWebhook | None,
        Field(
            description='Optional webhook configuration for automated reporting delivery. Updates the reporting configuration for this media buy.'
        ),
    ] = None
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time. This is separate from reporting_webhook which configures ongoing campaign reporting.'
        ),
    ] = None
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated idempotency key for safe retries. If an update fails without a response, resending with the same idempotency_key guarantees the update is applied at most once. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var account : adcp.types.generated_poc.core.account_ref.AccountReference
var canceled : Literal[True] | None
var cancellation_reason : str | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var end_time : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var idempotency_key : str
var invoice_recipient : adcp.types.generated_poc.core.business_entity.BusinessEntity | None
var media_buy_id : str
var model_config
var new_packages : list[adcp.types.generated_poc.media_buy.package_request.PackageRequest] | None
var packages : collections.abc.Sequence[adcp.types.generated_poc.media_buy.package_update.PackageUpdate] | None
var paused : bool | None
var push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | None
var reporting_webhook : adcp.types.generated_poc.core.reporting_webhook.ReportingWebhook | None
var revision : int | None
var start_time : adcp.types.generated_poc.core.start_timing.StartTiming | None

Inherited members

class UpdateMediaBuySuccessResponse (**data: Any)
Expand source code
class UpdateMediaBuyResponse1(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    media_buy_id: str
    media_buy_status: media_buy_status_1.MediaBuyStatus | None = None
    status: Literal['completed']
    revision: Annotated[int, Field(ge=1)]
    currency: Annotated[str, StringConstraints(pattern='^[A-Z]{3}$')] | None = None
    total_budget: Annotated[float, Field(ge=0)] | None = None
    implementation_date: AwareDatetime | None = None
    invoice_recipient: business_entity_1.BusinessEntity | None = None
    affected_packages: Sequence[package_1.Package] | None = None
    valid_actions: list[media_buy_valid_action_1.MediaBuyValidAction] | None = None
    available_actions: list[media_buy_available_action_1.MediaBuyAvailableAction] | None = None
    sandbox: bool | None = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

    @model_validator(mode='before')
    @classmethod
    def _normalize_legacy_status(cls, data: Any) -> Any:
        if not isinstance(data, dict):
            return data
        raw_status = unwrap_enum_value(data.get('status'))
        media_buy_status = unwrap_enum_value(data.get('media_buy_status'))
        if raw_status is None:
            data = dict(data)
            data['status'] = 'completed'
        elif raw_status == 'completed':
            data = dict(data)
            data['status'] = 'completed'
        elif media_buy_status is None and raw_status in MEDIA_BUY_LEGACY_STATUS_VALUES:
            data = dict(data)
            data['media_buy_status'] = raw_status
            data['status'] = 'completed'
        elif media_buy_status is not None and raw_status == media_buy_status:
            data = dict(data)
            data['status'] = 'completed'
        return data

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var affected_packages : collections.abc.Sequence[adcp.types.generated_poc.core.package.Package] | None
var available_actions : list[adcp.types.generated_poc.core.media_buy_available_action.MediaBuyAvailableAction] | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var currency : str | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var implementation_date : pydantic.types.AwareDatetime | None
var invoice_recipient : adcp.types.generated_poc.core.business_entity.BusinessEntity | None
var media_buy_id : str
var media_buy_status : adcp.types.generated_poc.enums.media_buy_status.MediaBuyStatus | None
var model_config
var revision : int
var sandbox : bool | None
var status : Literal['completed']
var total_budget : float | None
var valid_actions : list[adcp.types.generated_poc.enums.media_buy_valid_action.MediaBuyValidAction] | None

Inherited members

class UpdateMediaBuyErrorResponse (**data: Any)
Expand source code
class UpdateMediaBuyResponse2(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    errors: Annotated[list[error_1.Error], Field(min_length=1)]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var errors : list[adcp.types.generated_poc.core.error.Error]
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var model_config

Inherited members

class UpdateMediaBuySubmittedResponse (**data: Any)
Expand source code
class UpdateMediaBuyResponse3(AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(extra='allow', validate_default=True)
    status: Literal[task_status_1.TaskStatus.submitted] = task_status_1.TaskStatus.submitted
    task_id: str
    message: Annotated[str, StringConstraints(max_length=2000)] | None = None
    errors: list[error_1.Error] | None = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Base model for AdCP types with spec-compliant serialization.

Defaults to extra='ignore' so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas set additionalProperties: true override this with extra='allow' in their own model_config.

Set ADCP_STRICT_VALIDATION=1 in the environment ("1", "true", "yes", "on" are accepted) to flip the default to extra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.

Important

The env var is resolved once at module import time. Set it in your shell or CI environment before import adcp runs — mutating os.environ["ADCP_STRICT_VALIDATION"] after the first adcp import has no effect on already-imported model classes (they captured the policy at class-body evaluation).

Consumers who want per-model strict validation can override model_config on their subclass.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

  • adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
  • adcp.types.generated_poc.core.protocol_envelope.ProtocolEnvelope
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var errors : list[adcp.types.generated_poc.core.error.Error] | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var message : str | None
var model_config
var status : Literal[]
var task_id : str

Inherited members