Module adcp.types.legacy

Explicit raw/legacy creative wire types.

Application code should import canonical models from :mod:adcp or :mod:adcp.types. These aliases exist for migration, conformance tooling, and AdCP 3.0/3.1 wire adapters.

Classes

class LegacyBuildCreativeRequest (**data: Any)
Expand source code
class BuildCreativeRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    governance_context: Annotated[
        str | None,
        Field(
            description='Opaque intent authorization when this creative execution incurs vendor cost.',
            max_length=4096,
            min_length=1,
            pattern='^[\\x20-\\x7E]+$',
        ),
    ] = None
    message: Annotated[
        str | None,
        Field(
            description='Natural language instructions for the transformation or generation. For pure generation, this is the creative brief. For transformation, this provides guidance on how to adapt the creative. For refinement, this describes the desired changes.'
        ),
    ] = None
    creative_manifest: Annotated[
        creative_manifest_1.CreativeManifest | None,
        Field(
            description='Creative manifest to transform or generate from. On the canonical 3.2 path it carries `format_kind`, optional `format_option_ref`, and the required input assets. For transformation (for example resizing or reformatting), this is the complete creative to adapt. When creative_id is provided, the agent resolves the creative from its library and this field is ignored.'
        ),
    ] = None
    creative_id: Annotated[
        str | None,
        Field(
            description="Reference to a creative in the agent's library. The creative agent resolves this to a manifest from its library. Use this instead of creative_manifest when retrieving an existing creative for tag generation or format adaptation."
        ),
    ] = None
    concept_id: Annotated[
        str | None,
        Field(
            description='Creative concept containing the creative. Creative agents SHOULD assign globally unique creative_id values; when they cannot guarantee uniqueness, concept_id is REQUIRED to disambiguate.'
        ),
    ] = None
    media_buy_id: Annotated[
        str | None,
        Field(
            description='Media buy identifier for tag generation context. When the creative agent is also the ad server, this provides the trafficking context needed to generate placement-specific tags (e.g., CM360 placement ID). Not needed when tags are generated at the creative level (most creative platforms).'
        ),
    ] = None
    package_id: Annotated[
        str | None,
        Field(
            description='Package identifier within the media buy. Used with media_buy_id when the creative agent needs line-item-level context for tag generation. Omit to get a tag not scoped to a specific package.'
        ),
    ] = None
    target_format_id: Annotated[
        format_id.FormatReferenceStructuredObject | None,
        Field(
            deprecated=True,
            description='**DEPRECATED in 3.2.** Legacy named-format selector. Use `target_capability_id` with a value advertised in `get_adcp_capabilities.creative.supported_formats[].capability_id`.',
        ),
    ] = None
    target_format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='**DEPRECATED in 3.2.** Legacy named-format selectors. Use `target_capability_ids` with values advertised in `get_adcp_capabilities.creative.supported_formats[].capability_id`.',
            max_length=50,
            min_length=1,
        ),
    ] = None
    target_capability_id: Annotated[
        str | None,
        Field(
            description='Canonical 3.2 single-output selector. Matches exactly one `get_adcp_capabilities.creative.supported_formats[].capability_id` advertised by this creative agent. The matched entry supplies the canonical `format` declaration used to validate inputs and the returned manifest. Mutually exclusive with `target_capability_ids` and the deprecated target_format_id fields.',
            pattern='^[a-zA-Z0-9_-]+$',
        ),
    ] = None
    target_capability_ids: Annotated[
        list[TargetCapabilityId] | None,
        Field(
            description='Canonical 3.2 multi-output selector. Each value matches a `get_adcp_capabilities.creative.supported_formats[].capability_id`. The creative agent produces one canonical manifest per capability in request order. Mutually exclusive with `target_capability_id` and the deprecated target_format_id fields.',
            max_length=50,
            min_length=1,
        ),
    ] = None
    transformer_id: Annotated[
        str | None,
        Field(
            description="Selects an account-scoped transformer (discovered via list_transformers) to perform the build. One transformer per call. When present, the build uses this transformer and target_capability_id/target_capability_ids select which of its outputs to produce — they MUST be a subset of the transformer's output_capability_ids. Deprecated target_format_id fields use the legacy output_format_ids compatibility path. Render configuration goes in `config`."
        ),
    ] = None
    config: Annotated[
        dict[str, Any] | None,
        Field(
            description='Typed render configuration for the selected transformer, keyed by each param\'s `field` (from the transformer\'s params[] in list_transformers). Example: { "voice": "isaac", "speaking_rate": 1.1, "mastering_preset": "podcast" }. The agent MUST validate `config` against the transformer\'s live params for this account and reject unrecognized keys and out-of-range / non-enumerated values with a field-attributed error (e.g. `config.voice`) rather than silently ignoring them — config drives a paid render. Genuinely vendor-specific or experimental knobs not declared as params belong in `ext`, not here. (The schema leaves this object open because legal keys are dynamic per transformer; strict validation is a normative agent obligation.) When `refine_from_build_variant_id` is set, `config` is applied as a DELTA over the parent leaf\'s config.'
        ),
    ] = None
    refine_from_build_variant_id: Annotated[
        str | None,
        Field(
            description='Refine a previously produced variant and return new lineage-linked variants. The transformer and target capability are inherited from the parent leaf. A refinement request MUST omit transformer_id, target_capability_id(s), and deprecated target_format_id(s); changing transformer or output format is a new transformation build, not refinement. Requires creative.supports_refinement.'
        ),
    ] = None
    mode: Annotated[
        Mode | None,
        Field(
            description="`execute` (default) produces and bills the creative(s). `estimate` is a DRY RUN: the agent produces nothing and bills nothing, and returns a BuildCreativeEstimate with a projected cost band (cost_low/cost_high) computed against THIS request's actual inputs (script length, brief, catalog size, max_creatives × max_variants) — the band the buyer cannot derive itself, since per_unit gives the rate but not the unit count. Requires the agent to advertise `creative.supports_spend_controls`; otherwise rejected with `UNSUPPORTED_FEATURE`."
        ),
    ] = Mode.execute
    max_spend: Annotated[
        MaxSpend | None,
        Field(
            description='Hard per-call spend ceiling. The agent produces leaves until the NEXT leaf would push the run\'s aggregate vendor_cost over `amount`, then STOPS and returns the partial BuildCreativeVariantSuccess produced so far with `budget_status: "capped"` (every returned leaf is real, trafficable, and billed — nothing produced is discarded; the leaf shortfall is `leaves_returned` < `leaves_total`). If even the first leaf would exceed the cap, the call fails with BUDGET_CAP_REACHED. `currency` MUST match the rate card\'s currency (the agent does not FX-convert) or the request is rejected with INVALID_REQUEST (error.field `max_spend.currency`). Requires `creative.supports_spend_controls`. Caps a SINGLE call — to bound a refinement loop, track aggregate vendor_cost across calls and stop issuing them (buyer responsibility in this revision). max_spend bounds only build-time vendor_cost: CPM-priced builds (estimate basis `cpm_deferred`) have build-time vendor_cost 0 and accrue at serve time, so max_spend never engages for them — bound a CPM fan-out with max_creatives instead.'
        ),
    ] = None
    max_creatives: Annotated[
        int | None,
        Field(
            description='Caps how many DISTINCT creatives to produce along the catalog/item fan-out axis — one creative per catalog item. Use it to sample a large catalog (e.g. send 150 job openings, set max_creatives: 5 to preview five). Distinct from item_limit, which caps how many catalog items a SINGLE creative consumes (DCO-style). Omitted with a catalog input means one creative per item up to the catalog/format bound; omitted without a catalog collapses to a single creative. Large fan-outs may return asynchronously. Mutually exclusive with `refine_from_build_variant_id` (refinement targets one prior creative, not a catalog fan-out). Supported only when the agent advertises `creative.multiplicity.supports_catalog_fanout`; values above `max_creatives_limit` are clamped. Pair with `max_spend` to bound the bill of a large fan-out.',
            ge=1,
        ),
    ] = None
    signal_conditions: Annotated[
        list[SignalCondition] | None,
        Field(
            description="Advisory keep-all PRODUCTION axis: produce one distinct creative group per signal condition, each kept and trafficked with its own signal targeting (e.g. a rain creative AND a sun creative). Sibling to max_creatives (catalog axis), NOT a variant_axis value (which is choose-among). Each item reuses SignalTargeting (value_type-discriminated binary/categorical/numeric over signal_ref) so the produced group's signal_condition resolves condition identity through the SAME schema the sales-side package targeting uses, plus an optional signal_agent_segment_id carrying the RESOLVED-segment identity (vs signal_ref's definition identity) — echo a provider-exposed handle verbatim; it is the primary trafficking-compatibility key, with categorical signal_ref+value as the weaker fallback. Per #5280 this is an ADVISORY context pointer — it informs production and MUST NOT hard-block at the build_creative layer; trafficking-compatibility (a sun creative MUST NOT serve into rain-targeted packages) is enforced reject-at-trafficking on the sales side (SIGNAL_TARGETING_INCOMPATIBLE), not here. Triggers the BuildCreativeVariantSuccess shape. Supported only when the agent advertises creative.multiplicity.supports_signal_fanout; condition counts above max_signal_conditions_limit are CLAMPED (not rejected), consistent with max_creatives. Composes with max_creatives (catalog × conditions cross-product) and max_variants (variants per group).",
            min_length=1,
        ),
    ] = None
    max_variants: Annotated[
        int | None,
        Field(
            description='Caps how many ALTERNATIVES to produce per creative (different voices, themes, best-of-N, etc.). Default 1 preserves single-output behavior. Each variant is a real, independently-billed build (you pay for all produced); the buyer keeps one or many. When variant_axis.values[] is provided, its length is authoritative over max_variants. Resolutions/quality tiers are NOT variants — request them as additional target formats.',
            ge=1,
        ),
    ] = 1
    variant_axis: Annotated[
        VariantAxis | None,
        Field(
            description='Declares the dimension along which variants differ. When `values` is provided, the agent produces exactly one variant per value (e.g. an A/B of two voices). When only `dimension` is provided, the agent chooses up to max_variants variants along that dimension (e.g. best-of-N, themes).'
        ),
    ] = None
    keep_mode: Annotated[
        KeepMode | None,
        Field(
            description='Advisory hint for how the buyer intends to use the variants. `keep_one` (best-of-N) and `keep_some` signal the agent to set `recommended`/`rank` on returned variants. Advisory only — it does not change what is returned or billed; every produced variant is returned and charged. Keeping is a client act of trafficking the chosen build_variant_id(s).'
        ),
    ] = KeepMode.keep_all
    selection_strategy: Annotated[
        creative_selection_strategy.CreativeSelectionStrategy | None,
        Field(
            description='Governs HOW the agent samples when max_creatives < items_total (folds #5262). audience_relevance draws its ranking input from the SAME signal_ref pointers in signal_conditions / package targeting — NOT a parallel signals[] array. proximity takes a location input (geo shape TBD — WG open). inventory_priority is seller-side catalog metadata (margin/overstock/promo; no buyer input). random is the status-quo default. Per-creative selection ordering surfaces on the existing rank / recommended fields of creatives[].variants[], not a new selection_rank. Advisory; absent => agent default (random).'
        ),
    ] = None
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description='Account reference for pricing and billing. When present, the creative agent applies account-specific pricing from the rate card, records the build against the account for billing, and can enforce account-level quotas or entitlements. Required by creative agents that charge for their services.'
        ),
    ] = None
    brand: Annotated[
        brand_ref.BrandReference | None,
        Field(
            description='Brand reference for creative generation. Resolved to full brand identity (colors, logos, tone) at execution time.'
        ),
    ] = None
    quality: Annotated[
        creative_quality.CreativeQuality | None,
        Field(
            description="Quality tier for generation. 'draft' produces fast, lower-fidelity output for iteration and review. 'production' produces full-quality output for final delivery. If omitted, the creative agent uses its own default. For non-generative transforms (e.g., format resizing), creative agents MAY ignore this field."
        ),
    ] = None
    evaluator: Annotated[
        evaluator_spec.EvaluatorSpec | None,
        Field(
            description="Optional advisory evaluator (buyer-attached pointer, #5280) declaring how produced variants should be evaluated and ranked — the rank-side of the get_creative_features feature oracle. Experimental (x-status: experimental): the whole evaluator surface is new and unfrozen, and requires creative.supports_evaluator, which sellers MUST pair with `creative.evaluator` in experimental_features. Drives the producing agent's gate-then-rank pipeline over its best_of_n exploration: per leaf, evaluate (the chosen form) → optionally GATE (`evaluator.feature_requirement[]`, drop fails — internal pruning of which leaves the agent recommends, never an AdCP-layer block of an already-produced billable leaf) → RANK survivors (`evaluator.rank_by`, an explicit {feature_id, direction} ordering). Feature discovery uses get_adcp_capabilities governance.creative_features for rank_by, feature_requirement, and eval.features[]; evaluator_id is a pre-provisioned/account-arranged preset, not an ID discovered from that catalog. Populates a per-leaf `eval` block of creative-feature values (creative-feature-result[]) when supports_evaluator. When the evaluator names an external agent (`evaluator.feature_agent.agent_url` or the agent-form `agent_url`), that agent MUST appear in the seller's `creative_policy.accepted_verifiers[]` (the same allowlist #5280 established for provenance verify_agent); an off-list agent is rejected with `EVALUATOR_AGENT_NOT_ACCEPTED`. The outbound evaluator call authenticates on the transport (request signing/JWKS, mTLS, or a pre-provisioned static credential); credentials and caller-supplied trust material MUST NOT appear in evaluator, context, ext, or creative payload fields, and credential- or trust-material keys should be rejected with `CREDENTIAL_IN_ARGS`. With no `feature_requirement`, evaluation is advisory only and does not change what is produced or billed; an unreachable/unknown on-list agent degrades to seller-default ranking (advisory errors[] note), not a failure. Requires creative.supports_evaluator; otherwise ignored."
        ),
    ] = None
    item_limit: Annotated[
        int | None,
        Field(
            description="Maximum number of catalog items a SINGLE creative consumes when generating (DCO-style — e.g. how many items fill one carousel/feed creative). When a catalog asset contains more items than this limit, the creative agent selects the top items based on relevance or catalog ordering. When item_limit exceeds the format's max_items, the creative agent SHOULD use the lesser of the two. Ignored when the manifest contains no catalog assets. Distinct from `max_creatives`, which fans OUT across catalog items to produce one distinct creative per item.",
            ge=1,
        ),
    ] = None
    include_preview: Annotated[
        bool | None,
        Field(
            description="When true, requests the creative agent to include preview renders in the response alongside the manifest. Agents that support this return a 'preview' object in the response using the same structure as preview_creative. Agents that do not support inline preview simply omit the field. This avoids a separate preview_creative round trip for platforms that generate previews as a byproduct of building."
        ),
    ] = None
    preview_inputs: Annotated[
        list[PreviewInput] | None,
        Field(
            description='Input sets for preview generation when include_preview is true. Supported with a single target_capability_id; multi-capability requests generate one default preview per output. Deprecated target-format selectors retain equivalent compatibility behavior.',
            min_length=1,
        ),
    ] = None
    preview_quality: Annotated[
        creative_quality.CreativeQuality | None,
        Field(
            description="Render quality for inline preview when include_preview is true. 'draft' produces fast, lower-fidelity renderings. 'production' produces full-quality renderings. Independent of the build quality parameter — you can build at draft quality and preview at production quality, or vice versa. If omitted, the creative agent uses its own default. Ignored when include_preview is false or omitted."
        ),
    ] = None
    preview_output_format: Annotated[
        preview_output_format_1.PreviewOutputFormat | None,
        Field(
            description="Output format for preview renders when include_preview is true. 'url' returns preview_url (iframe-embeddable URL), 'html' returns preview_html (raw HTML). Ignored when include_preview is false or omitted."
        ),
    ] = preview_output_format_1.PreviewOutputFormat.url
    macro_values: Annotated[
        dict[str, str] | None,
        Field(
            description="Macro values to pre-substitute into the output manifest's assets. Keys are universal macro names (e.g., CLICK_URL, CACHEBUSTER); values are the substitution strings. The creative agent translates universal macros to its platform's native syntax. Substitution is literal — all occurrences of each macro in output assets are replaced with the provided value. The caller is responsible for URL-encoding values if the output context requires it. Macros not provided here remain as {MACRO} placeholders for the sales agent to resolve at serve time. Creative agents MUST ignore keys they do not recognize — unknown macro names are not an error."
        ),
    ] = None
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated unique key for this request. Prevents duplicate creative generation on retries. 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}$',
        ),
    ]
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Optional webhook configuration for async terminal completion/failure notifications on build_creative. Meaningful only when the request enters the async lifecycle and returns a Submitted envelope. Submitted envelopes with `task_id` remain pollable through `get_task_status` (legacy `tasks/get`) whether or not this field is present. If a request includes this field and the agent returns a Submitted envelope, the agent MUST deliver at least the terminal completion/failure notification to the configured URL; intermediate progress notifications are MAY. If the agent cannot honor the webhook channel, it MUST reject the request with a structured error instead of silently accepting. This field does not change response timing semantics: agents MUST NOT route a request through the async/Submitted arm or emit async delivery solely because `push_notification_config` is present; requests that can be completed inline still return the synchronous success shape.'
        ),
    ] = 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 brand : adcp.types.generated_poc.core.brand_ref.BrandReference | None
var concept_id : str | None
var config : dict[str, typing.Any] | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_id : str | None
var creative_manifest : adcp.types.generated_poc.core.creative_manifest.CreativeManifest | None
var evaluator : adcp.types.generated_poc.core.evaluator_spec.EvaluatorSpec | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var governance_context : str | None
var idempotency_key : str
var include_preview : bool | None
var item_limit : int | None
var keep_mode : adcp.types.generated_poc.media_buy.build_creative_request.KeepMode | None
var macro_values : dict[str, str] | None
var max_creatives : int | None
var max_spend : adcp.types.generated_poc.media_buy.build_creative_request.MaxSpend | None
var max_variants : int | None
var media_buy_id : str | None
var message : str | None
var mode : adcp.types.generated_poc.media_buy.build_creative_request.Mode | None
var model_config
var package_id : str | None
var preview_inputs : list[adcp.types.generated_poc.media_buy.build_creative_request.PreviewInput] | None
var preview_output_format : adcp.types.generated_poc.enums.preview_output_format.PreviewOutputFormat | None
var preview_quality : adcp.types.generated_poc.enums.creative_quality.CreativeQuality | None
var push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | None
var quality : adcp.types.generated_poc.enums.creative_quality.CreativeQuality | None
var refine_from_build_variant_id : str | None
var selection_strategy : adcp.types.generated_poc.enums.creative_selection_strategy.CreativeSelectionStrategy | None
var signal_conditions : list[adcp.types.generated_poc.media_buy.build_creative_request.SignalCondition] | None
var target_capability_id : str | None
var target_capability_ids : list[adcp.types.generated_poc.media_buy.build_creative_request.TargetCapabilityId] | None
var target_format_id : adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject | None
var target_format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var transformer_id : str | None
var variant_axis : adcp.types.generated_poc.media_buy.build_creative_request.VariantAxis | None

Inherited members

class LegacyBuildCreativeResponse1 (**data: Any)
Expand source code
class BuildCreativeResponse1(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    creative_manifest: creative_manifest_1.CreativeManifest
    build_variant_id: str | None = None
    recipe_hash: str | None = None
    sandbox: bool | None = None
    expires_at: AwareDatetime | None = None
    preview: Preview | None = None
    preview_error: error_1.Error | None = None
    pricing_option_id: str | None = None
    vendor_cost: Annotated[float, Field(ge=0)] | None = None
    currency: Annotated[str, StringConstraints(pattern='^[A-Z]{3}$')] | None = None
    consumption: creative_consumption_1.CreativeConsumption | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var build_variant_id : str | None
var consumption : adcp.types.generated_poc.core.creative_consumption.CreativeConsumption | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_manifest : adcp.types.generated_poc.core.creative_manifest.CreativeManifest
var currency : str | None
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var model_config
var preview : adcp.types.generated_poc.media_buy.build_creative_response.Preview | None
var preview_error : adcp.types.generated_poc.core.error.Error | None
var pricing_option_id : str | None
var recipe_hash : str | None
var sandbox : bool | None
var vendor_cost : float | None
class LegacyBuildCreativeSuccessResponse (**data: Any)
Expand source code
class BuildCreativeResponse1(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    creative_manifest: creative_manifest_1.CreativeManifest
    build_variant_id: str | None = None
    recipe_hash: str | None = None
    sandbox: bool | None = None
    expires_at: AwareDatetime | None = None
    preview: Preview | None = None
    preview_error: error_1.Error | None = None
    pricing_option_id: str | None = None
    vendor_cost: Annotated[float, Field(ge=0)] | None = None
    currency: Annotated[str, StringConstraints(pattern='^[A-Z]{3}$')] | None = None
    consumption: creative_consumption_1.CreativeConsumption | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var build_variant_id : str | None
var consumption : adcp.types.generated_poc.core.creative_consumption.CreativeConsumption | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_manifest : adcp.types.generated_poc.core.creative_manifest.CreativeManifest
var currency : str | None
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var model_config
var preview : adcp.types.generated_poc.media_buy.build_creative_response.Preview | None
var preview_error : adcp.types.generated_poc.core.error.Error | None
var pricing_option_id : str | None
var recipe_hash : str | None
var sandbox : bool | None
var vendor_cost : float | None

Inherited members

class LegacyBuildCreativeResponse2 (**data: Any)
Expand source code
class BuildCreativeResponse2(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
class LegacyBuildCreativeErrorResponse (**data: Any)
Expand source code
class BuildCreativeResponse2(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 LegacyBuildCreativeResponse3 (**data: Any)
Expand source code
class BuildCreativeResponse3(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    creative_manifests: Annotated[list[creative_manifest_1.CreativeManifest], Field(min_length=1)]
    sandbox: bool | None = None
    expires_at: AwareDatetime | None = None
    preview: Preview3 | None = None
    preview_error: error_1.Error | None = None
    pricing_option_id: str | None = None
    vendor_cost: Annotated[float, Field(ge=0)] | None = None
    currency: Annotated[str, StringConstraints(pattern='^[A-Z]{3}$')] | None = None
    consumption: creative_consumption_1.CreativeConsumption | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var consumption : adcp.types.generated_poc.core.creative_consumption.CreativeConsumption | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_manifests : list[adcp.types.generated_poc.core.creative_manifest.CreativeManifest]
var currency : str | None
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var model_config
var preview : adcp.types.generated_poc.media_buy.build_creative_response.Preview3 | None
var preview_error : adcp.types.generated_poc.core.error.Error | None
var pricing_option_id : str | None
var sandbox : bool | None
var vendor_cost : float | None

Inherited members

class LegacyBuildCreativeResponse4 (**data: Any)
Expand source code
class BuildCreativeResponse4(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    creatives: Annotated[list[Creative], Field(min_length=1)]
    items_total: Annotated[int, Field(ge=0)] | None = None
    items_returned: Annotated[int, Field(ge=0)] | None = None
    leaves_total: Annotated[int, Field(ge=0)] | None = None
    leaves_returned: Annotated[int, Field(ge=0)] | None = None
    vendor_cost: Annotated[float, Field(ge=0)] | None = None
    currency: Annotated[str, StringConstraints(pattern='^[A-Z]{3}$')] | None = None
    keep_mode_applied: Literal['keep_all', 'keep_one', 'keep_some'] | None = None
    selection_strategy_applied: creative_selection_strategy_1.CreativeSelectionStrategy | None = None
    budget_status: Literal['complete', 'capped'] | None = None
    errors: list[error_1.Error] | None = None
    sandbox: bool | None = None
    expires_at: AwareDatetime | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var budget_status : Literal['complete', 'capped'] | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creatives : list[adcp.types.generated_poc.media_buy.build_creative_response.Creative]
var currency : str | None
var errors : list[adcp.types.generated_poc.core.error.Error] | None
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var items_returned : int | None
var items_total : int | None
var keep_mode_applied : Literal['keep_all', 'keep_one', 'keep_some'] | None
var leaves_returned : int | None
var leaves_total : int | None
var model_config
var sandbox : bool | None
var selection_strategy_applied : adcp.types.generated_poc.enums.creative_selection_strategy.CreativeSelectionStrategy | None
var vendor_cost : float | None

Inherited members

class LegacyBuildCreativeResponse5 (**data: Any)
Expand source code
class BuildCreativeResponse5(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    mode: Literal['estimate'] = 'estimate'
    estimate: Estimate
    expires_at: AwareDatetime | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var estimate : adcp.types.generated_poc.media_buy.build_creative_response.Estimate
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var mode : Literal['estimate']
var model_config

Inherited members

class LegacyBuildCreativeResponse6 (**data: Any)
Expand source code
class BuildCreativeResponse6(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
class LegacyBuildCreativeSubmittedResponse (**data: Any)
Expand source code
class BuildCreativeResponse6(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 LegacyCreateMediaBuyRequest (**data: Any)
Expand source code
class CreateMediaBuyRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    governance_context: Annotated[
        str | None,
        Field(
            description='Opaque intent authorization for this media-buy commitment. Required when governance applies to the resolved account.',
            max_length=4096,
            min_length=1,
            pattern='^[\\x20-\\x7E]+$',
        ),
    ] = None
    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(
            deprecated=True,
            description='DEPRECATED on seller-facing requests. New buyers send the approved governance_context on the protocol envelope; the seller forwards that opaque context and does not need the plan identifier. If both are present, the governance agent MUST reject a mismatch. Removed in 4.0.',
        ),
    ] = 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 the exact committed proposal snapshot to execute. With total_budget, the publisher creates packages using the proposal's fixed percentages or seller-optimized constraints. Mutually exclusive: provide packages or proposal_id, not both. AdCP 3.2 request_proposals and ordinary refine_proposals revisions issue drafts; refine_proposals action finalize creates the executable committed hold. Sellers reject draft, declined, or previously executed snapshots, while exact retries with the original idempotency key replay historical success. Changed commercial terms are issued under a new proposal_id, so no separate proposal version is required."
        ),
    ] = None
    opportunity: Annotated[
        Opportunity | None,
        Field(
            description='Optional planning-cycle closure. Sellers infer successful proposal execution as closed with close_reason accepted_with_seller when status is omitted; when status is present it MUST be closed with that reason. If the proposal was issued under an opportunity_id, a supplied ID MUST match it.'
        ),
    ] = None
    total_budget: Annotated[
        TotalBudget | None,
        Field(
            description='Hard aggregate lifetime budget for the media buy. Required when executing a proposal and for seller-optimized explicit packages. Optional in fixed explicit-package mode; when present there, amount MUST equal the sum of package budgets. For a fixed proposal, the publisher applies allocation percentages to this amount. For a seller-optimized proposal or explicit buy, packages draw dynamically from this shared total.'
        ),
    ] = None
    daily_budget_cap: Annotated[
        float | None,
        Field(
            description='Optional hard aggregate daily spend ceiling in the media-buy currency. It limits total spend without allocating package amounts. Package caps are subordinate and need not sum to it. Requires advertised media_buy budget-capping scope; otherwise rejected with UNSUPPORTED_FEATURE.',
            ge=0.0,
        ),
    ] = None
    budget_cap_timezone: Annotated[
        str | None,
        Field(
            description='Optional shared IANA day boundary override for all caps. Requires buyer_timezone_override; otherwise rejected with UNSUPPORTED_FEATURE. When omitted, budget_capping.timezone_basis selects Account.timezone or the advertised fixed_timezone.',
            min_length=1,
        ),
    ] = None
    budget_allocation: Annotated[
        budget_allocation_1.BudgetAllocation | None,
        Field(
            description='How budget is allocated across explicit packages. Omit for legacy fixed allocation. In proposal mode the committed proposal supplies this configuration and callers MUST omit it here.'
        ),
    ] = None
    packages: Annotated[
        Sequence[package_request.PackageRequest] | None,
        Field(
            description='Array of package configurations. Required when not using proposal_id. Mutually exclusive: provide packages or proposal_id, not both. Fixed allocation requires budget on every package. Seller-optimized allocation permits package budget to be omitted or to act as a hard cap. When executing a proposal, omit packages; the seller derives them from the committed proposal.',
            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
    name: Annotated[
        str | None,
        Field(
            description='Human-readable name for this media buy, shared by buyer and seller for trafficking UI display and operational communication. When supplied, the seller MUST persist it and echo it unchanged on the create success response and subsequent get_media_buys reads. This display label is not an identifier or financial reference.',
            max_length=255,
            min_length=1,
            pattern='\\S',
        ),
    ] = 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')
    ]
    pacing: Annotated[
        pacing_1.Pacing | None,
        Field(
            description='Aggregate pacing strategy for the media-buy budget across the media-buy flight. This controls how much the buy spends over time. Package pacing is subordinate and influences which package receives the aggregate spend; package pacing MUST NOT cause aggregate delivery to exceed this strategy. Defaults to even when total_budget is present. When executing a proposal that carries pacing, omit this field or send the identical value; the seller MUST reject a conflicting override with TERMS_REJECTED.'
        ),
    ] = None
    bidding: Annotated[
        bidding_policy.BiddingPolicy | None,
        Field(
            description="Complete media-buy bidding default inherited by packages that omit package.bidding. `{automatic:true}` records an explicit automatic policy. In seller-optimized mode, cost_per/roas bind to the primary budget_allocation_1.optimization_goals goal. In fixed mode, inherited cost_per is valid only when inheriting package primary-goal result units are compatible; inherited roas requires value-bearing primary goals. Every monetary field uses total_budget.currency or the single currency derived for the media buy, and every affected pricing option MUST declare that currency. Sellers MUST reject incompatible units, combinations, currency, or overrides before mutation with BIDDING_PLACEMENT_CONFLICT. Media-buy bidding combined with any inheriting package's legacy bid_price or legacy monetary optimization-goal target is ambiguous and MUST be rejected with AMBIGUOUS_BIDDING_POLICY."
        ),
    ] = None
    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 bidding : adcp.types.generated_poc.core.bidding_policy.BiddingPolicy | None
var brand : adcp.types.generated_poc.core.brand_ref.BrandReference
var budget_allocation : adcp.types.generated_poc.core.budget_allocation.BudgetAllocation | None
var budget_cap_timezone : str | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var daily_budget_cap : float | None
var end_time : pydantic.types.AwareDatetime
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var governance_context : str | 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 name : str | None
var opportunity : adcp.types.generated_poc.media_buy.create_media_buy_request.Opportunity | None
var pacing : adcp.types.generated_poc.enums.pacing.Pacing | None
var packages : collections.abc.Sequence[adcp.types.generated_poc.media_buy.package_request.PackageRequest] | None
var paused : bool | 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

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var plan_id : str | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyCreateMediaBuyResponse1 (**data: Any)
Expand source code
class CreateMediaBuyResponse1(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    status: Literal['completed'] = 'completed'
    proposal_id: Annotated[str, StringConstraints(min_length=1)] | None = None
    media_buy_id: str
    name: Annotated[str, StringConstraints(pattern='\\S', min_length=1, max_length=255)] | None = None
    account: account_1.Account | None = None
    invoice_recipient: business_entity_1.BusinessEntity | None = None
    media_buy_status: media_buy_status_1.MediaBuyStatus | None = None
    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
    daily_budget_cap: Annotated[float, Field(ge=0)] | None = None
    budget_cap_timezone: str | None = None
    budget_allocation: Any | None = None
    pacing: pacing_1.Pacing | None = None
    bidding: Any | 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
    warnings: list[warning_1.Warning] | 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 bidding : typing.Any | None
var budget_allocation : typing.Any | None
var budget_cap_timezone : str | 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 daily_budget_cap : float | 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 name : str | None
var pacing : adcp.types.generated_poc.enums.pacing.Pacing | None
var packages : list[adcp.types.generated_poc.core.package.Package]
var planned_delivery : adcp.types.generated_poc.core.planned_delivery.PlannedDelivery | None
var proposal_id : str | 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
var warnings : list[adcp.types.generated_poc.core.warning.Warning] | None

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyCreateMediaBuyResponse2 (**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 LegacyCreateMediaBuyResponse3 (**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 LegacyCreativeAsset (root: RootModelRootType = PydanticUndefined, **data)
Expand source code
class CreativeAsset(RootModel[CreativeAsset1 | CreativeAsset2]):
    root: Annotated[
        CreativeAsset1 | CreativeAsset2,
        Field(
            description='Creative asset for upload to library — supports static assets, generative formats, and third-party snippets. Identifies which format this creative conforms to via EITHER a legacy `format_id` (structured `{agent_url, id}`) OR a 3.1+ `format_kind` (canonical format name), with optional `format_option_ref` when the target product needs disambiguation. Mutually exclusive — see the `oneOf` at the schema root.',
            title='Creative Asset',
        ),
    ]
    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[CreativeAsset1, CreativeAsset2]]
  • pydantic.root_model.RootModel
  • pydantic.main.BaseModel
  • typing.Generic

Class variables

var model_config
var root : adcp.types.generated_poc.core.creative_asset.CreativeAsset1 | adcp.types.generated_poc.core.creative_asset.CreativeAsset2
class LegacyCreativeFilters (**data: Any)
Expand source code
class CreativeFilters(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    accounts: Annotated[
        list[account_ref.AccountReference] | None,
        Field(
            description='Filter creatives by owning accounts. Useful for agencies managing multiple client accounts.',
            min_length=1,
        ),
    ] = None
    statuses: Annotated[
        list[creative_status.CreativeStatus] | None,
        Field(description='Filter by creative approval statuses', min_length=1),
    ] = None
    tags: Annotated[
        list[str] | None,
        Field(description='Filter by creative tags (all tags must match)', min_length=1),
    ] = None
    tags_any: Annotated[
        list[str] | None,
        Field(description='Filter by creative tags (any tag must match)', min_length=1),
    ] = None
    name_contains: Annotated[
        str | None,
        Field(description='Filter by creative names containing this text (case-insensitive)'),
    ] = None
    creative_ids: Annotated[
        list[str] | None,
        Field(description='Filter by specific creative IDs', max_length=100, min_length=1),
    ] = None
    created_after: Annotated[
        AwareDatetime | None,
        Field(description='Filter creatives created after this date (ISO 8601)'),
    ] = None
    created_before: Annotated[
        AwareDatetime | None,
        Field(description='Filter creatives created before this date (ISO 8601)'),
    ] = None
    updated_after: Annotated[
        AwareDatetime | None,
        Field(description='Filter creatives last updated after this date (ISO 8601)'),
    ] = None
    updated_before: Annotated[
        AwareDatetime | None,
        Field(description='Filter creatives last updated before this date (ISO 8601)'),
    ] = None
    assigned_to_packages: Annotated[
        list[str] | None,
        Field(
            description='Filter creatives assigned to any of these packages. Sales-agent-specific — standalone creative agents SHOULD ignore this filter.',
            min_length=1,
        ),
    ] = None
    media_buy_ids: Annotated[
        list[str] | None,
        Field(
            description='Filter creatives assigned to any of these media buys. Sales-agent-specific — standalone creative agents SHOULD ignore this filter.',
            min_length=1,
        ),
    ] = None
    unassigned: Annotated[
        bool | None,
        Field(
            description='Filter for unassigned creatives when true, assigned creatives when false. Sales-agent-specific — standalone creative agents SHOULD ignore this filter.'
        ),
    ] = None
    has_served: Annotated[
        bool | None,
        Field(
            description='When true, return only creatives that have served at least one impression. When false, return only creatives that have never served.'
        ),
    ] = None
    indicator_types: Annotated[
        list[indicator_type.IndicatorType] | None,
        Field(
            description='Return creatives with at least one package assignment carrying any requested current indicator type. Values within this field use OR logic; this field composes with other filters using AND logic. Sales-agent-specific: sellers support this filter only when media_buy.relationship_notifications.projection_tasks includes list_creatives. Other agents SHOULD ignore it and apply remaining filters. Buyers needing exact results MUST verify capability support and paginate the outer result set; assignment_projection: matching bounds nested rows.',
            min_length=1,
        ),
    ] = None
    concept_ids: Annotated[
        list[str] | None,
        Field(
            description='Filter by creative concept IDs. Concepts group related creatives across sizes and formats (e.g., Flashtalking concepts, Celtra campaign folders, CM360 creative groups).',
            min_length=1,
        ),
    ] = None
    format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='Deprecated in AdCP 3.2; removed in AdCP 4.0. Filter legacy named-format creatives. Use `format_kinds` for canonical libraries.',
            min_length=1,
        ),
    ] = None
    format_kinds: Annotated[
        list[canonical_format_kind.CanonicalFormatKind] | None,
        Field(
            description='Filter by canonical format kinds. Returns creatives matching any supplied kind.',
            min_length=1,
        ),
    ] = None
    asset_types: Annotated[
        list[asset_content_type.AssetContentType] | None,
        Field(
            description="Filter by asset types present on direct object values in the creative's top-level `assets` map. A creative matches when any directly assigned object has an `asset_type` in this array (OR within this field); this filter is conjunctive with every other active filter (AND across fields). Do not inspect array-valued slots or recurse into nested asset fields such as `cards[].media`; broader traversal is deferred. Agents that do not implement this filter MUST ignore it and apply the remaining filters rather than reject the request. Exact asset-type values use the shared AssetContentType vocabulary; `published_post` selects existing-published-post reference creatives without relying on publisher-specific format IDs.",
            min_length=1,
        ),
    ] = None
    has_variables: Annotated[
        bool | None,
        Field(
            description='When true, return only creatives with dynamic variables (DCO). When false, return only static creatives.'
        ),
    ] = None
    ext: Annotated[
        ext_1.ExtensionObject | None,
        Field(
            description='Vendor-namespaced extension parameters for seller- or platform-specific creative filter criteria not covered by standard fields. Keys MUST be namespaced under a vendor or platform key (e.g., ext.gam, ext.platform_x). Sellers MUST treat all values as untrusted buyer input; avoid unbounded logging or labels, and do not interpolate values into caller-visible error strings, LLM prompts, SQL queries, or system commands without sanitization. Persistent use of an extension key across multiple buyers is a signal to propose standardization.'
        ),
    ] = 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 accounts : list[adcp.types.generated_poc.core.account_ref.AccountReference] | None
var asset_types : list[adcp.types.generated_poc.enums.asset_content_type.AssetContentType] | None
var assigned_to_packages : list[str] | None
var concept_ids : list[str] | None
var created_after : pydantic.types.AwareDatetime | None
var created_before : pydantic.types.AwareDatetime | None
var creative_ids : list[str] | 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_kinds : list[adcp.types.generated_poc.core.canonical_format_kind.CanonicalFormatKind] | None
var has_served : bool | None
var has_variables : bool | None
var indicator_types : list[adcp.types.generated_poc.enums.indicator_type.IndicatorType] | None
var media_buy_ids : list[str] | None
var model_config
var name_contains : str | None
var statuses : list[adcp.types.generated_poc.enums.creative_status.CreativeStatus] | None
var tags : list[str] | None
var tags_any : list[str] | None
var unassigned : bool | None
var updated_after : pydantic.types.AwareDatetime | None
var updated_before : pydantic.types.AwareDatetime | None

Inherited members

class LegacyFormat (**data: Any)
Expand source code
class Format(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    format_id: Annotated[
        format_id_1.FormatReferenceStructuredObject,
        Field(
            description="This format's own identifier — a structured object {agent_url, id}, not a string. See /schemas/core/format-id.json for the full shape."
        ),
    ]
    name: Annotated[str, Field(description='Human-readable format name')]
    description: Annotated[
        str | None,
        Field(
            description='Plain text explanation of what this format does and what assets it requires'
        ),
    ] = None
    example_url: Annotated[
        AnyUrl | None,
        Field(
            description='Optional URL to showcase page with examples and interactive demos of this format'
        ),
    ] = None
    accepts_parameters: Annotated[
        list[format_id_parameter.FormatIdParameter] | None,
        Field(
            description='List of parameters this format accepts in format_id. Template formats define which parameters (dimensions, duration, etc.) can be specified when instantiating the format. Empty or omitted means this is a concrete format with fixed parameters.'
        ),
    ] = None
    renders: Annotated[
        list[Renders | Renders1] | None,
        Field(
            description='Specification of rendered pieces for this format. Most formats produce a single render. Companion ad formats (video + banner), adaptive formats, and multi-placement formats produce multiple renders. Each render specifies its role and dimensions.',
            min_length=1,
        ),
    ] = None
    assets: Annotated[
        list[
            Assets
            | Assets11
            | Assets12
            | Assets13
            | Assets14
            | Assets15
            | Assets16
            | Assets17
            | Assets18
            | Assets19
            | Assets20
            | Assets21
            | Assets22
            | Assets23
            | Assets24
            | Assets25
        ]
        | None,
        Field(
            description="Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory."
        ),
    ] = None
    delivery: Annotated[
        dict[str, Any] | None,
        Field(description='Delivery method specifications (e.g., hosted, VAST, third-party tags)'),
    ] = None
    supported_macros: Annotated[
        list[universal_macro.UniversalMacro | str] | None,
        Field(
            description='List of universal macros supported by this format (e.g., MEDIA_BUY_ID, CACHEBUSTER, DEVICE_ID). Used for validation and developer tooling. See docs/creative/universal-macros.mdx for full documentation.'
        ),
    ] = None
    input_format_ids: Annotated[
        list[format_id_1.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='**DEPRECATED in 3.1. Removed at 4.0.** Use `list_transformers` instead — a transformer declares its own `input_format_ids`/`output_format_ids`, so build capability is a property of the transformer (the unit you select and that carries pricing), not a relationship hung on a format. Discover build capability via `list_transformers` (optionally filtered by `input_format_ids`/`output_format_ids`).\n\nMigration: sellers that expressed transform capability by hanging `input_format_ids` on a format SHOULD declare a transformer via `list_transformers` instead. Buyers SHOULD discover build capability via `list_transformers` rather than filtering formats.\n\n*Legacy behavior, retained for 3.1–3.x backward compatibility:* array of format IDs this format accepts as input creative manifests; when present, indicates this format can take existing creatives in these formats as input. SDKs reading 3.1 catalogs MUST continue to honor this field when present; 4.0+ SDKs MAY reject it. New code SHOULD NOT emit this field.',
        ),
    ] = None
    output_format_ids: Annotated[
        list[format_id_1.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='**DEPRECATED in 3.1. Removed at 4.0.** Use `list_transformers` instead — a transformer declares its own `output_format_ids`, so what a builder can produce is a property of the transformer, not a relationship hung on a format. Discover via `list_transformers`.\n\nMigration: sellers that expressed multi-output build capability (e.g. a multi-publisher template) by hanging `output_format_ids` on a format SHOULD declare a transformer via `list_transformers` instead.\n\n*Legacy behavior, retained for 3.1–3.x backward compatibility:* array of format IDs this format can produce as output; when present, indicates this format can build creatives in these output formats. SDKs reading 3.1 catalogs MUST continue to honor this field when present; 4.0+ SDKs MAY reject it. New code SHOULD NOT emit this field.',
        ),
    ] = None
    format_card: Annotated[
        FormatCard | None,
        Field(
            description='Optional standard visual card (300x400px) for displaying this format in user interfaces. Can be rendered via preview_creative or pre-generated.'
        ),
    ] = None
    accessibility: Annotated[
        Accessibility | None,
        Field(
            description='Accessibility posture of this format. Declares the WCAG conformance level that creatives produced by this format will meet.'
        ),
    ] = None
    supported_disclosure_positions: Annotated[
        list[disclosure_position.DisclosurePosition] | None,
        Field(
            description='Disclosure positions this format can render. Buyers use this to determine whether a format can satisfy their compliance requirements before submitting a creative. When omitted, the format makes no disclosure rendering guarantees — creative agents SHOULD treat this as incompatible with briefs that require specific disclosure positions. Values correspond to positions on creative-brief.json required_disclosures.',
            min_length=1,
        ),
    ] = None
    disclosure_capabilities: Annotated[
        list[DisclosureCapability] | None,
        Field(
            description='Structured disclosure capabilities per position with persistence modes. Declares which persistence behaviors each disclosure position supports, enabling persistence-aware matching against provenance render guidance and brief requirements. When present, supersedes supported_disclosure_positions for persistence-aware queries. The flat supported_disclosure_positions field is retained for backward compatibility. Each position MUST appear at most once; validators and agents SHOULD reject duplicates.',
            min_length=1,
        ),
    ] = None
    format_card_detailed: Annotated[
        FormatCardDetailed | None,
        Field(
            description='Optional detailed card with carousel and full specifications. Provides rich format documentation similar to ad spec pages.'
        ),
    ] = None
    reported_metrics: Annotated[
        list[available_metric.AvailableMetric] | None,
        Field(
            description='Metrics this format can produce in delivery reporting. Buyers receive the intersection of format reported_metrics and product available_metrics. If omitted, the format defers entirely to product-level metric declarations.',
            min_length=1,
        ),
    ] = None
    pricing_options: Annotated[
        list[vendor_pricing_option.VendorPricingOption] | None,
        Field(
            deprecated=True,
            description='**DEPRECATED in 3.1. Removed at 4.0.** Use `transformer.pricing_options` (via `list_transformers`) instead — pricing belongs on the transformer (the unit selected and billed), exactly as it belongs on a media-buy product. Once formats only describe output shape, format-level pricing is vestigial.\n\nMigration: transformation/generation agents that charged via `format.pricing_options` SHOULD move the same `vendor-pricing-option` entries onto the corresponding transformer. The applied option is echoed per-leaf on the build_creative response and reconciled via report_usage, unchanged.\n\n*Legacy behavior, retained for 3.1–3.x backward compatibility:* pricing options for this format, used by transformation/generation agents that charge per format adapted, per image generated, or per unit of work; present when the request included include_pricing=true and account. SDKs reading 3.1 catalogs MUST continue to honor this field when present; 4.0+ SDKs MAY reject it. New code SHOULD NOT emit this field.',
            min_length=1,
        ),
    ] = None
    canonical: Annotated[
        canonical_projection_ref.CanonicalProjectionReference | None,
        Field(
            description='Optional v2 canonical-projection annotation. Always an object — bare-string shorthand (`canonical: "image"`) is not supported; the minimal form is `canonical: { "kind": "image" }`. Carries `kind` (which canonical the v1 format projects to) plus optional `asset_source` and `slots_override` for cases where the v1 format\'s shape doesn\'t follow the canonical\'s defaults (e.g., generative entries whose input is `generation_prompt: text` instead of `image_main: image`).\n\nWhen set, SDKs use this annotation as the authoritative v1 → v2 mapping for this format, bypassing the [v1 canonical mapping registry](/schemas/registries/v1-canonical-mapping.json) lookup. Combined with the slot-level `asset_group_id` declarations on each `assets[i]` entry, a v1 format declaration with `canonical` set is fully self-describing for v1↔v2 translation.\n\nResolution order for SDK projection from v1 wire shape to v2 (per RFC #3305 amendment #3767):\n1. If this `canonical` field is set, use it (seller-declared, highest priority). Apply `asset_source` and `slots_override` from the projection ref when present; otherwise inherit the canonical\'s defaults.\n2. Else, look up `format_id` in the canonical mapping registry\'s `format_id_glob` entries.\n3. Else, attempt structural match against the registry\'s `structural` entries (asset types, slot shape, vast_versions, etc.).\n4. Else, fail closed: SDK MUST NOT emit `format_options` for products carrying this format. Surface `FORMAT_PROJECTION_FAILED` on the response `errors[]` suggesting the seller add an explicit `canonical` annotation or file a registry entry.\n\nWhen `canonical.kind` is `custom`, the seller MUST also declare `canonical_format_shape` and `canonical_format_schema` (parallel to ProductFormatDeclaration\'s `format_shape` and `format_schema`) so buyer SDKs can fetch the seller\'s custom format schema.\n\nSee `canonical-projection-ref.json` for full projection semantics and examples (default-slot case, generative case, brief-driven case).'
        ),
    ] = None
    canonical_parameters: Annotated[
        product_format_declaration.ProductFormatDeclaration | None,
        Field(
            deprecated=True,
            description="**DEPRECATED in 3.1. Removed at 4.0.** Use `v1_format_ref` on the v2 `ProductFormatDeclaration` instead — the seller authors a v2 declaration (in `Product.format_options` or `creative.supported_formats`) and links it back to this v1 format via `v1_format_ref: { agent_url, id }`. The directional link from v2 → v1 is the same fact as `canonical_parameters` without the parallel-shape drift surface (v1 file and `canonical_parameters` were two declarations of the same thing; hand-authored, drifting silently).\n\nMigration: every seller currently authoring `canonical_parameters` SHOULD migrate to authoring a v2 declaration on the corresponding product (or capability) with `v1_format_ref` pointing back at this v1 format. v1 files become pure v1 again — no v2-shape mirroring.\n\n*Legacy behavior, retained for 3.1–3.x backward compatibility:* When `canonical` is set, this field carries the full ProductFormatDeclaration that the SDK projects this v1 format into. The `format_kind` MUST equal the `canonical` field value (validators enforce). When set, this is the authoritative source for SDK v1→v2 projection — the registry's structural-match parameter inference is bypassed. SDKs reading 3.1 catalogs MUST continue to honor `canonical_parameters` when present; 4.0+ SDKs MAY reject the field. New code SHOULD NOT emit this field.\n\n**Drift contract (still normative while supported).** Hand-authored `canonical_parameters` MUST satisfy the *narrows* relation against this v1 format's `requirements` and `assets[*]` shape (see canonical-formats.mdx 'Narrows — formal definition'). SDKs that read this v1 file SHOULD lint-time check the equivalence at build/load and emit `FORMAT_PROJECTION_FAILED` if the two disagree.",
        ),
    ] = 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 accepts_parameters : list[adcp.types.generated_poc.enums.format_id_parameter.FormatIdParameter] | None
var accessibility : adcp.types.generated_poc.core.format.Accessibility | None
var assets : list[typing.Union[adcp.types.generated_poc.core.format.Assets, adcp.types.generated_poc.core.format.Assets11, adcp.types.generated_poc.core.format.Assets12, adcp.types.generated_poc.core.format.Assets13, adcp.types.generated_poc.core.format.Assets14, adcp.types.generated_poc.core.format.Assets15, adcp.types.generated_poc.core.format.Assets16, adcp.types.generated_poc.core.format.Assets17, adcp.types.generated_poc.core.format.Assets19, adcp.types.generated_poc.core.format.Assets20, adcp.types.generated_poc.core.format.Assets21, adcp.types.generated_poc.core.format.Assets22, adcp.types.generated_poc.core.format.Assets23, adcp.types.generated_poc.core.format.Assets24, adcp.types.generated_poc.core.format.Assets25, UnknownFormatAsset]] | None
var canonical : adcp.types.generated_poc.core.canonical_projection_ref.CanonicalProjectionReference | None
var delivery : dict[str, typing.Any] | None
var description : str | None
var disclosure_capabilities : list[adcp.types.generated_poc.core.format.DisclosureCapability] | None
var example_url : pydantic.networks.AnyUrl | None
var format_card : adcp.types.generated_poc.core.format.FormatCard | None
var format_card_detailed : adcp.types.generated_poc.core.format.FormatCardDetailed | None
var format_id : adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject
var model_config
var name : str
var renders : list[adcp.types.generated_poc.core.format.Renders | adcp.types.generated_poc.core.format.Renders1] | None
var reported_metrics : list[adcp.types.generated_poc.enums.available_metric.AvailableMetric] | None
var supported_disclosure_positions : list[adcp.types.generated_poc.enums.disclosure_position.DisclosurePosition] | None
var supported_macros : list[adcp.types.generated_poc.enums.universal_macro.UniversalMacro | str] | None

Instance variables

var canonical_parameters : adcp.types.generated_poc.core.product_format_declaration.ProductFormatDeclaration | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var input_format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var output_format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var pricing_options : list[adcp.types.generated_poc.core.vendor_pricing_option.VendorPricingOption] | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyGetCreativeDeliveryResponse (**data: Any)
Expand source code
class GetCreativeDeliveryResponse(AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account_id: Annotated[
        str | None,
        Field(
            description='Account identifier. Present when the response spans or is scoped to a specific account.'
        ),
    ] = None
    media_buy_id: Annotated[
        str | None,
        Field(
            description="Publisher's media buy identifier. Present when the request was scoped to a single media buy."
        ),
    ] = None
    currency: Annotated[
        str,
        Field(
            description="ISO 4217 currency code for monetary values in this response (e.g., 'USD', 'EUR')",
            pattern='^[A-Z]{3}$',
        ),
    ]
    reporting_period: Annotated[ReportingPeriod, Field(description='Date range for the report.')]
    creatives: Annotated[
        Sequence[Creative], Field(description='Creative delivery data with variant breakdowns')
    ]
    pagination: Annotated[
        Pagination | None,
        Field(
            description='Pagination information. Present when the request included pagination parameters. **Note:** `get_creative_delivery` uses page-based pagination (`limit`/`offset`) for historical reasons, distinct from the cursor-based [`PaginationResponse`](/schemas/v3/core/pagination-response.json) used by `list_*` tools. Field naming aligned with `PaginationResponse.total_count` in 3.1; the legacy `total` field is retained as a deprecated alias until 4.0. Sellers MUST populate both fields identically; buyers SHOULD prefer `total_count` (the canonical name) and ignore `total` if both are present.'
        ),
    ] = None
    errors: Annotated[
        list[error.Error] | None, Field(description='Task-specific errors and warnings')
    ] = 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 account_id : str | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creatives : Sequence[adcp.types.generated_poc.creative.get_creative_delivery_response.Creative]
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_id : str | None
var model_config
var pagination : adcp.types.generated_poc.creative.get_creative_delivery_response.Pagination | None
var reporting_period : adcp.types.generated_poc.creative.get_creative_delivery_response.ReportingPeriod

Inherited members

class LegacyGetMediaBuyDeliveryResponse (**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='Half-open date range for the report: start is inclusive and end is exclusive. 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

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyGetMediaBuysResponse (**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. A read may return media_buys plus nonfatal resource-state errors. If a pinned place target becomes unexecutable, sellers MUST include PLACE_TARGET_UNAVAILABLE with recovery=correctable, field pointing to the exact media_buys[N].packages[M].targeting_overlay.geo_places[_exclude][A].values[V] response path, and details containing media_buy_id, package_id, system, system_version, country, place_type, and value. The persisted target remains echoed until an intentional update replaces it.'
        ),
    ] = 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 LegacyGetProductsRequest (**data: Any)
Expand source code
class GetProductsRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    idempotency_key: Annotated[
        str | None,
        Field(
            description='Optional client-generated key for retry-safe use of the AdCP 3.x compatibility facade. New callers SHOULD use the compact 3.2 tasks; each stateful split task has its own idempotency identity, so callers MUST retry with the same tool name. Keys MUST be unique per seller and logical request.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ] = None
    buying_mode: Annotated[
        BuyingMode,
        Field(
            description="Declares buyer intent for this request. 'brief': publisher curates product recommendations from the provided brief. 'wholesale': buyer requests raw product inventory to apply their own audiences — brief must not be provided, and proposals are omitted. 'refine': iterate on products and proposals from a previous get_products response using the refine array of change requests. v3 clients MUST include buying_mode. Sellers receiving requests from pre-v3 clients without buying_mode SHOULD default to 'brief'. Timing semantics: 'wholesale' is a wholesale product feed read — sellers SHOULD return a synchronous response and MUST NOT route a 'wholesale' request through the async/Submitted arm; partial completion is signalled via the response's incomplete[] field (with optional estimated_wait), not via a task-handoff envelope. 'brief' and 'refine' MAY complete synchronously, or MAY return a Submitted envelope (see get-products-async-response-submitted.json) when curation requires upstream-system queries or HITL review the seller cannot complete inside time_budget. Buyers needing predictable fast wholesale product feed access MUST use 'wholesale'; buyers open to slower curation use 'brief' or 'refine'."
        ),
    ]
    brief: Annotated[
        str | None,
        Field(
            description="Natural language description of campaign requirements. Required when buying_mode is 'brief'. Must not be provided when buying_mode is 'wholesale' or 'refine'. Buyers SHOULD use structured fields for every requirement that can be expressed structurally, and reserve brief prose for goals, context, preferences, and requirements without a structured representation. Sellers MUST apply explicit hard requirements stated in the brief even when the buyer did not duplicate them in a structured field. When a seller translates hard prose into structured targeting that materially affects product eligibility, pricing, or forecasting, it MUST confirm that interpretation once in GetProductsResponse.targeting_resolution.brief_targeting; otherwise confirmation remains a best practice. If hard prose contradicts a structured field, sellers MUST reject the request with INVALID_REQUEST rather than choose one interpretation or return an unexplained empty result."
        ),
    ] = None
    refine: Annotated[
        list[Refine] | None,
        Field(
            description="Array of change requests for iterating on products and proposals from a previous get_products response. Each entry declares a scope (request, product, or proposal) and what the buyer is asking for. Only valid when buying_mode is 'refine'. The seller responds to each entry via refinement_applied in the response, matched by position.\n\nFinalize-exclusivity rule: if any entry has `action: 'finalize'`, ALL entries in the array MUST be proposal-scoped with `action: 'finalize'` — mixing finalize entries with `include`/`omit` entries or with request- / product-scoped entries MUST be rejected by the seller with `INVALID_REQUEST`. Finalize is a commit, not a refinement; the buyer expressing intent to commit means refinements have already converged. Buyers needing to refine AND commit in close succession sequence the calls: first a refine call (no finalize), then a finalize call against the resulting `proposal_id`(s).\n\nMulti-finalize semantics: multiple finalize entries against different `proposal_id` values in a single call are allowed and MUST be **atomic at the observation point** — sellers MUST NOT return a success response unless every named proposal has both completed and been persisted as committed. Pre-commit validation runs before any side-effects (inventory pull, terms lock, governance attestation); if any proposal fails validation, the seller MUST reject the entire call without committing any of the named proposals. There is no rollback operation in the spec — an `unfinalize` would itself be a new mutation surface; the atomicity guarantee runs entirely on the seller's pre-commit validation gate, not on post-commit reversal. Sellers that cannot guarantee atomic pre-commit validation MUST reject multi-finalize arrays with `MULTI_FINALIZE_UNSUPPORTED` (preferred — distinguishes seller-side capability gap from a malformed request) or `INVALID_REQUEST` (acceptable fallback for sellers on a pre-3.1 error catalog). If a mid-commit failure occurs *after* validation passed but before all proposals persist (e.g., a downstream ad server fails between commits one and two), the seller MUST return `INTERNAL_ERROR` with `refinement_applied[]` carrying per-position outcomes — the spec does NOT define a recovery path for this case, and buyers SHOULD treat the resulting state as undefined and re-read via `get_media_buys` / equivalent before retrying. Buyers MUST NOT assume multi-finalize support without a successful first attempt — there is no capability flag for this; the failure response is the discovery surface. Buyers whose intent specifically requires atomic commit (e.g., budget-shared proposals where one finalizing without the other is incoherent) MUST be prepared to abandon the intent if the seller returns `MULTI_FINALIZE_UNSUPPORTED` — there is no recovery for that loss of buyer intent beyond sequencing single-finalize calls and accepting the looser commit guarantee.",
            min_length=1,
        ),
    ] = None
    brand: Annotated[
        brand_ref.BrandReference | None,
        Field(
            description='Brand reference for product discovery context. Resolved to full brand identity at execution time.'
        ),
    ] = None
    catalog: Annotated[
        catalog_1.Catalog | None,
        Field(
            description='Catalog of items the buyer wants to promote. The seller matches catalog items against its inventory and returns products where matches exist. Supports all catalog types: a job catalog finds job ad products, a product catalog finds sponsored product slots. Reference a synced catalog by catalog_id, or provide inline items.'
        ),
    ] = None
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description="Account for product lookup. Returns products with pricing specific to this account's rate card."
        ),
    ] = None
    preferred_delivery_types: Annotated[
        list[delivery_type_1.DeliveryType] | None,
        Field(
            description='Delivery types the buyer prefers, in priority order. Unlike filters.delivery_type which excludes non-matching products, this signals preference for curation — the publisher may still include other delivery types when they match the brief well.',
            min_length=1,
        ),
    ] = None
    filters: Annotated[
        product_filters.ProductFilters | None,
        Field(
            description="Offer filters. Valid in brief, wholesale, and refine modes. In every mode, sellers MUST exclude products that do not satisfy them: brief controls curation, wholesale controls feed behavior, and refine controls iteration, but none changes filter semantics. On refine, presence is the complete replacement filter state; when omitted, each referenced product's bound discovery constraints remain in force. Targeting-like legacy fields remain accepted during migration but are deprecated in favor of targeting_overlay and required_overlay_support."
        ),
    ] = None
    targeting_overlay: Annotated[
        targeting.TargetingOverlay | None,
        Field(
            description="Concrete delivery constraints the buyer expects to carry into create_media_buy. Buyers SHOULD use this field instead of putting equivalent exact targeting only in brief prose. Sellers evaluate these constraints during discovery and scope returned pricing and forecasts to the effective targeting. If a product cannot honor the request exactly, the seller may omit it or return a request-scoped configured product with Product targeting_resolution modifications. Absence of Product targeting_resolution means exact acceptance of this structured overlay; it does not confirm how targeting in the brief was interpreted. On refine, presence is complete replacement state for returned configurations; when omitted, each referenced product's bound targeting remains in force."
        ),
    ] = None
    required_overlay_support: Annotated[
        targeting_overlay_requirements.TargetingOverlayRequirements | None,
        Field(
            description="Minimum product-scoped targeting dimensions the buyer must be able to set independently on packages later. This requests selectable capability, not current targeting values, value-specific availability or forecasts, and not one product per possible value. A requirement true matches support true or any valid support object; an object requirement matches support true or an object containing every requested boolean and requested array subset. Unrequested object fields and numeric limits do not participate. Missing or unknown requirement fields do not match. Seller limit fields are response-only and cannot be requested here. On refine, presence is complete replacement state; when omitted, each referenced product's bound future-support requirements remain in force."
        ),
    ] = None
    property_list: Annotated[
        property_list_ref.PropertyListReference | None,
        Field(
            deprecated=True,
            description='DEPRECATED discovery-only property filter. Use targeting_overlay.property_list when the list is a concrete delivery constraint, or required_overlay_support.property_list when the list will be supplied later.',
        ),
    ] = None
    fields: Annotated[
        list[Field1] | None,
        Field(
            description='Specific product fields to include in the response. When omitted, all fields are returned. Use for lightweight discovery calls where only a subset of product data is needed. product_id and name are always included. `format_ids` is a deprecated 3.x compatibility projection; new integrations request canonical `format_options`. Safety-critical request-specific fields override projection: Product.targeting_resolution and expires_at MUST be included whenever the seller returns modifications, overlay_support MUST be included when required_overlay_support was requested, and audience_evidence_selections MUST be included when filters.audience_evidence_requirements affects eligibility or ranking. fields controls the optional audience_evidence payload, not the evidence decision receipt. Response-level brief targeting confirmation is not a projected product field.',
            min_length=1,
        ),
    ] = None
    time_budget: Annotated[
        duration.Duration | None,
        Field(
            description='Maximum time the buyer will commit to this request. The seller returns the best results achievable within this budget and does not start processes (human approvals, expensive external queries) that cannot complete in time. When omitted, the seller decides timing.'
        ),
    ] = None
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Optional webhook configuration for async terminal completion/failure notifications on curated discovery. Meaningful only for `buying_mode: "brief"` and `buying_mode: "refine"` requests that enter the async lifecycle. Submitted envelopes with `task_id` remain pollable through `get_task_status` (legacy `tasks/get`) whether or not this field is present. If a brief/refine request includes this field and the seller returns a Submitted envelope, the seller MUST deliver at least the terminal completion/failure notification to the configured URL; intermediate progress notifications are MAY. If the seller cannot honor the webhook channel, it MUST reject the request with a structured error instead of silently accepting. This field does not change wholesale timing semantics: sellers MUST NOT route `buying_mode: "wholesale"` requests through the async/Submitted arm or emit async delivery solely because `push_notification_config` is present; partial wholesale completion is reported via `incomplete[]`.'
        ),
    ] = None
    pagination: Annotated[
        pagination_request.PaginationRequest | None,
        Field(
            description="Cursor-based pagination controls for get_products. Valid in all buying modes. In brief mode, pagination bounds the seller's returned products[] for the curated answer to the brief and is not an exhaustive catalog-enumeration contract. In refine mode, pagination bounds the refined products[] result implied by refine[] and filters; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope. In wholesale mode, pagination walks the wholesale product feed and may be combined with wholesale feed versioning."
        ),
    ] = None
    if_wholesale_feed_version: Annotated[
        str | None,
        Field(
            description="Opaque wholesale_feed_version token returned by a prior wholesale-mode get_products response from this agent. Only valid when buying_mode is wholesale. When provided, the seller compares against its current wholesale product feed version for the buyer's cache_scope and MAY return an unchanged: true response (with products omitted) if nothing has changed. The token is scope-keyed: buyers cache `(cache_scope, wholesale_feed_version)` pairs. Scoping dimensions: (agent, buying_mode, filters, targeting_overlay, required_overlay_support, deprecated property_list, catalog) for cache_scope: 'public'; that tuple plus account identity for cache_scope: 'account'. pagination.cursor is NOT part of the scoping tuple. Backward-compatible: pre-v3.1 agents that ignore this field simply return the full payload, same as the unchanged-server path. See specs/wholesale-feed-webhooks.md for the full sync pattern."
        ),
    ] = None
    if_pricing_version: Annotated[
        str | None,
        Field(
            description="Opaque pricing_version token from a prior get_products response. MUST only be sent together with if_wholesale_feed_version — pricing version has no structural baseline to compare against on its own. Evaluation order: (1) if_wholesale_feed_version mismatch → seller returns the full payload (pricing is implicitly stale); (2) if_wholesale_feed_version matches but if_pricing_version mismatches → seller returns the full payload so the buyer sees updated pricing_options; (3) both match → seller MAY return unchanged: true. Agents that don't track pricing separately ignore if_pricing_version and fall back to if_wholesale_feed_version semantics. Useful for storefronts that re-price compositions far more often than they re-render product mirrors."
        ),
    ] = None
    context: context_1.ContextObject | None = None
    required_policies: Annotated[
        list[str] | None,
        Field(
            description='Registry policy IDs that the buyer requires to be enforced for products in this response. Sellers filter products to only those that comply with or already enforce the requested policies.'
        ),
    ] = 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 brand : adcp.types.generated_poc.core.brand_ref.BrandReference | None
var brief : str | None
var buying_mode : adcp.types.generated_poc.media_buy.get_products_request.BuyingMode | None
var catalog : adcp.types.generated_poc.core.catalog.Catalog | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var fields : list[adcp.types.generated_poc.media_buy.get_products_request.Field1] | None
var filters : adcp.types.generated_poc.core.product_filters.ProductFilters | None
var idempotency_key : str | None
var if_pricing_version : str | None
var if_wholesale_feed_version : str | None
var model_config
var pagination : adcp.types.generated_poc.core.pagination_request.PaginationRequest | None
var preferred_delivery_types : list[adcp.types.generated_poc.enums.delivery_type.DeliveryType] | None
var push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | None
var refine : list[adcp.types.generated_poc.media_buy.get_products_request.Refine] | None
var required_overlay_support : adcp.types.generated_poc.core.targeting_overlay_requirements.TargetingOverlayRequirements | None
var required_policies : list[str] | None
var targeting_overlay : adcp.types.generated_poc.core.targeting.TargetingOverlay | None
var time_budget : adcp.types.generated_poc.core.duration.Duration | None

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var property_list : adcp.types.generated_poc.core.property_list_ref.PropertyListReference | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyGetProductsResponse (**data: Any)
Expand source code
class GetProductsResponse(AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    products: Annotated[
        list[product.Product] | None, Field(description='Array of matching products')
    ] = None
    targeting_resolution: Annotated[
        get_products_targeting_resolution.ProductDiscoveryTargetingResolution | None,
        Field(
            description='Request-level confirmation of structured hard targeting inferred from the brief. Sellers MUST include this when their structured interpretation of hard prose materially affects product eligibility, pricing, or forecasting; otherwise inclusion is a best practice. Omitted when no hard targeting was inferred from the brief.'
        ),
    ] = None
    extensions: Annotated[
        dict[Annotated[str, StringConstraints(pattern=r'^https?://[^@]+@sha256:[a-f0-9]{64}$')], Extensions] | None,
        Field(
            description='Bundled platform-extension definitions referenced by any product in `products`. Keyed by `<extension_uri>@<digest>` (e.g., `https://creative.adcontextprotocol.org/translated/meta/extensions/meta_pixel@sha256:abc...`). When present, lets buyers resolve `platform_extensions` references on product format declarations without a separate fetch. Buyer SDKs cache by URI@digest; subsequent get_products responses MAY omit definitions the buyer already has cached and rely on the digest match. Each value is an extension definition with `extends` (the canonical concept it extends, e.g., `tracking`), `fields` (the schema for additional fields the extension contributes), `version`, and optional `description`.'
        ),
    ] = None
    proposals: Annotated[
        list[proposal.Proposal] | None,
        Field(
            description='Optional array of proposed media plans with budget allocations across products. Publishers include proposals when they can provide strategic guidance based on the brief. Proposals are actionable - buyers can refine them via follow-up get_products calls within the same session, or execute them directly via create_media_buy.'
        ),
    ] = None
    errors: Annotated[
        list[error.Error] | None,
        Field(description='Task-specific errors and warnings (e.g., product filtering issues)'),
    ] = None
    reason: Annotated[
        str | None,
        Field(
            description='Buyer-facing market explanation required only on the GetProductsRejected arm. MAY be sanitized to protect confidential seller rules. Plain text only.',
            max_length=2000,
            min_length=1,
        ),
    ] = None
    suggestions: Annotated[
        list[Suggestion] | None,
        Field(
            description='Actionable alternatives available only on the GetProductsRejected arm.',
            max_length=20,
        ),
    ] = None
    property_list_applied: Annotated[
        bool | None,
        Field(
            description='[AdCP 3.0] Indicates whether property_list filtering was applied. True if the agent filtered products based on the provided property_list. Absent or false if property_list was not provided or not supported by this agent.'
        ),
    ] = None
    catalog_applied: Annotated[
        bool | None,
        Field(
            description='Whether the seller filtered results based on the provided catalog. True if the seller matched catalog items against its inventory. Absent or false if no catalog was provided or the seller does not support catalog matching.'
        ),
    ] = None
    refinement_applied: Annotated[
        list[RefinementApplied] | None,
        Field(
            description="Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'. Each entry MUST echo the request entry's scope and — for product and proposal scopes — the matching id field (product_id or proposal_id), so orchestrators can cross-validate alignment."
        ),
    ] = None
    incomplete: Annotated[
        list[IncompleteItem] | None,
        Field(
            description="Declares what the seller could not finish within the buyer's time_budget or due to internal limits while still returning a usable response. Each entry identifies a scope that is missing or partial. Absent when the response is fully complete. This field does not classify the condition as retryable; retryability is carried by error.recovery on the error channel.",
            min_length=1,
        ),
    ] = None
    filter_diagnostics: Annotated[
        FilterDiagnostics | None,
        Field(
            description="Optional non-fatal diagnostic block describing how the request's `filters` narrowed the candidate set. Use this to disambiguate empty/small result lists between 'no inventory matches the brief' and 'a specific filter excluded everything', without breaking the filter-not-fail convention (sellers still silently exclude unmatched products; this block is observability, not error reporting). Sellers MAY populate this when meaningful narrowing occurred; buyers MAY use it for triage UX without depending on its presence. Counts only — products are not enumerated by name to avoid leaking competitive intelligence about adjacent campaigns or seller inventory. `total_candidates` and `excluded_by` are independently optional — sellers whose baseline candidate set size is sensitive MAY emit `excluded_by` without `total_candidates`, or vice versa.",
            examples=[
                {
                    'semantics': 'only',
                    'total_candidates': 47,
                    'excluded_by': {
                        'required_metrics': {'count': 31, 'values': ['completed_views']},
                        'required_geo_targeting': {'count': 9},
                        'pricing_currencies': {'count': 3, 'values': ['USD']},
                        'budget_range': {'count': 7},
                    },
                }
            ],
        ),
    ] = None
    pagination: Annotated[
        pagination_response.PaginationResponse | None,
        Field(
            description="Cursor metadata for paginated get_products responses. In brief/refine mode, continuation pages bound returned products[] for the seller's curated or refined answer; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope, and pagination does not convert the response into an exhaustive feed contract. In wholesale mode, continuation pages walk the wholesale product feed."
        ),
    ] = None
    wholesale_feed_version: Annotated[
        str | None,
        Field(
            description="Opaque token representing the version of the wholesale product feed state used to compose this response. Sellers that implement conditional-fetch (if_wholesale_feed_version) MUST return this on every wholesale-mode response so buyers can cache and probe later. Buyers MUST treat the value as opaque — no format, no ordering, no inspection. The token is scope-keyed: it describes a version for the cache_scope declared on this response, NOT a global agent version. A buyer caches `(cache_scope, wholesale_feed_version)` pairs and presents the matching token on the next request. Scoping dimensions: (agent, buying_mode, filters, targeting_overlay, required_overlay_support, deprecated property_list, catalog) for cache_scope: 'public'; that tuple plus account_id for cache_scope: 'account'. pagination.cursor is NOT part of the scoping tuple. See specs/wholesale-feed-webhooks.md for the full cache layering model."
        ),
    ] = None
    pricing_version: Annotated[
        str | None,
        Field(
            description='Opaque token representing the version of the pricing layer, including product pricing_options and nested signal_targeting_options pricing_options. When the seller supports independent pricing versioning, pricing_version changes when prices move but wholesale_feed_version changes only when structure/metadata moves. Same cache_scope keying as wholesale_feed_version. Sellers not separating these MAY omit pricing_version and use wholesale_feed_version for both.'
        ),
    ] = None
    cache_scope: Annotated[
        CacheScope | None,
        Field(
            description="Declares whether the wholesale_feed_version and pricing_version on this response describe a universal layer or an account-specific overlay. REQUIRED on every 3.1+ response (the 3.1 schema enforces this — the safety property of the two-layer cache model depends on it). 'public': this response describes the seller's published rate card; the buyer MAY dedupe under (agent, buying_mode, filters, targeting_overlay, required_overlay_support, deprecated property_list, catalog) without scoping by account. 'account': this response includes account-specific overrides; the buyer MUST cache the version under (agent, buying_mode, filters, targeting_overlay, required_overlay_support, deprecated property_list, catalog, account_id). When the request did NOT include `account`, the seller MUST return `cache_scope: 'public'`. When the request included `account`, the seller MUST return either: 'public' (this account prices off the public rate card — buyer dedupes) or 'account' (account-specific overrides exist — buyer caches under the account key). Sellers MAY return 'public' on an account-scoped request that previously had overrides — buyers SHOULD interpret this as a downgrade and drop their account-overlay for the (agent, filters, targeting, support, mode) tuple. Without schema-required cache_scope, a seller silently omitting the field on an account-scoped response would cause buyers to mis-key the cache and serve account-overlay payloads to other accounts — the canonical safety invariant of the entire cache layering model. **Backward-compatibility note for 3.1 validators:** SDKs that validate strictly against the 3.1 schema MUST select the validator based on the server-declared `adcp_version` (release-precision version negotiation, 3.1). For responses with `adcp_version` starting `3.0`, the 3.1 cache_scope-required constraint MUST be relaxed — pre-3.1 sellers correctly emit no cache_scope and remain conformant to their declared version. This is a tightening within 3.1, not a 3.0 break."
        ),
    ] = CacheScope.public
    unchanged: Annotated[
        Literal[True] | None,
        Field(
            description="Present and `true` ONLY on wholesale-mode responses when the request carried if_wholesale_feed_version (and/or if_pricing_version) matching the seller's current version for the buyer's cache_scope, in which case products[] MUST be omitted; wholesale_feed_version (echoed), cache_scope (echoed), and pricing_version (echoed when used) MUST still be present. Buyers receiving unchanged: true MUST NOT mutate their local wholesale product mirror. **One shape per state:** sellers MUST NOT emit `unchanged: false` — the absence of the field IS the signal that the response carries products. Two shapes ({ unchanged: false, products: [...] } vs. { products: [...] }) for the same state would let some sellers always emit the field and some never would, creating an inconsistency the wire shouldn't carry. **Cross-scope isolation:** the comparator that decides `unchanged` MUST be keyed on `(cache_scope, wholesale_feed_version)`, not on the token value alone. A seller MUST NOT emit `unchanged: true` when it resolves the request to a different `cache_scope` than the one whose token the buyer echoed in `if_wholesale_feed_version` (and/or `if_pricing_version`): because the token is scope-keyed, a value minted for `cache_scope: 'public'` cannot match the seller's current token for `cache_scope: 'account'` (or vice-versa), so such a request MUST return the full feed for the resolved scope with that scope's own token."
        ),
    ] = 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 cache_scope : adcp.types.generated_poc.media_buy.get_products_response.CacheScope | None
var catalog_applied : bool | None
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 extensions : dict[str, adcp.types.generated_poc.media_buy.get_products_response.Extensions] | None
var filter_diagnostics : adcp.types.generated_poc.media_buy.get_products_response.FilterDiagnostics | None
var incomplete : list[adcp.types.generated_poc.media_buy.get_products_response.IncompleteItem] | None
var model_config
var pagination : adcp.types.generated_poc.core.pagination_response.PaginationResponse | None
var pricing_version : str | None
var products : list[adcp.types.generated_poc.core.product.Product] | None
var property_list_applied : bool | None
var proposals : list[adcp.types.generated_poc.core.proposal.Proposal] | None
var reason : str | None
var refinement_applied : list[adcp.types.generated_poc.media_buy.get_products_response.RefinementApplied] | None
var sandbox : bool | None
var status : adcp.types.generated_poc.enums.task_status.TaskStatus | None
var suggestions : list[adcp.types.generated_poc.media_buy.get_products_response.Suggestion] | None
var targeting_resolution : adcp.types.generated_poc.media_buy.get_products_targeting_resolution.ProductDiscoveryTargetingResolution | None
var unchanged : Literal[True] | None
var wholesale_feed_version : str | None

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyFormatId (**data: Any)
Expand source code
class LegacyFormatId(FormatReferenceStructuredObject):
    """Legacy tuple that validates a URL without rewriting its wire spelling."""

    model_config = ConfigDict(extra="allow")

    # A wire-preserving string intentionally narrows the generated AnyUrl
    # field: AnyUrl appends a slash and changes the normative legacy tuple.
    agent_url: str  # type: ignore[assignment]
    id: Annotated[str, Field(pattern=r"^[a-zA-Z0-9_-]+$")]
    width: Annotated[StrictInt | None, Field(ge=1)] = None
    height: Annotated[StrictInt | None, Field(ge=1)] = None
    duration_ms: Annotated[StrictInt | StrictFloat | None, Field(ge=1)] = None

    @field_validator("agent_url")
    @classmethod
    def _validate_agent_url(cls, value: str) -> str:
        _URL_ADAPTER.validate_python(value)
        return value

    def model_dump(self, **kwargs: Any) -> dict[str, Any]:
        """Preserve the original agent_url bytes in explicit legacy output."""

        return super().model_dump(**kwargs)

Legacy tuple that validates a URL without rewriting its wire spelling.

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.format_id.FormatReferenceStructuredObject
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var agent_url : str
var duration_ms : int | float | None
var height : int | None
var id : str
var model_config
var width : int | None

Methods

def model_dump(self, **kwargs: Any) ‑> dict[str, typing.Any]
Expand source code
def model_dump(self, **kwargs: Any) -> dict[str, Any]:
    """Preserve the original agent_url bytes in explicit legacy output."""

    return super().model_dump(**kwargs)

Preserve the original agent_url bytes in explicit legacy output.

class LegacyFormatReferenceStructuredObject (**data: Any)
Expand source code
class LegacyFormatId(FormatReferenceStructuredObject):
    """Legacy tuple that validates a URL without rewriting its wire spelling."""

    model_config = ConfigDict(extra="allow")

    # A wire-preserving string intentionally narrows the generated AnyUrl
    # field: AnyUrl appends a slash and changes the normative legacy tuple.
    agent_url: str  # type: ignore[assignment]
    id: Annotated[str, Field(pattern=r"^[a-zA-Z0-9_-]+$")]
    width: Annotated[StrictInt | None, Field(ge=1)] = None
    height: Annotated[StrictInt | None, Field(ge=1)] = None
    duration_ms: Annotated[StrictInt | StrictFloat | None, Field(ge=1)] = None

    @field_validator("agent_url")
    @classmethod
    def _validate_agent_url(cls, value: str) -> str:
        _URL_ADAPTER.validate_python(value)
        return value

    def model_dump(self, **kwargs: Any) -> dict[str, Any]:
        """Preserve the original agent_url bytes in explicit legacy output."""

        return super().model_dump(**kwargs)

Legacy tuple that validates a URL without rewriting its wire spelling.

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.format_id.FormatReferenceStructuredObject
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var agent_url : str
var duration_ms : int | float | None
var height : int | None
var id : str
var model_config
var width : int | None

Methods

def model_dump(self, **kwargs: Any) ‑> dict[str, typing.Any]
Expand source code
def model_dump(self, **kwargs: Any) -> dict[str, Any]:
    """Preserve the original agent_url bytes in explicit legacy output."""

    return super().model_dump(**kwargs)

Preserve the original agent_url bytes in explicit legacy output.

Inherited members

class LegacyListCreativeFormatsRequest (**data: Any)
Expand source code
class ListCreativeFormatsRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='Deprecated in AdCP 3.2; removed in AdCP 4.0. Return only these specific named-format IDs (for example, from a 3.x get_products response). Use canonical-format discovery in 4.0.',
            min_length=1,
        ),
    ] = None
    asset_types: Annotated[
        list[asset_content_type.AssetContentType] | None,
        Field(
            description="Filter to formats that include these asset types. For third-party tags, search for 'html' or 'javascript'. For published-post reference formats, search for 'published_post'. E.g., ['image', 'text'] returns formats with images and text, ['javascript'] returns formats accepting JavaScript tags.",
            min_length=1,
        ),
    ] = None
    max_width: Annotated[
        int | None,
        Field(
            description='Maximum width in pixels (inclusive). Returns formats where ANY render has width <= this value. For multi-render formats, matches if at least one render fits.'
        ),
    ] = None
    max_height: Annotated[
        int | None,
        Field(
            description='Maximum height in pixels (inclusive). Returns formats where ANY render has height <= this value. For multi-render formats, matches if at least one render fits.'
        ),
    ] = None
    min_width: Annotated[
        int | None,
        Field(
            description='Minimum width in pixels (inclusive). Returns formats where ANY render has width >= this value.'
        ),
    ] = None
    min_height: Annotated[
        int | None,
        Field(
            description='Minimum height in pixels (inclusive). Returns formats where ANY render has height >= this value.'
        ),
    ] = None
    is_responsive: Annotated[
        bool | None,
        Field(
            description='Filter for responsive formats that adapt to container size. When true, returns formats without fixed dimensions.'
        ),
    ] = None
    name_search: Annotated[
        str | None, Field(description='Search for formats by name (case-insensitive partial match)')
    ] = None
    publisher_domain: Annotated[
        str | None,
        Field(
            deprecated=True,
            description="Deprecated compatibility filter for older 3.x callers. A compatibility implementation MAY project publisher-origin or community-catalog declarations obtained through the registry publisher lookup, but MUST NOT synthesize a publisher catalog from seller products. New callers use `GET /api/registry/publisher?domain=...` for publisher acceptance and `get_products` for this seller's deliverability. The pattern below is a syntactic floor, not an SSRF guard.",
            pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$',
        ),
    ] = None
    property_id: Annotated[
        property_id_1.PropertyId | None,
        Field(
            description="Filter to formats supported on the named property within the publisher's catalog. Resolves to a property in the publisher's `adagents.json` `properties[]`; the agent returns only `formats[]` entries whose `applies_to_property_ids` includes this property (or entries with no scope, which apply to all properties). Typically used in combination with `publisher_domain`."
        ),
    ] = None
    wcag_level: Annotated[
        wcag_level_1.WcagLevel | None,
        Field(
            description='Filter to formats that meet at least this WCAG conformance level (A < AA < AAA)'
        ),
    ] = None
    disclosure_positions: Annotated[
        list[disclosure_position.DisclosurePosition] | None,
        Field(
            description="Filter to formats that support all of these disclosure positions. When a format has disclosure_capabilities, match against those positions. Otherwise fall back to supported_disclosure_positions. Use to find formats compatible with a brief's compliance requirements.",
            min_length=1,
        ),
    ] = None
    disclosure_persistence: Annotated[
        list[disclosure_persistence_1.DisclosurePersistence] | None,
        Field(
            description='Filter to formats where each requested persistence mode is supported by at least one position in disclosure_capabilities. Different positions may satisfy different modes. Use to find formats compatible with jurisdiction-specific persistence requirements (e.g., continuous for EU AI Act).',
            min_length=1,
        ),
    ] = None
    output_format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            description="Filter to formats whose output_format_ids includes any of these format IDs. Returns formats that can produce these outputs — inspect each result's input_format_ids to see what inputs they accept.",
            min_length=1,
        ),
    ] = None
    input_format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            description="Filter to formats whose input_format_ids includes any of these format IDs. Returns formats that accept these creatives as input — inspect each result's output_format_ids to see what they can produce.",
            min_length=1,
        ),
    ] = None
    pagination: pagination_request.PaginationRequest | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var asset_types : list[adcp.types.generated_poc.enums.asset_content_type.AssetContentType] | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var disclosure_persistence : list[adcp.types.generated_poc.enums.disclosure_persistence.DisclosurePersistence] | None
var disclosure_positions : list[adcp.types.generated_poc.enums.disclosure_position.DisclosurePosition] | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var input_format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var is_responsive : bool | None
var max_height : int | None
var max_width : int | None
var min_height : int | None
var min_width : int | None
var model_config
var output_format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var pagination : adcp.types.generated_poc.core.pagination_request.PaginationRequest | None
var property_id : adcp.types.generated_poc.core.property_id.PropertyId | None
var wcag_level : adcp.types.generated_poc.enums.wcag_level.WcagLevel | None

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var publisher_domain : str | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyListCreativeFormatsResponse (**data: Any)
Expand source code
class ListCreativeFormatsResponse(AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    formats: Annotated[
        list[format.Format],
        Field(
            deprecated=True,
            description="Deprecated named-format definitions projected for older 3.x callers. This list is neither the publisher acceptance catalog nor the seller's canonical product deliverability contract.",
        ),
    ]
    source: Annotated[
        Source | None,
        Field(
            deprecated=True,
            description='Deprecated compatibility provenance. `publisher` means publisher-origin catalog; `aao_mirror` means community catalog; `agent_derived` is retained only to parse historical 3.x responses and MUST NOT be produced by a new 3.2 implementation because seller products are not publisher authority.',
        ),
    ] = None
    creative_agents: Annotated[
        list[CreativeAgent] | None,
        Field(
            deprecated=True,
            description="Deprecated recursive discovery projection retained for historical 3.x responses. New buyers query the registry's canonical creative capability index and confirm candidates with get_adcp_capabilities; they do not recursively walk agent-provided lists.",
        ),
    ] = None
    errors: Annotated[
        list[error.Error] | None,
        Field(description='Task-specific errors and warnings (e.g., format availability issues)'),
    ] = None
    pagination: pagination_response.PaginationResponse | None = 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 model_config
var pagination : adcp.types.generated_poc.core.pagination_response.PaginationResponse | None
var sandbox : bool | None
var status : adcp.types.generated_poc.enums.task_status.TaskStatus | None

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var creative_agents : list[adcp.types.generated_poc.media_buy.list_creative_formats_response.CreativeAgent] | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var formats : list[adcp.types.generated_poc.core.format.Format]
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var source : adcp.types.generated_poc.media_buy.list_creative_formats_response.Source | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyListCreativesRequest (**data: Any)
Expand source code
class ListCreativesRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    filters: creative_filters.CreativeFilters | None = None
    sort: Annotated[Sort | None, Field(description='Sorting parameters')] = None
    pagination: pagination_request.PaginationRequest | None = None
    include_assignments: Annotated[
        bool | None, Field(description='Include package assignment information in response')
    ] = True
    assignment_projection: Annotated[
        AssignmentProjection | None,
        Field(
            description='Controls nested assigned_packages projection when assignments are included. all returns up to assignment_limit active assignments per creative. matching returns only assignments matching filters.indicator_types and requires that filter. Use matching for compact indicator discovery; get_media_buys remains the complete authoritative repair path when assignments_truncated is true.'
        ),
    ] = AssignmentProjection.all
    assignment_limit: Annotated[
        int | None,
        Field(
            description='Maximum assigned_packages rows returned per creative. Sellers MUST set assignments.assignments_truncated when additional qualifying rows exist.',
            ge=1,
            le=200,
        ),
    ] = 50
    include_snapshot: Annotated[
        bool | None,
        Field(
            description='Include a lightweight delivery snapshot per creative (lifetime impressions and last-served date). For detailed performance analytics, use get_creative_delivery.'
        ),
    ] = False
    include_items: Annotated[
        bool | None,
        Field(description='Include items for multi-asset formats like carousels and native ads'),
    ] = False
    include_variables: Annotated[
        bool | None,
        Field(
            description='Include dynamic content variable definitions (DCO slots) for each creative'
        ),
    ] = False
    include_pricing: Annotated[
        bool | None,
        Field(
            description='Include pricing_options on each creative. Requires account to be provided. When false or omitted, pricing is not computed.'
        ),
    ] = False
    include_purged: Annotated[
        bool | None,
        Field(
            description="Include soft-purged creative tombstones in the result set. When true, creatives destroyed via `creative.purged` with `purge_kind: soft` surface as tombstone records carrying `purged: true`, `purged_at`, and the purge reason — within the seller's webhook activity retention window (30 days from `purged_at`, MUST match `webhook-activity-record` retention). Hard-purged creatives MUST NOT appear regardless of this flag. When false or omitted, the result set excludes all purged creatives — same default as today."
        ),
    ] = False
    include_webhook_activity: Annotated[
        bool | None,
        Field(
            description='Include recent webhook activity per creative. When true, each returned creative carries a `webhook_activity[]` array of the most recent fires scoped to that creative — `creative.status_changed` and `creative.purged` deliveries. Adoption of the `webhook_activity[]` pattern per `snapshot-and-log.mdx § Webhook activity log pattern`. Retention is 30 days from `completed_at` (MUST). Three-state presence applies: omitted = seller does not surface; `[]` = persists but no recent fires; non-empty = actual records.'
        ),
    ] = False
    webhook_activity_limit: Annotated[
        int | None,
        Field(
            description="Maximum number of `webhook_activity[]` records to return per creative. Only meaningful when `include_webhook_activity: true`. Sellers MUST respect the cap; structural enforcement is provided by the response schema's `maxItems: 200` on the array.",
            ge=1,
            le=200,
        ),
    ] = 50
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description="Account reference for pricing and access. When provided with include_pricing, the agent returns pricing_options from this account's rate card on each creative."
        ),
    ] = None
    fields: Annotated[
        list[Field1] | None,
        Field(
            description="Specific fields to include in response (omit for all fields). The 'concept' value returns both concept_id and concept_name. `format_id` is a deprecated 3.x compatibility projection; new integrations request `format_kind` and `format_option_ref`. Selecting localization automatically includes creative_id, status, assets, the selected format identity, and localization_unavailable when applicable. Selecting rights_attestation_evaluations automatically includes rights so each seller-produced result can be reconciled with the exact retained constraint and reference.",
            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

  • 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 assignment_limit : int | None
var assignment_projection : adcp.types.generated_poc.creative.list_creatives_request.AssignmentProjection | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var fields : list[adcp.types.generated_poc.creative.list_creatives_request.Field1] | None
var filters : adcp.types.generated_poc.core.creative_filters.CreativeFilters | None
var include_assignments : bool | None
var include_items : bool | None
var include_pricing : bool | None
var include_purged : bool | None
var include_snapshot : bool | None
var include_variables : bool | None
var include_webhook_activity : bool | None
var model_config
var pagination : adcp.types.generated_poc.core.pagination_request.PaginationRequest | None
var sort : adcp.types.generated_poc.creative.list_creatives_request.Sort | None
var webhook_activity_limit : int | None

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyListCreativesResponse (**data: Any)
Expand source code
class ListCreativesResponse(AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    query_summary: Annotated[
        QuerySummary, Field(description='Summary of the query that was executed')
    ]
    pagination: pagination_response.PaginationResponse
    creatives: Annotated[
        Sequence[Creatives | Creatives1],
        Field(description='Array of creative assets matching the query'),
    ]
    format_summary: Annotated[
        dict[Annotated[str, StringConstraints(pattern=r'^[a-zA-Z0-9_-]+$')], int] | None,
        Field(
            description='Breakdown of creatives by canonical format kind. Keys SHOULD be `format_kind` values; an implementation may append a stable option suffix when separate product or publisher options must be distinguished.'
        ),
    ] = None
    status_summary: Annotated[
        StatusSummary | None, Field(description='Breakdown of creatives by status')
    ] = None
    errors: Annotated[
        list[error.Error] | None,
        Field(description='Task-specific errors (e.g., invalid filters, account not found)'),
    ] = 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 creatives : Sequence[adcp.types.generated_poc.creative.list_creatives_response.Creatives | adcp.types.generated_poc.creative.list_creatives_response.Creatives1]
var errors : list[adcp.types.generated_poc.core.error.Error] | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var format_summary : dict[str, int] | None
var model_config
var pagination : adcp.types.generated_poc.core.pagination_response.PaginationResponse
var query_summary : adcp.types.generated_poc.creative.list_creatives_response.QuerySummary
var sandbox : bool | None
var status : adcp.types.generated_poc.enums.task_status.TaskStatus | None
var status_summary : adcp.types.generated_poc.creative.list_creatives_response.StatusSummary | None

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyPackage (**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
    audience_evidence_selections: Annotated[
        list[audience_evidence_selection.AudienceEvidenceSelection] | None,
        Field(
            description='Exact immutable audience-evidence snapshots that affected recommendation, eligibility, or package construction. A confirmed package MUST include a package_construction selection matching every buyer audience_evidence_pin and every snapshot used to satisfy package audience_evidence_requirements; this readback remains mandatory on subsequent package read surfaces. This is decision provenance only; applied targeting remains exclusively in targeting_overlay and targeting_resolution.demographics.',
            min_length=1,
        ),
    ] = None
    budget: Annotated[
        float | None,
        Field(
            description='Hard lifetime spend cap for this package in the media-buy currency. Every selected pricing option in an AdCP-authored media buy MUST declare that same currency. In seller-optimized allocation mode this is a ceiling, not a current allocation. May be omitted when the package is bounded only by the shared media-buy total.',
            ge=0.0,
        ),
    ] = None
    min_spend_target: Annotated[
        float | None,
        Field(
            description='Soft lifetime spend target accepted for this package under seller-optimized budget allocation. This is an allocation preference, not a billing or delivery guarantee.',
            ge=0.0,
        ),
    ] = None
    daily_budget_cap: Annotated[
        float | None,
        Field(
            description="The hard package spend ceiling per shared media-buy cap day, in the media buy's currency. Sellers MUST echo this whenever a package daily cap is set. It is a subordinate ceiling, not a reserved or current allocation; the media buy's budget_cap_timezone defines its day boundary.",
            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(
            deprecated=True,
            description='DEPRECATED legacy bidding representation. 3.2 sellers normalize accepted legacy input and SHOULD echo bidding instead. Removed in the next major.',
            ge=0.0,
        ),
    ] = None
    bidding: Annotated[
        bidding_policy.BiddingPolicy | None,
        Field(
            description='Package-authored bidding policy, echoed only when the buyer authored a package override. `{automatic:true}` is an explicit automatic-bidding override. Omission means the package inherits media-buy bidding or, when both scopes are absent, uses provider automatic delivery. Monetary fields are denominated in the media-buy currency. Sellers MUST NOT materialize inherited media-buy policy here.'
        ),
    ] = 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(
            deprecated=True,
            description='Deprecated in AdCP 3.2; removed in AdCP 4.0. 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: Annotated[
        targeting.TargetingOverlay | None,
        Field(
            description='Complete effective targeting accepted for this package, including targeting bound through configured product selection plus package-specific targeting. Sellers MUST echo placement, property, and collection selection so buyers can audit purchased inventory.'
        ),
    ] = None
    targeting_resolution: Annotated[
        package_targeting_resolution.PackageTargetingResolution | None,
        Field(
            description="Execution details for the package's accepted targeting. Sellers MUST include targeting_resolution.demographics whenever demographic targeting was requested or applied."
        ),
    ] = 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, including the committed package-scoped rotation policy. Omitted rotation_mode reads as weighted for backward compatibility; all assignments resolve to one effective mode, and sequential positions are unique within each package-local group.'
        ),
    ] = None
    formats_to_provide: Annotated[
        list[product_format_declaration.ProductFormatDeclaration] | None,
        Field(
            description='Canonical creative contracts that the buyer must satisfy for this package. Each entry is a package-time snapshot of a selected Product.format_options declaration (or the equivalent declaration normalized from a direct format_kind + params selector) and MUST equal or narrow that product contract. Full declarations keep the requirement stable if the live product or publisher catalog later changes and remain usable when format_option_id is absent. Sellers SHOULD emit this field whenever additional creative coverage is required.',
            min_length=1,
        ),
    ] = None
    formats_pending: Annotated[
        list[product_format_declaration.ProductFormatDeclaration] | None,
        Field(
            description='The declarations from formats_to_provide that do not yet have creative coverage through sync_creatives or inline creative assignment. An empty emitted array means every required format is covered. Absence means readiness was not reported, so buyers MUST NOT infer full coverage from omission. Sellers SHOULD emit this field with formats_to_provide when returning current package readiness.'
        ),
    ] = None
    format_ids_to_provide: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='**DEPRECATED in 3.2.** Legacy named-format projection of formats_to_provide retained for older 3.x peers. New sellers emit canonical formats_to_provide declarations.',
        ),
    ] = None
    format_ids_pending: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='**DEPRECATED in 3.2.** Legacy named-format projection of formats_pending retained for older 3.x peers. New sellers emit canonical formats_pending declarations. An empty emitted array means every projected requirement is covered. Absence means legacy readiness was not reported and MUST NOT be interpreted as full coverage.',
        ),
    ] = 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 audience_evidence_selections : list[adcp.types.generated_poc.core.audience_evidence_selection.AudienceEvidenceSelection] | None
var bid_price : float | None
var bidding : adcp.types.generated_poc.core.bidding_policy.BiddingPolicy | 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 daily_budget_cap : float | 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_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 formats_pending : list[adcp.types.generated_poc.core.product_format_declaration.ProductFormatDeclaration] | None
var formats_to_provide : list[adcp.types.generated_poc.core.product_format_declaration.ProductFormatDeclaration] | None
var impressions : float | None
var measurement_terms : adcp.types.generated_poc.core.measurement_terms.MeasurementTerms | None
var min_spend_target : float | 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
var targeting_resolution : adcp.types.generated_poc.core.package_targeting_resolution.PackageTargetingResolution | None

Inherited members

class LegacyPackageRequest (**data: Any)
Expand source code
class PackageRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    product_id: Annotated[
        str,
        Field(
            description="Opaque configured product ID returned by get_products. Selecting it accepts the product's disclosed targeting_resolution, pricing, forecast assumptions, and terms. Sellers MUST echo this value on every response package object that represents this requested package."
        ),
    ]
    format_ids: Annotated[
        list[format_id_1.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='Deprecated in AdCP 3.2; removed in AdCP 4.0. Legacy named-format selector retained for older 3.x peers. New buyers MUST NOT emit this field. Sellers MUST normalize every entry through the canonical mapping path before product satisfaction checks; an entry that cannot be normalized is rejected with `UNSUPPORTED_FEATURE` before any equivalence check. When this field coexists with `format_option_refs` or `format_kind` plus `params`, sellers MUST compare the product option sets selected by each resolved route. Legacy parameter compatibility follows the asymmetric v2-narrows-v1 relation defined by canonical formats, not raw object equality. Different format shapes, selected option sets, or incompatible dimensions are rejected with `CONFLICTING_SELECTORS`; sellers MUST NOT silently ignore the legacy projection. Equivalent dual emission remains valid during the 3.x compatibility window. If omitted and no canonical selector is present, all formats supported by the product are active.',
            min_length=1,
        ),
    ] = None
    format_option_refs: Annotated[
        list[format_option_ref_1.FormatOptionReference] | None,
        Field(
            description='Canonical 3.2 format-option selector. Each reference matches one target product `format_options[]` entry. Publisher-backed options match `{ scope: "publisher", publisher_domain, format_option_id }`; product-local options match `{ scope: "product", format_option_id }`. Sellers reject unresolved options with `UNSUPPORTED_FEATURE` and a field path to the failing entry before comparing co-present routes. New buyers MUST use this route by itself and MUST NOT dual-emit either a direct canonical selector or deprecated `format_ids`. Receivers handling older 3.x multi-route requests MUST resolve every present route, require each route to select the same product option set, and reject disagreement with `CONFLICTING_SELECTORS` before treating `format_option_refs` as authoritative.',
            min_length=1,
        ),
    ] = None
    format_kind: Annotated[
        canonical_format_kind.CanonicalFormatKind | None,
        Field(
            description='Canonical 3.2 direct selector. Names the canonical format shape this package targets when the buyer is not selecting a published `format_option_ref`. Pair with `params` for dimensions, duration, codecs, or other constraints. New buyers MUST NOT combine this route with `format_option_refs` or deprecated `format_ids`. Receivers handling older 3.x multi-route requests MUST equivalence-check every present route before applying precedence and reject disagreement with `CONFLICTING_SELECTORS`. Product satisfaction is directional: broad `{ format_kind: "image" }` does not satisfy a fixed-size product declaration.'
        ),
    ] = 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. Requires `format_kind`. For fixed-size image selectors, `width` and `height` MUST co-occur; a selector containing only one dimension is schema-invalid. New buyers omit `params` when selecting by `format_option_refs` or `format_ids`; older multi-route requests are accepted only when every route selects the same product option set."
        ),
    ] = None
    budget: Annotated[
        float | None,
        Field(
            description="Hard lifetime spend cap for this package in the media buy's currency. Required in fixed allocation mode. Optional in seller-optimized mode; when omitted, the package is bounded by the shared total_budget and any other package constraints. In seller-optimized mode this is a ceiling, not a reserved or current allocation.",
            ge=0.0,
        ),
    ] = None
    min_spend_target: Annotated[
        float | None,
        Field(
            description="Soft lifetime spend target for this package in the media buy's currency. Only valid with seller-optimized budget allocation. The seller SHOULD attempt to deliver at least this amount before allocating incremental spend elsewhere, but inventory, policy, optimization targets, or other delivery constraints may prevent it. This is not a billing guarantee. Must not exceed the package budget when both are present; sellers MUST reject with `INVALID_REQUEST` when this constraint is violated.",
            ge=0.0,
        ),
    ] = None
    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(
            deprecated=True,
            description='DEPRECATED in 3.2 and removed in the next major. Use bidding.bid_amount or bidding.max_bid. Legacy normalization: selected pricing_option.max_bid=true maps to bidding.max_bid; otherwise maps to bidding.bid_amount. A package MUST NOT supply both representations.',
            ge=0.0,
        ),
    ] = None
    bidding: Annotated[
        bidding_policy.BiddingPolicy | None,
        Field(
            description='Package-authored bidding policy. This complete block replaces, rather than field-merges with, any media-buy bidding policy for this package. `{automatic:true}` explicitly overrides a media-buy policy with provider automatic bidding; omission inherits the complete media-buy block. Monetary fields use the media-buy currency, while the selected pricing option supplies only the auction unit and MUST declare that same currency. Sellers MUST reject a new bidding block combined with legacy bid_price or legacy monetary optimization-goal targets on the same effective package with AMBIGUOUS_BIDDING_POLICY.'
        ),
    ] = None
    impressions: Annotated[
        float | None, Field(description='Impression goal for this package', ge=0.0)
    ] = None
    daily_budget_cap: Annotated[
        float | None,
        Field(
            description="Optional hard package daily spend ceiling in the media-buy currency. It is subordinate, not a reserved allocation; package caps need not sum to the aggregate cap. Uses the media buy's cap timezone. Requires advertised package budget-capping scope; otherwise rejected with UNSUPPORTED_FEATURE.",
            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: Annotated[
        targeting.TargetingOverlay | None,
        Field(
            description="Optional package-specific targeting that further constrains targeting already bound to the configured product. It cannot broaden or remove configured-product targeting. Fields supplied here MUST be declared in the product's overlay_support unless they were already accepted during discovery. The one fixed-inventory restatement exception is placement_selection equal to the product's complete, explicitly enumerated mode: included placement set: that set is an inherent exact match across discovery, create, and update and does not require overlay_support.placement_selection; partial selection still requires a selectable product. Opaque property_list and collection_list references have no equivalent exception because their membership can change independently and cannot be proven equal from the product wire representation. The seller applies the intersection exactly or rejects the package; package readback echoes the complete effective targeting. A supported value with no current inventory returns PRODUCT_UNAVAILABLE rather than a silent substitute or reprice."
        ),
    ] = None
    audience_evidence_requirements: Annotated[
        audience_evidence_requirements_1.AudienceEvidenceRequirements | None,
        Field(
            description='Buyer policy that the selected product and constructed package MUST satisfy using product audience evidence. This remains planning and suitability evidence, not a targeting instruction. Sellers MUST reject an unsatisfied required policy rather than silently drop it, and a confirmed package MUST include every evidence snapshot used to satisfy this policy in audience_evidence_selections with decision_use package_construction.'
        ),
    ] = None
    audience_evidence_pins: Annotated[
        list[audience_evidence_pin.AudienceEvidencePin] | None,
        Field(
            description="Exact immutable evidence snapshots selected by the buyer during discovery. The seller MUST match evidence_id, snapshot_id, version, and content_digest against one published snapshot and MUST reject catalog mutation, snapshot reuse, missing snapshots, or substitutions. Every accepted pin MUST be echoed in the confirmed package's audience_evidence_selections with decision_use package_construction.",
            min_length=1,
        ),
    ] = 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[CommittedMetrics] | 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 rotation, grouping, weights, and placement targeting. rotation_mode is package-scoped: omission resolves to weighted, and every assignment MUST resolve to the same effective mode. In sequential mode, sequence_position MUST be unique within each package-local group. Sellers reject conflicts with VALIDATION_ERROR before creating the package.',
            min_length=1,
        ),
    ] = None
    creatives: Annotated[
        Sequence[Creative] | None,
        Field(
            description="Upload creative assets inline and assign to this package. Native localization is not accepted on this path; use sync_creatives before assigning the library creative. 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

    @model_validator(mode='after')
    def _validate_format_params(self) -> PackageRequest:
        if self.params is not None and self.format_kind is None:
            raise ValueError('params requires format_kind')
        if self.params is not None and self.format_kind == 'image':
            if ('width' in self.params) != ('height' in self.params):
                raise ValueError('image params width and height must co-occur')
        return self

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 audience_evidence_pins : list[adcp.types.generated_poc.core.audience_evidence_pin.AudienceEvidencePin] | None
var audience_evidence_requirements : adcp.types.generated_poc.core.audience_evidence_requirements.AudienceEvidenceRequirements | None
var bidding : adcp.types.generated_poc.core.bidding_policy.BiddingPolicy | None
var budget : float | None
var catalogs : list[adcp.types.generated_poc.core.catalog.Catalog] | None
var committed_metrics : list[adcp.types.generated_poc.media_buy.package_request.CommittedMetrics] | 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.media_buy.package_request.Creative] | None
var daily_budget_cap : float | None
var end_time : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | 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 min_spend_target : float | 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

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var bid_price : float | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.
var format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyPackageUpdate (**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 hard spend cap for this package in the media-buy currency. Every selected pricing option in an AdCP-authored media buy MUST declare that same currency. In seller-optimized mode a number changes the package ceiling and null removes it so only the shared total and other constraints bound the package. null is invalid when the resulting allocation mode is fixed.',
            ge=0.0,
        ),
    ] = None
    min_spend_target: Annotated[
        float | None,
        Field(
            description='Updated soft lifetime spend target for this package. A number is valid only for seller-optimized allocation and must not exceed the resulting package budget when one exists. null removes the target. Sellers MUST validate the complete post-update state atomically.',
            ge=0.0,
        ),
    ] = None
    pacing: pacing_1.Pacing | None = None
    bid_price: Annotated[
        float | None,
        Field(
            deprecated=True,
            description='DEPRECATED in 3.2 and removed in the next major. Use bidding. A package update MUST NOT supply both a non-null bidding object and bid_price. During migration, bidding:null MAY accompany bid_price to clear the canonical block and set the legacy representation atomically.',
            ge=0.0,
        ),
    ] = None
    bidding: Annotated[
        bidding_policy.BiddingPolicy | None,
        Field(
            description='Replace the complete package-authored bidding policy. An object replaces any prior package block and remains a complete override of the media-buy default. `{automatic:true}` explicitly selects provider automatic bidding at package scope. null clears the package-authored block so the package inherits media-buy bidding; if the media-buy block is also absent, provider automatic delivery applies. Monetary fields use the media-buy currency and require the package pricing option to declare that currency. During legacy migration, null MAY accompany bid_price or monetary optimization-goal targets; only a non-null canonical bidding object conflicts with those representations.'
        ),
    ] = None
    impressions: Annotated[
        float | None, Field(description='Updated impression goal for this package', ge=0.0)
    ] = None
    daily_budget_cap: Annotated[
        float | None,
        Field(
            description="Replace this package's hard daily cap; null removes it. Numeric changes apply immediately with current-day package spend counted. A cap below that spend pauses the package for the day; the aggregate cap remains independently binding.",
            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. When true, package cancellation takes precedence over sibling fields on this package: the seller applies only canceled and cancellation_reason for this package and SHOULD return a structured warning naming ignored sibling fields. Root fields and other package updates still participate in the same atomic update when root canceled is absent. 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="Complete effective targeting overlay to apply to this package. On update, this replaces the package's current effective targeting, including values originally accepted through configured-product selection; omit the field to leave targeting unchanged. Every replacement must remain executable by the product. Sellers reject unsupported or partially applicable changes and use REQUOTE_REQUIRED when a change, including a broader inventory set, falls outside the priced envelope. placement_selection is purchased-inventory targeting; mode default restores the product default, and successful readback echoes the committed selected set when enumerable. If the replacement removes a placement referenced by an existing creative assignment, the seller MUST reject the update unless the same atomic package mutation supplies a compatible complete creative_assignments replacement. Sellers MUST NOT silently delete assignments or retain orphan placement refs."
        ),
    ] = 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 rotation, grouping, weights, and placement routing. Uses replacement semantics - omit to leave assignments unchanged. rotation_mode is package-scoped: omission resolves to weighted, and every assignment MUST resolve to the same effective mode. In sequential mode, sequence_position MUST be unique within each package-local group. Sellers reject conflicts with VALIDATION_ERROR before mutation. When the same mutation narrows targeting_overlay.placement_selection, this complete replacement MUST remove or reroute every assignment reference that would otherwise be orphaned; the seller validates both changes atomically.'
        ),
    ] = None
    creatives: Annotated[
        list[Creative] | None,
        Field(
            description="Replace this package's inline creative assets. Native localization is not accepted on this path; use sync_creatives before assigning the library creative. 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 bidding : adcp.types.generated_poc.core.bidding_policy.BiddingPolicy | 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.media_buy.package_update.Creative] | None
var daily_budget_cap : float | 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 min_spend_target : float | 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

Instance variables

var bid_price : float | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyPlacement (**data: Any)
Expand source code
class Placement(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    kind: Annotated[
        Kind,
        Field(
            description="Placement structure discriminator. `publisher_ref` identifies a placement by `{publisher_domain, placement_id}` and resolves public metadata from the named publisher's adagents.json placement declarations; `seller_inline` identifies buyer-facing placement metadata defined inline by the sales agent (still in the named publisher namespace when `publisher_domain` is present, or the seller's own namespace in legacy single-publisher contexts)."
        ),
    ]
    placement_id: Annotated[
        str,
        Field(
            description="Placement identifier in the publisher namespace. When `publisher_domain` is present, this matches a placement ID in that publisher's adagents.json catalog or a seller-defined inline placement in that publisher namespace. Buyers use this with `publisher_domain` in `creative_assignments[].placement_refs`; legacy `creative_assignments[].placement_ids` strings are only unambiguous in single-publisher contexts."
        ),
    ]
    publisher_domain: Annotated[
        str | None,
        Field(
            description='Publisher domain whose adagents.json placement declarations define this placement. Required for `kind: "publisher_ref"`. Omitted only for `kind: "seller_inline"` in legacy single-publisher seller contexts where the seller agent\'s own publisher domain is the namespace.',
            pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$',
        ),
    ] = None
    name: Annotated[
        str | None,
        Field(
            description='Human-readable name for the placement (e.g., \'Homepage Banner\', \'Article Sidebar\'). Required for `kind: "seller_inline"`. May be omitted for publisher-referenced placements because buyers resolve the name from the publisher declaration identified by `{publisher_domain, placement_id}`.'
        ),
    ] = None
    description: Annotated[
        str | None, Field(description='Detailed description of where and how the placement appears')
    ] = None
    mode: Annotated[
        Mode,
        Field(
            description="Required product-level relationship to this placement. targetable means the buyer may include the publisher-scoped ref in targeting_overlay.placement_selection; a creative may be routed there only after it is purchased. included means fixed product inventory: it cannot be independently selected, but across discovery, create, and update a selected request exactly equal to the product's complete included placement set is an inherent restatement and may be echoed on the package without overlay_support.placement_selection. A product containing any included placement MUST NOT declare overlay_support.placement_selection; partial selection requires a separately selectable product configuration. During the migration window ending 2026-11-25, buyers MAY tolerate legacy products that omit mode and treat them as targetable; after that date buyers SHOULD fail closed."
        ),
    ]
    tags: Annotated[
        list[str] | None,
        Field(
            description="Optional tags for grouping placements within a product (e.g., 'homepage', 'native', 'premium'). When the placement_id comes from the publisher registry, these should align with the registry tags unless the product is narrowing scope."
        ),
    ] = None
    format_ids: Annotated[
        Sequence[format_id.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='Deprecated in AdCP 3.2; removed in AdCP 4.0. Legacy named-format placement narrowing. Can include concrete, template, or parameterized format IDs. When present on a product placement, this field narrows the product-level `format_ids` contract and MUST NOT introduce formats the product does not accept. Use canonical `format_options`.',
            min_length=1,
        ),
    ] = None
    format_options: Annotated[
        list[product_format_declaration.ProductFormatDeclaration] | None,
        Field(
            description="Canonical seller-side narrowing for this product placement. When present, these declarations are intersected with the product-level format_options and MUST NOT introduce a format outside that product upper bound. For kind publisher_ref, buyers MUST also resolve {publisher_domain, placement_id} in the publisher's adagents.json and intersect the publisher catalog constraint: use the public placement's format_options when present (resolving bare format_option_id references against same-file top-level formats[]), otherwise use applicable top-level formats[] scoped to that placement's properties. Omitting this inline field removes only the seller-inline layer; it does not bypass a publisher placement or property-scoped narrowing. The placement inherits the full product-level set only when no applicable publisher catalog narrowing exists. Unresolved publisher placement or format-option references fail closed. Locale policy participates in the same intersection: when the product policy is absent, a placement may introduce any concrete policy as a narrowing of the unconstrained option; when both are present, every placement accepted_language_range must be contained by a product range under RFC 4647 Basic Filtering (`fr-CA` narrows `fr`; `fr` does not narrow `fr-CA`). Buyers compute effective locale eligibility independently for each placement. Any effective locale-constrained route is canonical-only and has no projecting product or placement format_id.",
            min_length=1,
        ),
    ] = None
    video_placement_types: Annotated[
        list[video_placement_type.VideoPlacementType] | None,
        Field(
            description='Declared video placement types for this product placement, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    audio_distribution_types: Annotated[
        list[audio_distribution_type.AudioDistributionType] | None,
        Field(
            description='Declared audio distribution types for this product placement, using IAB Tech Lab/OpenRTB 2.6 audio.feed definitions with AdCP-native names. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    sponsored_placement_types: Annotated[
        list[sponsored_placement_type.SponsoredPlacementType] | None,
        Field(
            description='Declared sponsored-placement types for this product placement, distinguishing where the catalog-driven retail-media placement renders on the retailer surface. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    social_placement_surfaces: Annotated[
        list[social_placement_surface.SocialPlacementSurface] | None,
        Field(
            description='Declared social-placement surfaces for this product placement, distinguishing the in-app surface where the social placement renders. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            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 audio_distribution_types : list[adcp.types.generated_poc.enums.audio_distribution_type.AudioDistributionType] | None
var description : str | None
var format_ids : collections.abc.Sequence[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var format_options : list[adcp.types.generated_poc.core.product_format_declaration.ProductFormatDeclaration] | None
var kind : adcp.types.generated_poc.core.placement.Kind
var mode : adcp.types.generated_poc.core.placement.Mode
var model_config
var name : str | None
var placement_id : str
var publisher_domain : str | None
var social_placement_surfaces : list[adcp.types.generated_poc.enums.social_placement_surface.SocialPlacementSurface] | None
var sponsored_placement_types : list[adcp.types.generated_poc.enums.sponsored_placement_type.SponsoredPlacementType] | None
var tags : list[str] | None
var video_placement_types : list[adcp.types.generated_poc.enums.video_placement_type.VideoPlacementType] | None

Inherited members

class LegacyPreviewCreativeRequest (**data: Any)
Expand source code
class PreviewCreativeRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    request_type: Annotated[
        RequestType,
        Field(
            description="Preview mode. 'single' previews one creative manifest. 'batch' previews multiple creatives in one call. 'variant' replays a post-flight variant by ID."
        ),
    ]
    creative_manifest: Annotated[
        creative_manifest_1.CreativeManifest | None,
        Field(
            description='Complete creative manifest with all required assets for the format. In single mode, provide exactly one of creative_manifest or creative_id. Also accepted per item in batch mode.'
        ),
    ] = None
    target_capability_id: Annotated[
        str | None,
        Field(
            description="Canonical preview-operation selector. Identifies one get_adcp_capabilities creative.supported_formats[].capability_id entry whose operations contains preview. In single mode it selects the renderer for this request; in batch mode it is the default for items that omit their own target_capability_id. When omitted, the agent MAY resolve the renderer only if exactly one advertised preview capability satisfies the manifest's canonical declaration; zero matches or multiple matches MUST be rejected with FORMAT_NOT_SUPPORTED rather than choosing nondeterministically. Mutually exclusive with deprecated format_id.",
            pattern='^[a-zA-Z0-9_-]+$',
        ),
    ] = None
    format_id: Annotated[
        format_id_1.FormatReferenceStructuredObject | None,
        Field(
            deprecated=True,
            description='**DEPRECATED in 3.2.** Legacy named-format preview route. New requests select an advertised preview renderer with target_capability_id and carry portable format identity in creative_manifest_1.format_kind plus optional creative_manifest_1.format_option_ref.',
        ),
    ] = None
    inputs: Annotated[
        list[Input] | None,
        Field(
            description='Array of input sets for generating multiple preview variants. Each input set defines macros and context values for one preview rendering. Used in single mode.',
            min_length=1,
        ),
    ] = None
    template_id: Annotated[
        str | None,
        Field(description='Specific template ID for custom format rendering. Used in single mode.'),
    ] = None
    quality: Annotated[
        creative_quality.CreativeQuality | None,
        Field(
            description="Render quality. 'draft' produces fast, lower-fidelity renderings. 'production' produces full-quality renderings. In batch mode, sets the default for all requests (individual items can override)."
        ),
    ] = None
    output_format: Annotated[
        preview_output_format.PreviewOutputFormat | None,
        Field(
            description="Output format. 'url' returns preview_url (iframe-embeddable URL), 'html' returns preview_html (raw HTML). In batch mode, sets the default for all requests (individual items can override). Default: 'url'."
        ),
    ] = preview_output_format.PreviewOutputFormat.url
    item_limit: Annotated[
        int | None,
        Field(
            description='Maximum number of catalog items to render per preview variant. Used in single mode. Creative agents SHOULD default to a reasonable sample when omitted and the catalog is large.',
            ge=1,
        ),
    ] = None
    requests: Annotated[
        list[Request] | None,
        Field(
            description="Array of preview requests (1-50 items). Required when request_type is 'batch'. Each item follows the single request structure.",
            max_length=50,
            min_length=1,
        ),
    ] = None
    variant_id: Annotated[
        str | None,
        Field(
            description="Platform-assigned variant identifier from get_creative_delivery response. Required when request_type is 'variant'."
        ),
    ] = None
    creative_id: Annotated[
        str | None,
        Field(
            description='Creative-library identifier. In single mode, previews the stored canonical creative without requiring the caller to reconstruct its manifest. Also available as context in variant mode.'
        ),
    ] = None
    allow_async: Annotated[
        bool | None,
        Field(
            description="Opt in to an asynchronous preview response. When true, the creative agent MAY return status 'submitted' with a task_id only when rendering has been handed to a queue or external renderer and will continue after the request connection is released. Active processing on an open connection uses working progress instead. The buyer polls get_task_status for completion. When false or absent, the agent MUST return a synchronous preview response or a terminal protocol error; it MUST NOT return the submitted shape. This field applies to preview_creative only; build_creative already defines its own async lifecycle."
        ),
    ] = False
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Optional webhook configuration for terminal completion/failure notifications when allow_async is true and preview_creative returns a submitted task envelope. Submitted tasks remain pollable through get_task_status whether or not this field is present. If the agent accepts this configuration and returns submitted, it MUST deliver at least the terminal notification; if it cannot honor the webhook, it MUST return a structured error. Presence of this field alone MUST NOT cause asynchronous execution.'
        ),
    ] = 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 allow_async : bool | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_id : str | None
var creative_manifest : adcp.types.generated_poc.core.creative_manifest.CreativeManifest | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var format_id : adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject | None
var inputs : list[adcp.types.generated_poc.creative.preview_creative_request.Input] | None
var item_limit : int | None
var model_config
var output_format : adcp.types.generated_poc.enums.preview_output_format.PreviewOutputFormat | None
var push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | None
var quality : adcp.types.generated_poc.enums.creative_quality.CreativeQuality | None
var request_type : adcp.types.generated_poc.creative.preview_creative_request.RequestType
var requests : list[adcp.types.generated_poc.creative.preview_creative_request.Request] | None
var target_capability_id : str | None
var template_id : str | None
var variant_id : str | None

Inherited members

class LegacyPreviewCreativeResponse1 (**data: Any)
Expand source code
class PreviewCreativeResponse1(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    response_type: Literal['single'] = 'single'
    previews: Annotated[list[Preview], Field(min_length=1)]
    quality_used: creative_quality_1.CreativeQuality | None = None
    interactive_url: AnyUrl | None = None
    expires_at: AwareDatetime | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var interactive_url : pydantic.networks.AnyUrl | None
var model_config
var previews : list[adcp.types.generated_poc.creative.preview_creative_response.Preview]
var quality_used : adcp.types.generated_poc.enums.creative_quality.CreativeQuality | None
var response_type : Literal['single']
class LegacyPreviewCreativeSingleResponse (**data: Any)
Expand source code
class PreviewCreativeResponse1(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    response_type: Literal['single'] = 'single'
    previews: Annotated[list[Preview], Field(min_length=1)]
    quality_used: creative_quality_1.CreativeQuality | None = None
    interactive_url: AnyUrl | None = None
    expires_at: AwareDatetime | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var interactive_url : pydantic.networks.AnyUrl | None
var model_config
var previews : list[adcp.types.generated_poc.creative.preview_creative_response.Preview]
var quality_used : adcp.types.generated_poc.enums.creative_quality.CreativeQuality | None
var response_type : Literal['single']

Inherited members

class LegacyPreviewCreativeResponse2 (**data: Any)
Expand source code
class PreviewCreativeResponse2(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    response_type: Literal['batch'] = 'batch'
    results: Annotated[list[Result], 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 ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var model_config
var response_type : Literal['batch']
var results : list[adcp.types.generated_poc.creative.preview_creative_response.Result]
class LegacyPreviewCreativeBatchResponse (**data: Any)
Expand source code
class PreviewCreativeResponse2(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    response_type: Literal['batch'] = 'batch'
    results: Annotated[list[Result], 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 ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var model_config
var response_type : Literal['batch']
var results : list[adcp.types.generated_poc.creative.preview_creative_response.Result]

Inherited members

class LegacyPreviewCreativeResponse3 (**data: Any)
Expand source code
class PreviewCreativeResponse3(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    response_type: Literal['variant'] = 'variant'
    variant_id: str
    creative_id: str | None = None
    previews: Annotated[list[Preview3], Field(min_length=1)]
    manifest: creative_manifest_1.CreativeManifest | None = None
    expires_at: AwareDatetime | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_id : str | None
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var manifest : adcp.types.generated_poc.core.creative_manifest.CreativeManifest | None
var model_config
var previews : list[adcp.types.generated_poc.creative.preview_creative_response.Preview3]
var response_type : Literal['variant']
var variant_id : str
class LegacyPreviewCreativeVariantResponse (**data: Any)
Expand source code
class PreviewCreativeResponse3(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    response_type: Literal['variant'] = 'variant'
    variant_id: str
    creative_id: str | None = None
    previews: Annotated[list[Preview3], Field(min_length=1)]
    manifest: creative_manifest_1.CreativeManifest | None = None
    expires_at: AwareDatetime | 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
  • AdCPBaseModel
  • pydantic.main.BaseModel

Class variables

var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_id : str | None
var expires_at : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var manifest : adcp.types.generated_poc.core.creative_manifest.CreativeManifest | None
var model_config
var previews : list[adcp.types.generated_poc.creative.preview_creative_response.Preview3]
var response_type : Literal['variant']
var variant_id : str

Inherited members

class LegacyProduct (**data: Any)
Expand source code
class Product(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )


    @model_validator(mode='before')
    @classmethod
    def _coerce_publisher_property_models(cls, data: Any) -> Any:
        if isinstance(data, dict) and isinstance(data.get('publisher_properties'), list):
            coerced = []
            changed = False
            for item in data['publisher_properties']:
                if hasattr(item, 'model_dump'):
                    coerced.append(item.model_dump(mode='json', exclude_none=True))
                    changed = True
                else:
                    coerced.append(item)
            if changed:
                data = dict(data)
                data['publisher_properties'] = coerced
        return data
    product_id: Annotated[
        str,
        Field(
            description='Opaque identifier for this buyable product. For a non-custom wholesale product, sellers MUST reuse the ID for the same logical catalog offer within the seller and declared cache_scope across reads and wholesale-feed webhooks; feed and pricing versions communicate temporal catalog mutation, while retirement or replacement may end the identity. Concurrent or request-bound configurations whose effective targeting, disclosed targeting modifications, forecast assumptions, terms, or overlay support differ MUST use distinguishable configured product IDs. For is_custom: true, the ID identifies only the request-specific discovery/refinement lineage and is not stable across independent contexts. Sellers MUST keep every issued configured ID resolvable for its promised lifetime. Pricing variants within one logical product are distinguished by pricing_option_id: a seller MUST mint a new pricing_option_id whenever a binding fixed price, floor, currency, model, or priced applicability changes, and MUST NOT reinterpret an issued option ID at a new price. Selecting product_id plus pricing_option_id in create_media_buy accepts that returned configuration and commercial option.'
        ),
    ]
    name: Annotated[str, Field(description='Human-readable product name')]
    description: Annotated[
        str, Field(description='Detailed description of the product and its inventory')
    ]
    publisher_properties: Annotated[
        list[PublisherProperty],
        Field(
            description="SDK implementers MUST enforce singular-only at runtime: each entry uses the singular `publisher_domain` form; the compact `publisher_domains[]` form is rejected on products. Codegen toolchains (json-schema-to-typescript, quicktype, datamodel-code-generator, openapi-typescript-codegen) often flatten the `allOf + $ref + not.required` restriction below poorly and may drop the rejection constraint silently, emitting an unrestricted type — runtime enforcement is the safety net. Publisher properties covered by this product. Buyers fetch actual property definitions from each publisher's adagents.json and validate agent authorization. Selection patterns mirror the authorization patterns in adagents.json for consistency. The compact `publisher_domains[]` form is reserved for adagents.json `authorized_agents[].publisher_properties[]` so that buy-side traffic-and-pricing flatteners can always treat each entry as exactly one publisher.",
            min_length=1,
        ),
    ]
    channels: Annotated[
        list[channels_1.MediaChannel] | None,
        Field(
            description="Advertising channels this product is sold as. Products inherit from their properties' supported_channels but may narrow the scope. For example, a product covering YouTube properties might be sold as ['ctv'] even though those properties support ['olv', 'social', 'ctv']."
        ),
    ] = None
    format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='Deprecated in AdCP 3.2; removed in AdCP 4.0. Legacy named-format compatibility path. Products MUST carry `format_ids`, `format_options`, or both during the 3.x migration window. New products MUST author canonical `format_options[]`; sellers MAY additionally project those declarations to `format_ids` for legacy buyers. When both fields are present they MUST describe the same underlying formats, and buyers MUST prefer `format_options`. Do not author a new product from `format_ids` alone.',
        ),
    ] = None
    format_options: Annotated[
        list[product_format_declaration.ProductFormatDeclaration] | None,
        Field(
            description="Canonical format-option path: one or more inline format declarations the product accepts. Each element narrows a canonical format with parameters, slots, platform_extensions, and optional locale_policy. New 3.2 products MUST carry format_options; a seller MAY additionally project the same declarations to deprecated format_ids for older 3.x peers. A declaration carrying locale_policy is canonical-only because legacy format_ids cannot preserve locale eligibility; no product or placement format_id may project to an effective locale-constrained option.\n\nWhen placements are published, product-level format_options are the union of formats deliverable somewhere in the product and the upper bound for every placement. A placement's effective accepted set is the intersection of every applicable layer: (1) the product format_options; (2) the product placement's inline format_options, when present; and (3) for kind publisher_ref, the named publisher's adagents.json catalog narrowing. Resolve layer 3 by locating the matching placements[] entry: use its format_options when present, resolving bare format_option_id references against that same file's top-level formats[]; otherwise use top-level formats[] applicable to the placement's property_ids/property_tags. An omitted optional layer is unconstrained, but an unresolved publisher placement or format-option reference MUST fail closed. A publisher-referenced placement without inline product format_options therefore does NOT inherit the full product union when the publisher catalog supplies narrower placement or property-scoped acceptance.\n\nMatch publisher-declared options by {publisher_domain, format_option_id}, match product-local options by format_option_id when publisher_domain is omitted, and otherwise match declarations with the same format_kind whose narrower parameters satisfy the broader declaration. A product- or placement-level declaration MUST NOT introduce a format outside the product upper bound. Locale policy follows the same intersection. If the product locale policy is absent, a placement may introduce any concrete policy as a narrowing of an unconstrained option; when both are present, every placement range must be contained by a product range under RFC 4647 Basic Filtering. Locale eligibility is checked independently for every placement where an assignment may serve.\n\nFor a product or package containing multiple included placements, a single creative intended for every placement MUST lie in the intersection of every selected placement's effective set. Distinct per-placement creatives MAY use the union, but the selected creative set MUST cover every included placement; uncovered inventory MUST be rejected or refined, never silently omitted. If a product spans multiple publishers but omits placements[], there is no public routing key for per-placement creatives: its format_options MUST therefore be the common intersection accepted across every selected publisher/property scope. A seller that needs a union of publisher-specific formats MUST publish placements[] with publisher-scoped identities and narrowing. Commercial terms such as price, floor, availability, and deal eligibility are product facts, not format parameters.",
            min_length=1,
        ),
    ] = None
    placements: Annotated[
        list[placement.Placement] | None,
        Field(
            description="Optional array of specific public placements within this product. Placement IDs are scoped by publisher domain. Product placements declare `kind` to distinguish publisher-referenced placements (`publisher_ref`) from seller-defined inline placements (`seller_inline`). Publisher-referenced placements carry `publisher_domain` plus `placement_id` and may omit `name` because buyers resolve the name from the publisher's adagents.json placement declarations. Seller-inline placements carry buyer-facing `name` directly; when `publisher_domain` is omitted, buyers MAY interpret the placement ID relative to the seller agent's own publisher domain only during the legacy single-publisher transition. Community-maintained fallback files are resolver/source metadata, not a distinct placement kind. Each placement MUST declare `mode: 'targetable'` (buyer may purchase it through targeting_overlay.placement_selection) or `mode: 'included'` (part of fixed/default product composition and not independently selectable). Creative assignments route creatives only after placement inventory is purchased. Placement-level format declarations narrow the product-level creative contract and MUST NOT broaden it. Seller-private delivery objects, source/origin details, and ad-server mappings MUST NOT be exposed here.",
            min_length=1,
        ),
    ] = None
    video_placement_types: Annotated[
        list[video_placement_type.VideoPlacementType] | None,
        Field(
            description='Declared video placement types that may be included in this product, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. Use on OLV, CTV, and other video products when buyers need to distinguish instream, accompanying-content, interstitial, and standalone/no-content inventory. Aggregate products and ad-network products MAY declare multiple values. When `placements[]` also carry `video_placement_types`, this product-level array SHOULD be the union of the placement-level declarations the seller may deliver under the product. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    audio_distribution_types: Annotated[
        list[audio_distribution_type.AudioDistributionType] | None,
        Field(
            description='Declared audio distribution types that may be included in this product, using IAB Tech Lab/OpenRTB 2.6 audio.feed definitions with AdCP-native names. Use on radio, streaming-audio, podcast, gaming, and other audio products when buyers need to distinguish music streaming services, FM/AM broadcast, podcasts, catch-up radio, web radio, video-game audio, and text-to-speech inventory without changing the buyer-facing channel or adagents.json property type. Aggregate products and ad-network products MAY declare multiple values. When `placements[]` also carry `audio_distribution_types`, this product-level array SHOULD be the union of the placement-level declarations the seller may deliver under the product. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    sponsored_placement_types: Annotated[
        list[sponsored_placement_type.SponsoredPlacementType] | None,
        Field(
            description='Declared sponsored-placement types that may be included in this product, distinguishing where catalog-driven retail-media placements render on the retailer surface (sponsored search, sponsored display, or sponsored native). Use on retail-media products when buyers need to distinguish search-keyed, display, and native in-grid sponsored inventory. Aggregate products and ad-network products MAY declare multiple values. When `placements[]` also carry `sponsored_placement_types`, this product-level array SHOULD be the union of the placement-level declarations the seller may deliver under the product. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    social_placement_surfaces: Annotated[
        list[social_placement_surface.SocialPlacementSurface] | None,
        Field(
            description='Declared social-placement surfaces that may be included in this product, distinguishing the in-app surface where social placements render (feed, stories, short_video, explore, or search). Use on social products when buyers need to distinguish feed, story, short-video, and discovery surfaces. Aggregate products and ad-network products MAY declare multiple values. When `placements[]` also carry `social_placement_surfaces`, this product-level array SHOULD be the union of the placement-level declarations the seller may deliver under the product. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    delivery_type: delivery_type_1.DeliveryType
    exclusivity: Annotated[
        exclusivity_1.Exclusivity | None,
        Field(
            description="Whether this product offers exclusive access to its inventory. Defaults to 'none' when absent. Most relevant for guaranteed products tied to specific collections or placements."
        ),
    ] = None
    pricing_options: Annotated[
        list[pricing_option.PricingOption],
        Field(
            description="Available pricing models for this product. Fixed prices and auction floors are binding for every later targeting selection permitted by this product's overlay_support; price_guidance remains non-binding. Declaring broad overlay support alongside a binding option is therefore a uniform-price promise, not permission to calculate a different price at create time. A seller with value-dependent rates MUST return a request-specific configured product after rediscovery with concrete targeting, split the inventory into separately priced products, or expose only non-binding guidance until it can issue a binding option. The seller MUST mint a new pricing_option_id whenever a binding price, floor, currency, model, or priced applicability changes. It MUST NOT silently reprice a create request or reuse the selected option ID with different terms.",
            min_length=1,
        ),
    ]
    forecast: Annotated[
        delivery_forecast.DeliveryForecast | None,
        Field(
            description="Forecasted delivery metrics for this product. Concrete discovery targeting scopes the forecast to those effective values. When discovery requested only required_overlay_support for a dimension, the forecast describes the product's discovery/default scope and is not a value-specific forecast for every later selection; buyers rediscover with concrete targeting_overlay values when they need that forecast."
        ),
    ] = None
    outcome_measurement: Annotated[
        outcome_measurement_1.OutcomeMeasurement | None,
        Field(
            deprecated=True,
            description='**Deprecated as of this minor.** Outcome capabilities (incremental sales lift, brand lift, foot traffic, etc.) are now declared via `reporting_capabilities.available_metrics` (the same path used for impressions, conversions, ROAS) with `qualifier.attribution_methodology` and `qualifier.attribution_window` carrying the methodology and window on commit. New implementations SHOULD use the unified pattern; this field is retained for one-minor backwards compatibility and removed at the next major. See `outcome-measurement.json` description for migration guidance.',
        ),
    ] = None
    delivery_measurement: Annotated[
        DeliveryMeasurement | None,
        Field(
            description='Measurement vendors and methodology for delivery metrics. The buyer accepts the declared vendors as the source of truth for the buy. When absent, buyers should apply their own measurement defaults. Senders SHOULD populate `vendors` (structured BrandRef array) for new implementations; the legacy `provider` string field is deprecated and retained for one-minor backwards compatibility.'
        ),
    ] = None
    measurement_terms: Annotated[
        measurement_terms_1.MeasurementTerms | None,
        Field(
            description="Seller's default billing measurement and makegood terms. Declares who counts the billing metric and what remedies apply when thresholds are breached. Buyers may propose different terms at media buy creation — sellers accept, reject (TERMS_REJECTED), or adjust per their policy."
        ),
    ] = None
    performance_standards: Annotated[
        list[performance_standard.PerformanceStandard] | None,
        Field(
            description="Seller's default performance standards for this product: viewability, IVT, completion rate, brand safety, attention score. Buyers may propose different standards at media buy creation. When absent, no structured performance standards apply.",
            min_length=1,
        ),
    ] = None
    cancellation_policy: Annotated[
        cancellation_policy_1.CancellationPolicy | None,
        Field(
            description='Cancellation terms for this product. Declares the minimum notice period required before cancellation takes effect and any penalties for insufficient notice. Relevant for guaranteed delivery products. Buyers accept these terms by creating a media buy against the product.'
        ),
    ] = None
    allowed_actions: Annotated[
        list[product_allowed_action.ProductAllowedAction] | None,
        Field(
            description='Actions buyers may perform on buys created against this product, scoped to statuses and modes. Advisory template — the authoritative per-buy capability is `available_actions[]` on the buy response, which resolves modes against current buy state, account tier, and negotiated terms. Buyers SHOULD use this for pre-flight product selection ("which products let me self-serve cancel within 72hr?") and read `available_actions[]` for runtime decisions. The array is uniquely keyed by `action` — sellers MUST NOT emit two entries with the same `action` value. Absence means the seller has not declared a structured action surface for this product — buyers fall back to `valid_actions[]` on buy responses for the flat string vocabulary.',
            min_length=1,
        ),
    ] = None
    reporting_capabilities: reporting_capabilities_1.ReportingCapabilities
    creative_policy: creative_policy_1.CreativePolicy | None = None
    is_custom: Annotated[
        bool | None,
        Field(
            description='Whether this product is a request-specific configured offer rather than a reusable baseline product. Sellers MUST set true when targeting, disclosed resolution, pricing, forecast assumptions, inventory, or terms are bound for a particular discovery/refinement lineage. Products issued through targeting-aware discovery include expires_at even when exact acceptance omits targeting_resolution. For backward compatibility, is_custom alone does not make expires_at schema-required.'
        ),
    ] = None
    property_targeting_allowed: Annotated[
        bool | None,
        Field(
            description="Whether buyers can select a subset of this product's publisher_properties through targeting_overlay.property_list. When false, the product is fixed inventory: it matches requested property targeting only when its inherent property set already satisfies the request, or when a configured product discloses additional inventory through targeting_resolution."
        ),
    ] = False
    data_provider_signals: Annotated[
        list[data_provider_signal_selector.DataProviderSignalSelector] | None,
        Field(
            deprecated=True,
            description='Deprecated. Legacy/non-selectable metadata for data-provider signals already bundled into or associated with this product. This field does not provide buyer-selectable options, prices, or seller activation handles. Use included_signals for non-selectable product signal metadata, or signal_targeting_options for selectable package-level signal groups.',
        ),
    ] = None
    included_signals: Annotated[
        list[signal_listing.SignalListing] | None,
        Field(
            description="Non-selectable signal metadata for signals already included in, bundled with, or planned into this product. These signals describe what the product is; buyers do not select them in packages[].targeting_overlay.signal_targeting_groups and this field does not imply package-level signal targeting. Use signal_ref scope 'data_provider' or 'signal_source' to reference externally defined signals without redefining their name or value_type. Use signal_ref scope 'product' with name and value_type when the included signal is defined only by this product.",
            min_length=1,
        ),
    ] = None
    signal_targeting_options: Annotated[
        list[product_signal_targeting_option.ProductSignalTargetingOption] | None,
        Field(
            description="Inline seller-offered signals that may be applied to packages for this product at create_media_buy time. Each entry references a named signal definition with signal_ref scope 'product' for a product-local signal option, scope 'data_provider' for an external signal definition published in adagents.json signals[] that the seller is authorized to apply, or scope 'signal_source' for a source-native signal. Product-local options define name and value_type inline; data-provider and signal-source options may omit those fields when the referenced definition or source is authoritative. Use this field when the selectable menu is product-specific, has product-specific pricing or activation handles, is the relevant subset for a brief/refine result, or should be rendered without an additional get_signals call. Wholesale products may omit this field and rely on get_signals for the selectable signal feed. Buyers select eligible signals through packages[].targeting_overlay.signal_targeting_groups when signal_targeting_rules allow; fixed/default entries are applied by the seller and echoed on the package state. Sellers MUST set signal_targeting_allowed to true whenever this field is present. Bundled, non-selectable signal metadata belongs in included_signals; legacy data_provider_signals may appear only for backwards compatibility.",
            min_length=1,
        ),
    ] = None
    signal_targeting_rules: Annotated[
        signal_targeting_rules_1.SignalTargetingRules | None,
        Field(
            description='Composition rules for selecting signals on this product. The selectable signal menu may come from inline signal_targeting_options or from get_signals when a wholesale product omits inline options. This is product-scoped because products may be backed by different ad servers with different Boolean targeting support and group limits.'
        ),
    ] = None
    signal_targeting_allowed: Annotated[
        bool | None,
        Field(
            description='Whether this product has a package-level signal_targeting_groups surface. When false (default), signals are bundled into the product terms and cannot be selected or explicitly echoed as package signal groups. When true, eligible signals from inline signal_targeting_options or from get_signals may be buyer-selected or seller-applied according to signal_targeting_rules and are represented through packages[].targeting_overlay.signal_targeting_groups. Editability is controlled by signal_targeting_rules; fixed/default-only products still set this to true when applied signal groups are echoed.'
        ),
    ] = False
    demographic_targeting: Annotated[
        demographic_targeting_capability.DemographicTargetingCapability | None,
        Field(
            description='Exact demographic execution available for this product. Buyers MUST use this product-scoped declaration, not the seller-wide get_adcp_capabilities rollup, to preflight a demographic predicate.'
        ),
    ] = None
    overlay_support: Annotated[
        targeting_overlay_support.TargetingOverlaySupport | None,
        Field(
            description='Binding product-scoped targeting dimensions the buyer may set independently on packages after discovery. Presence guarantees selectable capability subject to disclosed limits, not inventory or a forecast for every possible value. Targeting satisfied only through inherent product scope does not appear here. Returned products MUST cover every field requested through get_products.required_overlay_support. A later supported selection with no available inventory returns PRODUCT_UNAVAILABLE on create; an update outside the original priced envelope may return REQUOTE_REQUIRED.'
        ),
    ] = None
    targeting_resolution: Annotated[
        product_targeting_resolution.ProductTargetingResolution | None,
        Field(
            description='Discovery-time targeting resolution bound to this configured product. modifications sparsely disclose product-specific differences from get_products.targeting_overlay. Request-level brief interpretation is returned once on GetProductsResponse.targeting_resolution. Exact structured overlay values are not repeated. Selecting product_id accepts the disclosed modifications; product forecast and pricing MUST reflect them.'
        ),
    ] = None
    audience_evidence: Annotated[
        list[audience_evidence_1.AudienceEvidence] | None,
        Field(
            description='Immutable population-level evidence explaining why this inventory may suit an audience. This supports discovery, comparison, and planning only. It does not imply exact demographic targeting, user-level signal membership, or legal-age verification. Sellers MUST publish each distinct snapshot with a new snapshot_id and content_digest.',
            min_length=1,
        ),
    ] = None
    audience_evidence_selections: Annotated[
        list[audience_evidence_selection.AudienceEvidenceSelection] | None,
        Field(
            description='Exact evidence snapshots that satisfied required eligibility or affected seller ranking for this get_products result. When audience_evidence_requirements was supplied and evidence influenced inclusion or rank, sellers MUST return the relevant selections; an absent-evidence match under evidence_presence when_available has no selection. Product selections use decision_use recommendation or eligibility.',
            min_length=1,
        ),
    ] = None
    catalog_types: Annotated[
        list[catalog_type.CatalogType] | None,
        Field(
            description='Catalog types this product supports for catalog-driven campaigns. A sponsored product listing declares ["product"], a job board declares ["job", "offering"]. Buyers match synced catalogs to products via this field.',
            min_length=1,
        ),
    ] = None
    metric_optimization: Annotated[
        MetricOptimization | None,
        Field(
            description="Metric optimization capabilities for this product. Presence indicates the product supports optimization_goals with kind: 'metric'. No event source or conversion tracking setup required — the seller tracks these metrics natively."
        ),
    ] = None
    vendor_metric_optimization: Annotated[
        vendor_metric_optimization_1.VendorMetricOptimization | None,
        Field(
            description="Vendor-attested metric optimization capabilities for this product. Presence indicates the product supports `optimization_goals` with `kind: 'vendor_metric'` — the seller's bidding stack can steer delivery toward a specific vendor's measurement (e.g., DV/IAS/Adelaide attention, Scope3 emissions, Kantar brand lift, retail-media partner metrics). Distinct from `metric_optimization` (seller-native metrics with no vendor binding) and from `reporting_capabilities.vendor_metrics` (which declares what the product can *report* rather than what it can *optimize against*). A product may report a vendor metric without being able to optimize for it. Buyers MUST verify the goal's `(vendor, metric_id)` is in `supported_metrics` AND that the package's `committed_metrics[]` includes a matching `{ scope: 'vendor', vendor, metric_id }` entry — optimization without committed reporting is unverifiable and is rejected at the wire level."
        ),
    ] = None
    max_optimization_goals: Annotated[
        int | None,
        Field(
            description='Maximum number of optimization_goals this product accepts on a package. When absent, no limit is declared. Most social platforms accept only 1 goal — buyers sending arrays longer than this value should expect the seller to use only the highest-priority (lowest priority number) goal.',
            ge=1,
        ),
    ] = None
    measurement_readiness: Annotated[
        measurement_readiness_1.MeasurementReadiness | None,
        Field(
            description="Assessment of whether the buyer's event source setup is sufficient for this product to optimize effectively. Only present when the seller can evaluate the buyer's account context. Buyers should check this before creating media buys with event-based optimization goals."
        ),
    ] = None
    conversion_tracking: Annotated[
        ConversionTracking | None,
        Field(
            description="Conversion event tracking for this product. Presence indicates the product supports optimization_goals with kind: 'event'. Seller-level capabilities (supported event types, UID types, attribution windows) are declared in get_adcp_capabilities."
        ),
    ] = None
    catalog_match: Annotated[
        CatalogMatch | None,
        Field(
            description='When the buyer provides a catalog on get_products, indicates which catalog items are eligible for this product. Only present for products where catalog matching is relevant (e.g., sponsored product listings, job boards, hotel ads).'
        ),
    ] = None
    brief_relevance: Annotated[
        str | None,
        Field(
            description='Explanation of why this product matches the brief (only included when brief is provided)'
        ),
    ] = None
    expires_at: Annotated[
        AwareDatetime | None,
        Field(
            description='Expiration timestamp. Required for request-specific configured products whose targeting resolution, price, forecast, inventory, or terms are time-bound. After this time, a seller that still recognizes the issued configured ID within the authenticated account and referenced discovery/refinement lineage rejects create_media_buy with PRODUCT_EXPIRED and the buyer re-runs get_products. Once the seller no longer retains an expiry tombstone, or whenever the ID belongs to another account or lineage, PRODUCT_NOT_FOUND applies instead; sellers are not required to retain tombstones indefinitely and MUST NOT disclose cross-tenant existence through error choice.'
        ),
    ] = None
    product_card: Annotated[
        ProductCard | None,
        Field(
            description='Optional standard visual card for displaying this product in user interfaces (catalog browsers, dashboards, agent UIs). Distinct from `format` — product_card describes the UI rendering of the product itself, not the ad creative the product accepts. Typed inline; no format_id indirection. Receivers render the card directly from these fields.'
        ),
    ] = None
    product_card_detailed: Annotated[
        ProductCardDetailed | None,
        Field(
            description='Optional detailed card with hero + carousel + structured specifications, for rich product presentation (media-kit-style pages, full product detail views). Distinct from `format` — describes the UI rendering of the product itself, not the ad creative the product accepts. Typed inline; no format_id indirection.'
        ),
    ] = None
    collections: Annotated[
        list[collection_selector.CollectionSelector] | None,
        Field(
            description='Collections available in this product. Each entry references collections declared in an adagents.json by domain and collection ID. Buyers resolve full collection objects from the referenced adagents.json.',
            min_length=1,
        ),
    ] = None
    collection_targeting_allowed: Annotated[
        bool | None,
        Field(
            description="Whether buyers can select a subset of this product's collections through targeting_overlay.collection_list. When false, the product is a fixed bundle; when true, collection selection is a product-scoped overlay capability."
        ),
    ] = False
    installments: Annotated[
        list[installment.Installment] | None,
        Field(
            description='Specific installments included in this product. Each installment references its parent collection via collection_id when the product spans multiple collections. When absent with collections present, the product covers the collections broadly (run-of-collection).'
        ),
    ] = None
    enforced_policies: Annotated[
        list[str] | None,
        Field(
            description='Registry policy IDs the seller enforces for this product. Enforcement level comes from the policy registry. Buyers can filter products by required policies.'
        ),
    ] = None
    trusted_match: Annotated[
        TrustedMatch | None,
        Field(
            description='Trusted Match Protocol capabilities for this product. When present, the product supports real-time contextual and/or identity matching via TMP. Buyers use this to determine what response types the publisher can accept and whether brands can be selected dynamically at match time.'
        ),
    ] = None
    material_submission: Annotated[
        MaterialSubmission | None,
        Field(
            description="Instructions for submitting physical creative materials (print, static OOH, cinema). Present only for products requiring physical delivery outside the digital creative assignment flow. Buyer agents MUST validate url and email domains against the seller's known domains (from adagents.json) before submitting materials. Never auto-submit without human confirmation."
        ),
    ] = 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 allowed_actions : list[adcp.types.generated_poc.core.product_allowed_action.ProductAllowedAction] | None
var audience_evidence : list[adcp.types.generated_poc.core.audience_evidence.AudienceEvidence] | None
var audience_evidence_selections : list[adcp.types.generated_poc.core.audience_evidence_selection.AudienceEvidenceSelection] | None
var audio_distribution_types : list[adcp.types.generated_poc.enums.audio_distribution_type.AudioDistributionType] | None
var brief_relevance : str | None
var cancellation_policy : adcp.types.generated_poc.core.cancellation_policy.CancellationPolicy | None
var catalog_match : adcp.types.generated_poc.core.product.CatalogMatch | None
var catalog_types : list[adcp.types.generated_poc.enums.catalog_type.CatalogType] | None
var channels : list[adcp.types.generated_poc.enums.channels.MediaChannel] | None
var collection_targeting_allowed : bool | None
var collections : list[adcp.types.generated_poc.core.collection_selector.CollectionSelector] | None
var conversion_tracking : adcp.types.generated_poc.core.product.ConversionTracking | None
var creative_policy : adcp.types.generated_poc.core.creative_policy.CreativePolicy | None
var data_provider_signals : list[adcp.types.generated_poc.core.data_provider_signal_selector.DataProviderSignalSelector] | None
var delivery_measurement : adcp.types.generated_poc.core.product.DeliveryMeasurement | None
var delivery_type : adcp.types.generated_poc.enums.delivery_type.DeliveryType
var demographic_targeting : adcp.types.generated_poc.core.demographic_targeting_capability.DemographicTargetingCapability | None
var description : str
var enforced_policies : list[str] | None
var exclusivity : adcp.types.generated_poc.enums.exclusivity.Exclusivity | 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 format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None
var format_options : list[adcp.types.generated_poc.core.product_format_declaration.ProductFormatDeclaration] | None
var included_signals : list[adcp.types.generated_poc.core.signal_listing.SignalListing] | None
var installments : list[adcp.types.generated_poc.core.installment.Installment] | None
var is_custom : bool | None
var material_submission : adcp.types.generated_poc.core.product.MaterialSubmission | None
var max_optimization_goals : int | None
var measurement_readiness : adcp.types.generated_poc.core.measurement_readiness.MeasurementReadiness | None
var measurement_terms : adcp.types.generated_poc.core.measurement_terms.MeasurementTerms | None
var metric_optimization : adcp.types.generated_poc.core.product.MetricOptimization | None
var model_config
var name : str
var outcome_measurement : adcp.types.generated_poc.core.outcome_measurement.OutcomeMeasurement | None
var overlay_support : adcp.types.generated_poc.core.targeting_overlay_support.TargetingOverlaySupport | None
var performance_standards : list[adcp.types.generated_poc.core.performance_standard.PerformanceStandard] | None
var placements : list[adcp.types.generated_poc.core.placement.Placement] | None
var pricing_options : list[adcp.types.generated_poc.core.pricing_option.PricingOption]
var product_card : adcp.types.generated_poc.core.product.ProductCard | None
var product_card_detailed : adcp.types.generated_poc.core.product.ProductCardDetailed | None
var product_id : str
var property_targeting_allowed : bool | None
var publisher_properties : list[adcp.types.generated_poc.core.product.PublisherProperty]
var reporting_capabilities : adcp.types.generated_poc.core.reporting_capabilities.ReportingCapabilities
var signal_targeting_allowed : bool | None
var signal_targeting_options : list[adcp.types.generated_poc.core.product_signal_targeting_option.ProductSignalTargetingOption] | None
var signal_targeting_rules : adcp.types.generated_poc.core.signal_targeting_rules.SignalTargetingRules | None
var social_placement_surfaces : list[adcp.types.generated_poc.enums.social_placement_surface.SocialPlacementSurface] | None
var sponsored_placement_types : list[adcp.types.generated_poc.enums.sponsored_placement_type.SponsoredPlacementType] | None
var targeting_resolution : adcp.types.generated_poc.core.product_targeting_resolution.ProductTargetingResolution | None
var trusted_match : adcp.types.generated_poc.core.product.TrustedMatch | None
var vendor_metric_optimization : adcp.types.generated_poc.core.vendor_metric_optimization.VendorMetricOptimization | None
var video_placement_types : list[adcp.types.generated_poc.enums.video_placement_type.VideoPlacementType] | None

Inherited members

class LegacyProductFilters (**data: Any)
Expand source code
class ProductFilters(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    delivery_type: delivery_type_1.DeliveryType | None = None
    exclusivity: Annotated[
        exclusivity_1.Exclusivity | None,
        Field(
            description="Filter by exclusivity level. Returns products matching the specified exclusivity (e.g., 'exclusive' returns only sole-sponsorship products)."
        ),
    ] = None
    is_fixed_price: Annotated[
        bool | None,
        Field(
            description='Legacy filter for fixed versus auction pricing availability. true returns options with fixed_price; false returns auction options whose price is established through bid_price. Contingent options such as revenue_share match neither value and MUST be omitted whenever this filter is present. Use pricing_structures to discover contingent pricing. Products with both fixed and auction options match both true and false, but sellers MUST return only entries matching the requested structure.'
        ),
    ] = None
    pricing_structures: Annotated[
        list[pricing_structure.PricingStructure] | None,
        Field(
            description='Filter by how the payable price is determined. fixed selects options with fixed_price, auction selects options established through bid_price, and contingent selects options calculated from a measured business outcome after delivery (currently revenue_share). Products match when at least one pricing option has a requested structure. Sellers MUST return only matching pricing_options entries. When combined with is_fixed_price, both filters apply and the returned entries must satisfy both.',
            min_length=1,
        ),
    ] = None
    pricing_currencies: Annotated[
        list[PricingCurrency] | None,
        Field(
            description='Filter by currencies the buyer can use for the media product transaction, using ISO 4217 currency codes. Products match when they offer at least one product-level pricing_options entry in one of the requested currencies and any seller-applied or otherwise mandatory product-scoped signal charges are satisfiable in one of those currencies or have no incremental price. Mandatory custom signal pricing without currency is not satisfiable for this filter unless the seller can truthfully treat it as having no incremental price. Sellers MUST return only product pricing_options entries whose currency is in this list so buyers can select deterministically from discovery. This filter does not require pruning optional signal or vendor add-on pricing; buyers should avoid optional add-ons priced only in unsupported currencies.',
            min_length=1,
        ),
    ] = None
    format_ids: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='Deprecated in AdCP 3.2; removed in AdCP 4.0. Filter by legacy named-format references. Use `format_kinds` or `format_option_refs`.',
            min_length=1,
        ),
    ] = None
    format_kinds: Annotated[
        list[canonical_format_kind.CanonicalFormatKind] | None,
        Field(
            description='Filter to products accepting any of these canonical format kinds.',
            min_length=1,
        ),
    ] = None
    format_option_refs: Annotated[
        list[format_option_ref.FormatOptionReference] | None,
        Field(
            description='Filter to products accepting any of these exact publisher- or product-scoped canonical format options.',
            min_length=1,
        ),
    ] = None
    standard_formats_only: Annotated[
        bool | None, Field(description='Only return products accepting IAB standard formats')
    ] = None
    min_exposures: Annotated[
        int | None,
        Field(description='Minimum exposures/impressions needed for measurement validity', ge=1),
    ] = None
    start_date: Annotated[
        date | None,
        Field(
            description='Campaign start date (ISO 8601 date format: YYYY-MM-DD) for availability checks'
        ),
    ] = None
    end_date: Annotated[
        date | None,
        Field(
            description='Campaign end date (ISO 8601 date format: YYYY-MM-DD) for availability checks'
        ),
    ] = None
    budget_range: Annotated[
        BudgetRange | None, Field(description='Budget range to filter appropriate products')
    ] = None
    countries: Annotated[
        list[Country] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use get_products.targeting_overlay.geo_countries so returned pricing and forecasts are scoped to the concrete delivery constraint.',
            min_length=1,
        ),
    ] = None
    regions: Annotated[
        list[Region] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use get_products.targeting_overlay.geo_regions. Sellers resolve the requested outcome through inherent product scope or selectable targeting.',
            min_length=1,
        ),
    ] = None
    metros: Annotated[
        list[Metro] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use get_products.targeting_overlay.geo_metros for known values or required_overlay_support.geo_metros when values will be supplied on packages later.',
            min_length=1,
        ),
    ] = None
    channels: Annotated[
        list[channels_1.MediaChannel] | None,
        Field(
            description="Filter by advertising channels (e.g., ['display', 'ctv', 'dooh'])",
            min_length=1,
        ),
    ] = None
    video_placement_types: Annotated[
        list[video_placement_type.VideoPlacementType] | None,
        Field(
            description='Filter product metadata by declared video placement types, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. A product matches when its declared array intersects the requested array. This is discovery classification only and does not promise delivery exclusively on a requested type; buyers needing exact placement inventory use targeting_overlay.placement_selection against targetable placements. This filter has set semantics for wholesale feed canonicalization.',
            min_length=1,
        ),
    ] = None
    audio_distribution_types: Annotated[
        list[audio_distribution_type.AudioDistributionType] | None,
        Field(
            description='Filter product metadata by declared audio distribution types, using IAB Tech Lab/OpenRTB 2.6 audio.feed definitions with AdCP-native names. A product matches when its declared array intersects the requested array. This is discovery classification only and does not promise delivery exclusively on a requested type. This filter has set semantics for wholesale feed canonicalization.',
            min_length=1,
        ),
    ] = None
    sponsored_placement_types: Annotated[
        list[sponsored_placement_type.SponsoredPlacementType] | None,
        Field(
            description='Filter retail-media product metadata by declared sponsored-placement types (sponsored search, sponsored display, or sponsored native). A product matches when its declared array intersects the requested array. This is discovery classification only and does not promise delivery exclusively on a requested type. This filter has set semantics for wholesale feed canonicalization.',
            min_length=1,
        ),
    ] = None
    social_placement_surfaces: Annotated[
        list[social_placement_surface.SocialPlacementSurface] | None,
        Field(
            description='Filter social-product metadata by declared placement surfaces (feed, stories, short_video, explore, or search). A product matches when its declared array intersects the requested array. This is discovery classification only and does not promise delivery exclusively on a requested surface; buyers needing an exact public placement use targeting_overlay.placement_selection. This filter has set semantics for wholesale feed canonicalization.',
            min_length=1,
        ),
    ] = None
    required_axe_integrations: Annotated[
        list[AnyUrl] | None,
        Field(
            deprecated=True,
            description='Deprecated: Use trusted_match filter instead. Filter to products executable through specific agentic ad exchanges. URLs are canonical identifiers.',
        ),
    ] = None
    trusted_match: Annotated[
        TrustedMatch | None,
        Field(
            description='Filter products by Trusted Match Protocol capabilities. Only products with matching TMP support are returned.'
        ),
    ] = None
    required_features: Annotated[
        media_buy_features.MediaBuyFeatures | None,
        Field(
            description='Filter to products from sellers supporting specific protocol features. Only features set to true are used for filtering.'
        ),
    ] = None
    required_geo_targeting: Annotated[
        list[RequiredGeoTargetingItem] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use get_products.required_overlay_support, which is product-scoped and applies consistently to geographic and non-geographic targeting dimensions.',
            min_length=1,
        ),
    ] = None
    signal_targeting: Annotated[
        list[SignalTargetingItem] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use get_products.targeting_overlay.signal_targeting_groups for known selections or required_overlay_support.signal_targeting_groups when selection will happen later. Legacy entries remain accepted during migration.',
            min_length=1,
        ),
    ] = None
    postal_areas: Annotated[
        list[postal_area.PostalArea] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use get_products.targeting_overlay.geo_postal_areas for known values or required_overlay_support.geo_postal_areas when values will be supplied later.',
            min_length=1,
        ),
    ] = None
    geo_proximity: Annotated[
        list[GeoProximityItem] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use get_products.targeting_overlay.geo_proximity. Sellers resolve the requested outcome through inherent product scope or selectable targeting and forecast the resulting inventory.',
            min_length=1,
        ),
    ] = None
    required_performance_standards: Annotated[
        list[performance_standard.PerformanceStandard] | None,
        Field(
            description="Filter to products that can meet the buyer's performance standard requirements. Each entry specifies a metric, minimum threshold, and optionally a required vendor and standard. Products that cannot meet these thresholds or do not support the specified vendors are excluded. Use this to tell the seller upfront: 'I need DoubleVerify for viewability at 70% MRC.'",
            min_length=1,
        ),
    ] = None
    required_metrics: Annotated[
        list[available_metric.AvailableMetric] | None,
        Field(
            description="Filter to products whose `reporting_capabilities.available_metrics` is a superset of these metrics — i.e., products that commit to reporting all listed metrics in delivery responses. Use this for capability-level discovery (e.g., 'I need products that report `completed_views` for a CTV CPCV buy'); guarantee-level requirements with thresholds belong in `required_performance_standards` and `measurement_terms`. Sellers MUST silently exclude products that cannot meet this list (filter-not-fail; do not return an error). The product's declared `available_metrics` becomes the binding reporting contract carried into the resulting media buy — the same metric vocabulary is used to compute `missing_metrics` on `get_media_buy_delivery`.",
            examples=[
                ['completed_views'],
                ['completed_views', 'completion_rate'],
                ['impressions', 'spend', 'engagements'],
            ],
            min_length=1,
        ),
    ] = None
    required_vendor_metrics: Annotated[
        list[RequiredVendorMetric] | None,
        Field(
            description="Filter to products whose `reporting_capabilities.vendor_metrics` matches these criteria. Each entry pins a `vendor` (matches any metric from that vendor), a `metric_id` (matches the metric across any vendor that uses that identifier), or both (specific vendor's specific metric). A product matches if its declared `vendor_metrics` covers ALL listed entries (AND across entries; pins within an entry are conjunctive). Cross-vendor discovery (e.g., 'I need attention measurement from any vendor that does it') is the buyer agent's responsibility — the agent resolves which vendors offer a category via the vendors' `brand.json` records, then enumerates them as filter entries. AdCP does not carry vendor-side metric metadata (category, methodology, standard alignment) in the filter surface; that lives at the vendor and is queried out-of-band. Sellers MUST silently exclude non-matching products (filter-not-fail; do not return an error) — same convention as the other `required_*` filters.",
            examples=[
                [{'vendor': {'domain': 'attentionvendor.example'}}],
                [
                    {
                        'vendor': {'domain': 'panelmeasurement.example'},
                        'metric_id': 'demographic_reach',
                    }
                ],
                [
                    {'vendor': {'domain': 'attentionvendor.example'}},
                    {'vendor': {'domain': 'secondattentionvendor.example'}},
                ],
            ],
            min_length=1,
        ),
    ] = None
    keywords: Annotated[
        list[Keyword] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use get_products.targeting_overlay.keyword_targets for concrete terms or required_overlay_support.keyword_targets when terms will be supplied later. Broad thematic intent remains in brief.',
            min_length=1,
        ),
    ] = None
    audience_evidence_requirements: Annotated[
        audience_evidence_requirements_1.AudienceEvidenceRequirements | None,
        Field(
            description='Buyer policy for evaluating Product.audience_evidence. In required mode, sellers MUST apply the evidence_presence and admissibility semantics and exclude non-matching products; they MUST NOT ignore an unsupported hard requirement. In preferred mode, sellers use matches for ranking and explain the evidence selected. Buyers SHOULD inspect media_buy.audience_evidence capabilities before sending this object.'
        ),
    ] = None
    ext: Annotated[
        ext_1.ExtensionObject | None,
        Field(
            description='Vendor-namespaced extension parameters for seller-specific filter criteria not covered by standard fields. Keys MUST be namespaced under a vendor or platform key (e.g., ext.gam, ext.platform_x). Sellers MUST treat all values as untrusted buyer input; do not interpolate into LLM prompts, SQL queries, or system commands without sanitization. Persistent use of an extension key across multiple buyers is a signal to propose standardization.'
        ),
    ] = 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 audience_evidence_requirements : adcp.types.generated_poc.core.audience_evidence_requirements.AudienceEvidenceRequirements | None
var audio_distribution_types : list[adcp.types.generated_poc.enums.audio_distribution_type.AudioDistributionType] | None
var budget_range : adcp.types.generated_poc.core.product_filters.BudgetRange | None
var channels : list[adcp.types.generated_poc.enums.channels.MediaChannel] | None
var countries : list[adcp.types.generated_poc.core.product_filters.Country] | None
var delivery_type : adcp.types.generated_poc.enums.delivery_type.DeliveryType | None
var end_date : datetime.date | None
var exclusivity : adcp.types.generated_poc.enums.exclusivity.Exclusivity | 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_kinds : list[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 geo_proximity : list[adcp.types.generated_poc.core.product_filters.GeoProximityItem] | None
var is_fixed_price : bool | None
var keywords : list[adcp.types.generated_poc.core.product_filters.Keyword] | None
var metros : list[adcp.types.generated_poc.core.product_filters.Metro] | None
var min_exposures : int | None
var model_config
var postal_areas : list[adcp.types.generated_poc.core.postal_area.PostalArea] | None
var pricing_currencies : list[adcp.types.generated_poc.core.product_filters.PricingCurrency] | None
var pricing_structures : list[adcp.types.generated_poc.enums.pricing_structure.PricingStructure] | None
var regions : list[adcp.types.generated_poc.core.product_filters.Region] | None
var required_axe_integrations : list[pydantic.networks.AnyUrl] | None
var required_features : adcp.types.generated_poc.core.media_buy_features.MediaBuyFeatures | None
var required_geo_targeting : list[adcp.types.generated_poc.core.product_filters.RequiredGeoTargetingItem] | None
var required_metrics : list[adcp.types.generated_poc.enums.available_metric.AvailableMetric] | None
var required_performance_standards : list[adcp.types.generated_poc.core.performance_standard.PerformanceStandard] | None
var required_vendor_metrics : list[adcp.types.generated_poc.core.product_filters.RequiredVendorMetric] | None
var signal_targeting : list[adcp.types.generated_poc.core.product_filters.SignalTargetingItem] | None
var social_placement_surfaces : list[adcp.types.generated_poc.enums.social_placement_surface.SocialPlacementSurface] | None
var sponsored_placement_types : list[adcp.types.generated_poc.enums.sponsored_placement_type.SponsoredPlacementType] | None
var standard_formats_only : bool | None
var start_date : datetime.date | None
var trusted_match : adcp.types.generated_poc.core.product_filters.TrustedMatch | None
var video_placement_types : list[adcp.types.generated_poc.enums.video_placement_type.VideoPlacementType] | None

Inherited members

class LegacyProductFormatDeclaration (**data: Any)
Expand source code
class ProductFormatDeclaration(AdCPBaseModel):
    format_option_id: Annotated[
        str | None,
        Field(
            description="Stable identifier for this declaration within its namespace. REQUIRED when a product contains multiple declarations with the same format_kind and SHOULD be set on every entry. Publisher-backed options pair it with publisher_domain; product-local options omit publisher_domain. When a single declaration has a unique format_kind and no ID, buyers author canonically with format_kind plus params; they MUST NOT fall back to deprecated format_ids merely because this optional ID is absent. Examples: 'display_image_300x250', 'responsive_search', 'daily_pulse_homepage_image'."
        ),
    ] = None
    publisher_domain: Annotated[
        str | None,
        Field(
            description="Namespace for `format_option_id` when this declaration references or narrows a publisher-declared format option from that publisher's adagents.json top-level `formats[]`. Product-local options omit this field and are selected by `format_option_id` within the target product.",
            pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$',
        ),
    ] = None
    display_name: Annotated[
        str | None,
        Field(
            description="Optional seller-controlled human-readable label for this format declaration. Used by buyer dashboards, catalog UIs, and reporting surfaces to show a seller's own naming ('Homepage Takeover', 'Branded Canvas', 'Reels Premium Video') rather than the raw `format_kind` or `format_option_id`. Has no machine semantics — buyer agents route on `format_kind` and `format_option_id`; `display_name` is purely for human presentation. Freeform; no enumeration. Sellers SHOULD keep it stable once published to avoid dashboard churn."
        ),
    ] = None
    sample_render_url: Annotated[
        AnyUrl | None,
        Field(
            description='Optional public HTTPS page where a human can inspect a sample render of this declaration using assets chosen by the party publishing the enclosing declaration. Consumers MUST identify that source correctly: publisher or community mirror for `adagents.json` `formats[]`, seller for product or inline-placement declarations, and creative agent for `creative.supported_formats`. Informational only: this is not a renderer endpoint, buyer-asset preview, validation result, creative approval, proof of publisher acceptance, or guarantee of live delivery. Declaring parties SHOULD keep the URL stable while the declaration is active.'
        ),
    ] = None
    applies_to_channels: Annotated[
        list[channels.MediaChannel] | None,
        Field(
            description="Optional subset of the parent product's `channels` to which this declaration applies. When omitted, the declaration applies to ALL channels declared on the product. Lets a multi-channel product (e.g., `channels: ['display', 'video']`) carry distinct format_options per channel — `format_options: [{format_kind: 'image', applies_to_channels: ['display']}, {format_kind: 'video_hosted', applies_to_channels: ['video']}]`. Buyers ship channel-appropriate manifests per `applies_to_channels`."
        ),
    ] = None
    seller_preference: Annotated[
        SellerPreference | None,
        Field(
            description="Optional soft routing hint *within* a product's accepted set of formats — NOT an enforcement axis. `preferred` — seller actively recommends this format (often because of measurement, viewability, or render-quality differences); `accepted` — supported on equal footing with other format_options (default when omitted); `discouraged` — supported but suboptimal (e.g., legacy 3p-tag where the seller would prefer html5 for OM-SDK coverage). Buyer agents picking between format_options SHOULD respect seller preferences when their own constraints don't override.\n\n**Not an enforcement axis (normative).** `seller_preference` does NOT carry the meaning of 'this format won't work / required-only'. That case is structural: `format_options[]` IS the closed set of accepted formats; anything outside the list is rejected at `create_media_buy` regardless of preference. A seller that accepts only one format lists exactly that one entry — the structural fact does the enforcement work, no enum value needed. There is intentionally no `required` value; preference is bounded to *ranking within the already-accepted set*, not gating into it."
        ),
    ] = None
    locale_policy: Annotated[
        creative_locale_policy.CreativeLocalePolicy | None,
        Field(
            description='Optional seller-enforced creative-locale constraint for this format option. This is product/placement eligibility, not a new format kind or synthetic locale-specific format ID. Because legacy format_ids cannot preserve this constraint, declarations carrying locale_policy MUST set canonical_formats_only to true and MUST NOT carry v1_format_ref.'
        ),
    ] = None
    canonical_formats_only: Annotated[
        bool | None,
        Field(
            description='When true, this format declaration has no clean v1 projection and SDKs MUST NOT synthesize a v1 `format_id` for it. Buyers reading the product on the v1 wire path see this declaration absent from `format_ids`; only v2-aware buyers (reading `format_options`) discover it. Set explicitly for `format_kind: "custom"` declarations (no canonical exists in v1 to project onto) and for declarations whose canonical/parameter shape cannot round-trip through a v1 named format without semantic loss. The protocol does NOT mint synthetic v1 format_ids for unmappable declarations — the alternative (an `aao-synth/*` namespace populated automatically) was considered and rejected because adopters would index on synthetic IDs that have no stable identity. Producers SHOULD set `canonical_formats_only: true` rather than omit the declaration from `format_options` — explicit v2-only is more useful than silent absence.'
        ),
    ] = False
    experimental: Annotated[
        bool | None,
        Field(
            description="When true, this seller's specific canonical declaration may not work as declared even if the underlying canonical is stable. Buyers SHOULD preflight it with validate_input or in a sandbox before routing production budget and SHOULD filter it from default views unless the caller opts in. Experimental status never makes the deprecated named-format path preferable. This field is independent of the canonical's own experimental flag and replaces the earlier runtime_status enum."
        ),
    ] = False
    format_shape: Annotated[
        str | None,
        Field(
            description='REQUIRED when `format_kind: "custom"`; otherwise MUST be absent. Recognized global pattern this custom shape is an instance of, drawn from the [format-shape vocabulary registry](/schemas/core/format-shape-vocabulary.json) (`multi_placement_takeover`, `roadblock`, `branded_content`, `cross_screen_sponsorship`, `sponsorship_lockup`, `newsletter_sponsorship`, `ar_lens`, `playable`, `live_event_sponsorship`, …). Non-canonical values valid (validators MAY soft-warn) — adopters CAN ship a shape that isn\'t yet in the registry. Adding entries is a vocabulary PR. Once a `format_shape` entry sees 2+ adopters with substantively similar `format_schema` content for 90+ days, the working group promotes it to a first-class canonical.'
        ),
    ] = None
    v1_format_ref: Annotated[
        list[format_id.FormatReferenceStructuredObject] | None,
        Field(
            description="Authoritative v2 → v1 link, expressed as an array of one or more v1 `format_id` ({agent_url, id}) values. Each entry asserts that this canonical-formats declaration IS the same underlying format as the referenced v1 named format. Always an array (single-ref is `[{...}]`) so the multi-size case below has a clean wire shape — adopters surveyed in the SDK implementor review pushed for this over the lossy single-ref form.\n\nThe v2 declaration's `params` MUST narrow (be compatible with) each referenced v1 format's `requirements` — see the 'Narrows — formal definition' section in canonical-formats.mdx. SDKs comparing dual-emitted shapes (`Product.format_ids[]` ⊇ entries from `v1_format_ref` AND `Product.format_options[]` carrying this declaration) treat the link as the authoritative pairing and run the narrowing check between this declaration and EACH referenced v1 format file's `requirements`.\n\n**Multi-size fan-out (normative).** When the declaration carries `params.sizes: [{w,h}, ...]` (multi-size flexible slot), sellers SHOULD carry one `v1_format_ref[]` entry per size, each pointing at the per-size v1 named format in the AAO catalog. Example: a multi-size image declaration with `sizes: [300x250, 728x90, 970x250]` SHOULD carry `v1_format_ref: [{aao, display_300x250_image}, {aao, display_728x90_image}, {aao, display_970x250_image}]`. v1-only buyers then see the product on all three sizes via the `format_ids[]` dual-emission. When `v1_format_ref[]` count < `sizes[]` count, SDKs MUST emit `FORMAT_DECLARATION_V1_LOSSY_MULTI_SIZE` on the response `errors[]` (advisory, alongside the partial-coverage v1 emit — NOT in place of it). SDKs MAY (non-normative) fan out automatically by catalog lookup when `v1_format_ref[]` has length 1 and `sizes[]` has length N — opt-in, requires catalog access; sellers asserting refs is the source of truth.\n\nMutually exclusive with `canonical_formats_only: true` — a declaration can EITHER assert no v1 projection (`canonical_formats_only: true`) OR link to v1 named formats (`v1_format_ref[]`), never both. When neither is present, SDKs fall back to the resolution order in `v1-canonical-mapping.json` (seller's explicit `canonical` field on the v1 file → registry glob → structural match → fail-closed).\n\nThis is the v2-side authoritative replacement for the v1-side `canonical_parameters` field on `format.json` (which is deprecated for 3.1, removed at 4.0). Sellers SHOULD prefer authoring v2 declarations with `v1_format_ref[]` over mirroring the v2 shape onto v1 files via `canonical_parameters`; the directional link (v2 declaration → v1 identifiers) is the same fact without the parallel-shape drift surface.\n\n**AAO-hosted convention (normative).** For IAB-standard formats (image dimensions, VAST/DAAST tags, standard third-party tags, HTML5 banner bundles), sellers SHOULD point each `v1_format_ref[].agent_url` at the AAO-hosted canonical agent URL `https://creative.adcontextprotocol.org` and use the registry-published id (e.g., `display_300x250_image`, `video_vast_30s`, `audio_standard_30s`, `display_300x250_html`, `display_js`). This converges the v1-wire namespace: every seller's IAB MREC points at the same `{agent_url, id}` pair, so v1-only buyers' allowlists work uniformly. Without this convention, every publisher's 300x250 ships with a different `v1_format_ref` (theirs vs nytimes.example vs cnn.example vs …) and the v1 wire fragments into per-publisher namespaces — exactly what canonical-formats was designed to eliminate.\n\nFor platform-specific formats (Meta Reels, TikTok Spark, Snap Spotlight, etc.), each `v1_format_ref[].agent_url` SHOULD point at the platform's own agent_url when the platform has adopted AdCP and publishes its own `adagents.json` with `formats[]`. When the platform has NOT adopted AdCP, sellers SHOULD point at the AAO community-registry mirror — `https://creative.adcontextprotocol.org/translated/<platform>` + `id: <platform-format-name>` (e.g., `https://creative.adcontextprotocol.org/translated/meta` + `id: meta_reels`). This keeps the v1 namespace converged across all sellers selling that platform's inventory until the platform owns its own adagents.json.\n\n**Platform-adoption cutover (normative).** When a platform adopts AdCP and publishes its own adagents.json, sellers MUST update `v1_format_ref[].agent_url` to the platform's adopted agent_url in the same minor release as the AAO mirror entry's `superseded_by` field goes live (see `static/schemas/source/adagents.json#superseded_by`). The AAO mirror entry SHOULD continue serving for ≥1 minor release after `superseded_by` is set, returning an advisory 'superseded' marker so v1 buyer allowlists keyed on the mirror URL get an explicit signal rather than a silent break. **Identity-confusion note**: the mirror URL is *format-shape namespace*, NOT seller identity. Inventory authorization always flows from `authorized_agents[]` + publisher signing keys; a buyer matching `v1_format_ref[].agent_url` against an allowlist is matching format-shape provenance, not seller identity.\n\n**Mirror domain migration (3.1).** Earlier drafts used `https://mirror.adcontextprotocol.org/translated/<platform>`. As of this release, the convention is `https://creative.adcontextprotocol.org/translated/<platform>` — sibling content under the AAO catalog domain we already host. Adopters who hardcoded the earlier mirror URL MUST migrate to the new path; the canonical-formats.mdx migration section documents the move. No transitional redirect is currently published (the earlier subdomain was never provisioned).\n\nFor seller-bespoke formats (a publisher's `acme_homepage_takeover` that doesn't fit IAB conventions), each `v1_format_ref[].agent_url` is the seller's own agent_url and the id is seller-namespaced. These won't appear in `v1-canonical-mapping.json`'s registry; they're seller-asserted only.",
            min_length=1,
        ),
    ] = None
    format_schema: Annotated[
        platform_extension_ref.PlatformExtensionReference | None,
        Field(
            description='REQUIRED when `format_kind: "custom"`; otherwise MUST be absent. URI+digest reference to a fetchable schema describing this custom shape\'s actual `params` and `slots`. Same hosting model as `platform_extensions`: open-ecosystem publishers host the artifact at the canonical URI on their subdomain; closed-platform / walled-garden shapes resolve through the AAO mirror at `https://creative.adcontextprotocol.org/translated/...`. Buyer agents fetch by `uri@digest` (immutable per digest, aggressive caching, `Cache-Control: public, max-age=31536000, immutable`), validate `params` and `slots` against the fetched schema, and reason about manifests structurally — same mechanic as platform_extensions but at the format-structure level. Without `format_schema`, custom shapes would be opaque to buyer agents and the protocol would regress to per-seller integration code; that\'s why the schema is required, not optional.\n\n**Fetch contract (normative)** — `format_schema` is load-bearing for validation (unlike `platform_extensions`, which is informational on the *consumption* side). The *transport* rules below apply identically to BOTH fields — any SDK fetching a `platform-extension-ref.json` URI MUST apply this contract regardless of whether the field name is `format_schema` or `platform_extensions`. A shared SDK fetch path that drops to the weakest bar undermines `format_schema`\'s hardening. The consumption distinction (load-bearing vs informational) is about *what the body means*; the transport distinction is `https`-and-allowlisted regardless.\n\n- **Transport**: `https` only. Buyers MUST reject `http://`, `file://`, `data:`, and any non-`https` scheme. The URI MUST resolve to a JSON document that is itself a valid JSON Schema (Draft 07 or 2020-12; producers MUST declare `$schema`).\n- **SSRF protection**: buyers MUST resolve the URI hostname and reject if any resolved address is in RFC 1918 private space (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`), loopback (`127.0.0.0/8`, `::1`), link-local (`169.254.0.0/16`, `fe80::/10`), CGNAT (`100.64.0.0/10`), or any RFC 6761 special-use name (`.local`, `.localhost`, `.internal`, `.test`, `.example`, `.invalid`). Cloud metadata endpoints (`169.254.169.254`, `metadata.google.internal`, `kubernetes.default.svc`) are explicitly forbidden — these are credential-leak primitives. Buyers MUST pin the connection to the resolved IP (or re-resolve and re-validate the allowlist per request) to defeat DNS rebinding.\n- **HTTP redirects**: MUST be disabled. If a follow is implemented at all, the redirect target MUST pass the same scheme + SSRF + allowlist checks; otherwise the fetch hard-fails. Open redirects on same-origin paths are otherwise a free SSRF primitive.\n- **Response size cap**: response body MUST be capped at 1 MiB. Enforce during streaming, not after full buffering. Over-cap hard-fails identically to digest mismatch.\n- **Timeout**: SDKs SHOULD apply a fetch timeout ≤5 seconds. Timeout SHOULD be treated identically to an HTTP 5xx response (transient — retry policy at the SDK\'s discretion; on persistent failure surface as unresolved and skip the declaration for this session).\n- **Digest verification**: SHA-256 of the response body MUST equal `digest`. **Digest mismatch is a hard fail** — the buyer MUST treat the format declaration as unresolvable and MUST NOT validate manifests against the mismatched body. A divergent digest is either a malicious substitution or producer error; either way, falling back to the un-verified body breaks the trust model. Digest format: `sha256:` prefix + 64 lowercase hex characters. Cache key is `uri@digest`; digest mismatch MUST NOT be cached as a negative result keyed on `uri` alone (defeats CDN-flap recovery), and MUST be distinguishable in telemetry from network 5xx / 404 (sustained mismatch is a substitution-attack signal, not a flap).\n- **Sandboxing of `$ref`**: fetched schemas MAY use `$ref`. Buyers MUST resolve `$ref` only to URIs that are (a) same-origin as the parent `format_schema.uri` after RFC 3986 §6 normalization (lowercase scheme + host, strip default port, normalize path dot-segments, no userinfo component), OR (b) hosted under the AAO catalog domain (`https://creative.adcontextprotocol.org/...`), OR (c) intra-document JSON Pointer refs (`#/...`) bounded to the parent document\'s parsed tree. Cross-origin `$ref` to arbitrary URIs MUST be rejected. `$ref: file://...` MUST be rejected unconditionally. Transitive `$ref` chains MUST be bounded at depth ≤8 AND `$ref` count ≤256 across the resolved tree (depth 8 with breadth 100 per level is 10^16 nodes — depth alone is not enough). Publishers SHOULD inline rather than $ref where possible.\n- **Schema-compile bounds (DoS protection)**: validators MUST bound CPU/memory on fetched schemas. Recommended: compiled-schema keyword count ≤10 000, `pattern` regexes evaluated with a non-backtracking engine (re2) OR under a per-pattern timeout, per-manifest validation budget ≤250 ms (exceeded budget → treat manifest as invalid, surface telemetry signal). Without these, a \'valid\' schema with catastrophic regex backtracking or exponential `allOf`/`anyOf` expansion pins a CPU forever.\n- **Cache**: buyers cache fetched schemas by `uri@digest` and treat them as immutable (the same hosting contract as `platform_extensions`). On `404`, network partition, or persistent fetch failure, buyers SHOULD degrade gracefully (treat the declaration as unresolved, skip it for the current `get_products` response, surface via `errors[]` with the relevant code) rather than failing the entire session.\n- **Schema-not-valid handling**: if the fetched body parses as JSON but is not a valid JSON Schema, the buyer MUST treat the declaration as unresolvable (same as digest mismatch) and surface via `errors[]`. Validators MUST NOT attempt partial validation against an invalid schema.\n- **AAO catalog trust**: `https://creative.adcontextprotocol.org/*` is a single trust anchor in the same-origin allowlist; compromise of the catalog domain or its CA compromises every buyer agent. Catalog-served bodies MUST be digest-pinned identically to origin fetches (the digest is on the *parent* `format_schema.uri@digest`, not on the catalog response). Future hardening (signed bodies, transparency log) is tracked separately.'
        ),
    ] = 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 applies_to_channels : list[adcp.types.generated_poc.enums.channels.MediaChannel] | None
var canonical_formats_only : bool | None
var display_name : str | None
var experimental : bool | None
var format_option_id : str | None
var format_schema : adcp.types.generated_poc.core.platform_extension_ref.PlatformExtensionReference | None
var format_shape : str | None
var locale_policy : adcp.types.generated_poc.core.creative_locale_policy.CreativeLocalePolicy | None
var model_config
var publisher_domain : str | None
var sample_render_url : pydantic.networks.AnyUrl | None
var seller_preference : adcp.types.generated_poc.core.product_format_declaration.SellerPreference | None
var v1_format_ref : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | None

Inherited members

class LegacySyncCreativesRequest (**data: Any)
Expand source code
class SyncCreativesRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference, Field(description='Account that owns these creatives.')
    ]
    creatives: Annotated[
        list[Creative] | None,
        Field(
            description='Array of creative assets to sync (create or update)',
            max_length=100,
            min_length=1,
        ),
    ] = None
    creative_ids: Annotated[
        list[str] | None,
        Field(
            description='Optional filter to limit sync scope to specific creative IDs. When provided, only these creatives will be created/updated. Other creatives in the library are unaffected. Useful for partial updates and error recovery.',
            max_length=100,
            min_length=1,
        ),
    ] = None
    assignments: Annotated[
        list[Assignment] | None,
        Field(
            deprecated=True,
            description='Deprecated additive assignment shorthand. Each entry upserts one creative-to-package assignment. Use assignment_operations for explicit assign, unassign, and replace semantics. Standalone creative agents that do not manage media buys ignore this field.',
            min_length=1,
        ),
    ] = None
    assignment_operations: Annotated[
        list[AssignmentOperations] | None,
        Field(
            description='Explicit, ordered assignment mutations. These operations may be sent without creatives to traffic existing creative IDs independently from MediaBuy commercial control. The entire request is atomic under idempotency_key and therefore requires strict validation; lenient partial processing is not permitted.',
            max_length=500,
            min_length=1,
        ),
    ] = None
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated idempotency key for safe retries. If a sync fails without a response, resending with the same idempotency_key guarantees at-most-once execution. 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}$',
        ),
    ]
    delete_missing: Annotated[
        bool | None,
        Field(
            description='When true, creatives not included in this sync will be archived. Use with caution for full library replacement. Invalid when creative_ids is provided — delete_missing applies to the entire library scope, not a filtered subset.'
        ),
    ] = False
    dry_run: Annotated[
        bool | None,
        Field(
            description="When true, rehearse this sync_creatives operation without applying it. Validates the actual trafficking request in the seller's current context, including library upsert semantics, creative IDs, assignments, account-scoped gates, and seller policies, then returns what would be created/updated/deleted. This is distinct from validate_input, which only validates manifest structure against canonical/product format targets."
        ),
    ] = False
    validation_mode: Annotated[
        validation_mode_1.ValidationMode | None,
        Field(
            description="Validation strictness. 'strict' fails entire sync on any validation error. 'lenient' processes valid creatives and reports errors."
        ),
    ] = validation_mode_1.ValidationMode.strict
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Optional webhook configuration for async sync notifications. The agent will send a webhook when sync completes if the operation takes longer than immediate response time (typically for large bulk operations or manual approval/HITL).'
        ),
    ] = 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 assignment_operations : list[adcp.types.generated_poc.creative.sync_creatives_request.AssignmentOperations] | None
var assignments : list[adcp.types.generated_poc.creative.sync_creatives_request.Assignment] | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var creative_ids : list[str] | None
var creatives : list[adcp.types.generated_poc.creative.sync_creatives_request.Creative] | None
var delete_missing : bool | None
var dry_run : bool | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var idempotency_key : str
var model_config
var push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | None
var validation_mode : adcp.types.generated_poc.enums.validation_mode.ValidationMode | None

Inherited members

class LegacyUpdateMediaBuyRequest (**data: Any)
Expand source code
class UpdateMediaBuyRequest(AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    governance_context: Annotated[
        str | None,
        Field(
            description='Opaque intent authorization for a commitment-increasing media-buy update.',
            max_length=4096,
            min_length=1,
            pattern='^[\\x20-\\x7E]+$',
        ),
    ] = None
    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")]
    name: Annotated[
        str | None,
        Field(
            description='Replacement human-readable name for this media buy, used for trafficking UI display and operational communication. Sellers that cannot update name mid-flight SHOULD echo the prior unchanged value in the success response rather than silently dropping the field. This display label is not an identifier or financial reference.',
            max_length=255,
            min_length=1,
            pattern='\\S',
        ),
    ] = None
    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
    total_budget: Annotated[
        TotalBudget | None,
        Field(
            description='Updated hard aggregate lifetime budget. currency MUST equal the existing media-buy currency; an update does not redenominate a buy. When supplied alone (without packages or new_packages), in fixed mode the seller MUST atomically scale every active package budget in proportion to its current committed budget, rejecting the entire request if any derived budget cannot be accepted. When supplied with packages or new_packages, the amount MUST equal the resulting fixed-mode package sum; the seller applies the explicit package mutations and rejects with VALIDATION_ERROR if the total is inconsistent. In seller-optimized mode this changes the shared pool without converting package caps into allocations. Already-spent amounts still count against the new total.'
        ),
    ] = None
    daily_budget_cap: Annotated[
        float | None,
        Field(
            description='Replace the hard aggregate daily cap; null removes it. Numeric changes apply immediately with current-day spend counted. A cap below that spend pauses delivery for the day. Package caps are unchanged. Requires advertised media_buy scope; otherwise rejected with UNSUPPORTED_FEATURE.',
            ge=0.0,
        ),
    ] = None
    budget_cap_timezone: Annotated[
        str | None,
        Field(
            description='Replace the shared IANA cap-day timezone; null restores the default selected by budget_capping.timezone_basis (Account.timezone or fixed_timezone). Requires buyer_timezone_override. Changes start at the next boundary in the previously effective timezone; numeric cap changes remain immediate.',
            min_length=1,
        ),
    ] = None
    budget_allocation: Annotated[
        budget_allocation_1.BudgetAllocation | None,
        Field(
            description='Updated allocation configuration. Switching between fixed and seller-optimized modes is allowed only when update_budget_allocation is advertised in available_actions and the resulting package constraints are valid.'
        ),
    ] = None
    pacing: Annotated[
        pacing_1.Pacing | None,
        Field(
            description='Updated aggregate media-buy pacing. Package pacing remains subordinate to this aggregate strategy.'
        ),
    ] = None
    bidding: Annotated[
        bidding_policy.BiddingPolicy | None,
        Field(
            description='Replace the complete media-buy-authored bidding default. An object replaces the prior block; `{automatic:true}` records an explicit automatic policy. null clears it; packages with explicit package.bidding remain explicit, while packages without overrides fall back to provider automatic delivery. Goal binding follows the resulting budget allocation: seller-optimized outcome controls bind to allocation goals, while fixed inherited cost_per requires compatible package result units. Monetary fields use the media-buy currency and all affected pricing options MUST match it. The seller MUST validate all resulting policies atomically before mutation.'
        ),
    ] = 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. When budget_allocation is omitted or fixed, every new package MUST carry budget and MUST NOT carry min_spend_target. To add a package without a hard cap to an existing seller-optimized buy, include its resulting seller_optimized budget_allocation block in the update so the allocation context is schema-visible. Repeating an unchanged allocation block does not itself switch modes. 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 bidding : adcp.types.generated_poc.core.bidding_policy.BiddingPolicy | None
var budget_allocation : adcp.types.generated_poc.core.budget_allocation.BudgetAllocation | None
var budget_cap_timezone : str | None
var canceled : Literal[True] | None
var cancellation_reason : str | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var daily_budget_cap : float | None
var end_time : pydantic.types.AwareDatetime | None
var ext : adcp.types.generated_poc.core.ext.ExtensionObject | None
var governance_context : str | 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 name : str | None
var new_packages : list[adcp.types.generated_poc.media_buy.package_request.PackageRequest] | None
var pacing : adcp.types.generated_poc.enums.pacing.Pacing | 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
var total_budget : adcp.types.generated_poc.media_buy.update_media_buy_request.TotalBudget | None

Inherited members

class LegacyUpdateMediaBuyResponse1 (**data: Any)
Expand source code
class UpdateMediaBuyResponse1(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    status: Literal['completed'] = 'completed'
    media_buy_id: str
    name: Annotated[str, StringConstraints(pattern='\\S', min_length=1, max_length=255)] | None = None
    media_buy_status: media_buy_status_1.MediaBuyStatus | 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
    daily_budget_cap: Annotated[float, Field(ge=0)] | None = None
    budget_cap_timezone: str | None = None
    budget_allocation: Any | None = None
    pacing: pacing_1.Pacing | None = None
    bidding: Any | 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
    warnings: list[warning_1.Warning] | 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 bidding : typing.Any | None
var budget_allocation : typing.Any | None
var budget_cap_timezone : str | None
var context : adcp.types.generated_poc.core.context.ContextObject | None
var currency : str | None
var daily_budget_cap : float | 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 name : str | None
var pacing : adcp.types.generated_poc.enums.pacing.Pacing | 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
var warnings : list[adcp.types.generated_poc.core.warning.Warning] | None

Instance variables

var adcp_major_version : int | None
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
    if obj is None:
        if self.wrapped_property is not None:
            return self.wrapped_property.__get__(None, obj_type)
        raise AttributeError(self.field_name)

    warnings.warn(self.msg, DeprecationWarning, stacklevel=2)

    if self.wrapped_property is not None:
        return self.wrapped_property.__get__(obj, obj_type)
    return obj.__dict__[self.field_name]

Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.

Attributes
-----=
msg
The deprecation message to be emitted.
wrapped_property
The property instance if the deprecated field is a computed field, or None.
field_name
The name of the field being deprecated.

Inherited members

class LegacyUpdateMediaBuyResponse2 (**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 LegacyUpdateMediaBuyResponse3 (**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