Module adcp.types.buyer

AdCP buyer types — curated partial surface.

Buy-side (DSP / agency) surface — product discovery, briefs / refine, pricing, media buys the buyer sends, performance feedback, brand rights.

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

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

from adcp.types.buyer import GetProductsRequest

Classes

class AcceptProposalRequest (**data: Any)
Expand source code
class AcceptProposalRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='forbid',
    )
    idempotency_key: Annotated[
        str, Field(max_length=255, min_length=16, pattern='^[A-Za-z0-9_.:-]{16,255}$')
    ]
    name: Annotated[
        str | None,
        Field(
            description='Human-readable MediaBuy name supplied by the buyer for trafficking UI display and operational communication. When supplied, this value wins over proposal.name; the seller MUST persist it and echo it unchanged on the commitment success response and subsequent get_media_buys reads. It is operational metadata outside accepted_proposal and is not covered by proposal_terms_digest or terms_digest. When an acceptance creates a MediaBuy and name is absent, the seller MAY seed the MediaBuy name from proposal.name only when proposal.name already satisfies the MediaBuy name constraints (non-whitespace and no longer than 255 characters); the seller MUST NOT silently truncate or otherwise rewrite it. A seeded value counts as a name created through AdCP and MUST be reported on commitment and read surfaces. This display label is not an identifier or financial reference.',
            max_length=255,
            min_length=1,
            pattern='\\S',
        ),
    ] = None
    account: canonical_account_ref.CanonicalAccountReference
    proposal_id: Annotated[str, Field(min_length=1)]
    proposal_terms_digest: Annotated[
        str,
        Field(
            description='terms_digest from the committed proposal. The seller MUST atomically verify both ID and digest before acceptance.',
            pattern='^sha256:[A-Za-z0-9_-]{43}$',
        ),
    ]
    total_budget: Annotated[
        TotalBudget | None,
        Field(
            description='Execution amount when the committed proposal defines scalable percentages or constraints rather than a fixed total.'
        ),
    ] = None
    daily_budget_cap: Annotated[
        StrictFloat | None,
        Field(
            description="Optional hard aggregate daily spend ceiling applied when the committed proposal is accepted. It constrains execution without changing the proposal's negotiated pricing.",
            ge=0.0,
        ),
    ] = None
    budget_cap_timezone: Annotated[
        str | None,
        Field(
            description='Optional shared IANA cap-day timezone override. Requires buyer_timezone_override support. When omitted, budget_capping.timezone_basis selects Account.timezone or fixed_timezone.',
            min_length=1,
        ),
    ] = None
    io_acceptance: IoAcceptance | None = None
    purchase_order_ref: Annotated[str | None, Field(max_length=255, min_length=1)] = None
    governance_context: Annotated[str | None, Field(max_length=4096, min_length=1)] = None
    push_notification_config: push_notification_config_1.PushNotificationConfig | None = None
    reporting_webhook: Annotated[
        reporting_webhook_1.ReportingWebhook | None,
        Field(
            description='Optional reporting delivery configuration established atomically when the proposal is accepted. This is execution metadata and does not alter the accepted commercial terms digest.'
        ),
    ] = None
    opportunity: Annotated[
        Opportunity | None,
        Field(
            description='Optional planning-cycle closure. Success infers closed with accepted_with_seller when status is omitted. If the proposal carries opportunity_id, a supplied ID MUST match; the accepted proposal preserves that association.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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

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

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

Ancestors

Class variables

var account : CanonicalAccountReference1 | CanonicalAccountReference2
var budget_cap_timezone : str | None
var context : ContextObject | None
var daily_budget_cap : float | None
var ext : ExtensionObject | None
var governance_context : str | None
var idempotency_key : str
var io_acceptance : IoAcceptance | None
var model_config
var name : str | None
var opportunity : Opportunity | None
var proposal_id : str
var proposal_terms_digest : str
var purchase_order_ref : str | None
var push_notification_config : PushNotificationConfig | None
var reporting_webhook : ReportingWebhook | None
var total_budget : 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.

Inherited members

class AcquireRightsRequest (**data: Any)
Expand source code
class AcquireRightsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    governance_context: Annotated[
        str | None,
        Field(
            description='Opaque intent authorization for this rights commitment. Required when governance applies to the resolved account.',
            max_length=4096,
            min_length=1,
            pattern='^[\\x20-\\x7E]+$',
        ),
    ] = None
    rights_id: Annotated[
        str, Field(description='Rights offering identifier from get_rights response')
    ]
    pricing_option_id: Annotated[
        str, Field(description='Selected pricing option from the rights offering')
    ]
    buyer: Annotated[brand_ref.BrandReference, Field(description="The buyer's brand identity")]
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description='Account context for this acquisition. Used by the brand agent to resolve any governance agent previously bound for this brand+operator pair via sync_governance. When both an inline governance_context token and a bound governance agent are present, the token is verified against that resolved relationship. An agent advertising adcp.governance_enforcement for acquire_rights MUST resolve an account and returns ACCOUNT_REQUIRED when neither the request nor an existing resource supplies one; it MUST NOT infer that a missing token means ungoverned. Legacy non-claiming agents may continue to treat omission of both fields as ungoverned during 3.x. Pass a natural key (brand, operator, optional sandbox) or a seller-assigned account_id from list_accounts.'
        ),
    ] = None
    campaign: Annotated[Campaign, Field(description='Campaign details for rights clearance')]
    revocation_webhook: Annotated[
        push_notification_config_1.PushNotificationConfig,
        Field(
            description='Webhook for rights revocation notifications. If the rights holder needs to revoke rights (talent scandal, contract violation, etc.), they POST a revocation-notification to this URL. The buyer is responsible for stopping creative delivery upon receipt.'
        ),
    ]
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Webhook for async status updates if the acquisition requires approval. The rights agent sends a webhook notification when the status transitions to acquired or rejected.'
        ),
    ] = None
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated key for safe retries. Resubmitting with the same key returns the original response rather than creating a duplicate acquisition. 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

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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

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

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

Ancestors

Class variables

var account : AccountReference1 | AccountReference2 | None
var buyer : BrandReference
var campaign : Campaign
var context : ContextObject | None
var ext : ExtensionObject | None
var governance_context : str | None
var idempotency_key : str
var model_config
var pricing_option_id : str
var push_notification_config : PushNotificationConfig | None
var revocation_webhook : PushNotificationConfig
var rights_id : str

Inherited members

class BrandIdentity (**data: Any)
Expand source code
class Brand(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    id: Annotated[
        BrandId, Field(description='Brand identifier within the house. House chooses this ID.')
    ]
    url: Annotated[
        AnyUrl | None, Field(description='Primary brand URL for context and asset discovery')
    ] = None
    identity_relying_parties: Annotated[
        list[IdentityRelyingParty] | None,
        Field(
            description='Verified-identity relying parties scoped to this brand/property, for attestation provenance in TMP Identity Match. Use when a brand or property runs its own relying_party_id (per-property pseudonyms); entity-wide relying parties live on the house object. See specs/tmp-verified-identity-attestation.md.'
        ),
    ] = None
    names: Annotated[
        list[LocalizedName],
        Field(
            description='Localized brand names. Multiple entries per language allowed for aliases.',
            min_length=1,
        ),
    ]
    keller_type: KellerType | None = None
    parent_brand: Annotated[
        BrandId | None, Field(description='Parent brand ID for sub-brands and endorsed brands')
    ] = None
    description: Annotated[str | None, Field(description='Brand description')] = None
    industries: Annotated[
        list[str] | None,
        Field(
            description="Brand industries (e.g., ['automotive'] or ['pharmaceutical', 'cpg'] for a consumer health company). Describes what the company does — not what regulatory regimes apply (use policy_categories for that).",
            min_length=1,
        ),
    ] = None
    target_audience: Annotated[str | None, Field(description='Primary target audience')] = None
    logos: Annotated[list[Logo] | None, Field(description='Brand logo assets')] = None
    colors: Colors | None = None
    fonts: Fonts | None = None
    tone: Annotated[
        str | Tone | None, Field(description='Brand voice and messaging tone guidelines')
    ] = None
    tagline: Annotated[
        str | Tagline | None,
        Field(
            description='Brand tagline or slogan. Accepts a plain string or a localized array matching the names pattern.'
        ),
    ] = None
    assets: Annotated[list[Asset] | None, Field(description='Brand asset library')] = None
    properties: Annotated[
        list[Property] | None,
        Field(
            description='Digital properties associated with this brand — owned, managed, or represented'
        ),
    ] = None
    product_catalog: ProductCatalog | None = None
    privacy_policy_url: Annotated[
        AnyUrl | None, Field(description="URL to the brand's privacy policy")
    ] = None
    data_subject_contestation: DataSubjectContestation | None = None
    disclaimers: Annotated[
        list[Disclaimer] | None, Field(description='Legal disclaimers for creatives')
    ] = None
    trademarks: Annotated[
        list[Trademark] | None,
        Field(
            description="Brand-level registered trademarks. Use for marks the brand owns or controls (e.g., a sub-brand's own marks distinct from the corporate parent). House-level trademarks live on the house object; resolution between the two is union — both lists are valid claims."
        ),
    ] = None
    voice_synthesis: Annotated[
        VoiceSynthesis | None,
        Field(description='TTS voice synthesis configuration for AI-generated audio'),
    ] = None
    avatar: Annotated[Avatar | None, Field(description='Visual avatar configuration')] = None
    visual_guidelines: Annotated[
        VisualGuidelines | None,
        Field(description='Structured visual rules for generative creative systems'),
    ] = None
    agents: Annotated[
        Agents | None,
        Field(
            description='Agents authorized to act on behalf of this brand. Consumers resolving an agent by URL use the matching brand-level entry; do not infer a type-wide override of unrelated house-level entries when multiple same-type entries exist.'
        ),
    ] = None
    brand_agent: Annotated[
        BrandAgent | None,
        Field(
            deprecated=True,
            description="Deprecated: use agents array with type 'brand' instead. Brand agent that provides dynamic brand data via MCP.",
        ),
    ] = None
    rights_agent: Annotated[
        RightsAgent | None,
        Field(
            deprecated=True,
            description="Deprecated: use agents array with type 'rights' instead. Rights licensing agent for this brand.",
        ),
    ] = None
    contact: Annotated[Contact1 | None, Field(description='Brand-level contact information')] = None
    collections: Annotated[
        list[Collection] | None,
        Field(
            description="Collections this person or brand is associated with. Enables bidirectional linking: a collection's talent references brand.json via brand_url, and brand.json links back to collections."
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Subclasses

Class variables

var agents : Agents | None
var assets : list[Asset] | None
var avatar : Avatar | None
var brand_agent : BrandAgent | None
var collections : list[Collection] | None
var colors : Colors | None
var contact : Contact1 | None
var data_subject_contestation : DataSubjectContestation | None
var description : str | None
var disclaimers : list[Disclaimer] | None
var fonts : Fonts | None
var id : BrandId
var identity_relying_parties : list[IdentityRelyingParty] | None
var industries : list[str] | None
var keller_type : KellerType | None
var logos : list[Logo] | None
var model_config
var names : list[LocalizedName]
var parent_brand : BrandId | None
var privacy_policy_url : pydantic.networks.AnyUrl | None
var product_catalog : ProductCatalog | None
var properties : list[Property] | None
var rights_agent : RightsAgent | None
var tagline : str | Tagline | None
var target_audience : str | None
var tone : str | Tone | None
var trademarks : list[Trademark] | None
var url : pydantic.networks.AnyUrl | None
var visual_guidelines : VisualGuidelines | None
var voice_synthesis : VoiceSynthesis | None

Inherited members

class BrandReference (**data: Any)
Expand source code
class BrandReference(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    domain: Annotated[
        str,
        Field(
            description="Domain where /.well-known/brand.json is hosted, or the brand's operating domain",
            pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$',
        ),
    ]
    brand_id: Annotated[
        brand_id_1.BrandId | None,
        Field(
            description='Brand identifier within the house portfolio. Optional for single-brand domains.'
        ),
    ] = None
    countries: Annotated[
        list[Country] | None,
        Field(
            description='Canonical set of ISO 3166-1 alpha-2 countries for this advertiser identity. Omit for a global/default identity. Array order is not meaningful; producers MUST sort codes lexicographically before computing keys or signatures. This qualifies account identity and is not delivery targeting.',
            min_length=1,
        ),
    ] = None
    industries: Annotated[
        list[str] | None,
        Field(
            description="Inline override for the brand's industries. Useful when the caller cannot modify the brand's canonical brand.json but needs to declare industries for governance (e.g., Annex III vertical detection). brand.json remains the canonical source; when omitted here, governance agents SHOULD resolve from brand.json."
        ),
    ] = None
    data_subject_contestation: Annotated[
        DataSubjectContestation | None,
        Field(
            description="Inline override for the brand's contestation contact point. Useful when the operator does not control brand.json but needs to discharge Art 22(3) for this plan. brand.json is canonical; when omitted, governance agents resolve brand → house → missing."
        ),
    ] = None
    brand_kit_override: Annotated[
        BrandKitOverride | None,
        Field(
            description="Inline override for brand-kit fields normally resolved from `/.well-known/brand.json` on `domain` (logo, colors, voice, tagline). Use when brand.json is missing, stale, or inappropriate for this specific call — e.g., a campaign-scoped tagline, a co-branded creative, a freshly-rebranded color palette the brand.json hasn't shipped yet. Same inline-override pattern as `industries` and `data_subject_contestation` above: brand.json is canonical, the override is per-call. Adopters needing to override fields outside this subset (`voice_attributes`, `prohibited_terms`, etc.) MUST publish a different brand.json and reference it via a different `domain` — the inline override is intentionally narrow to a small high-traffic subset.\n\n**Merge semantics (normative).** The merge is **field-level**, not whole-object replacement. Each field within `brand_kit_override` (`logo`, `colors`, `voice`, `tagline`) is evaluated independently — when a field is present on the override the override value applies; when a field is absent the brand.json value applies (or is absent if brand.json doesn't carry one either). For composite fields (`colors.primary`, `colors.secondary`, `colors.accent`), the merge is one level deeper: each color slot is evaluated independently — a producer can override `colors.primary` while still inheriting `colors.secondary` from brand.json. SDKs MUST NOT treat a present `brand_kit_override.colors` as wiping the brand.json `colors` block entirely; only the per-slot fields present in the override take precedence. Without this rule, a partial-override semantics would diverge across SDKs and produce inconsistent rendering for the same payload."
        ),
    ] = 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 brand_id : BrandId | None
var brand_kit_override : BrandKitOverride | None
var countries : list[Country] | None
var data_subject_contestation : DataSubjectContestation | None
var domain : str
var industries : list[str] | None
var model_config

Inherited members

class BrandSource (*args, **kwds)
Expand source code
class BrandSource(Enum):
    brand_json = "brand_json"
    community = "community"
    enriched = "enriched"

Create a collection of name/value pairs.

Example enumeration:

>>> class Color(Enum):
...     RED = 1
...     BLUE = 2
...     GREEN = 3

Access them by:

  • attribute access::
>>> Color.RED
<Color.RED: 1>
  • value lookup:
>>> Color(1)
<Color.RED: 1>
  • name lookup:
>>> Color['RED']
<Color.RED: 1>

Enumerations can be iterated over, and know how many members they have:

>>> len(Color)
3
>>> list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

Methods can be added to enumerations, and members can have their own attributes – see the documentation for details.

Ancestors

  • enum.Enum

Class variables

var brand_json
var community
var enriched
class BuyProductsRequest (**data: Any)
Expand source code
class BuyProductsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='forbid',
    )
    idempotency_key: Annotated[
        str, Field(max_length=255, min_length=16, pattern='^[A-Za-z0-9_.:-]{16,255}$')
    ]
    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 commitment success response and subsequent get_media_buys reads. The name is operational metadata outside accepted_proposal and is not covered by terms_digest. This display label is not an identifier or financial reference.',
            max_length=255,
            min_length=1,
            pattern='\\S',
        ),
    ] = None
    account: Annotated[
        canonical_account_ref.CanonicalAccountReference,
        Field(
            description='Execution account. A natural-key account is the single brand source and MUST NOT be combined with top-level brand.'
        ),
    ]
    brand: Annotated[
        brand_key.BrandKey | None,
        Field(
            description='Brand source required when account is ID-only. Omit when account already contains brand and operator.'
        ),
    ] = None
    advertiser_industry: Annotated[
        advertiser_industry_1.AdvertiserIndustry | None,
        Field(
            description='Industry classification for this campaign. Sellers may infer it from the resolved brand manifest when omitted.'
        ),
    ] = None
    feed_version: Annotated[
        str,
        Field(
            description='list_products feed_version containing the published offers being accepted. Sellers reject stale or mismatched versions rather than silently applying changed terms.',
            min_length=1,
        ),
    ]
    pricing_version: Annotated[
        str | None,
        Field(
            description='list_products pricing_version containing the accepted rate. Buyers MUST include this whenever list_products returned one; omission means the seller does not version pricing separately.',
            min_length=1,
        ),
    ] = None
    purchases: Annotated[list[product_purchase_input.ProductPurchaseInput], Field(min_length=1)]
    total_budget: TotalBudget | None = None
    daily_budget_cap: Annotated[
        StrictFloat | None,
        Field(
            description="Optional hard aggregate daily spend ceiling in total_budget.currency or the media buy's derived currency. It bounds the shared daily spend pool without allocating or reserving amounts for purchases.",
            ge=0.0,
        ),
    ] = None
    frequency_cap: Annotated[
        media_buy_frequency_cap.MediaBuyFrequencyCap | None,
        Field(
            description='Optional max-impression cap using one counter across purchases. Buyers send it only when aggregate_frequency_capping is advertised. Every selected product must declare compatible media_buy_support; otherwise the purchase is rejected atomically with UNSUPPORTED_FEATURE before any mutation, never clamped.'
        ),
    ] = None
    budget_cap_timezone: Annotated[
        str | None,
        Field(
            description='Optional IANA timezone override shared by every aggregate and purchase daily cap. Requires buyer_timezone_override support; otherwise rejected with UNSUPPORTED_FEATURE. When omitted, budget_capping.timezone_basis selects Account.timezone or fixed_timezone.',
            min_length=1,
        ),
    ] = None
    budget_allocation: canonical_budget_allocation.CanonicalBudgetAllocation | None = None
    start_time: start_timing.StartTiming
    end_time: AwareDatetime
    pacing: Annotated[
        pacing_1.Pacing | None,
        Field(
            description='Aggregate media-buy pacing. In seller-optimized allocation, a seller declaring media_buy.features.seller_optimized_budget MUST accept omission and `even`; it MAY reject `asap` or `front_loaded` with UNSUPPORTED_FEATURE (error.field `pacing`) before any provider mutation and MUST NOT silently coerce them to `even`. Fixed-allocation semantics are unchanged.'
        ),
    ] = None
    bidding: bidding_policy.BiddingPolicy | None = None
    paused: StrictBool | None = False
    purchase_order_ref: Annotated[str | None, Field(max_length=255, min_length=1)] = None
    agency_estimate_number: Annotated[str | None, Field(max_length=100)] = None
    invoice_recipient: Annotated[
        business_entity.BusinessEntity | None,
        Field(description='Authorized per-buy billing entity override.'),
    ] = None
    governance_context: Annotated[str | None, Field(max_length=4096, min_length=1)] = None
    push_notification_config: push_notification_config_1.PushNotificationConfig | None = None
    reporting_webhook: Annotated[
        reporting_webhook_1.ReportingWebhook | None,
        Field(
            description='Optional reporting delivery configuration established atomically with the MediaBuy. This is execution metadata and is not part of the immutable product pricing terms.'
        ),
    ] = None
    opportunity: Annotated[
        Opportunity | None,
        Field(
            description='Optional planning-cycle closure for a direct product purchase. Success infers closed with accepted_with_seller when status is omitted; an explicit status MUST carry that same closure.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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

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

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

Ancestors

Class variables

var account : CanonicalAccountReference1 | CanonicalAccountReference2
var advertiser_industry : AdvertiserIndustry | None
var agency_estimate_number : str | None
var bidding : BiddingPolicy | None
var brand : BrandKey | None
var budget_allocation : CanonicalBudgetAllocation1 | CanonicalBudgetAllocation2 | None
var budget_cap_timezone : str | None
var context : ContextObject | None
var daily_budget_cap : float | None
var end_time : pydantic.types.AwareDatetime
var ext : ExtensionObject | None
var feed_version : str
var frequency_cap : MediaBuyFrequencyCap | None
var governance_context : str | None
var idempotency_key : str
var invoice_recipient : BusinessEntity | None
var model_config
var name : str | None
var opportunity : Opportunity | None
var pacing : Pacing | None
var paused : bool | None
var pricing_version : str | None
var purchase_order_ref : str | None
var purchases : list[ProductPurchaseInput]
var push_notification_config : PushNotificationConfig | None
var reporting_webhook : ReportingWebhook | None
var start_time : Literal['asap'] | pydantic.types.AwareDatetime
var total_budget : 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.

Inherited members

class ControlMediaBuyRequest (**data: Any)
Expand source code
class ControlMediaBuyRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='forbid',
    )
    idempotency_key: Annotated[
        str, Field(max_length=255, min_length=16, pattern='^[A-Za-z0-9_.:-]{16,255}$')
    ]
    account: canonical_account_ref.CanonicalAccountReference
    media_buy_id: Annotated[str, Field(min_length=1)]
    revision: Annotated[
        SchemaInt,
        Field(
            description='Required optimistic-concurrency revision from the latest MediaBuy snapshot.',
            ge=1,
        ),
    ]
    name: Annotated[
        str | None,
        Field(
            description='Replace the human-readable MediaBuy name as revision-checked operational metadata. This display label is not an identifier, financial reference, or change to the accepted commercial terms.',
            max_length=255,
            min_length=1,
            pattern='\\S',
        ),
    ] = None
    paused: StrictBool | None = None
    canceled: Annotated[
        Literal[True] | None,
        Field(
            description='Exercise an already-accepted unilateral cancellation right. A cancellation requiring seller agreement is requested by refining the accepted proposal.'
        ),
    ] = None
    cancellation_reason: Annotated[str | None, Field(max_length=500, min_length=1)] = None
    total_budget: TotalBudget | None = None
    daily_budget_cap: Annotated[
        StrictFloat | None,
        Field(
            description='Replace the hard aggregate daily cap; null removes it. Numeric changes apply immediately with current-cap-day spend counted and do not redistribute purchase caps.',
            ge=0.0,
        ),
    ] = None
    frequency_cap: Annotated[
        media_buy_frequency_cap.MediaBuyFrequencyCap | None,
        Field(
            description='Replace the shared MediaBuy frequency cap; null removes it. The change applies immediately without resetting counters: qualifying prior exposures still count in the resulting active window. Sellers MUST reject the complete mutation with UNSUPPORTED_FEATURE, before any change, if the cap is outside declared constraints or any active package cannot participate in the resulting shared counter, and MUST NOT clamp it. Requires update_media_buy_frequency_cap in available_actions.'
        ),
    ] = None
    budget_cap_timezone: Annotated[
        str | None,
        Field(
            description='Replace the shared IANA cap-day timezone override; null restores the default selected by budget_capping.timezone_basis (Account.timezone or fixed_timezone). A timezone change begins at the next boundary under the previously effective timezone.',
            min_length=1,
        ),
    ] = None
    budget_allocation: canonical_budget_allocation.CanonicalBudgetAllocation | None = None
    pacing: Annotated[
        pacing_1.Pacing | None,
        Field(
            description='Replace aggregate media-buy pacing. In seller-optimized allocation, a seller declaring media_buy.features.seller_optimized_budget MUST accept omission and `even`; it MAY reject `asap` or `front_loaded` with UNSUPPORTED_FEATURE (error.field `pacing`) before any provider mutation and MUST NOT silently coerce them to `even`. Fixed-allocation semantics are unchanged.'
        ),
    ] = None
    bidding: bidding_policy.BiddingPolicy | None = None
    packages: Annotated[
        list[package_control.PackageControl] | None,
        Field(
            description='Operational patches keyed by package_id. Each package_id MUST appear at most once; sellers reject duplicate IDs atomically.',
            min_length=1,
        ),
    ] = None
    reporting_webhook: reporting_webhook_1.ReportingWebhook | None = None
    governance_context: Annotated[str | None, Field(max_length=4096, min_length=1)] = None
    push_notification_config: push_notification_config_1.PushNotificationConfig | None = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

    @model_validator(mode='after')
    def _require_schema_required_group(self) -> ControlMediaBuyRequest:
        # ``required`` asks whether the caller supplied the field, which is what
        # model_fields_set answers. An explicit null is a supplied value — on a
        # mutation input it is the command to clear — and a default the caller
        # never sent is not.
        for group in (('name',), ('paused',), ('canceled',), ('total_budget',), ('daily_budget_cap',), ('frequency_cap',), ('budget_cap_timezone',), ('budget_allocation',), ('pacing',), ('bidding',), ('packages',), ('reporting_webhook',),):
            if all(name in self.model_fields_set for name in group):
                return self
        raise ValueError(
            'ControlMediaBuyRequest requires at least one of these field groups: name | paused | canceled | total_budget | daily_budget_cap | frequency_cap | budget_cap_timezone | budget_allocation | pacing | bidding | packages | reporting_webhook'
        )

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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

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

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

Ancestors

Class variables

var account : CanonicalAccountReference1 | CanonicalAccountReference2
var bidding : BiddingPolicy | None
var budget_allocation : CanonicalBudgetAllocation1 | CanonicalBudgetAllocation2 | None
var budget_cap_timezone : str | None
var canceled : Literal[True] | None
var cancellation_reason : str | None
var context : ContextObject | None
var daily_budget_cap : float | None
var ext : ExtensionObject | None
var frequency_cap : MediaBuyFrequencyCap | None
var governance_context : str | None
var idempotency_key : str
var media_buy_id : str
var model_config
var name : str | None
var pacing : Pacing | None
var packages : list[PackageControl] | None
var paused : bool | None
var push_notification_config : PushNotificationConfig | None
var reporting_webhook : ReportingWebhook | None
var revision : int
var total_budget : 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.

Inherited members

class CpaPricingOption (**data: Any)
Expand source code
class CpaPricingOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    pricing_option_id: Annotated[
        str, Field(description='Unique identifier for this pricing option within the product')
    ]
    pricing_model: Annotated[
        Literal['cpa'], Field(description='Cost per acquisition (conversion event)')
    ] = 'cpa'
    event_type: Annotated[
        event_type_1.EventType,
        Field(
            description='The conversion event type that triggers billing (e.g., purchase, lead, app_install)'
        ),
    ]
    custom_event_name: Annotated[
        str | None,
        Field(
            description="Name of the custom event when event_type is 'custom'. Required when event_type is 'custom', ignored otherwise."
        ),
    ] = None
    event_source_id: Annotated[
        str | None,
        Field(
            description='When present, only events from this specific event source count toward billing. Allows different CPA rates for different sources (e.g., online vs in-store purchases). Must match an event source configured via sync_event_sources.'
        ),
    ] = None
    currency: Annotated[
        str,
        Field(
            description='ISO 4217 currency code',
            examples=['USD', 'EUR', 'GBP', 'JPY'],
            pattern='^[A-Z]{3}$',
        ),
    ]
    fixed_price: Annotated[
        StrictFloat,
        Field(description='Fixed price per acquisition in the specified currency', gt=0.0),
    ]
    min_spend_per_package: Annotated[
        StrictFloat | None,
        Field(
            description='Minimum spend requirement per package using this pricing option, in the specified currency',
            ge=0.0,
        ),
    ] = None
    price_breakdown: Annotated[
        price_breakdown_1.PriceBreakdown | None,
        Field(
            description='Breakdown of how fixed_price was derived from the list (rate card) price. Only meaningful when fixed_price is present.'
        ),
    ] = None
    eligible_adjustments: Annotated[
        list[adjustment_kind.PriceAdjustmentKind] | None,
        Field(
            description='Adjustment kinds applicable to this pricing option. Tells buyer agents which adjustments are available before negotiation. When absent, no adjustments are pre-declared — the buyer should check price_breakdown if present.'
        ),
    ] = 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 currency : str
var custom_event_name : str | None
var eligible_adjustments : list[PriceAdjustmentKind] | None
var event_source_id : str | None
var event_type : EventType
var fixed_price : float
var min_spend_per_package : float | None
var model_config
var price_breakdown : PriceBreakdown | None
var pricing_model : Literal['cpa']
var pricing_option_id : str

Inherited members

class CpcPricingOption (**data: Any)
Expand source code
class CpcPricingOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    pricing_option_id: Annotated[
        str, Field(description='Unique identifier for this pricing option within the product')
    ]
    pricing_model: Annotated[Literal['cpc'], Field(description='Cost per click')] = 'cpc'
    currency: Annotated[
        str,
        Field(
            description='ISO 4217 currency code',
            examples=['USD', 'EUR', 'GBP', 'JPY'],
            pattern='^[A-Z]{3}$',
        ),
    ]
    fixed_price: Annotated[
        StrictFloat | None,
        Field(
            description='Fixed price per click. If present, this is fixed pricing. If absent, auction-based.',
            ge=0.0,
        ),
    ] = None
    floor_price: Annotated[
        StrictFloat | None,
        Field(
            description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.',
            ge=0.0,
        ),
    ] = None
    max_bid: Annotated[
        StrictBool | None,
        Field(
            deprecated=True,
            description='DEPRECATED in 3.2 and removed in the next major. Legacy hint used only to normalize package bid_price to bidding.max_bid (true) or bidding.bid_amount (false/absent). New buyers express intent directly in bidding.',
        ),
    ] = False
    price_guidance: Annotated[
        price_guidance_1.PriceGuidance | None,
        Field(description='Optional pricing guidance for auction-based bidding'),
    ] = None
    min_spend_per_package: Annotated[
        StrictFloat | None,
        Field(
            description='Minimum spend requirement per package using this pricing option, in the specified currency',
            ge=0.0,
        ),
    ] = None
    price_breakdown: Annotated[
        price_breakdown_1.PriceBreakdown | None,
        Field(
            description='Breakdown of how fixed_price was derived from the list (rate card) price. Only meaningful when fixed_price is present.'
        ),
    ] = None
    eligible_adjustments: Annotated[
        list[adjustment_kind.PriceAdjustmentKind] | None,
        Field(
            description='Adjustment kinds applicable to this pricing option. Tells buyer agents which adjustments are available before negotiation. When absent, no adjustments are pre-declared — the buyer should check price_breakdown if present.'
        ),
    ] = 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 currency : str
var eligible_adjustments : list[PriceAdjustmentKind] | None
var fixed_price : float | None
var floor_price : float | None
var max_bid : bool | None
var min_spend_per_package : float | None
var model_config
var price_breakdown : PriceBreakdown | None
var price_guidance : PriceGuidance | None
var pricing_model : Literal['cpc']
var pricing_option_id : str

Inherited members

class CpmPricingOption (**data: Any)
Expand source code
class CpmPricingOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    pricing_option_id: Annotated[
        str, Field(description='Unique identifier for this pricing option within the product')
    ]
    pricing_model: Annotated[Literal['cpm'], Field(description='Cost per 1,000 impressions')] = 'cpm'
    currency: Annotated[
        str,
        Field(
            description='ISO 4217 currency code',
            examples=['USD', 'EUR', 'GBP', 'JPY'],
            pattern='^[A-Z]{3}$',
        ),
    ]
    fixed_price: Annotated[
        StrictFloat | None,
        Field(
            description='Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.',
            ge=0.0,
        ),
    ] = None
    floor_price: Annotated[
        StrictFloat | None,
        Field(
            description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.',
            ge=0.0,
        ),
    ] = None
    max_bid: Annotated[
        StrictBool | None,
        Field(
            deprecated=True,
            description='DEPRECATED in 3.2 and removed in the next major. Legacy hint used only to normalize package bid_price to bidding.max_bid (true) or bidding.bid_amount (false/absent). New buyers express intent directly in bidding.',
        ),
    ] = False
    price_guidance: Annotated[
        price_guidance_1.PriceGuidance | None,
        Field(description='Optional pricing guidance for auction-based bidding'),
    ] = None
    min_spend_per_package: Annotated[
        StrictFloat | None,
        Field(
            description='Minimum spend requirement per package using this pricing option, in the specified currency',
            ge=0.0,
        ),
    ] = None
    price_breakdown: Annotated[
        price_breakdown_1.PriceBreakdown | None,
        Field(
            description='Breakdown of how fixed_price was derived from the list (rate card) price. Only meaningful when fixed_price is present.'
        ),
    ] = None
    eligible_adjustments: Annotated[
        list[adjustment_kind.PriceAdjustmentKind] | None,
        Field(
            description='Adjustment kinds applicable to this pricing option. Tells buyer agents which adjustments are available before negotiation. When absent, no adjustments are pre-declared — the buyer should check price_breakdown if present.'
        ),
    ] = 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 currency : str
var eligible_adjustments : list[PriceAdjustmentKind] | None
var fixed_price : float | None
var floor_price : float | None
var max_bid : bool | None
var min_spend_per_package : float | None
var model_config
var price_breakdown : PriceBreakdown | None
var price_guidance : PriceGuidance | None
var pricing_model : Literal['cpm']
var pricing_option_id : str

Inherited members

class CreateMediaBuyRequest (**data: Any)
Expand source code
class CreateMediaBuyRequest(_LegacyCreateMediaBuyRequest, CanonicalBoundaryModel):
    """Canonical create request; packages are canonical package requests."""

    packages: list[PackageRequest] | None = None

Canonical create request; packages are canonical package requests.

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 model_config
var packages : list[PackageRequest] | None

Inherited members

class DeclineProposalsRequest (**data: Any)
Expand source code
class DeclineProposalsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='forbid',
    )
    context_id: Annotated[
        str | None,
        Field(
            description='MCP compatibility field: servers ignore this value; A2A uses transport-native Message/Task contextId.',
            min_length=1,
        ),
    ] = None
    context: context_1.ContextObject | None = None
    governance_context: Annotated[str | None, Field(max_length=4096, min_length=1)] = None
    push_notification_config: push_notification_config_1.PushNotificationConfig | None = None
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated key required for retry-safe proposal decline.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ]
    declines: Annotated[
        list[proposal_decline.ProposalDecline],
        Field(
            description='Proposal declines to apply. proposal_id is the semantic uniqueness key and values MUST be unique even when two entries otherwise differ; implementations enforce this rule because JSON Schema uniqueItems only compares whole objects. Results preserve request order.',
            max_length=25,
            min_length=1,
        ),
    ]
    opportunity: Annotated[
        opportunity_context.OpportunityContext | None,
        Field(
            description='Optional planning-cycle update. Every named proposal MUST belong to this opportunity_id. Sellers apply the update only when every result is declined; if any result is unable, the opportunity remains unchanged. Use status closed when these declines end the broader opportunity.'
        ),
    ] = None

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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 context : ContextObject | None
var context_id : str | None
var declines : list[ProposalDecline]
var governance_context : str | None
var idempotency_key : str
var model_config
var opportunity : OpportunityContext | None
var push_notification_config : PushNotificationConfig | None

Inherited members

class FeedbackSource (*args, **kwds)
Expand source code
class FeedbackSource(StrEnum):
    buyer_attribution = 'buyer_attribution'
    third_party_measurement = 'third_party_measurement'
    platform_analytics = 'platform_analytics'
    verification_partner = 'verification_partner'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var buyer_attribution
var platform_analytics
var third_party_measurement
var verification_partner
class FlatRatePricingOption (**data: Any)
Expand source code
class FlatRatePricingOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    pricing_option_id: Annotated[
        str, Field(description='Unique identifier for this pricing option within the product')
    ]
    pricing_model: Annotated[
        Literal['flat_rate'], Field(description='Fixed cost regardless of delivery volume')
    ] = 'flat_rate'
    currency: Annotated[
        str,
        Field(
            description='ISO 4217 currency code',
            examples=['USD', 'EUR', 'GBP', 'JPY'],
            pattern='^[A-Z]{3}$',
        ),
    ]
    fixed_price: Annotated[
        StrictFloat | None,
        Field(
            description='Flat rate cost. If present, this is fixed pricing. If absent, auction-based.',
            ge=0.0,
        ),
    ] = None
    floor_price: Annotated[
        StrictFloat | None,
        Field(
            description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.',
            ge=0.0,
        ),
    ] = None
    price_guidance: Annotated[
        price_guidance_1.PriceGuidance | None,
        Field(description='Optional pricing guidance for auction-based bidding'),
    ] = None
    parameters: Annotated[
        Parameters | None,
        Field(
            description='DOOH inventory allocation parameters. Sponsorship and takeover flat_rate options omit this field entirely — only include for digital out-of-home inventory.',
            title='DoohParameters',
        ),
    ] = None
    min_spend_per_package: Annotated[
        StrictFloat | None,
        Field(
            description='Minimum spend requirement per package using this pricing option, in the specified currency',
            ge=0.0,
        ),
    ] = None
    price_breakdown: Annotated[
        price_breakdown_1.PriceBreakdown | None,
        Field(
            description='Breakdown of how fixed_price was derived from the list (rate card) price. Only meaningful when fixed_price is present.'
        ),
    ] = None
    eligible_adjustments: Annotated[
        list[adjustment_kind.PriceAdjustmentKind] | None,
        Field(
            description='Adjustment kinds applicable to this pricing option. Tells buyer agents which adjustments are available before negotiation. When absent, no adjustments are pre-declared — the buyer should check price_breakdown if present.'
        ),
    ] = 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 currency : str
var eligible_adjustments : list[PriceAdjustmentKind] | None
var fixed_price : float | None
var floor_price : float | None
var min_spend_per_package : float | None
var model_config
var parameters : Parameters | None
var price_breakdown : PriceBreakdown | None
var price_guidance : PriceGuidance | None
var pricing_model : Literal['flat_rate']
var pricing_option_id : str

Inherited members

class GetBrandIdentityRequest (**data: Any)
Expand source code
class GetBrandIdentityRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    brand_id: Annotated[str, Field(description='Brand identifier from brand.json brands array')]
    fields: Annotated[
        list[Field1] | None,
        Field(
            description='Optional identity sections to include in the response. When omitted, all sections the caller is authorized to see are returned. Core fields (brand_id, house, names) are always returned and do not need to be requested.',
            min_length=1,
        ),
    ] = None
    use_case: Annotated[
        str | None,
        Field(
            description="Intended use case, so the agent can tailor the response. A 'voice_synthesis' use case returns voice configs; a 'likeness' use case returns high-res photos and appearance guidelines."
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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 brand_id : str
var context : ContextObject | None
var ext : ExtensionObject | None
var fields : list[Field1] | None
var model_config
var use_case : str | None

Inherited members

class GetProductsInputRequiredResponse (**data: Any)
Expand source code
class GetProductsInputRequired(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    reason: Annotated[
        Reason | None, Field(description='Reason code indicating why input is needed')
    ] = None
    partial_results: Annotated[
        list[product.Product] | None,
        Field(description='Partial product results that may help inform the clarification'),
    ] = None
    suggestions: Annotated[
        list[str] | None, Field(description='Suggested values or options for the required input')
    ] = 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 context : ContextObject | None
var ext : ExtensionObject | None
var model_config
var partial_results : list[Product] | None
var reason : Reason | None
var suggestions : list[str] | None

Inherited members

class GetProductsRequest (**data: Any)
Expand source code
class GetProductsRequest(_LegacyGetProductsRequest, CanonicalBoundaryModel):
    """Canonical discovery request with legacy response-field selection rejected."""

    filters: ProductFilters | None = None

    @field_validator("fields")
    @classmethod
    def _reject_legacy_fields(cls, value: Any) -> Any:
        if value and any(
            is_legacy_creative_identity_key(getattr(item, "value", item)) for item in value
        ):
            raise ValueError(
                "format_id and format_ids are unavailable on the canonical get_products API"
            )
        return value

Canonical discovery request with legacy response-field selection rejected.

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 filters : ProductFilters | None
var model_config
class GetProductsBriefRequest (**data: Any)
Expand source code
class GetProductsRequest(_LegacyGetProductsRequest, CanonicalBoundaryModel):
    """Canonical discovery request with legacy response-field selection rejected."""

    filters: ProductFilters | None = None

    @field_validator("fields")
    @classmethod
    def _reject_legacy_fields(cls, value: Any) -> Any:
        if value and any(
            is_legacy_creative_identity_key(getattr(item, "value", item)) for item in value
        ):
            raise ValueError(
                "format_id and format_ids are unavailable on the canonical get_products API"
            )
        return value

Canonical discovery request with legacy response-field selection rejected.

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 filters : ProductFilters | None
var model_config
class GetProductsRefineRequest (**data: Any)
Expand source code
class GetProductsRequest(_LegacyGetProductsRequest, CanonicalBoundaryModel):
    """Canonical discovery request with legacy response-field selection rejected."""

    filters: ProductFilters | None = None

    @field_validator("fields")
    @classmethod
    def _reject_legacy_fields(cls, value: Any) -> Any:
        if value and any(
            is_legacy_creative_identity_key(getattr(item, "value", item)) for item in value
        ):
            raise ValueError(
                "format_id and format_ids are unavailable on the canonical get_products API"
            )
        return value

Canonical discovery request with legacy response-field selection rejected.

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 filters : ProductFilters | None
var model_config
class GetProductsWholesaleRequest (**data: Any)
Expand source code
class GetProductsRequest(_LegacyGetProductsRequest, CanonicalBoundaryModel):
    """Canonical discovery request with legacy response-field selection rejected."""

    filters: ProductFilters | None = None

    @field_validator("fields")
    @classmethod
    def _reject_legacy_fields(cls, value: Any) -> Any:
        if value and any(
            is_legacy_creative_identity_key(getattr(item, "value", item)) for item in value
        ):
            raise ValueError(
                "format_id and format_ids are unavailable on the canonical get_products API"
            )
        return value

Canonical discovery request with legacy response-field selection rejected.

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 filters : ProductFilters | None
var model_config

Inherited members

class GetProductsResponse (**data: Any)
Expand source code
class GetProductsResponse(_LegacyGetProductsResponse, CanonicalBoundaryModel):
    """Canonical discovery response; products are canonical products."""

    products: list[Product] | None = None  # type: ignore[assignment]

Canonical discovery response; products are canonical products.

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 model_config
var products : list[Product] | None
class GetProductsSuccessResponse (**data: Any)
Expand source code
class GetProductsResponse(_LegacyGetProductsResponse, CanonicalBoundaryModel):
    """Canonical discovery response; products are canonical products."""

    products: list[Product] | None = None  # type: ignore[assignment]

Canonical discovery response; products are canonical products.

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 model_config
var products : list[Product] | None

Inherited members

class GetProductsSubmittedResponse (**data: Any)
Expand source code
class GetProductsSubmitted(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    status: Annotated[
        Literal['submitted'],
        Field(
            description='Task-level status literal. Discriminates this async envelope from the synchronous success shape, whose products array is issued in-line. See task-status.json for the full task-status enum.'
        ),
    ] = 'submitted'
    task_id: Annotated[
        str,
        Field(
            description='Task handle the buyer uses with get_task_status (or the legacy AdCP tasks/get alias), and that the seller references on push-notification callbacks. The products array is issued on the completion artifact, not here. This AdCP application-layer handle remains the snake_case task_id in every transport payload and is distinct from any transport-native A2A Task id.'
        ),
    ]
    message: Annotated[
        str | None,
        Field(
            description="Optional human-readable explanation of why the task is submitted — e.g., 'Custom curation queued; typical turnaround 10–30 minutes.' Plain text only. Buyers MUST treat this as untrusted seller input: escape before rendering to HTML UIs, and sanitize or isolate before passing to an LLM prompt context — a hostile seller may inject prompt-injection payloads aimed at the buyer's agent.",
            max_length=2000,
        ),
    ] = None
    estimated_completion: Annotated[
        AwareDatetime | None, Field(description='Estimated completion time for the search')
    ] = None
    errors: Annotated[
        list[error.Error] | None,
        Field(
            description='Optional advisory errors accompanying the submitted envelope. Use only for non-blocking warnings (e.g., throttled_severity advisories, governance observations). Terminal failures belong in the error branch, not here.'
        ),
    ] = 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 context : ContextObject | None
var errors : list[Error] | None
var estimated_completion : pydantic.types.AwareDatetime | None
var ext : ExtensionObject | None
var message : str | None
var model_config
var status : Literal['submitted']
var task_id : str

Inherited members

class GetProductsWorkingResponse (**data: Any)
Expand source code
class GetProductsWorking(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    percentage: Annotated[
        StrictFloat | None,
        Field(description='Progress percentage of the search operation', ge=0.0, le=100.0),
    ] = None
    current_step: Annotated[
        str | None,
        Field(
            description="Current step in the search process (e.g., 'searching_inventory', 'validating_availability')"
        ),
    ] = None
    total_steps: Annotated[
        SchemaInt | None, Field(description='Total number of steps in the search process')
    ] = None
    step_number: Annotated[
        SchemaInt | None, Field(description='Current step number (1-indexed)')
    ] = 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 context : ContextObject | None
var current_step : str | None
var ext : ExtensionObject | None
var model_config
var percentage : float | None
var step_number : int | None
var total_steps : int | None

Inherited members

class GetRightsRequest (**data: Any)
Expand source code
class GetRightsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    query: Annotated[
        str,
        Field(
            description='Natural language description of desired rights. The agent interprets intent, budget signals, and compatibility from this text.',
            max_length=2000,
        ),
    ]
    uses: Annotated[
        list[right_use.RightUse],
        Field(
            description='Rights uses being requested. The agent returns options covering these uses, potentially bundled into composite pricing.',
            min_length=1,
        ),
    ]
    buyer_brand: Annotated[
        brand_ref.BrandReference | None,
        Field(
            description="The buyer's brand. The agent fetches the buyer's brand.json for compatibility filtering (e.g., dietary conflicts, competitor exclusions)."
        ),
    ] = None
    countries: Annotated[
        list[Country] | None,
        Field(
            description='Countries where rights are needed (ISO 3166-1 alpha-2). Filters to rights available in these markets.'
        ),
    ] = None
    brand_id: Annotated[
        str | None,
        Field(
            description="Search within a specific brand's rights. If omitted, searches across the agent's full roster."
        ),
    ] = None
    right_type: Annotated[
        right_type_1.RightType | None,
        Field(description='Filter by type of rights (talent, music, stock_media, etc.)'),
    ] = None
    include_excluded: Annotated[
        StrictBool | None,
        Field(
            description='Include filtered-out results in the excluded array with reasons. Defaults to false.'
        ),
    ] = False
    pagination: Annotated[
        pagination_request.PaginationRequest | None,
        Field(description='Pagination parameters for large result sets'),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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 brand_id : str | None
var buyer_brand : BrandReference | None
var context : ContextObject | None
var countries : list[Country] | None
var ext : ExtensionObject | None
var include_excluded : bool | None
var model_config
var pagination : PaginationRequest | None
var query : str
var right_type : RightType | None
var uses : list[RightUse]

Inherited members

class ListProductsRequest (**data: Any)
Expand source code
class ListProductsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='forbid',
    )
    idempotency_key: Annotated[
        str | None,
        Field(
            description='Optional replay key accepted uniformly on read calls.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ] = None
    context_id: Annotated[
        str | None,
        Field(
            description='MCP compatibility field: servers ignore this value; A2A uses transport-native Message/Task contextId.',
            min_length=1,
        ),
    ] = None
    context: context_1.ContextObject | None = None
    governance_context: Annotated[str | None, Field(max_length=4096, min_length=1)] = None
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Uniform per-call envelope field accepted for SDK compatibility. This does not register a wholesale feed subscription; durable product.* and wholesale_feed.bulk_change subscribers are registered through sync_accounts notification_configs.'
        ),
    ] = None
    account: Annotated[
        canonical_account_ref.CanonicalAccountReference | None,
        Field(
            description='Account scope for pricing and availability. A natural-key account is the single brand source and MUST NOT be combined with top-level brand.'
        ),
    ] = None
    brand: brand_key.BrandKey | None = None
    criteria: product_discovery_criteria.ProductDiscoveryCriteria | None = None
    fields: product_fields.ProductResponseFields | None = None
    cursor: Annotated[str | None, Field(min_length=1)] = None
    max_results: Annotated[SchemaInt | None, Field(ge=1, le=100)] = 25
    if_feed_version: Annotated[
        str | None,
        Field(
            description='Opaque feed version returned by a prior list_products response or wholesale product-feed webhook for the same cache scope and canonicalized selection. Used for repair and conditional reconciliation, not routine polling when webhooks are active.'
        ),
    ] = None
    if_pricing_version: Annotated[
        str | None,
        Field(
            description='Opaque pricing version returned by a prior list_products response. Valid only with if_feed_version.'
        ),
    ] = None

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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

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

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

Ancestors

Class variables

var account : CanonicalAccountReference1 | CanonicalAccountReference2 | None
var brand : BrandKey | None
var context : ContextObject | None
var context_id : str | None
var criteria : ProductDiscoveryCriteria | None
var cursor : str | None
var fields : ProductResponseFields | None
var governance_context : str | None
var idempotency_key : str | None
var if_feed_version : str | None
var if_pricing_version : str | None
var max_results : int | None
var model_config
var push_notification_config : PushNotificationConfig | None

Inherited members

class PackageRequest (**data: Any)
Expand source code
class PackageRequest(_LegacyPackageRequest, CanonicalBoundaryModel):
    """Canonical package request preserving beta.3 selector constraints."""

    if TYPE_CHECKING:  # the removed field, hidden from the constructor too
        format_ids: _RemovedFormatIds = Field(default=None, init=False)

    creatives: list[CreativeAsset] | None = Field(default=None, min_length=1)

    @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

Canonical package request preserving beta.3 selector constraints.

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 creatives : list[CreativeAsset] | None
var model_config
var targeting_overlay : TargetingOverlayInput | TargetingOverlay | None

Inherited members

class PerformanceFeedback (**data: Any)
Expand source code
class PerformanceFeedback(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    feedback_id: Annotated[
        str, Field(description='Unique identifier for this performance feedback submission')
    ]
    media_buy_id: Annotated[str, Field(description="Publisher's media buy identifier")]
    package_id: Annotated[
        str | None,
        Field(
            description='Specific package within the media buy (if feedback is package-specific)'
        ),
    ] = None
    creative_id: Annotated[
        str | None, Field(description='Specific creative asset (if feedback is creative-specific)')
    ] = None
    measurement_period: Annotated[
        MeasurementPeriod, Field(description='Time period for performance measurement')
    ]
    performance_index: Annotated[
        StrictFloat,
        Field(
            description='Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)',
            ge=0.0,
        ),
    ]
    metric_type: Annotated[
        metric_type_1.MetricType | None,
        Field(
            deprecated=True,
            description='**Deprecated as of this minor.** The legacy free-form metric enum that mixes metrics, verification, and attribution into one list. New implementations SHOULD use `metric` (the discriminated `(scope, metric_id, qualifier)` row shape) and populate `metric_type` with a best-effort string for one-minor backwards compatibility. When both `metric` and `metric_type` are present, consumers MUST use `metric` for dispatch. Removed at the next major. See [docs/measurement/taxonomy](https://docs.adcontextprotocol.org/docs/measurement/taxonomy) for why the layered shape replaces the flat enum.',
        ),
    ] = None
    metric: Annotated[
        Metric | Metric7 | None,
        Field(
            description='The metric this feedback row pertains to, using the same `(scope, metric_id, qualifier)` row shape as `committed_metrics` and package-level delivery values (`metric_values` or `vendor_metric_values`). Preferred over the legacy `metric_type` field for new implementations. Brings performance-feedback into the same atomic unit and dispatch model as the rest of the measurement surface — buyer agents reconcile feedback against the contract surface using the row-level join on `(scope, metric_id, qualifier)`. **Optional and may be omitted entirely for holistic feedback** (e.g., a trader flagging a campaign as underperforming without a specific metric in mind — `performance_index` plus the response narrative carry the signal). Senders SHOULD populate `metric` when the feedback is metric-specific so consumers can route it to the right optimization path; senders MAY omit it for general performance feedback.',
            discriminator='scope',
        ),
    ] = None
    feedback_source: Annotated[
        feedback_source_1.FeedbackSource, Field(description='Source of the performance data')
    ]
    vendor: Annotated[
        brand_ref.BrandReference | None,
        Field(
            description="Vendor that produced this feedback. SHOULD be populated when `feedback_source` is `third_party_measurement` or `verification_partner` AND a single attesting vendor exists — without it, the row is unattributed and consumers can't verify authorization, resolve metric definitions, or route disputes. OMIT for blended outputs where no single vendor owns the result: MMM mixes (Nielsen MMM, Analytic Partners, in-house mix models combining multiple vendor inputs), multi-touch attribution outputs that join across vendors, and clean-room outputs (LiveRamp, Habu, AWS Clean Rooms) where the clean room is not the measurement source. For these cases, leave `vendor` absent and use the response's narrative payload to describe provenance. Optional for `buyer_attribution` and `platform_analytics` (those sources are implicit from context). The vendor's `brand.json` `agents[type='measurement']` is the discovery anchor; metric definitions live on the agent's `get_adcp_capabilities.measurement.metrics[]` block. Same identity discipline as `vendor_metric_value.vendor` and `performance-standard.vendor`."
        ),
    ] = None
    status: Annotated[Status, Field(description='Processing status of the performance feedback')]
    submitted_at: Annotated[
        AwareDatetime, Field(description='ISO 8601 timestamp when feedback was submitted')
    ]
    applied_at: Annotated[
        AwareDatetime | None,
        Field(
            description='ISO 8601 timestamp when feedback was applied to optimization algorithms'
        ),
    ] = 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 applied_at : pydantic.types.AwareDatetime | None
var creative_id : str | None
var feedback_id : str
var feedback_source : FeedbackSource
var measurement_period : MeasurementPeriod
var media_buy_id : str
var metric : Metric | Metric7 | None
var metric_type : MetricType | None
var model_config
var package_id : str | None
var performance_index : float
var status : Status
var submitted_at : pydantic.types.AwareDatetime
var vendor : BrandReference | None

Inherited members

class PriceGuidance (**data: Any)
Expand source code
class PriceGuidance(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    p25: Annotated[
        StrictFloat | None, Field(description='25th percentile of recent winning bids', ge=0.0)
    ] = None
    p50: Annotated[
        StrictFloat | None, Field(description='Median of recent winning bids', ge=0.0)
    ] = None
    p75: Annotated[
        StrictFloat | None, Field(description='75th percentile of recent winning bids', ge=0.0)
    ] = None
    p90: Annotated[
        StrictFloat | None, Field(description='90th percentile of recent winning bids', ge=0.0)
    ] = None

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Class variables

var model_config
var p25 : float | None
var p50 : float | None
var p75 : float | None
var p90 : float | None

Inherited members

class PricingCurrency (value: Any = <object object>, *, root: Any = <object object>)
Expand source code
class PricingCurrency(ScalarStr):
    __slots__ = ()
    _constraints = {'pattern': '^[A-Z]{3}$'}
    _json_schema_extra = {'description': "ISO 4217 currency code (e.g., 'USD', 'EUR', 'GBP')"}

A str generated from a JSON Schema string root.

Ancestors

  • adcp.types._scalar.ScalarStr
  • adcp.types._scalar._ScalarRoot
  • builtins.str
class PricingModel (*args, **kwds)
Expand source code
class PricingModel(StrEnum):
    cpm = 'cpm'
    vcpm = 'vcpm'
    cpc = 'cpc'
    cpcv = 'cpcv'
    cpv = 'cpv'
    cpp = 'cpp'
    cpa = 'cpa'
    revenue_share = 'revenue_share'
    flat_rate = 'flat_rate'
    time = 'time'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var cpa
var cpc
var cpcv
var cpm
var cpp
var cpv
var flat_rate
var revenue_share
var time
var vcpm
class Product (**data: Any)
Expand source code
class Product(_LegacyProduct, CanonicalBoundaryModel):
    """Canonical product; formats, placements and pricing are canonical."""

    if TYPE_CHECKING:  # the removed field, hidden from the constructor too
        format_ids: _RemovedFormatIds = Field(default=None, init=False)

    format_options: list[Format] = Field(  # type: ignore[assignment]
        min_length=1, description="Canonical creative formats accepted by this product."
    )
    placements: list[Placement] | None = Field(default=None, min_length=1)  # type: ignore[assignment]
    pricing_options: list[CanonicalPricingOption] = Field(min_length=1)

Canonical product; formats, placements and pricing are canonical.

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 format_ids : list[FormatReferenceStructuredObject] | None
var format_options : list[Format]
var model_config
var placements : list[Placement] | None
var pricing_options : list[CpmPricingOption | VcpmPricingOption | CpcPricingOption | CpcvPricingOption | CpvPricingOption | CppPricingOption | CpaPricingOption | RevenueSharePricingOption | FlatRatePricingOption | TimeBasedPricingOption]

Instance variables

var data_provider_signals : list[DataProviderSignalSelector1 | DataProviderSignalSelector2 | DataProviderSignalSelector3] | 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 outcome_measurement : OutcomeMeasurement | 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 ProductCard (**data: Any)
Expand source code
class ProductCard(AdCPBaseModel):
    title: Annotated[bound_value.A2UiBoundValue, Field(description='Product name')]
    price: Annotated[bound_value.A2UiBoundValue, Field(description='Price display string')]
    image: Annotated[bound_value.A2UiBoundValue | None, Field(description='Product image URL')] = (
        None
    )
    description: Annotated[
        bound_value.A2UiBoundValue | None, Field(description='Product description')
    ] = None
    badge: Annotated[
        bound_value.A2UiBoundValue | None, Field(description="Badge text (e.g., 'Best Seller')")
    ] = None
    ctaLabel: Annotated[
        bound_value.A2UiBoundValue | None, Field(description='CTA button label')
    ] = None
    action: Action23 | 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 action : Action23 | None
var badge : A2UiBoundValue1 | A2UiBoundValue2 | A2UiBoundValue3 | A2UiBoundValue4 | A2UiBoundValue5 | None
var ctaLabel : A2UiBoundValue1 | A2UiBoundValue2 | A2UiBoundValue3 | A2UiBoundValue4 | A2UiBoundValue5 | None
var description : A2UiBoundValue1 | A2UiBoundValue2 | A2UiBoundValue3 | A2UiBoundValue4 | A2UiBoundValue5 | None
var image : A2UiBoundValue1 | A2UiBoundValue2 | A2UiBoundValue3 | A2UiBoundValue4 | A2UiBoundValue5 | None
var model_config
var price : A2UiBoundValue1 | A2UiBoundValue2 | A2UiBoundValue3 | A2UiBoundValue4 | A2UiBoundValue5
var title : A2UiBoundValue1 | A2UiBoundValue2 | A2UiBoundValue3 | A2UiBoundValue4 | A2UiBoundValue5

Inherited members

class ProductCardDetailed (**data: Any)
Expand source code
class ProductCardDetailed(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    hero_image: Annotated[
        image_asset.ImageAsset | None,
        Field(description='Primary hero image at the top of the detailed view.'),
    ] = None
    carousel_images: Annotated[
        list[image_asset.ImageAsset] | None,
        Field(description='Additional images for a swipeable carousel below the hero.'),
    ] = None
    title: Annotated[str | None, Field(description='Page title (typically the product name).')] = (
        None
    )
    description: Annotated[
        str | None,
        Field(
            description='Full descriptive copy. Markdown allowed in client renderers that support it; otherwise treat as plain text.'
        ),
    ] = None
    specifications: Annotated[
        list[Specification] | None,
        Field(
            description="Structured key/value specifications (e.g., 'Aspect ratio: 9:16', 'Duration: 30s'). Each item is a labeled fact about the product."
        ),
    ] = None
    price_label: Annotated[str | None, Field(description='Formatted price or pricing summary.')] = (
        None
    )
    cta_label: Annotated[str | None, Field(description='Call-to-action button label.')] = None
    reference_assets: Annotated[
        list[product_card_reference_asset.ProductCardReferenceAsset] | None,
        Field(
            description='Typed seller collateral for buyer planning — coverage maps, sample renders, environment photos, media kits. Distinct from hero_image/carousel_images, which are display-oriented.'
        ),
    ] = 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 carousel_images : list[ImageAsset] | None
var cta_label : str | None
var description : str | None
var hero_image : ImageAsset | None
var model_config
var price_label : str | None
var reference_assets : list[ProductCardReferenceAsset] | None
var specifications : list[Specification] | None
var title : str | None

Inherited members

class ProductFilters (**data: Any)
Expand source code
class ProductFilters(_LegacyProductFilters, CanonicalBoundaryModel):
    """Canonical product filters; legacy identity selection is unavailable."""

    if TYPE_CHECKING:  # the removed field, hidden from the constructor too
        format_ids: _RemovedFormatIds = Field(default=None, init=False)

Canonical product filters; legacy identity selection is unavailable.

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 format_ids : list[FormatReferenceStructuredObject] | None
var model_config

Instance variables

var countries : list[Country] | 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 geo_proximity : list[GeoProximityItem] | 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 keywords : list[Keyword] | 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 metros : list[Metro] | 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 postal_areas : list[PostalArea] | 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 regions : list[Region] | 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 required_axe_integrations : list[pydantic.networks.AnyUrl] | 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 required_geo_targeting : list[RequiredGeoTargetingItem] | 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 signal_targeting : list[SignalTargetingItem5 | SignalTargetingItem6 | SignalTargetingItem7] | 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 ProvidePerformanceFeedbackRequest (**data: Any)
Expand source code
class ProvidePerformanceFeedbackRequest(AdcpRequest, AdcpVersionEnvelope, PerformanceFeedbackAssertion):
    model_config = ConfigDict(
        extra='allow',
    )
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated unique key for this logical assertion. MUST be unique per receiving agent to prevent cross-agent correlation; use a fresh UUID v4 for each new assertion. Retries use the same key and payload.',
            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

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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 context : ContextObject | None
var ext : ExtensionObject | None
var idempotency_key : str
var model_config
class ProvidePerformanceFeedbackByMediaBuyRequest (**data: Any)
Expand source code
class ProvidePerformanceFeedbackRequest(AdcpRequest, AdcpVersionEnvelope, PerformanceFeedbackAssertion):
    model_config = ConfigDict(
        extra='allow',
    )
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated unique key for this logical assertion. MUST be unique per receiving agent to prevent cross-agent correlation; use a fresh UUID v4 for each new assertion. Retries use the same key and payload.',
            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

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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 context : ContextObject | None
var ext : ExtensionObject | None
var idempotency_key : str
var model_config
class ProvidePerformanceFeedbackByBuyerRefRequest (**data: Any)
Expand source code
class ProvidePerformanceFeedbackRequest(AdcpRequest, AdcpVersionEnvelope, PerformanceFeedbackAssertion):
    model_config = ConfigDict(
        extra='allow',
    )
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated unique key for this logical assertion. MUST be unique per receiving agent to prevent cross-agent correlation; use a fresh UUID v4 for each new assertion. Retries use the same key and payload.',
            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

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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 context : ContextObject | None
var ext : ExtensionObject | None
var idempotency_key : str
var model_config

Inherited members

class RefineProposalsRequest (**data: Any)
Expand source code
class RefineProposalsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='forbid',
    )
    context_id: Annotated[
        str | None,
        Field(
            description='MCP compatibility field: servers ignore this value; A2A uses transport-native Message/Task contextId.',
            min_length=1,
        ),
    ] = None
    context: context_1.ContextObject | None = None
    governance_context: Annotated[str | None, Field(max_length=4096, min_length=1)] = None
    push_notification_config: push_notification_config_1.PushNotificationConfig | None = None
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated key required for retry-safe proposal refinement.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ]
    refinements: Annotated[
        list[proposal_refinement.ProposalRefinement] | Refinements,
        Field(
            description='Proposal operations to apply, with at most 25 entries per request. revise creates a draft successor from a draft, committed, or accepted source. finalize MUST target a draft, reserves inventory, and creates a committed successor whose expires_at is the hold deadline. A batch containing finalize MUST contain only finalize entries and is atomic. proposal_id values MUST be unique; results preserve request order.',
            max_length=25,
            min_length=1,
        ),
    ]

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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 context : ContextObject | None
var context_id : str | None
var governance_context : str | None
var idempotency_key : str
var model_config
var push_notification_config : PushNotificationConfig | None
var refinements : list[ProposalRefinement2 | ProposalRefinement3 | ProposalRefinement4 | ProposalRefinement5 | ProposalRefinement6 | ProposalRefinement7 | ProposalRefinement8 | ProposalRefinement9] | Refinements

Inherited members

class RequestProposalsRequest (**data: Any)
Expand source code
class RequestProposalsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='forbid',
    )
    context_id: Annotated[
        str | None,
        Field(
            description='MCP compatibility field: servers ignore this value; A2A uses transport-native Message/Task contextId.',
            min_length=1,
        ),
    ] = None
    context: context_1.ContextObject | None = None
    governance_context: Annotated[str | None, Field(max_length=4096, min_length=1)] = None
    push_notification_config: push_notification_config_1.PushNotificationConfig | None = None
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated key required for retry-safe proposal creation.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ]
    account: Annotated[
        canonical_account_ref.CanonicalAccountReference | None,
        Field(
            description='Alternative brand source for proposal terms. Provide either this natural-key account containing brand and operator or top-level brand, not both.'
        ),
    ] = None
    brand: Annotated[
        brand_key.BrandKey | None,
        Field(
            description='Alternative brand source for proposal terms. Provide either top-level brand or a natural-key account containing brand and operator, not both.'
        ),
    ] = None
    brief: Annotated[
        str,
        Field(
            description='Campaign goal, strategy, and requirements that are not represented in structured criteria.',
            min_length=1,
        ),
    ]
    criteria: product_discovery_criteria.ProductDiscoveryCriteria | None = None
    opportunity: Annotated[
        Opportunity | None,
        Field(
            description='Optional planning-cycle context that the seller associates with every proposal created by this request.'
        ),
    ] = None

    @model_validator(mode='after')
    def _require_schema_required_group(self) -> RequestProposalsRequest:
        # ``required`` asks whether the caller supplied the field, which is what
        # model_fields_set answers. An explicit null is a supplied value — on a
        # mutation input it is the command to clear — and a default the caller
        # never sent is not.
        for group in (('brand',), ('account',),):
            if all(name in self.model_fields_set for name in group):
                return self
        raise ValueError(
            'RequestProposalsRequest requires at least one of these field groups: brand | account'
        )

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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

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

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

Ancestors

Class variables

var account : CanonicalAccountReference1 | CanonicalAccountReference2 | None
var brand : BrandKey | None
var brief : str
var context : ContextObject | None
var context_id : str | None
var criteria : ProductDiscoveryCriteria | None
var governance_context : str | None
var idempotency_key : str
var model_config
var opportunity : Opportunity | None
var push_notification_config : PushNotificationConfig | None

Inherited members

class RightsPricingOption (**data: Any)
Expand source code
class RightsPricingOption(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    pricing_option_id: Annotated[
        str,
        Field(
            description='Unique identifier for this pricing option. Referenced in acquire_rights and report_usage.'
        ),
    ]
    model: Annotated[
        pricing_model.PricingModel, Field(description='Pricing model (cpm, flat_rate, etc.)')
    ]
    price: Annotated[
        StrictFloat,
        Field(
            description='Price amount. Interpretation depends on model: CPM = cost per 1,000 impressions, flat_rate = fixed cost per period.',
            ge=0.0,
        ),
    ]
    currency: Annotated[str, Field(description='ISO 4217 currency code', pattern='^[A-Z]{3}$')]
    uses: Annotated[
        list[right_use.RightUse],
        Field(
            description='Which rights uses this pricing option covers. A single option can bundle multiple uses (e.g., likeness + voice).',
            min_length=1,
        ),
    ]
    period: Annotated[
        rights_billing_period.RightsBillingPeriod | None,
        Field(description='Billing period for flat_rate and time-based models'),
    ] = None
    impression_cap: Annotated[
        SchemaInt | None,
        Field(description='Maximum impressions included in this pricing option per period', ge=1),
    ] = None
    overage_cpm: Annotated[
        StrictFloat | None,
        Field(description='CPM rate applied to impressions exceeding the impression_cap', ge=0.0),
    ] = None
    description: Annotated[
        str | None, Field(description='Human-readable description of this pricing option')
    ] = 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 currency : str
var description : str | None
var ext : ExtensionObject | None
var impression_cap : int | None
var model : PricingModel
var model_config
var overage_cpm : float | None
var period : RightsBillingPeriod | None
var price : float
var pricing_option_id : str
var uses : list[RightUse]

Inherited members

class RightsTerms (**data: Any)
Expand source code
class RightsTerms(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    pricing_option_id: str
    amount: Annotated[StrictFloat, Field(ge=0.0)]
    currency: Annotated[str, Field(pattern='^[A-Z]{3}$')]
    period: rights_billing_period.RightsBillingPeriod | None = None
    uses: list[right_use.RightUse]
    impression_cap: Annotated[SchemaInt | None, Field(ge=1)] = None
    overage_cpm: Annotated[StrictFloat | None, Field(ge=0.0)] = None
    start_date: date | None = None
    end_date: date | None = None
    exclusivity: Annotated[
        Exclusivity | None, Field(description='Exclusivity terms if applicable')
    ] = 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 amount : float
var currency : str
var end_date : datetime.date | None
var exclusivity : Exclusivity | None
var impression_cap : int | None
var model_config
var overage_cpm : float | None
var period : RightsBillingPeriod | None
var pricing_option_id : str
var start_date : datetime.date | None
var uses : list[RightUse]

Inherited members

class TargetingOverlay (**data: Any)
Expand source code
class TargetingOverlay(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    geo_countries: Annotated[
        list[GeoCountry] | None,
        Field(
            description="Restrict delivery to specific countries. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').",
            min_length=1,
        ),
    ] = None
    geo_countries_exclude: Annotated[
        Sequence[GeoCountriesExcludeItem] | None,
        Field(
            description="Exclude specific countries from delivery. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').",
            min_length=1,
        ),
    ] = None
    geo_regions: Annotated[
        list[GeoRegion] | None,
        Field(
            description='Restrict delivery to exact canonical ISO 3166-2 subdivisions (states, provinces, regions, departments, or other subdivision categories). Unknown identifiers are invalid. At create or update, sellers MUST reject unsupported identifiers and MUST NOT silently widen, drop, or partially apply the list. During get_products, a seller may instead return a sparse, buyer-reviewable targeting_resolution modification for a valid but unsupported requested outcome. Exact internal translation preserves accepted identifiers in package readback.',
            min_length=1,
        ),
    ] = None
    geo_regions_exclude: Annotated[
        Sequence[GeoRegionsExcludeItem] | None,
        Field(
            description='Exclude exact canonical ISO 3166-2 subdivisions. Support is independent from geo_regions inclusion support. Unknown identifiers and values also present in geo_regions are invalid. At create or update, sellers MUST reject unsupported identifiers and partial application; during get_products, a seller may instead return a sparse, buyer-reviewable targeting_resolution modification for a valid but unsupported requested outcome.',
            min_length=1,
        ),
    ] = None
    geo_metros: Annotated[
        list[geo_metro.GeoMetro] | None,
        Field(
            description='Restrict delivery to specific metro areas. Each entry specifies the classification system and target values. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
            title='Targeting Geo Metros',
        ),
    ] = None
    geo_metros_exclude: Annotated[
        Sequence[GeoMetrosExcludeItem] | None,
        Field(
            description='Exclude specific metro areas from delivery. Each entry specifies the classification system and excluded values. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    geo_postal_areas: Annotated[
        list[postal_area.PostalArea] | None,
        Field(
            description='Restrict delivery to specific postal areas. Prefer the native country + postal system form. The deprecated legacy country-fused postal-system tokens remain accepted for compatibility. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    geo_postal_areas_exclude: Annotated[
        Sequence[postal_area.PostalArea] | None,
        Field(
            description='Exclude specific postal areas from delivery. Prefer the native country + postal system form. The deprecated legacy country-fused postal-system tokens remain accepted for compatibility. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    geo_places: Annotated[
        list[geo_place_area.GeographicPlaceArea] | None,
        Field(
            description='Restrict delivery to catalog-backed named places. Values MUST be stable identifiers in the declared system, not display names. Sellers must declare supported systems, countries, and place types in get_adcp_capabilities and reject unsupported entries rather than silently dropping them.',
            min_length=1,
        ),
    ] = None
    geo_places_exclude: Annotated[
        list[geo_place_area.GeographicPlaceArea] | None,
        Field(
            description='Exclude catalog-backed named places. Uses the same identifier-based shape as geo_places. Sellers MUST reject overlap with geo_places for the same country, system, place_type, and value.',
            min_length=1,
        ),
    ] = None
    daypart_targets: Annotated[
        list[daypart_target.DaypartTarget] | None,
        Field(
            description='Restrict delivery to specific time windows. Each entry specifies days of week, an hour range, and an optional timezone that defaults to inventory_local. A concrete IANA zone uses one shared civil-time clock, while inventory_local evaluates each inventory unit in its seller-assigned local timezone. Entries are independent and MAY use different clocks.',
            min_length=1,
        ),
    ] = None
    axe_include_segment: Annotated[
        str | None,
        Field(
            deprecated=True,
            description='Deprecated: Use TMP provider fields instead. AXE segment ID to include for targeting.',
        ),
    ] = None
    axe_exclude_segment: Annotated[
        str | None,
        Field(
            deprecated=True,
            description='Deprecated: Use TMP provider fields instead. AXE segment ID to exclude from targeting.',
        ),
    ] = None
    audience_include: Annotated[
        list[str] | None,
        Field(
            description='Restrict delivery to members of these first-party CRM audiences. Only users present in the uploaded lists are eligible. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Not for lookalike expansion — express that intent in the campaign brief. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    audience_exclude: Annotated[
        list[str] | None,
        Field(
            description='Suppress delivery to members of these first-party CRM audiences. Matched users are excluded regardless of other targeting. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    signal_targeting_groups: Annotated[
        package_signal_targeting_groups.PackageSignalTargetingGroups | None,
        Field(
            description="Basic Boolean grouping for seller-offered signals. v1 supports a required top-level operator 'all' and child groups with operator 'any' for include groups or 'none' for exclusion groups. Example semantics: group 1 any(A, B) plus group 2 none(C, D) means (A OR B) AND NOT (C OR D). Signal entries reference named signal definitions with signal_ref scope 'product' for product-local signal options or scope 'data_provider' for external signals published in adagents.json signals[]. For simple include-only targeting, send one child group with operator 'any'. Sellers SHOULD reject entries that are not available for the product through inline signal_targeting_options or get_signals, are not active for the account, or exceed the product's signal_targeting_allowed/signal_targeting_rules/product terms. Signal targeting limits are product-scoped, not declared in get_adcp_capabilities, because products may be backed by different ad servers. Sellers MUST echo applied signal_targeting_groups on the resulting package state, including fixed/default selections. Sellers MAY return REQUOTE_REQUIRED when a targeting mutation changes commercial terms.",
            title='Targeting Signal Groups',
        ),
    ] = None
    signal_targeting: Annotated[
        list[signal_targeting_1.SignalTargeting] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use signal_targeting_groups for package-level signal targeting. Legacy flat signal_targeting remains accepted during the SignalRef migration window but cannot express grouped include/exclude composition or product-scoped pricing.',
            min_length=1,
        ),
    ] = None
    demographics: Annotated[
        demographic_targeting_intent.DemographicTargetingIntent | None,
        Field(
            description='Canonical demographic audience targeting intent with optional constraints on how age may be determined. This is distinct from age_restriction: demographics selects an audience, while age_restriction expresses a legal eligibility or verification floor. Fresh create/update targeting MUST compile exactly or be rejected. During get_products, a seller may offer a different configured predicate only through sparse targeting_resolution modifications on a distinguishable product_id; selecting that product accepts the alternative. Sellers never silently broaden, narrow, default, drop, or substitute the basis.'
        ),
    ] = None
    frequency_cap: Annotated[
        frequency_cap_1.FrequencyCap | None, Field(title='Targeting Frequency Cap')
    ] = None
    property_list: Annotated[
        property_list_ref.PropertyListReference | None,
        Field(
            description="Reference to a property list for targeting specific properties within this product. The package runs on the intersection of the product's publisher_properties and this list. Sellers SHOULD return a validation error if the product has property_targeting_allowed: false.",
            title='Targeting Property List',
        ),
    ] = None
    property_list_exclude: Annotated[
        property_list_ref.PropertyListReference | None,
        Field(
            description="Reference to a property list whose properties must not carry the buyer's ads. Matched properties are removed from delivery. Use for brand-safety do-not-run lists (apps, sites). Exclude wins on overlap with property_list, and applies regardless of the product's property_targeting_allowed flag. Seller must declare support in get_adcp_capabilities."
        ),
    ] = None
    collection_list: Annotated[
        collection_list_ref.CollectionListReference | None,
        Field(
            description='Reference to a collection list for including specific collections (programs, publications, channels) within this product. The package runs on the intersection of matched collections and this list. Use for inclusion-based collection targeting. Seller must declare support in get_adcp_capabilities.',
            title='Targeting Collection List',
        ),
    ] = None
    collection_list_exclude: Annotated[
        collection_list_ref.CollectionListReference | None,
        Field(
            description="Reference to a collection list for excluding specific collections (programs, publications, channels) from this product. Matched collections must not carry the buyer's ads. Use for brand safety do-not-air lists. Seller must declare support in get_adcp_capabilities."
        ),
    ] = None
    placement_selection: Annotated[
        placement_selection_1.PlacementSelection | None,
        Field(
            description='Purchased placement selection within the product. This constrains package inventory; it is distinct from creative_assignments[].placement_refs, which only route individual creatives within the purchased set. On create, mode selected supplies the complete selected set and mode default uses the product default. In request-side Targeting Input, a non-null value replaces this dimension, omission preserves or inherits it, and null clears it when the product permits that broader inventory set.'
        ),
    ] = None
    collection_selection: Annotated[
        collection_selection_1.CollectionSelection | None,
        Field(
            description="Purchased collection selection within the product. On create, mode selected supplies the complete selected set and mode default uses the product's full bundle. On package readback this is the committed selection sellers MUST echo as concrete selectors, materializing any collection_list composition; collection_list fields remain the buyer-managed list mechanism. In request-side Targeting Input, a non-null value replaces this dimension, omission preserves or inherits it, and null clears it when the product permits that broader inventory set.",
            title='Targeting Collection Selection',
        ),
    ] = None
    age_restriction: Annotated[
        AgeRestriction | None,
        Field(
            description='Age restriction for compliance. Use for legal requirements (alcohol, gambling), not audience targeting.'
        ),
    ] = None
    device_platform: Annotated[
        list[device_platform_1.DevicePlatform] | None,
        Field(
            description='Restrict to specific platforms. Use for technical compatibility (app only works on iOS). Values from Sec-CH-UA-Platform standard, extended for CTV.',
            min_length=1,
        ),
    ] = None
    device_platform_exclude: Annotated[
        list[device_platform_1.DevicePlatform] | None,
        Field(
            description='Exclude specific operating-system platforms from delivery. When a platform appears in both device_platform and device_platform_exclude, exclusion wins. Sellers MUST reject a request they cannot enforce rather than silently dropping the exclusion.',
            min_length=1,
        ),
    ] = None
    device_type: Annotated[
        list[device_type_1.DeviceType] | None,
        Field(
            description='Restrict to specific device form factors. Use for campaigns targeting hardware categories rather than operating systems (e.g., mobile-only promotions, CTV campaigns).',
            min_length=1,
        ),
    ] = None
    device_type_exclude: Annotated[
        list[device_type_1.DeviceType] | None,
        Field(
            description='Exclude specific device form factors from delivery (e.g., exclude CTV for app-install campaigns).',
            min_length=1,
        ),
    ] = None
    browser: Annotated[
        list[browser_family.BrowserFamily] | None,
        Field(
            description='Restrict delivery to specific canonical browser families in the impression delivery and rendering environment, not the post-click landing-page browser. Values MUST NOT be inferred solely from operating system, device, web/mobile-web inventory, or placement. Values in this array use OR semantics. When browser is supplied, families not listed are ineligible: other includes a seller-recognized family that is not explicitly enumerated, while unknown includes a browser the seller cannot classify into a recognized family. When the same family appears in browser and browser_exclude, exclusion wins. Browser and device constraints intersect; a seller that cannot enforce the exact combination MUST exclude or explicitly reconfigure the product during discovery and MUST reject it at create or update rather than silently widening delivery. Browser versions and seller-native IDs are intentionally unsupported.',
            min_length=1,
        ),
    ] = None
    browser_exclude: Annotated[
        list[browser_family.BrowserFamily] | None,
        Field(
            description='Exclude specific canonical browser families from delivery. other excludes seller-recognized families that are not explicitly enumerated; unknown excludes browsers the seller cannot classify into a recognized family. When the same family appears in browser and browser_exclude, exclusion wins. Sellers MUST reject a request they cannot enforce rather than silently dropping the exclusion.',
            min_length=1,
        ),
    ] = None
    store_catchments: Annotated[
        list[StoreCatchment] | None,
        Field(
            description='Target users within store catchment areas from a synced store catalog. Each entry references a store-type catalog and optionally narrows to specific stores or catchment zones.',
            min_length=1,
        ),
    ] = None
    geo_proximity: Annotated[
        list[GeoProximityItem] | None,
        Field(
            description='Target users within travel time, distance, or a custom boundary around arbitrary geographic points. Multiple entries use OR semantics — a user within range of any listed point is eligible. For campaigns targeting 10+ locations, consider using store_catchments with a location catalog instead. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    language: Annotated[
        list[locale_tag.LanguageTag] | None,
        Field(
            description="Restrict to users with specific language preferences using canonical BCP 47 language ranges. Each buyer range is evaluated against a user's language-preference tag with RFC 4647 section 3.3.1 Basic Filtering: 'fr' matches 'fr', 'fr-CA', and 'fr-FR', while 'fr-CA' matches 'fr-CA' and more-specific descendants but not 'fr' or 'fr-FR'. Values use OR logic.",
            min_length=1,
            title='Targeting Languages',
        ),
    ] = None
    keyword_targets: Annotated[
        list[KeywordTarget] | None,
        Field(
            description='Keyword targeting for search and retail media platforms. Restricts delivery to queries matching the specified keywords. Each keyword is identified by the tuple (keyword, match_type) — the same keyword string with different match types are distinct targets. Sellers SHOULD reject duplicate (keyword, match_type) pairs within a single request. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
            title='Targeting Keywords',
        ),
    ] = None
    negative_keywords: Annotated[
        list[negative_keyword.NegativeKeyword] | None,
        Field(
            description='Keywords to exclude from delivery. Queries matching these keywords will not trigger the ad. Each negative keyword is identified by the tuple (keyword, match_type). Seller must declare support in get_adcp_capabilities.',
            min_length=1,
            title='Targeting Negative Keywords',
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Class variables

var age_restriction : AgeRestriction | None
var audience_exclude : list[str] | None
var audience_include : list[str] | None
var axe_exclude_segment : str | None
var axe_include_segment : str | None
var browser : list[BrowserFamily] | None
var browser_exclude : list[BrowserFamily] | None
var collection_list : CollectionListReference | None
var collection_list_exclude : CollectionListReference | None
var collection_selection : CollectionSelection1 | CollectionSelection2 | None
var daypart_targets : list[DaypartTarget] | None
var demographics : DemographicTargetingIntent | None
var device_platform : list[DevicePlatform] | None
var device_platform_exclude : list[DevicePlatform] | None
var device_type : list[DeviceType] | None
var device_type_exclude : list[DeviceType] | None
var frequency_cap : FrequencyCap | None
var geo_countries : list[GeoCountry] | None
var geo_countries_exclude : collections.abc.Sequence[GeoCountriesExcludeItem] | None
var geo_metros : list[GeoMetro] | None
var geo_metros_exclude : collections.abc.Sequence[GeoMetrosExcludeItem] | None
var geo_places : list[GeographicPlaceArea] | None
var geo_places_exclude : list[GeographicPlaceArea] | None
var geo_postal_areas : list[PostalArea] | None
var geo_postal_areas_exclude : collections.abc.Sequence[PostalArea] | None
var geo_proximity : list[GeoProximityItem] | None
var geo_regions : list[GeoRegion] | None
var geo_regions_exclude : collections.abc.Sequence[GeoRegionsExcludeItem] | None
var keyword_targets : list[KeywordTarget] | None
var language : list[LanguageTag] | None
var model_config
var negative_keywords : list[NegativeKeyword] | None
var placement_selection : PlacementSelection1 | PlacementSelection2 | None
var property_list : PropertyListReference | None
var property_list_exclude : PropertyListReference | None
var signal_targeting : list[SignalTargeting1 | SignalTargeting2 | SignalTargeting3] | None
var signal_targeting_groups : PackageSignalTargetingGroups | None
var store_catchments : list[StoreCatchment] | None

Inherited members

class TargetingOverlayInput (**data: Any)
Expand source code
class TargetingOverlayInput(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    geo_countries: Annotated[
        list[GeoCountry] | None,
        Field(
            description="Restrict delivery to specific countries. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').",
            min_length=1,
        ),
    ] = None
    geo_countries_exclude: Annotated[
        list[GeoCountriesExcludeItem] | None,
        Field(
            description="Exclude specific countries from delivery. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').",
            min_length=1,
        ),
    ] = None
    geo_regions: Annotated[
        list[GeoRegion] | None,
        Field(
            description='Restrict delivery to exact canonical ISO 3166-2 subdivisions (states, provinces, regions, departments, or other subdivision categories). Unknown identifiers are invalid. At create or update, sellers MUST reject unsupported identifiers and MUST NOT silently widen, drop, or partially apply the list. During get_products, a seller may instead return a sparse, buyer-reviewable targeting_resolution modification for a valid but unsupported requested outcome. Exact internal translation preserves accepted identifiers in package readback.',
            min_length=1,
        ),
    ] = None
    geo_regions_exclude: Annotated[
        list[GeoRegionsExcludeItem] | None,
        Field(
            description='Exclude exact canonical ISO 3166-2 subdivisions. Support is independent from geo_regions inclusion support. Unknown identifiers and values also present in geo_regions are invalid. At create or update, sellers MUST reject unsupported identifiers and partial application; during get_products, a seller may instead return a sparse, buyer-reviewable targeting_resolution modification for a valid but unsupported requested outcome.',
            min_length=1,
        ),
    ] = None
    geo_metros: Annotated[
        list[geo_metro.GeoMetro] | None,
        Field(
            description='Restrict delivery to specific metro areas. Each entry specifies the classification system and target values. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
            title='Targeting Geo Metros',
        ),
    ] = None
    geo_metros_exclude: Annotated[
        list[GeoMetrosExcludeItem] | None,
        Field(
            description='Exclude specific metro areas from delivery. Each entry specifies the classification system and excluded values. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    geo_postal_areas: Annotated[
        list[postal_area.PostalArea] | None,
        Field(
            description='Restrict delivery to specific postal areas. Prefer the native country + postal system form. The deprecated legacy country-fused postal-system tokens remain accepted for compatibility. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    geo_postal_areas_exclude: Annotated[
        list[postal_area.PostalArea] | None,
        Field(
            description='Exclude specific postal areas from delivery. Prefer the native country + postal system form. The deprecated legacy country-fused postal-system tokens remain accepted for compatibility. Seller must declare supported systems in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    geo_places: Annotated[
        list[geo_place_area.GeographicPlaceArea] | None,
        Field(
            description='Restrict delivery to catalog-backed named places. Values MUST be stable identifiers in the declared system, not display names. Sellers must declare supported systems, countries, and place types in get_adcp_capabilities and reject unsupported entries rather than silently dropping them.',
            min_length=1,
        ),
    ] = None
    geo_places_exclude: Annotated[
        list[geo_place_area.GeographicPlaceArea] | None,
        Field(
            description='Exclude catalog-backed named places. Uses the same identifier-based shape as geo_places. Sellers MUST reject overlap with geo_places for the same country, system, place_type, and value.',
            min_length=1,
        ),
    ] = None
    daypart_targets: Annotated[
        list[daypart_target.DaypartTarget] | None,
        Field(
            description='Restrict delivery to specific time windows. Each entry specifies days of week, an hour range, and an optional timezone that defaults to inventory_local. A concrete IANA zone uses one shared civil-time clock, while inventory_local evaluates each inventory unit in its seller-assigned local timezone. Entries are independent and MAY use different clocks.',
            min_length=1,
        ),
    ] = None
    axe_include_segment: Annotated[
        str | None,
        Field(
            deprecated=True,
            description='Deprecated: Use TMP provider fields instead. AXE segment ID to include for targeting.',
        ),
    ] = None
    axe_exclude_segment: Annotated[
        str | None,
        Field(
            deprecated=True,
            description='Deprecated: Use TMP provider fields instead. AXE segment ID to exclude from targeting.',
        ),
    ] = None
    audience_include: Annotated[
        list[str] | None,
        Field(
            description='Restrict delivery to members of these first-party CRM audiences. Only users present in the uploaded lists are eligible. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Not for lookalike expansion — express that intent in the campaign brief. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    audience_exclude: Annotated[
        list[str] | None,
        Field(
            description='Suppress delivery to members of these first-party CRM audiences. Matched users are excluded regardless of other targeting. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    signal_targeting_groups: package_signal_targeting_groups.PackageSignalTargetingGroups | None = (
        None
    )
    signal_targeting: Annotated[
        list[signal_targeting_1.SignalTargeting] | None,
        Field(
            deprecated=True,
            description='DEPRECATED. Use signal_targeting_groups for package-level signal targeting. Legacy flat signal_targeting remains accepted during the SignalRef migration window but cannot express grouped include/exclude composition or product-scoped pricing.',
            min_length=1,
        ),
    ] = None
    demographics: demographic_targeting_intent.DemographicTargetingIntent | None = None
    frequency_cap: frequency_cap_1.FrequencyCap | None = None
    property_list: property_list_ref.PropertyListReference | None = None
    property_list_exclude: property_list_ref.PropertyListReference | None = None
    collection_list: collection_list_ref.CollectionListReference | None = None
    collection_list_exclude: collection_list_ref.CollectionListReference | None = None
    placement_selection: placement_selection_1.PlacementSelection | None = None
    collection_selection: collection_selection_1.CollectionSelection | None = None
    age_restriction: targeting.AgeRestriction | None = None
    device_platform: Annotated[
        list[device_platform_1.DevicePlatform] | None,
        Field(
            description='Restrict to specific platforms. Use for technical compatibility (app only works on iOS). Values from Sec-CH-UA-Platform standard, extended for CTV.',
            min_length=1,
        ),
    ] = None
    device_platform_exclude: Annotated[
        list[device_platform_1.DevicePlatform] | None,
        Field(
            description='Exclude specific operating-system platforms from delivery. When a platform appears in both device_platform and device_platform_exclude, exclusion wins. Sellers MUST reject a request they cannot enforce rather than silently dropping the exclusion.',
            min_length=1,
        ),
    ] = None
    device_type: Annotated[
        list[device_type_1.DeviceType] | None,
        Field(
            description='Restrict to specific device form factors. Use for campaigns targeting hardware categories rather than operating systems (e.g., mobile-only promotions, CTV campaigns).',
            min_length=1,
        ),
    ] = None
    device_type_exclude: Annotated[
        list[device_type_1.DeviceType] | None,
        Field(
            description='Exclude specific device form factors from delivery (e.g., exclude CTV for app-install campaigns).',
            min_length=1,
        ),
    ] = None
    browser: Annotated[
        list[browser_family.BrowserFamily] | None,
        Field(
            description='Restrict delivery to specific canonical browser families in the impression delivery and rendering environment, not the post-click landing-page browser. Values MUST NOT be inferred solely from operating system, device, web/mobile-web inventory, or placement. Values in this array use OR semantics. When browser is supplied, families not listed are ineligible: other includes a seller-recognized family that is not explicitly enumerated, while unknown includes a browser the seller cannot classify into a recognized family. When the same family appears in browser and browser_exclude, exclusion wins. Browser and device constraints intersect; a seller that cannot enforce the exact combination MUST exclude or explicitly reconfigure the product during discovery and MUST reject it at create or update rather than silently widening delivery. Browser versions and seller-native IDs are intentionally unsupported.',
            min_length=1,
        ),
    ] = None
    browser_exclude: Annotated[
        list[browser_family.BrowserFamily] | None,
        Field(
            description='Exclude specific canonical browser families from delivery. other excludes seller-recognized families that are not explicitly enumerated; unknown excludes browsers the seller cannot classify into a recognized family. When the same family appears in browser and browser_exclude, exclusion wins. Sellers MUST reject a request they cannot enforce rather than silently dropping the exclusion.',
            min_length=1,
        ),
    ] = None
    store_catchments: Annotated[
        list[StoreCatchment] | None,
        Field(
            description='Target users within store catchment areas from a synced store catalog. Each entry references a store-type catalog and optionally narrows to specific stores or catchment zones.',
            min_length=1,
        ),
    ] = None
    geo_proximity: Annotated[
        list[GeoProximityItem] | None,
        Field(
            description='Target users within travel time, distance, or a custom boundary around arbitrary geographic points. Multiple entries use OR semantics — a user within range of any listed point is eligible. For campaigns targeting 10+ locations, consider using store_catchments with a location catalog instead. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
        ),
    ] = None
    language: Annotated[
        list[locale_tag.LanguageTag] | None,
        Field(
            description="Restrict to users with specific language preferences using canonical BCP 47 language ranges. Each buyer range is evaluated against a user's language-preference tag with RFC 4647 section 3.3.1 Basic Filtering: 'fr' matches 'fr', 'fr-CA', and 'fr-FR', while 'fr-CA' matches 'fr-CA' and more-specific descendants but not 'fr' or 'fr-FR'. Values use OR logic.",
            min_length=1,
            title='Targeting Languages',
        ),
    ] = None
    keyword_targets: Annotated[
        list[KeywordTarget] | None,
        Field(
            description='Keyword targeting for search and retail media platforms. Restricts delivery to queries matching the specified keywords. Each keyword is identified by the tuple (keyword, match_type) — the same keyword string with different match types are distinct targets. Sellers SHOULD reject duplicate (keyword, match_type) pairs within a single request. Seller must declare support in get_adcp_capabilities.',
            min_length=1,
            title='Targeting Keywords',
        ),
    ] = None
    negative_keywords: Annotated[
        list[negative_keyword.NegativeKeyword] | None,
        Field(
            description='Keywords to exclude from delivery. Queries matching these keywords will not trigger the ad. Each negative keyword is identified by the tuple (keyword, match_type). Seller must declare support in get_adcp_capabilities.',
            min_length=1,
            title='Targeting Negative Keywords',
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Class variables

var age_restriction : AgeRestriction | None
var audience_exclude : list[str] | None
var audience_include : list[str] | None
var axe_exclude_segment : str | None
var axe_include_segment : str | None
var browser : list[BrowserFamily] | None
var browser_exclude : list[BrowserFamily] | None
var collection_list : CollectionListReference | None
var collection_list_exclude : CollectionListReference | None
var collection_selection : CollectionSelection1 | CollectionSelection2 | None
var daypart_targets : list[DaypartTarget] | None
var demographics : DemographicTargetingIntent | None
var device_platform : list[DevicePlatform] | None
var device_platform_exclude : list[DevicePlatform] | None
var device_type : list[DeviceType] | None
var device_type_exclude : list[DeviceType] | None
var frequency_cap : FrequencyCap | None
var geo_countries : list[GeoCountry] | None
var geo_countries_exclude : list[GeoCountriesExcludeItem] | None
var geo_metros : list[GeoMetro] | None
var geo_metros_exclude : list[GeoMetrosExcludeItem] | None
var geo_places : list[GeographicPlaceArea] | None
var geo_places_exclude : list[GeographicPlaceArea] | None
var geo_postal_areas : list[PostalArea] | None
var geo_postal_areas_exclude : list[PostalArea] | None
var geo_proximity : list[GeoProximityItem] | None
var geo_regions : list[GeoRegion] | None
var geo_regions_exclude : list[GeoRegionsExcludeItem] | None
var keyword_targets : list[KeywordTarget] | None
var language : list[LanguageTag] | None
var model_config
var negative_keywords : list[NegativeKeyword] | None
var placement_selection : PlacementSelection1 | PlacementSelection2 | None
var property_list : PropertyListReference | None
var property_list_exclude : PropertyListReference | None
var signal_targeting : list[SignalTargeting1 | SignalTargeting2 | SignalTargeting3] | None
var signal_targeting_groups : PackageSignalTargetingGroups | None
var store_catchments : list[StoreCatchment] | None

Inherited members

class UpdateMediaBuyRequest (**data: Any)
Expand source code
class UpdateMediaBuyRequest(_LegacyUpdateMediaBuyRequest, CanonicalBoundaryModel):
    """Canonical update request; both package lists are canonical."""

    packages: list[PackageUpdate] | None = None
    new_packages: list[PackageRequest] | None = Field(  # type: ignore[assignment]
        default=None, min_length=1
    )

Canonical update request; both package lists are canonical.

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 model_config
var new_packages : list[PackageRequest] | None
var packages : list[PackageUpdate] | None

Inherited members

class VerifyBrandClaimsRequest (**data: Any)
Expand source code
class VerifyBrandClaimsRequest(VerifyBrandClaimsRequestBulk):
    pass

The request message of a task in the pinned bundle's task registry.

A consumer holding one can resolve its account, decide at-most-once, echo its context and negotiate version – the whole transport-boundary job – before knowing which tool it is. issubclass(model, AdcpRequest) is the registration-time proof that a model is spec-derived rather than a hand-written parallel: a field test passes for a forged model, descent does not.

Each accessor returns the field's value, or None when this tool's schema declares no such field. Only 49 of the 87 request schemas declare an account and only 43 an idempotency_key, so asking the request is what replaces getattr(req, "account", None) against Any at the boundary.

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 model_config

Inherited members