Module adcp.types.media_buy
AdCP media buy types — curated partial surface.
Media-buy lifecycle types — create / update / get media buys, packages, delivery, pacing, budget, targeting overlays, and media-buy status.
A stable, narrow alternative to importing the whole :mod:adcp.types
namespace. Every name here is also exported from :mod:adcp.types; this
module simply groups the ones a media buy integration reaches for, and never
exposes the internal generated layer.
This module is for curation and discoverability, not a separate
performance tier: importing it is cheap, but the first access to any AdCP
type (here or via :mod:adcp.types / :mod:adcp) realizes the full generated
Pydantic graph — there is no per-domain graph. Use it for a smaller, focused
import surface.
from adcp.types.media_buy import CreateMediaBuyRequest
Classes
class 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 = NoneThe 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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : CanonicalAccountReference1 | CanonicalAccountReference2var budget_cap_timezone : str | Nonevar context : ContextObject | Nonevar daily_budget_cap : float | Nonevar ext : ExtensionObject | Nonevar governance_context : str | Nonevar idempotency_key : strvar io_acceptance : IoAcceptance | Nonevar model_configvar name : str | Nonevar opportunity : Opportunity | Nonevar proposal_id : strvar proposal_terms_digest : strvar purchase_order_ref : str | Nonevar push_notification_config : PushNotificationConfig | Nonevar reporting_webhook : ReportingWebhook | Nonevar 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 AcceptanceContext (**data: Any)-
Expand source code
class AcceptanceContext(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) subjects: Annotated[list[Subject] | None, Field(min_length=1)] = None advertiser_roles: Annotated[list[AdvertiserRole] | None, Field(min_length=1)] = None advertiser_industry: advertiser_industry_1.AdvertiserIndustry | None = None advertiser_jurisdictions: Annotated[ list[AdvertiserJurisdiction] | None, Field( description='Jurisdictions in which the advertiser is established or legally organized. This is distinct from where an ad will be delivered.', min_length=1, ), ] = None delivery_jurisdictions: Annotated[ list[DeliveryJurisdiction] | None, Field( description="Jurisdictions in which the proposed advertising will be delivered. Seller acceptance rules' jurisdictions and jurisdiction_groups match this field.", min_length=1, ), ] = None ext: ext_1.ExtensionObject | None = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var advertiser_industry : AdvertiserIndustry | Nonevar advertiser_jurisdictions : list[AdvertiserJurisdiction] | Nonevar advertiser_roles : list[AdvertiserRole] | Nonevar delivery_jurisdictions : list[DeliveryJurisdiction] | Nonevar ext : ExtensionObject | Nonevar model_configvar subjects : list[Subject] | None
Inherited members
class AcceptancePolicyCatalog (**data: Any)-
Expand source code
class AcceptancePolicyCatalog(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) catalog_version: Annotated[str, Field(min_length=1)] generated_at: AwareDatetime | None = None profiles: Annotated[ list[acceptance_policy_profile.AcceptancePolicyProfile] | None, Field(min_length=1) ] = None registry_profiles: Annotated[ list[acceptance_policy_profile_ref.RegistryAcceptancePolicyProfileReference] | None, Field( description='Exact reusable profiles adopted from the shared policy registry. Resolution failure is unknown, never allowed. A seller adds a distinct local profile to narrow a registry profile.', min_length=1, ), ] = None ext: ext_1.ExtensionObject | None = None @model_validator(mode='after') def _require_schema_required_group(self) -> AcceptancePolicyCatalog: # ``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 (('profiles',), ('registry_profiles',),): if all(name in self.model_fields_set for name in group): return self raise ValueError( 'AcceptancePolicyCatalog requires at least one of these field groups: profiles | registry_profiles' )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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var catalog_version : strvar ext : ExtensionObject | Nonevar generated_at : pydantic.types.AwareDatetime | Nonevar model_configvar profiles : list[AcceptancePolicyProfile] | Nonevar registry_profiles : list[RegistryAcceptancePolicyProfileReference] | None
Inherited members
class AcceptancePolicyDiscovery (**data: Any)-
Expand source code
class AcceptancePolicyDiscovery(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) catalog_url: Annotated[ AnyUrl, Field(description='HTTPS document that validates against acceptance-policy-catalog.json.'), ] catalog_digest: Annotated[ str, Field( description='SHA-256 digest of the exact catalog representation fetched from catalog_url.', pattern='^sha256:[a-f0-9]{64}$', ), ] default_profile_ids: Annotated[ list[DefaultProfileId] | None, Field( description='Local or registry-referenced catalog profiles that apply seller-wide unless a product adds further profiles. IDs MUST resolve uniquely across profiles and registry_profiles; all referenced profiles compose restrictively.', min_length=1, ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var catalog_digest : strvar catalog_url : pydantic.networks.AnyUrlvar default_profile_ids : list[DefaultProfileId] | Nonevar model_config
Inherited members
class AcceptancePolicyProfile (**data: Any)-
Expand source code
class AcceptancePolicyProfile(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) profile_id: Annotated[str, Field(pattern='^[A-Za-z0-9_.:-]+$')] version: Annotated[str, Field(min_length=1)] content_digest: Annotated[ str, Field( description='SHA-256 digest of the RFC 8785 JCS serialization of this profile with content_digest omitted. A profile_id/version pair is immutable; consumers reject a resolved profile whose digest differs.', pattern='^sha256:[a-f0-9]{64}$', ), ] policy_refs: Annotated[ list[PolicyRef], Field( description='Exact registry policy versions from which this profile was derived. Consumers MUST NOT silently substitute a different version.', min_length=1, ), ] coverage: Annotated[ Coverage, Field( description='partial means additional unpublished rules may apply and omission is unknown. complete means this profile is exhaustive only for its declared scope and version.' ), ] scope: Annotated[ Scope | None, Field( description='The boundary within which a complete profile claims exhaustiveness. It is informative for partial profiles and mandatory for complete profiles.' ), ] = None region_aliases: Annotated[ dict[Annotated[str, StringConstraints(pattern=r'^[A-Z][A-Z0-9_-]*$')], list[RegionAliase]] | None, Field( description='Profile-local named country groups. Rules may reference only keys declared here; consumers expand them before matching.' ), ] = None description: Annotated[str | None, Field(min_length=1)] = None rules: Annotated[list[acceptance_policy_rule.AcceptancePolicyRule], Field(min_length=1)] ext: ext_1.ExtensionObject | None = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var content_digest : strvar coverage : Coveragevar description : str | Nonevar ext : ExtensionObject | Nonevar model_configvar policy_refs : list[PolicyRef]var profile_id : strvar region_aliases : dict[str, list[RegionAliase]] | Nonevar rules : list[AcceptancePolicyRule]var scope : Scope | Nonevar version : str
Inherited members
class AcceptancePolicyProfileId (value: Any = <object object>, *, root: Any = <object object>)-
Expand source code
class AcceptancePolicyProfileId(ScalarStr): __slots__ = () _constraints = {'min_length': 1}A
strgenerated from a JSON Schema string root.Ancestors
- adcp.types._scalar.ScalarStr
- adcp.types._scalar._ScalarRoot
- builtins.str
class AcceptancePolicyProfileIds (root: RootModelRootType = PydanticUndefined, **data)-
Expand source code
class AcceptancePolicyProfileIds(RootModel[list[AcceptancePolicyProfileId]]): root: Annotated[ list[AcceptancePolicyProfileId], Field( description='Acceptance-policy profiles from the seller catalog that apply to this product in addition to seller defaults. Profiles compose restrictively; the most restrictive matching disposition wins.', min_length=1, title='Acceptance Policy Profile IDs', ), ]Usage Documentation
A Pydantic
BaseModelfor the root object of the model.- Attributes
- -----=
root- The root object of the model.
__pydantic_root_model__- Whether the model is a RootModel.
__pydantic_private__- Private fields in the model.
__pydantic_extra__- Extra fields in the model.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- pydantic.root_model.RootModel[list[AcceptancePolicyProfileId]]
- pydantic.root_model.RootModel
- pydantic.main.BaseModel
- typing.Generic
Class variables
var model_configvar root : list[AcceptancePolicyProfileId]
class AcceptancePolicyRule (**data: Any)-
Expand source code
class AcceptancePolicyRule(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) rule_id: Annotated[str, Field(pattern='^[A-Za-z0-9_.:-]+$')] subject_category: Annotated[ str, Field( description='Registry policy-category-definition category_id. Named subject_category to avoid collision with PolicyEntry.category, whose values are regulation and standard.', pattern='^[a-z][a-z0-9_]*$', ), ] subject_facets: Annotated[ list[SubjectFacet] | None, Field( description='Facet IDs defined by the selected policy category. Omission means the rule applies to every facet in the category.', min_length=1, ), ] = None advertiser_roles: Annotated[ list[AdvertiserRole] | None, Field( description='Registry-extensible roles such as political_actor, election_authority, government_entity, news_publisher, or commercial_advertiser.', min_length=1, ), ] = None jurisdictions: Annotated[ list[Jurisdiction] | None, Field( description='Delivery jurisdictions where this rule applies. Omission means every jurisdiction served by the seller.', min_length=1, ), ] = None jurisdiction_groups: Annotated[ list[JurisdictionGroup] | None, Field( description="Named country groups declared by the containing profile's region_aliases. Unknown group IDs invalidate the profile; they never match permissively.", min_length=1, ), ] = None applies_to: Annotated[list[AppliesToEnum], Field(min_length=1)] disposition: Disposition requirements: Annotated[ list[acceptance_policy_requirement.AcceptancePolicyRequirement] | None, Field(min_length=1) ] = None policy_ids: Annotated[ list[PolicyId] | None, Field( description='Registry policies that define the exact obligations behind this coarse rule.', min_length=1, ), ] = None description: Annotated[ str | None, Field( description='Display-only explanation. Matchers MUST NOT interpret this text as executable instructions or use it to override typed fields.', max_length=1000, min_length=1, ), ] = None effective_at: AwareDatetime | None = None expires_at: AwareDatetime | None = None ext: ext_1.ExtensionObject | None = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var advertiser_roles : list[AdvertiserRole] | Nonevar applies_to : list[AppliesToEnum]var description : str | Nonevar disposition : Dispositionvar effective_at : pydantic.types.AwareDatetime | Nonevar expires_at : pydantic.types.AwareDatetime | Nonevar ext : ExtensionObject | Nonevar jurisdiction_groups : list[JurisdictionGroup] | Nonevar jurisdictions : list[Jurisdiction] | Nonevar model_configvar policy_ids : list[PolicyId] | Nonevar requirements : list[AcceptancePolicyRequirement1 | AcceptancePolicyRequirement2 | AcceptancePolicyRequirement3 | AcceptancePolicyRequirement4 | AcceptancePolicyRequirement5 | AcceptancePolicyRequirement6 | AcceptancePolicyRequirement7 | AcceptancePolicyRequirement8 | AcceptancePolicyRequirement9 | AcceptancePolicyRequirement10 | AcceptancePolicyRequirement11 | AcceptancePolicyRequirement12 | AcceptancePolicyRequirement13 | AcceptancePolicyRequirement14 | AcceptancePolicyRequirement15 | AcceptancePolicyRequirement16 | AcceptancePolicyRequirement17] | Nonevar rule_id : strvar subject_category : strvar subject_facets : list[SubjectFacet] | None
Inherited members
class AcceptedLoss (*args, **kwds)-
Expand source code
class AcceptedLoss(StrEnum): feed_version_not_atomic = 'feed_version_not_atomic' pricing_version_not_atomic = 'pricing_version_not_atomic' mutation_idempotency_not_guaranteed = 'mutation_idempotency_not_guaranteed'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var feed_version_not_atomicvar mutation_idempotency_not_guaranteedvar pricing_version_not_atomic
class AggregatedTotals (**data: Any)-
Expand source code
class AggregatedTotals(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) impressions: Annotated[ StrictFloat, Field(description='Total impressions delivered across all media buys', ge=0.0) ] spend: Annotated[ StrictFloat, Field(description='Total amount spent across all media buys', ge=0.0) ] clicks: Annotated[ StrictFloat | None, Field(description='Total clicks across all media buys (if applicable)', ge=0.0), ] = None completed_views: Annotated[ StrictFloat | None, Field( description='Total audio/video completions across all media buys (if applicable)', ge=0.0, ), ] = None views: Annotated[ StrictFloat | None, Field(description='Total views across all media buys (if applicable)', ge=0.0), ] = None conversions: Annotated[ StrictFloat | None, Field(description='Total conversions across all media buys (if applicable)', ge=0.0), ] = None conversion_value: Annotated[ StrictFloat | None, Field(description='Total conversion value across all media buys (if applicable)', ge=0.0), ] = None commissionable_value: Annotated[ StrictFloat | None, Field( description='Total settled conversion value eligible for revenue-share commission across all media buys (if applicable)', ge=0.0, ), ] = None roas: Annotated[ StrictFloat | None, Field( description='Aggregate return on ad spend across all media buys (total conversion_value / total spend)', ge=0.0, ), ] = None new_to_brand_rate: Annotated[ StrictFloat | None, Field( description='Fraction of total conversions across all media buys from first-time brand buyers (weighted by conversion volume, not a simple average of per-buy rates)', ge=0.0, le=1.0, ), ] = None cost_per_acquisition: Annotated[ StrictFloat | None, Field( description='Aggregate cost per conversion across all media buys (total spend / total conversions)', ge=0.0, ), ] = None completion_rate: Annotated[ StrictFloat | None, Field( description='Aggregate completion rate across all media buys (weighted by impressions, not a simple average of per-buy rates). Null indicates the metric is not applicable to the aggregated buys (e.g. all non-video inventory).', ge=0.0, le=1.0, ), ] = None reach: Annotated[ StrictFloat | None, Field( description='Reach across all media buys. Only present when all media buys share the same reach_unit. Omitted when reach units are heterogeneous — use per-buy reach values instead. The optional reach_aggregation field declares whether this value is deduplicated across buys or is a sum of constituent reach values.', ge=0.0, ), ] = None reach_aggregation: Annotated[ reach_aggregation_1.ReachAggregation | None, Field( description='How reach was combined across the media buys in this aggregate. When omitted, legacy reach semantics are unknown and consumers MUST NOT use reach as the denominator for frequency.' ), ] = None reach_unit: Annotated[ reach_unit_1.ReachUnit | None, Field( description='Unit of measurement for reach. Only present when all aggregated media buys use the same reach_unit.' ), ] = None frequency: Annotated[ StrictFloat | None, Field( description='Average frequency per reach unit across all media buys (impressions / reach). In new payloads, only present when reach is present and reach_aggregation is deduplicated. MUST be omitted when reach_aggregation is sum_of_constituent_reach. Legacy payloads that omit reach_aggregation remain schema-valid, but consumers MUST NOT treat their reach as a safe frequency denominator.', ge=0.0, ), ] = None media_buy_count: Annotated[ SchemaInt, Field(description='Number of media buys included in the response', ge=0) ] metric_aggregates: Annotated[ list[delivery_metric_aggregate.DeliveryMetricAggregate] | None, Field( description="Cross-buy delivery aggregates partitioned by qualifier. Row-symmetric with `package.committed_metrics` and `by_package[].missing_metrics` — same atomic unit `(scope, metric_id, qualifier)` — so reconciliation collapses to a row-level join on the tuple. Granularity rule: one row per `(metric_id, full-qualifier-set)`, reported at the finest available granularity; buyers re-aggregate up if they want a coarser view. Used only for metrics with non-empty qualifier sets — unqualified metrics (`impressions`, `spend`, `media_buy_count`, etc.) remain at the top of `aggregated_totals`. **Mutual exclusion MUST**: for any `metric_id` appearing in `metric_aggregates`, the corresponding top-level scalar in `aggregated_totals` MUST be omitted (not zeroed) — avoids duplicate sources of truth. The qualifier vocabulary on this delivery surface is closed today (`additionalProperties: false`, same content as `committed_metrics.qualifier`) but is expected to **diverge from contract qualifier in future minors** as transparency disclosures buyers don't commit to ship delivery-only (e.g., `tracker_firing` pending #3832 resolution). Each row carries a `value` plus inlined per-metric component fields (e.g., `measurable_impressions` and `viewable_impressions` for `viewable_rate`; `spend` and `conversions` for `cost_per_acquisition`). Per-buy `totals` keeps its flat shape — each buy is single-qualifier by definition; only the aggregate spans qualifiers. **Qualifier-set drift across reports**: when a campaign gains a new qualifier mid-flight (e.g., adds `tracker_firing` partitioning in week 2), prior periods' rows remain valid at their original granularity; buyers SHOULD NOT retroactively repartition.", examples=[ [ { 'scope': 'standard', 'metric_id': 'viewable_rate', 'qualifier': {'viewability_standard': 'mrc'}, 'value': 0.7286, 'measurable_impressions': 700000, 'viewable_impressions': 510000, }, { 'scope': 'standard', 'metric_id': 'viewable_rate', 'qualifier': {'viewability_standard': 'groupm'}, 'value': 0.55, 'measurable_impressions': 180000, 'viewable_impressions': 99000, }, { 'scope': 'vendor', 'vendor': {'domain': 'attentionvendor.example'}, 'metric_id': 'attention_units', 'qualifier': {}, 'value': 4.2, 'measurable_impressions': 800000, }, ] ], ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var clicks : float | Nonevar commissionable_value : float | Nonevar completed_views : float | Nonevar completion_rate : float | Nonevar conversion_value : float | Nonevar conversions : float | Nonevar cost_per_acquisition : float | Nonevar frequency : float | Nonevar impressions : floatvar media_buy_count : intvar metric_aggregates : list[DeliveryMetricAggregate1 | DeliveryMetricAggregate2] | Nonevar model_configvar new_to_brand_rate : float | Nonevar reach : float | Nonevar reach_aggregation : ReachAggregation | Nonevar reach_unit : ReachUnit | Nonevar roas : float | Nonevar spend : floatvar views : float | None
Inherited members
class AssignedPackage (**data: Any)-
Expand source code
class AssignedPackage(IndicatorBearingResourceState): model_config = ConfigDict( extra='allow', ) indicator_types_evaluated: Annotated[ list[IndicatorTypesEvaluatedEnum] | None, Field( description='Indicator types covered by this snapshot. Required whenever indicators is present. Types omitted from this list remain unknown even when indicators is empty. Every returned indicator.type MUST appear in this list.', min_length=1, ), ] = None indicators: Annotated[ list[Indicator] | None, Field( description='Current seller assertions for the indicator types and publisher/placement coverage named by the sibling evaluation fields. Omitted means unknown or not evaluated. A present empty array means evaluated with no current assertion for indicator_types_evaluated in the evaluated scope.' ), ] = None package_id: Annotated[str, Field(description='Package identifier')] media_buy_id: Annotated[ str | None, Field( description='Media buy containing this package. A seller advertising list_creatives in media_buy.relationship_notifications.projection_tasks MUST include this field on every assignment row, including rows where indicators is omitted as unknown, so buyers can key and reread the relationship unambiguously when package IDs are reused across media buys.' ), ] = None assigned_date: Annotated[AwareDatetime, Field(description='When this assignment was created')] approval_status: Annotated[ creative_approval_status.CreativeApprovalStatus | None, Field( description='Aggregate approval state for this creative in this package assignment. This mirrors the same relationship in get_media_buys. Sellers advertising list_creatives as an indicator projection task MUST include it; partially_approved requires approval_scopes.' ), ] = None rejection_reason: Annotated[ str | None, Field( description='Human-readable explanation when approval_status is rejected. Mirrors get_media_buys for the same relationship.' ), ] = None approval_scopes: Annotated[ list[creative_approval_scope.ScopedCreativeApproval] | None, Field( description='Complete, disjoint publisher/placement approval partition when approval_status is partially_approved. A normalized scope appears once. For one publisher, use either one publisher-wide row or placement-specific rows, never both. Omit when one approval_status applies uniformly to the whole assignment. The same scoped outcomes are mirrored on get_media_buys.', min_length=2, ), ] = None indicators_as_of: Annotated[ AwareDatetime | None, Field( description='When the seller last completed the evaluation represented by indicators for this relationship. Required whenever indicators is present, including an empty array.' ), ] = None indicators_evaluated_scope: Annotated[ list[indicator_scope.IndicatorScope] | None, Field( description='Optional publisher or placement scopes covered by this evaluation. Omit when indicators covers the whole package–creative assignment. When present, scopes not listed remain unknown; every returned indicator.scope entry MUST be contained by this set.', min_length=1, ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- IndicatorBearingResourceState
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var approval_scopes : list[ScopedCreativeApproval] | Nonevar approval_status : CreativeApprovalStatus | Nonevar assigned_date : pydantic.types.AwareDatetimevar indicator_types_evaluated : list[IndicatorTypesEvaluatedEnum] | Nonevar indicators : list[Indicator] | Nonevar indicators_as_of : pydantic.types.AwareDatetime | Nonevar indicators_evaluated_scope : list[IndicatorScope] | Nonevar media_buy_id : str | Nonevar model_configvar package_id : strvar rejection_reason : str | None
Inherited members
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 = NoneThe 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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : CanonicalAccountReference1 | CanonicalAccountReference2var advertiser_industry : AdvertiserIndustry | Nonevar agency_estimate_number : str | Nonevar bidding : BiddingPolicy | Nonevar brand : BrandKey | Nonevar budget_allocation : CanonicalBudgetAllocation1 | CanonicalBudgetAllocation2 | Nonevar budget_cap_timezone : str | Nonevar context : ContextObject | Nonevar daily_budget_cap : float | Nonevar end_time : pydantic.types.AwareDatetimevar ext : ExtensionObject | Nonevar feed_version : strvar frequency_cap : MediaBuyFrequencyCap | Nonevar governance_context : str | Nonevar idempotency_key : strvar invoice_recipient : BusinessEntity | Nonevar model_configvar name : str | Nonevar opportunity : Opportunity | Nonevar pacing : Pacing | Nonevar paused : bool | Nonevar pricing_version : str | Nonevar purchase_order_ref : str | Nonevar purchases : list[ProductPurchaseInput]var push_notification_config : PushNotificationConfig | Nonevar reporting_webhook : ReportingWebhook | Nonevar start_time : Literal['asap'] | pydantic.types.AwareDatetimevar 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 ByPackageItem (**data: Any)-
Expand source code
class ByPackageItem(DeliveryMetrics): package_id: Annotated[str, Field(description="Seller's package identifier")] pacing_index: Annotated[ StrictFloat | None, Field( description='Package delivery pace relative to its package-level pacing plan (1.0 = on track, <1.0 = behind, >1.0 = ahead). In seller-optimized mode this is a subordinate diagnostic and may be absent when no package pacing preference exists.', ge=0.0, ), ] = None pricing_model: Annotated[ pricing_model_1.PricingModel, Field( description='The pricing model used for this package (e.g., cpm, cpcv, cpp). Indicates how the package is billed and which metrics are most relevant for optimization.' ), ] rate: Annotated[ StrictFloat, Field( description='The pricing rate for this package. For fixed-rate pricing, this is the agreed currency-denominated unit rate (e.g., CPM rate of 12.50 means $12.50 per 1,000 impressions). For auction-based pricing, this is the effective rate based on actual delivery. For revenue_share, this is the decimal commission rate (e.g., 0.04 means 4%) and is not itself currency-denominated.', ge=0.0, ), ] currency: Annotated[ str, Field( description="ISO 4217 currency code for this package's spend and currency-denominated pricing rate. The rate for revenue_share is a dimensionless commission fraction, but attributed monetary values still use this currency. When the enclosing media_buy_deliveries[].currency is present, this value MUST equal it. For AdCP-authored buys both values MUST equal the media-buy currency. A different package currency is permitted only for a legacy or externally created mixed-currency buy whose row currency, daily_breakdown, and row/window monetary totals are omitted. AdCP does not perform currency conversion.", pattern='^[A-Z]{3}$', ), ] delivery_status: Annotated[ delivery_status_1.DeliveryStatus | None, Field( description="System-reported operational state of this package. Reflects actual delivery state independent of buyer pause control. 'not_delivering' means zero impressions were recorded for the entire reporting_period while the package was in-flight. Sellers SHOULD only report 'not_delivering' once the package's data is_final for the period — a provisional (is_final: false) zero may still be measurement catching up, not genuine non-delivery." ), ] = None paused: Annotated[ StrictBool | None, Field(description='Whether this package is currently paused by the buyer'), ] = None is_final: Annotated[ StrictBool | None, Field( description="Whether this delivery data is final for the reporting period. When false, the data may be updated as measurement matures (e.g., broadcast C7 window accumulating DVR playback) or as processing completes (e.g., IVT filtering, deduplication). When true, the seller considers this data closed — no further updates for this period — and is willing to invoice on it subject to the buy's `measurement_terms.billing_measurement`. Absent means the seller does not distinguish provisional from final data." ), ] = None finalized_at: Annotated[ AwareDatetime | None, Field( description="ISO 8601 timestamp at which this package's data became final. Present only when `is_final: true`. Anchors reconciliation and (when later defined) dispute-window clocks against the buy's `measurement_terms.billing_measurement.measurement_window`." ), ] = None measurement_window: Annotated[ str | None, Field( description="Which measurement window this data represents, referencing a window_id from the product's reporting_capabilities.measurement_windows. For broadcast: 'live', 'c3', 'c7'. When absent, the data is not windowed (standard digital reporting). When present with is_final: false, a later report for the same period will provide a wider window or more complete data.", examples=['live', 'c3', 'c7'], max_length=50, ), ] = None supersedes_window: Annotated[ str | None, Field( description="Which measurement window this data replaces. Present on window_update notifications to indicate progression (e.g., 'live' when reporting C3 data that supersedes live-only numbers). Absent on the first report for a period. Buyers should replace stored data for the superseded window with this report's data.", examples=['live', 'c3'], max_length=50, ), ] = None missing_metrics: Annotated[ list[missing_metric.MissingMetric] | None, Field( description="Metrics that the binding reporting contract declared but that are NOT populated in this report. Reconciliation source: when `package.committed_metrics` is present, `missing_metrics` is computed against entries where `committed_at < reporting_period.end` — independent of subsequent product mutations and respecting the commitment timestamp on each entry (a metric committed mid-flight is only flagged missing in reports for periods after its commitment). When `package.committed_metrics` is absent, fall back to the product's current `reporting_capabilities.available_metrics` (no timestamp filter). Empty array (or absent) indicates clean delivery against the contract. Non-empty signals an accountability breach — the seller committed to the metric but did not produce the value here. Sellers MUST exclude metrics that are not yet measurable for the current `measurement_window` (e.g., post-IVT counts during the live window) — those will appear (or not) when a wider window supersedes this report via `supersedes_window`. Each entry uses an explicit `scope` discriminator: `standard` for entries from the closed `available-metric.json` enum, `vendor` for vendor-defined metrics anchored on a BrandRef. Symmetric with `committed_metrics`. When the request narrowed the payload via requested_metrics, sellers MUST NOT list a committed metric here solely because the buyer excluded it — missing_metrics reports delivery gaps, not request narrowing.", examples=[ [], [{'scope': 'standard', 'metric_id': 'completed_views'}], [ {'scope': 'standard', 'metric_id': 'completed_views'}, { 'scope': 'vendor', 'vendor': {'domain': 'attentionvendor.example'}, 'metric_id': 'attention_units', }, ], ], ), ] = None metric_values: Annotated[ list[package_delivery_metric_value.PackageDeliveryMetricValue] | None, Field( description='Qualified standard delivery values for this package. Each entry is the delivered counterpart to a standard-scope package.committed_metrics or by_package[].missing_metrics row, using the same atomic key (scope, metric_id, qualifier). Sellers report one row per full qualifier set at package grain; when a metric appears here, its flat scalar counterpart on the package MUST be omitted to avoid two sources of truth. Vendor-scope values continue to use vendor_metric_values. Buyers reconcile rows directly and perform any compatible cross-package aggregation themselves.' ), ] = None by_catalog_item: Annotated[ list[catalog_item_delivery_metrics.CatalogItemDeliveryMetrics] | None, Field( description='Delivery by catalog item within this package. Available for catalog-driven packages when the seller supports item-level reporting.' ), ] = None by_catalog_item_truncated: Annotated[ StrictBool | None, Field( description='Whether by_catalog_item was truncated due to the requested limit or a seller-imposed maximum. Sellers MUST return this flag whenever by_catalog_item is present and the request included reporting_dimensions.catalog_item (false means the list is complete). When the breakdown was returned automatically without a request key, the flag is RECOMMENDED but not required — automatic rows carry no completeness contract.' ), ] = None by_catalog_item_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_catalog_item rows. Sellers MUST return this field whenever by_catalog_item is present and the request included reporting_dimensions.catalog_item. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric. When the breakdown was returned automatically without a request key, the field is RECOMMENDED but not required — automatic rows carry no completeness contract." ), ] = None by_catalog_item_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_catalog_item ordering. Sellers MUST return this field whenever by_catalog_item is present and the request included reporting_dimensions.catalog_item, alongside by_catalog_item_sorted_by. When the breakdown was returned automatically without a request key, the field is RECOMMENDED but not required — automatic rows carry no completeness contract.' ), ] = None by_creative: Annotated[ list[creative_delivery_metrics.CreativeDeliveryMetrics] | None, Field( description='Metrics broken down by creative within this package. Available when the seller supports creative-level reporting.' ), ] = None by_format: Annotated[ list[ByFormatItem] | None, Field( description="Delivery by canonical creative format kind within this package. Negotiated on the GET path when the buyer requests reporting_dimensions.format and the product declares supports_format_breakdown; reporting webhook configuration does not negotiate or guarantee this breakdown. Each row aggregates every served creative of that format kind. Sellers MUST aggregate all delivery using adopter-defined shapes into one format_kind 'custom' row. When by_format_truncated is false, additive metrics such as impressions and spend across the rows SHOULD reconcile to the corresponding package totals, subject to the measurement and attribution semantics of each metric. Buyers MUST NOT expect row-level correspondence between by_format and by_creative because the two breakdowns are independently produced at different grains." ), ] = None by_format_truncated: Annotated[ StrictBool | None, Field( description='Whether by_format was truncated due to the requested limit or a seller-imposed maximum. Sellers MUST return this flag whenever by_format is present (false means the list is complete).' ), ] = None by_format_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_format rows. Sellers MUST return this field whenever by_format is present. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric." ), ] = None by_format_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_format ordering. Sellers MUST return this field whenever by_format is present.' ), ] = None by_creative_truncated: Annotated[ StrictBool | None, Field( description='Whether by_creative was truncated due to the requested limit or a seller-imposed maximum. Sellers MUST return this flag whenever by_creative is present and the request included reporting_dimensions.creative (false means the list is complete). When the breakdown was returned automatically without a request key, the flag is RECOMMENDED but not required — automatic rows carry no completeness contract.' ), ] = None by_creative_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_creative rows. Sellers MUST return this field whenever by_creative is present and the request included reporting_dimensions.creative. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric. When the breakdown was returned automatically without a request key, the field is RECOMMENDED but not required — automatic rows carry no completeness contract." ), ] = None by_creative_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_creative ordering. Sellers MUST return this field whenever by_creative is present and the request included reporting_dimensions.creative, alongside by_creative_sorted_by. When the breakdown was returned automatically without a request key, the field is RECOMMENDED but not required — automatic rows carry no completeness contract.' ), ] = None by_keyword: Annotated[ list[keyword_delivery_metrics.KeywordDeliveryMetrics] | None, Field( description='Metrics broken down by keyword within this package. One row per (keyword, match_type) pair — the same keyword with different match types appears as separate rows. Keyword-grain only: rows reflect aggregate performance of each targeted keyword, not individual search queries. Rows may not sum to package totals when a single impression is attributed to the triggering keyword only. Available for search and retail media packages when the seller supports keyword-level reporting.' ), ] = None by_keyword_truncated: Annotated[ StrictBool | None, Field( description='Whether by_keyword was truncated due to the requested limit or a seller-imposed maximum. Sellers MUST return this flag whenever by_keyword is present and the request included reporting_dimensions.keyword (false means the list is complete). When the breakdown was returned automatically without a request key, the flag is RECOMMENDED but not required — automatic rows carry no completeness contract.' ), ] = None by_keyword_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_keyword rows. Sellers MUST return this field whenever by_keyword is present and the request included reporting_dimensions.keyword. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric. When the breakdown was returned automatically without a request key, the field is RECOMMENDED but not required — automatic rows carry no completeness contract." ), ] = None by_keyword_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_keyword ordering. Sellers MUST return this field whenever by_keyword is present and the request included reporting_dimensions.keyword, alongside by_keyword_sorted_by. When the breakdown was returned automatically without a request key, the field is RECOMMENDED but not required — automatic rows carry no completeness contract.' ), ] = None by_geo: Annotated[ list[geo_delivery_metrics.GeoDeliveryMetrics] | None, Field( description="Delivery by geographic area within this package. Available when the buyer requests geo breakdown via reporting_dimensions and the seller supports it. Each dimension's rows are independent slices that should sum to the package total." ), ] = None by_geo_truncated: Annotated[ StrictBool | None, Field( description='Whether by_geo was truncated due to the requested limit or a seller-imposed maximum. Sellers MUST return this flag whenever by_geo is present (false means the list is complete).' ), ] = None by_geo_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_geo rows. Sellers MUST return this field whenever by_geo is present. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric." ), ] = None by_geo_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_geo ordering. Sellers MUST return this field whenever by_geo is present.' ), ] = None by_device_type: Annotated[ list[ByDeviceTypeItem] | None, Field( description='Delivery by device form factor within this package. Available when the buyer requests device_type breakdown via reporting_dimensions and the seller supports it.' ), ] = None by_device_type_truncated: Annotated[ StrictBool | None, Field( description='Whether by_device_type was truncated. Sellers MUST return this flag whenever by_device_type is present (false means the list is complete).' ), ] = None by_device_type_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_device_type rows. Sellers MUST return this field whenever by_device_type is present. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric." ), ] = None by_device_type_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_device_type ordering. Sellers MUST return this field whenever by_device_type is present.' ), ] = None by_device_type_pagination: Annotated[ pagination_response.PaginationResponse | None, Field( description="Cursor to retrieve the remaining by_device_type rows when by_device_type_truncated is true. Sellers MUST return this field whenever by_device_type_truncated is true; omit when false or when by_device_type is absent. Pass the cursor back in the corresponding request's reporting_dimensions.device_type_1.cursor to fetch the next page; other reporting_dimensions.device_type request fields (limit, sort_by, sort_direction) MUST be repeated unchanged across paged requests." ), ] = None by_device_platform: Annotated[ list[ByDevicePlatformItem] | None, Field( description='Delivery by operating system within this package. Available when the buyer requests device_platform breakdown via reporting_dimensions and the seller supports it. Useful for CTV campaigns where tvOS vs Roku OS vs Fire OS matters.' ), ] = None by_device_platform_truncated: Annotated[ StrictBool | None, Field( description='Whether by_device_platform was truncated. Sellers MUST return this flag whenever by_device_platform is present (false means the list is complete).' ), ] = None by_device_platform_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_device_platform rows. Sellers MUST return this field whenever by_device_platform is present. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric." ), ] = None by_device_platform_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_device_platform ordering. Sellers MUST return this field whenever by_device_platform is present.' ), ] = None by_device_platform_pagination: Annotated[ pagination_response.PaginationResponse | None, Field( description="Cursor to retrieve the remaining by_device_platform rows when by_device_platform_truncated is true. Sellers MUST return this field whenever by_device_platform_truncated is true; omit when false or when by_device_platform is absent. Pass the cursor back in the corresponding request's reporting_dimensions.device_platform_1.cursor to fetch the next page; other reporting_dimensions.device_platform request fields (limit, sort_by, sort_direction) MUST be repeated unchanged across paged requests." ), ] = None by_audience: Annotated[ list[ByAudienceItem] | None, Field( description="Delivery by audience segment within this package. Available when the buyer requests audience breakdown via reporting_dimensions and the seller supports it. Only 'synced' audiences are directly targetable via the targeting overlay; other sources are informational." ), ] = None by_audience_truncated: Annotated[ StrictBool | None, Field( description='Whether by_audience was truncated. Sellers MUST return this flag whenever by_audience is present (false means the list is complete).' ), ] = None by_audience_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_audience rows. Sellers MUST return this field whenever by_audience is present. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric." ), ] = None by_audience_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_audience ordering. Sellers MUST return this field whenever by_audience is present.' ), ] = None by_audience_pagination: Annotated[ pagination_response.PaginationResponse | None, Field( description="Cursor to retrieve the remaining by_audience rows when by_audience_truncated is true. Sellers MUST return this field whenever by_audience_truncated is true; omit when false or when by_audience is absent. Pass the cursor back in the corresponding request's reporting_dimensions.audience.cursor to fetch the next page; other reporting_dimensions.audience request fields (limit, sort_by, sort_direction) MUST be repeated unchanged across paged requests." ), ] = None by_demographic: Annotated[ list[ByDemographicItem] | None, Field( description='Delivery by demographic within this package. Available when the buyer requests demographic breakdown and the product declares supports_demographic_breakdown. A free-form measurement code does not prove alignment with buyer targeting. When age is present it is the authoritative machine-comparable interval; for requested age_ranges, sellers MUST echo the exact requested interval and MUST NOT substitute a wider or narrower native bucket.' ), ] = None by_demographic_truncated: Annotated[ StrictBool | None, Field( description='Whether non-suppressed by_demographic rows were truncated due to the requested limit or a seller-imposed maximum. Sellers MUST return this flag whenever by_demographic is present. False means every non-suppressed row is present; inspect by_demographic_suppressed separately before reconciling rows to package totals.' ), ] = None by_demographic_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_demographic rows. Sellers MUST return this field whenever by_demographic is present. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric." ), ] = None by_demographic_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_demographic ordering. Sellers MUST return this field whenever by_demographic is present.' ), ] = None by_demographic_suppressed: Annotated[ StrictBool | None, Field( description='Whether one or more otherwise reportable demographic rows were omitted due to privacy, policy, or measurement thresholds. Sellers MUST return this flag whenever by_demographic is present. False means no rows were threshold-suppressed.' ), ] = None by_placement: Annotated[ list[placement_delivery_metrics.PlacementDeliveryMetrics] | None, Field( description='Delivery by placement within this package. placement_id remains required for 3.1 compatibility. New 3.2 sellers also emit placement_identity, whose discriminator separates publisher-catalog identity from sales-agent-defined inline identity.' ), ] = None by_placement_truncated: Annotated[ StrictBool | None, Field( description='Whether by_placement was truncated. Sellers MUST return this flag whenever by_placement is present (false means the list is complete).' ), ] = None by_placement_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description="The metric actually used to order by_placement rows. Sellers MUST return this field whenever by_placement is present. When the seller cannot sort by the requested sort_by metric it falls back to 'spend'; this echo makes the fallback visible instead of silently returning rows the buyer will misread as ordered by the requested metric." ), ] = None by_placement_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_placement ordering. Sellers MUST return this field whenever by_placement is present.' ), ] = None by_placement_pagination: Annotated[ pagination_response.PaginationResponse | None, Field( description="Cursor to retrieve the remaining by_placement rows when by_placement_truncated is true. Sellers MUST return this field whenever by_placement_truncated is true; omit when false or when by_placement is absent. Pass the cursor back in the corresponding request's reporting_dimensions.placement.cursor to fetch the next page; other reporting_dimensions.placement request fields (limit, sort_by, sort_direction) MUST be repeated unchanged across paged requests." ), ] = None by_property: Annotated[ list[property_delivery_metrics.PropertyDeliveryMetrics] | None, Field( description='Delivery by publisher property within this package. Each row identifies the actual surface with an operational identifier and adds property_ref when it resolves to a canonical publisher catalog entry. Rows are independent of by_collection.' ), ] = None by_property_truncated: Annotated[ StrictBool | None, Field( description='Whether non-suppressed by_property rows were truncated. Sellers MUST return this flag whenever by_property is present. False means every non-suppressed row is present; inspect by_property_suppressed before reconciling rows to package totals.' ), ] = None by_property_suppressed: Annotated[ StrictBool | None, Field( description='Whether one or more otherwise reportable by_property rows were omitted from this response due to privacy, policy, or measurement thresholds. Sellers MUST return this flag whenever by_property is present. False means no rows were threshold-suppressed. Both suppression and truncation may be true.' ), ] = None by_property_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description='The metric actually used to order by_property rows. Sellers MUST return this field whenever by_property is present.' ), ] = None by_property_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_property rows. Sellers MUST return this field whenever by_property is present.' ), ] = None by_collection: Annotated[ list[collection_delivery_metrics.CollectionDeliveryMetrics] | None, Field( description='Delivery by publisher-scoped collection within this package. This is a marginal breakdown and does not by itself prove which property carried a collection.' ), ] = None by_collection_truncated: Annotated[ StrictBool | None, Field( description='Whether by_collection was truncated. Sellers MUST return this flag whenever by_collection is present.' ), ] = None by_collection_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description='The metric actually used to order by_collection rows. Sellers MUST return this field whenever by_collection is present.' ), ] = None by_collection_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_collection rows. Sellers MUST return this field whenever by_collection is present.' ), ] = None by_installment: Annotated[ list[installment_delivery_metrics.InstallmentDeliveryMetrics] | None, Field(description='Delivery by canonically identified installment within this package.'), ] = None by_installment_truncated: Annotated[ StrictBool | None, Field( description='Whether by_installment was truncated. Sellers MUST return this flag whenever by_installment is present.' ), ] = None by_installment_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description='The metric actually used to order by_installment rows. Sellers MUST return this field whenever by_installment is present.' ), ] = None by_installment_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_installment rows. Sellers MUST return this field whenever by_installment is present.' ), ] = None by_collection_property: Annotated[ list[collection_property_delivery_metrics.CollectionPropertyDeliveryMetrics] | None, Field( description='Delivery at the collection × property intersection. A row is affirmative delivery evidence that the referenced collection ran on the referenced property; it is not merely a carriage or catalog assertion.' ), ] = None by_collection_property_truncated: Annotated[ StrictBool | None, Field( description='Whether non-suppressed by_collection_property rows were truncated. Sellers MUST return this flag whenever by_collection_property is present.' ), ] = None by_collection_property_suppressed: Annotated[ StrictBool | None, Field( description='Whether one or more otherwise reportable by_collection_property rows were omitted from this response due to privacy, policy, or measurement thresholds. Sellers MUST return this flag whenever by_collection_property is present. False means no rows were threshold-suppressed. Both suppression and truncation may be true.' ), ] = None by_collection_property_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description='The metric actually used to order by_collection_property rows. Sellers MUST return this field whenever by_collection_property is present.' ), ] = None by_collection_property_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_collection_property rows. Sellers MUST return this field whenever by_collection_property is present.' ), ] = None by_installment_property: Annotated[ list[installment_property_delivery_metrics.InstallmentPropertyDeliveryMetrics] | None, Field( description='Delivery at the installment × property intersection. A row is affirmative delivery evidence that the referenced airing, episode, issue, or programming block ran on the referenced property; it is not inferred from collection carriage or independent marginals.' ), ] = None by_installment_property_truncated: Annotated[ StrictBool | None, Field( description='Whether non-suppressed by_installment_property rows were truncated. Sellers MUST return this flag whenever by_installment_property is present.' ), ] = None by_installment_property_suppressed: Annotated[ StrictBool | None, Field( description='Whether one or more otherwise reportable by_installment_property rows were omitted from this response due to privacy, policy, or measurement thresholds. Sellers MUST return this flag whenever by_installment_property is present. False means no rows were threshold-suppressed. Both suppression and truncation may be true.' ), ] = None by_installment_property_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description='The metric actually used to order by_installment_property rows. Sellers MUST return this field whenever by_installment_property is present.' ), ] = None by_installment_property_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_installment_property rows. Sellers MUST return this field whenever by_installment_property is present.' ), ] = None by_placement_property: Annotated[ list[placement_property_delivery_metrics.PlacementPropertyDeliveryMetrics] | None, Field( description='Delivery at the placement × property intersection. This proves which actual property carried a placement that may span more than one property.' ), ] = None by_placement_property_truncated: Annotated[ StrictBool | None, Field( description='Whether non-suppressed by_placement_property rows were truncated. Sellers MUST return this flag whenever by_placement_property is present.' ), ] = None by_placement_property_suppressed: Annotated[ StrictBool | None, Field( description='Whether one or more otherwise reportable by_placement_property rows were omitted from this response due to privacy, policy, or measurement thresholds. Sellers MUST return this flag whenever by_placement_property is present. False means no rows were threshold-suppressed. Both suppression and truncation may be true.' ), ] = None by_placement_property_sorted_by: Annotated[ sort_metric.SortMetric | None, Field( description='The metric actually used to order by_placement_property rows. Sellers MUST return this field whenever by_placement_property is present.' ), ] = None by_placement_property_sort_direction: Annotated[ sort_direction.SortDirection | None, Field( description='The direction actually applied to by_placement_property rows. Sellers MUST return this field whenever by_placement_property is present.' ), ] = None by_spot: Annotated[ list[BySpotItem] | None, Field( description='Spot-level as-run airing records for broadcast TV, radio, or other scheduled inventory. Available when the buyer requests spot breakdown and the product declares supports_spot_breakdown. Sellers MUST order rows by aired_at ascending. The same spot_id is reused when a later package measurement_window adds or revises metrics. Network and station are optional so station-direct radio and network-level TV records use the same channel-neutral shape. Sellers SHOULD populate creative_id whenever they can associate a specific airing with a creative, particularly when the package could serve more than one creative during any part of the reporting period, including a mid-period replacement. Sellers that cannot make that association MUST omit creative_id rather than emit a default or placeholder. Buyers MUST NOT aggregate by_spot rows by creative_id and expect the result to equal by_creative impressions for the same creative: the two dimensions are independently produced at different granularities and are subject to different metric-maturation and attribution semantics within the package measurement_window. by_creative is the authoritative creative-performance aggregate; creative_id on a by_spot row identifies which creative aired, not an independent metric roll-up source.' ), ] = None by_spot_truncated: Annotated[ StrictBool | None, Field( description='Whether by_spot is incomplete because of the requested limit or a seller-imposed maximum. Sellers MUST return this flag whenever by_spot is present (false means the as-run log is complete for the requested reporting period).' ), ] = None daily_breakdown: Annotated[ list[DailyBreakdownItem] | None, Field( description='Day-by-day delivery for this package. Only present when include_package_daily_breakdown is true in the request. Enables per-package pacing analysis and line-item monitoring.' ), ] = None spend: AnyBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- DeliveryMetrics
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var by_audience : list[ByAudienceItem] | Nonevar by_audience_pagination : PaginationResponse | Nonevar by_audience_sort_direction : SortDirection | Nonevar by_audience_sorted_by : SortMetric | Nonevar by_audience_truncated : bool | Nonevar by_catalog_item : list[CatalogItemDeliveryMetrics] | Nonevar by_catalog_item_sort_direction : SortDirection | Nonevar by_catalog_item_sorted_by : SortMetric | Nonevar by_catalog_item_truncated : bool | Nonevar by_collection : list[CollectionDeliveryMetrics] | Nonevar by_collection_property : list[CollectionPropertyDeliveryMetrics] | Nonevar by_collection_property_sort_direction : SortDirection | Nonevar by_collection_property_sorted_by : SortMetric | Nonevar by_collection_property_suppressed : bool | Nonevar by_collection_property_truncated : bool | Nonevar by_collection_sort_direction : SortDirection | Nonevar by_collection_sorted_by : SortMetric | Nonevar by_collection_truncated : bool | Nonevar by_creative : list[CreativeDeliveryMetrics] | Nonevar by_creative_sort_direction : SortDirection | Nonevar by_creative_sorted_by : SortMetric | Nonevar by_creative_truncated : bool | Nonevar by_demographic : list[ByDemographicItem] | Nonevar by_demographic_sort_direction : SortDirection | Nonevar by_demographic_sorted_by : SortMetric | Nonevar by_demographic_suppressed : bool | Nonevar by_demographic_truncated : bool | Nonevar by_device_platform : list[ByDevicePlatformItem] | Nonevar by_device_platform_pagination : PaginationResponse | Nonevar by_device_platform_sort_direction : SortDirection | Nonevar by_device_platform_sorted_by : SortMetric | Nonevar by_device_platform_truncated : bool | Nonevar by_device_type : list[ByDeviceTypeItem] | Nonevar by_device_type_pagination : PaginationResponse | Nonevar by_device_type_sort_direction : SortDirection | Nonevar by_device_type_sorted_by : SortMetric | Nonevar by_device_type_truncated : bool | Nonevar by_format : list[ByFormatItem] | Nonevar by_format_sort_direction : SortDirection | Nonevar by_format_sorted_by : SortMetric | Nonevar by_format_truncated : bool | Nonevar by_geo : list[GeoDeliveryMetrics] | Nonevar by_geo_sort_direction : SortDirection | Nonevar by_geo_sorted_by : SortMetric | Nonevar by_geo_truncated : bool | Nonevar by_installment : list[InstallmentDeliveryMetrics] | Nonevar by_installment_property : list[InstallmentPropertyDeliveryMetrics] | Nonevar by_installment_property_sort_direction : SortDirection | Nonevar by_installment_property_sorted_by : SortMetric | Nonevar by_installment_property_suppressed : bool | Nonevar by_installment_property_truncated : bool | Nonevar by_installment_sort_direction : SortDirection | Nonevar by_installment_sorted_by : SortMetric | Nonevar by_installment_truncated : bool | Nonevar by_keyword : list[KeywordDeliveryMetrics] | Nonevar by_keyword_sort_direction : SortDirection | Nonevar by_keyword_sorted_by : SortMetric | Nonevar by_keyword_truncated : bool | Nonevar by_placement : list[PlacementDeliveryMetrics] | Nonevar by_placement_pagination : PaginationResponse | Nonevar by_placement_property : list[PlacementPropertyDeliveryMetrics] | Nonevar by_placement_property_sort_direction : SortDirection | Nonevar by_placement_property_sorted_by : SortMetric | Nonevar by_placement_property_suppressed : bool | Nonevar by_placement_property_truncated : bool | Nonevar by_placement_sort_direction : SortDirection | Nonevar by_placement_sorted_by : SortMetric | Nonevar by_placement_truncated : bool | Nonevar by_property : list[PropertyDeliveryMetrics] | Nonevar by_property_sort_direction : SortDirection | Nonevar by_property_sorted_by : SortMetric | Nonevar by_property_suppressed : bool | Nonevar by_property_truncated : bool | Nonevar by_spot : list[BySpotItem] | Nonevar by_spot_truncated : bool | Nonevar currency : strvar daily_breakdown : list[DailyBreakdownItem] | Nonevar delivery_status : DeliveryStatus | Nonevar finalized_at : pydantic.types.AwareDatetime | Nonevar is_final : bool | Nonevar measurement_window : str | Nonevar metric_values : list[PackageDeliveryMetricValue] | Nonevar missing_metrics : list[MissingMetric1 | MissingMetric2] | Nonevar model_configvar pacing_index : float | Nonevar package_id : strvar paused : bool | Nonevar pricing_model : PricingModelvar rate : floatvar spend : Anyvar supersedes_window : str | None
Inherited members
class CanonicalMediaBuyActionMode (*args, **kwds)-
Expand source code
class CanonicalMediaBuyActionMode(StrEnum): self_serve = 'self_serve' conditional_self_serve = 'conditional_self_serve' seller_managed = 'seller_managed' requires_approval = 'requires_approval'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var conditional_self_servevar requires_approvalvar self_servevar seller_managed
class CanonicalMediaBuyActionName (*args, **kwds)-
Expand source code
class CanonicalMediaBuyActionName(StrEnum): pause = 'pause' resume = 'resume' cancel = 'cancel' extend_flight = 'extend_flight' shorten_flight = 'shorten_flight' update_flight_dates = 'update_flight_dates' increase_budget = 'increase_budget' decrease_budget = 'decrease_budget' reallocate_budget = 'reallocate_budget' update_budget_allocation = 'update_budget_allocation' update_targeting = 'update_targeting' update_pacing = 'update_pacing' update_bidding = 'update_bidding' update_frequency_caps = 'update_frequency_caps' update_media_buy_frequency_cap = 'update_media_buy_frequency_cap' update_catalog_assignments = 'update_catalog_assignments' update_keywords = 'update_keywords' update_optimization_goals = 'update_optimization_goals' update_impression_goal = 'update_impression_goal' update_spend_target = 'update_spend_target' update_reporting_webhook = 'update_reporting_webhook' replace_creative = 'replace_creative' update_creative_assignments = 'update_creative_assignments' remove_creative = 'remove_creative' add_packages = 'add_packages' remove_packages = 'remove_packages'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var add_packagesvar cancelvar decrease_budgetvar extend_flightvar increase_budgetvar pausevar reallocate_budgetvar remove_creativevar remove_packagesvar replace_creativevar resumevar shorten_flightvar update_biddingvar update_budget_allocationvar update_catalog_assignmentsvar update_creative_assignmentsvar update_flight_datesvar update_frequency_capsvar update_impression_goalvar update_keywordsvar update_media_buy_frequency_capvar update_optimization_goalsvar update_pacingvar update_reporting_webhookvar update_spend_targetvar update_targeting
class CanonicalProductAction (**data: Any)-
Expand source code
class CanonicalProductAction(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) action: canonical_media_buy_action.CanonicalMediaBuyActionName modes: Annotated[ list[canonical_media_buy_action_mode.CanonicalMediaBuyActionMode], Field(min_length=1) ] allowed_statuses: Annotated[ list[media_buy_status.MediaBuyStatus] | None, Field(min_length=1) ] = None sla: sla_window.SlaWindow | None = None constraints: Annotated[ change_term_constraints.MediaBuyChangeTermConstraints | None, Field( description='Advisory machine-readable bounds for product selection; proposal change terms restate binding bounds.' ), ] = None terms_ref: Annotated[ str | None, Field( description='Optional advisory pointer to published commercial terms. It is not a proposal change-term identity.' ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var action : CanonicalMediaBuyActionNamevar allowed_statuses : list[MediaBuyStatus] | Nonevar constraints : MediaBuyChangeTermConstraints1 | MediaBuyChangeTermConstraints2 | MediaBuyChangeTermConstraints3 | MediaBuyChangeTermConstraints4 | Nonevar model_configvar modes : list[CanonicalMediaBuyActionMode]var sla : SlaWindow | Nonevar terms_ref : str | None
Inherited members
class CommercialTerms (**data: Any)-
Expand source code
class CommercialTerms(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) source_feed_version: Annotated[ str | None, Field( description='Wholesale product feed version against which direct published offers were accepted. Omitted when the seller authored terms outside a wholesale snapshot.', min_length=1, ), ] = None source_pricing_version: Annotated[ str | None, Field( description='Pricing-layer version against which published rates were accepted.', min_length=1, ), ] = None brand: brand_key.BrandKey advertiser_industry: advertiser_industry_1.AdvertiserIndustry | None = None purchases: Annotated[ list[product_purchase.ProductPurchase], Field( description='Exact canonical product, pricing, format, catalog, budget, targeting, bidding, optimization, resolved flight, measurement, and performance terms in the commercial envelope.', min_length=1, ), ] start_time: start_timing.StartTiming end_time: AwareDatetime total_budget: TotalBudget | None = None daily_budget_cap: Annotated[ StrictFloat | None, Field( description='Hard aggregate daily spend ceiling accepted as part of these terms. It bounds total spend without creating purchase allocations.', ge=0.0, ), ] = None frequency_cap: Annotated[ media_buy_frequency_cap.MediaBuyFrequencyCap | None, Field( description='Hard MediaBuy-level cap accepted as part of these terms. One counter aggregates exposures across every purchase; purchase targeting caps remain independently binding.' ), ] = None budget_cap_timezone: Annotated[ str | None, Field( description='Shared IANA calendar-day boundary for aggregate and purchase daily caps in these terms.', min_length=1, ), ] = None budget_allocation: canonical_budget_allocation.CanonicalBudgetAllocation | None = None pacing: pacing_1.Pacing | None = None bidding: Annotated[ bidding_policy.BiddingPolicy | None, Field( description="Media-buy bidding policy. A proposal answering criteria.outcome_target.cost_per states here the cost the seller can plan to, which the buyer adopts on acceptance: the requested strength, and an amount greater than or equal to the ask (the ask when the seller can forecast goal volume under it within the buyer's budget, otherwise the lowest such amount), denominated in the purchases' pricing currency, which equals cost_per.currency. It is an execution control, not an expected price; when the planned spend at that amount is below total_budget, forecast points carry metrics.spend. See outcome-target.json for goal binding." ), ] = None invoice_recipient: business_entity.BusinessEntity | None = None 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 reporting_commitments: Annotated[ list[ReportingCommitment] | None, Field( description='Binding reporting contract keyed by position in purchases. Amendments preserve prior entries and add metrics with effective_at; seller-assigned package IDs live in the execution binding, outside this digest.', min_length=1, ), ] = None cancellation_terms: CancellationTerms | None = None change_terms: Annotated[ list[change_term.MediaBuyChangeTerm] | None, Field( description='Binding buyer change rights included in the commercial envelope and therefore covered by terms_digest. Entries are uniquely keyed by action. When this field is present, an omitted action is not a negotiated change right. Omission of the entire field means legacy-unspecified rights, not a prohibition.', min_length=1, ), ] = None @model_validator(mode='after') def _validate_change_term_set(self) -> CommercialTerms: if self.change_terms is None: return self actions = [term.action.value for term in self.change_terms] term_ids = [term.term_id for term in self.change_terms] if len(set(actions)) != len(actions): raise ValueError('change_terms must be uniquely keyed by action') if len(set(term_ids)) != len(term_ids): raise ValueError('change_terms term_id values must be unique') currencies = set() for purchase in self.purchases: if purchase.pricing is None: raise ValueError('accepted commercial-term purchases require resolved pricing') currencies.add(purchase.pricing.currency) for term in self.change_terms: if term.constraints is None: continue constraint = term.constraints if constraint.kind == 'budget': money_fields = ( constraint.max_delta_amount, constraint.min_result_amount, constraint.max_result_amount, ) if any(money is not None and money.currency not in currencies for money in money_fields): raise ValueError('change-term monetary constraint currency must match purchases') if ( constraint.min_result_amount is not None and constraint.max_result_amount is not None and constraint.min_result_amount.amount > constraint.max_result_amount.amount ): raise ValueError('change-term minimum result exceeds maximum result') elif constraint.kind == 'flight': if ( constraint.earliest_result is not None and constraint.latest_result is not None and constraint.earliest_result > constraint.latest_result ): raise ValueError('change-term earliest result exceeds latest result') elif constraint.kind == 'effective_timing' and ( constraint.earliest_effective_at is not None and constraint.latest_effective_at is not None and constraint.earliest_effective_at > constraint.latest_effective_at ): raise ValueError('change-term earliest effective time exceeds latest time') return selfBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var advertiser_industry : AdvertiserIndustry | Nonevar agency_estimate_number : str | Nonevar bidding : BiddingPolicy | Nonevar brand : BrandKeyvar budget_allocation : CanonicalBudgetAllocation1 | CanonicalBudgetAllocation2 | Nonevar budget_cap_timezone : str | Nonevar cancellation_terms : CancellationTerms | Nonevar change_terms : list[MediaBuyChangeTerm] | Nonevar daily_budget_cap : float | Nonevar end_time : pydantic.types.AwareDatetimevar frequency_cap : MediaBuyFrequencyCap | Nonevar invoice_recipient : BusinessEntity | Nonevar model_configvar pacing : Pacing | Nonevar purchase_order_ref : str | Nonevar purchases : list[ProductPurchase]var reporting_commitments : list[ReportingCommitment] | Nonevar source_feed_version : str | Nonevar source_pricing_version : str | Nonevar start_time : Literal['asap'] | pydantic.types.AwareDatetimevar total_budget : TotalBudget | None
Inherited members
class CompatibilityPurchaseCoordinatorInput (**data: Any)-
Expand source code
class CompatibilityPurchaseCoordinatorInput(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) idempotency_key: Annotated[ UUID, Field( description='Replay identity for this logical coordinator operation. Exact retries resume the durable operation record instead of redeeming the continuation again.' ), ] continuation_token: Annotated[ str, Field( description='Opaque token returned by products_available.purchase_continuation.', min_length=16, ), ] account: Annotated[ account_ref.AccountReference, Field( description='Account identity that must match the account bound into the continuation token.' ), ] selected_product_ids: Annotated[ list[SelectedProductId], Field( description='Non-empty subset of the product IDs bound into the continuation.', min_length=1, json_schema_extra={'uniqueItems': True}, ), ] accepted_losses: Annotated[ list[AcceptedLoss], Field( description='Exact loss set returned with the continuation. Missing, extra, or stale consent fails before mutation.', min_length=2, json_schema_extra={ 'uniqueItems': True, 'allOf': [ {'contains': {'const': 'feed_version_not_atomic'}}, {'contains': {'const': 'pricing_version_not_atomic'}}, ], }, ), ] legacy_create_request: Annotated[ dict[str, Any], Field( description='Proposed create_media_buy payload. Before mutation the coordinator validates this object against create-media-buy-request.json from source_adcp_version, requires explicit-package mode, and requires its package product IDs to equal selected_product_ids.', min_length=1, ), ] @field_validator('selected_product_ids') @classmethod def _selected_product_ids_are_unique( cls, values: list[SelectedProductId] ) -> list[SelectedProductId]: if len(values) != len(set(values)): raise ValueError('selected_product_ids must contain unique items') return values @field_validator('accepted_losses') @classmethod def _accepted_losses_match_schema( cls, values: list[AcceptedLoss] ) -> list[AcceptedLoss]: value_set = set(values) if len(values) != len(value_set): raise ValueError('accepted_losses must contain unique items') required = { AcceptedLoss.feed_version_not_atomic, AcceptedLoss.pricing_version_not_atomic, } if not required.issubset(value_set): raise ValueError('accepted_losses must include the required compatibility losses') return valuesBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var accepted_losses : list[AcceptedLoss]var account : AccountReference1 | AccountReference2var continuation_token : strvar idempotency_key : uuid.UUIDvar legacy_create_request : dict[str, typing.Any]var model_configvar selected_product_ids : list[SelectedProductId]
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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : CanonicalAccountReference1 | CanonicalAccountReference2var bidding : BiddingPolicy | Nonevar budget_allocation : CanonicalBudgetAllocation1 | CanonicalBudgetAllocation2 | Nonevar budget_cap_timezone : str | Nonevar canceled : Literal[True] | Nonevar cancellation_reason : str | Nonevar context : ContextObject | Nonevar daily_budget_cap : float | Nonevar ext : ExtensionObject | Nonevar frequency_cap : MediaBuyFrequencyCap | Nonevar governance_context : str | Nonevar idempotency_key : strvar media_buy_id : strvar model_configvar name : str | Nonevar pacing : Pacing | Nonevar packages : list[PackageControl] | Nonevar paused : bool | Nonevar push_notification_config : PushNotificationConfig | Nonevar reporting_webhook : ReportingWebhook | Nonevar revision : intvar 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 CreateMediaBuyRequest (**data: Any)-
Expand source code
class CreateMediaBuyRequest(_LegacyCreateMediaBuyRequest, CanonicalBoundaryModel): """Canonical create request; packages are canonical package requests.""" packages: list[PackageRequest] | None = NoneCanonical 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreateMediaBuyRequest
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar packages : list[PackageRequest] | None
Inherited members
class CreateMediaBuySuccessResponse (**data: Any)-
Expand source code
class CreateMediaBuyResponse1(_LegacyCreateMediaBuyResponse1, CanonicalBoundaryModel): """Canonical create response preserving the 3.x legacy-status normalizer.""" packages: list[Package] # type: ignore[assignment] @model_validator(mode="before") @classmethod def _normalize_legacy_status(cls, data: Any) -> Any: if not isinstance(data, dict): return data raw_status = unwrap_enum_value(data.get("status")) media_buy_status = unwrap_enum_value(data.get("media_buy_status")) if raw_status is None or raw_status == "completed": return {**data, "status": "completed"} if media_buy_status is None and raw_status in MEDIA_BUY_LEGACY_STATUS_VALUES: return {**data, "media_buy_status": raw_status, "status": "completed"} if media_buy_status is not None and raw_status == media_buy_status: return {**data, "status": "completed"} return dataCanonical create response preserving the 3.x legacy-status normalizer.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreateMediaBuyResponse1
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar packages : list[Package]
Inherited members
class CreateMediaBuyErrorResponse (**data: Any)-
Expand source code
class CreateMediaBuyResponse2(_LegacyCreateMediaBuyResponse2, CanonicalBoundaryModel): """Canonical create-media-buy error arm."""Canonical create-media-buy error arm.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreateMediaBuyResponse2
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class CreateMediaBuySubmittedResponse (**data: Any)-
Expand source code
class CreateMediaBuyResponse3(_LegacyCreateMediaBuyResponse3, CanonicalBoundaryModel): """Canonical create-media-buy submitted arm."""Canonical create-media-buy submitted arm.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreateMediaBuyResponse3
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class DailyBreakdownItem (**data: Any)-
Expand source code
class DailyBreakdownItem(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) date: Annotated[ str, Field( description="Calendar date (YYYY-MM-DD) in the reporting timezone: reporting_period.timezone when present, otherwise this package's product reporting_capabilities.timezone. The row covers that local day, which can be 23 or 25 hours long across a DST change.", pattern='^\\d{4}-\\d{2}-\\d{2}$', ), ] impressions: Annotated[ StrictFloat, Field(description='Daily impressions for this package', ge=0.0) ] spend: Annotated[StrictFloat, Field(description='Daily spend for this package', ge=0.0)] conversions: Annotated[ StrictFloat | None, Field(description='Daily conversions for this package', ge=0.0) ] = None conversion_value: Annotated[ StrictFloat | None, Field(description='Daily conversion value for this package', ge=0.0) ] = None commissionable_value: Annotated[ StrictFloat | None, Field( description='Daily settled conversion value eligible for revenue-share commission for this package', ge=0.0, ), ] = None roas: Annotated[ StrictFloat | None, Field(description='Daily return on ad spend (conversion_value / spend)', ge=0.0), ] = None new_to_brand_rate: Annotated[ StrictFloat | None, Field( description='Daily fraction of conversions from first-time brand buyers (0 = none, 1 = all)', ge=0.0, le=1.0, ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var commissionable_value : float | Nonevar conversion_value : float | Nonevar conversions : float | Nonevar date : strvar impressions : floatvar model_configvar new_to_brand_rate : float | Nonevar roas : float | Nonevar spend : float
Inherited members
class DaypartTarget (**data: Any)-
Expand source code
class DaypartTarget(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) days: Annotated[ list[day_of_week.DayOfWeek], Field( description='Days of week this window applies to. Use multiple days for compact targeting (e.g., monday-friday in one object).', min_length=1, ), ] start_hour: Annotated[ SchemaInt, Field( description='Start hour (inclusive), 0-23 in 24-hour format. 0 = midnight, 6 = 6:00am, 18 = 6:00pm.', ge=0, le=23, ), ] end_hour: Annotated[ SchemaInt, Field( description='End hour (exclusive), 1-24 in 24-hour format. 10 = 10:00am, 24 = midnight. Must be greater than start_hour.', ge=1, le=24, ), ] timezone: Annotated[ Literal['inventory_local'] | iana_timezone.IanaTimezoneIdentifier | None, Field( description="Civil-time clock used to evaluate this window. 'inventory_local' evaluates the hours in the seller-assigned local timezone of each inventory unit that can deliver the impression, such as a screen, venue, station, or publisher property; it never means the buyer, account, or server timezone. A concrete IANA timezone identifier (for example, 'America/New_York', 'CET', or 'UTC') evaluates one shared civil-time clock across the targeted inventory. Omission defaults to 'inventory_local'. Buyers that begin with a user or account preference MUST resolve it to a concrete IANA identifier before sending the daypart; 'user_timezone' and 'account_timezone' are not wire values. For each candidate delivery instant, convert the instant into this clock and compare its resulting local day and hour with the half-open window: a skipped DST hour has no matching instants, while both occurrences of a repeated hour match. This delivery clock is independent of reporting_capabilities.timezone.", validate_default=True, ), ] = 'inventory_local' label: Annotated[ str | None, Field( description="Optional human-readable name for this time window (e.g., 'Morning Drive', 'Prime Time')" ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var days : list[DayOfWeek]var end_hour : intvar label : str | Nonevar model_configvar start_hour : intvar timezone : Literal['inventory_local'] | IanaTimezoneIdentifier | 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.' ), ] = NoneThe 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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var context : ContextObject | Nonevar context_id : str | Nonevar declines : list[ProposalDecline]var governance_context : str | Nonevar idempotency_key : strvar model_configvar opportunity : OpportunityContext | Nonevar push_notification_config : PushNotificationConfig | None
Inherited members
class DeliveryMetrics (**data: Any)-
Expand source code
class DeliveryMetrics(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) impressions: Annotated[ StrictFloat | None, Field(description='Impressions delivered', ge=0.0) ] = None spend: Annotated[StrictFloat | None, Field(description='Amount spent', ge=0.0)] = None clicks: Annotated[StrictFloat | None, Field(description='Total clicks', ge=0.0)] = None ctr: Annotated[ StrictFloat | None, Field(description='Click-through rate (clicks/impressions)', ge=0.0, le=1.0), ] = None views: Annotated[ StrictFloat | None, Field( description="Content engagements counted toward the billable view threshold. For video this is a platform-defined view event (e.g., 30 seconds or video midpoint); for audio/podcast it is a stream start; for other formats it follows the pricing model's view definition. When the package uses CPV pricing, spend = views × rate.", ge=0.0, ), ] = None completed_views: Annotated[ StrictFloat | None, Field( description='Video/audio completions. When the package has a completed_views optimization goal with view_duration_seconds, completions are counted at that threshold rather than 100% completion.', ge=0.0, ), ] = None completion_rate: Annotated[ StrictFloat | None, Field( description='Completion rate (completed_views/impressions). Null indicates the metric is not applicable to this package/buy (e.g. completion rate on a non-video buy).', ge=0.0, le=1.0, ), ] = None conversions: Annotated[ StrictFloat | None, Field( description='Total conversions attributed to this delivery. When by_event_type is present, this equals the sum of all by_event_type[].count entries.', ge=0.0, ), ] = None conversion_value: Annotated[ StrictFloat | None, Field( description='Total monetary value of attributed conversions (in the reporting currency)', ge=0.0, ), ] = None commissionable_value: Annotated[ StrictFloat | None, Field( description='Settled portion of attributed conversion value eligible for revenue-share commission, in the reporting currency. For revenue_share pricing, spend = round_currency(commissionable_value × commission_rate). This is distinct from conversion_value because taxes, shipping, discounts, returns, cancellations, or ineligible items may be excluded under the agreed commission basis.', ge=0.0, ), ] = None roas: Annotated[ StrictFloat | None, Field(description='Return on ad spend (conversion_value / spend)', ge=0.0), ] = None cost_per_acquisition: Annotated[ StrictFloat | None, Field(description='Cost per conversion (spend / conversions)', ge=0.0) ] = None new_to_brand_rate: Annotated[ StrictFloat | None, Field( description='Fraction of `conversions` (transactions) from first-time brand buyers, 0 = none, 1 = all. For retail-media unit-volume tracking of first-time buyers, see `new_to_brand_units` (count, not rate).', ge=0.0, le=1.0, ), ] = None leads: Annotated[ StrictFloat | None, Field( description="Leads generated (convenience alias for by_event_type where event_type='lead')", ge=0.0, ), ] = None incremental_sales_lift: Annotated[ StrictFloat | None, Field( description="Incremental sales lift attributed to the campaign — sales above the control/holdout baseline. Reported as a fraction (0.15 = 15% lift) or as an absolute value depending on seller convention. The seller's `attribution_methodology` qualifier (typically `deterministic_purchase` or `modeled`) and `attribution_window` qualifier on the matching `committed_metrics` entry disambiguate the methodology and window.", ge=0.0, ), ] = None brand_lift: Annotated[ StrictFloat | None, Field( description="Brand lift — measured change in a brand metric (awareness, consideration, favorability, purchase intent, or ad recall) attributed to the campaign. Typically panel-based or survey-based. Reported as a fraction (0.05 = 5% lift). **Multidimensional in production** — Kantar, Upwave, Cint, DV all report each dimension separately with its own sample size and confidence interval. The dimension flows through `qualifier.lift_dimension` on `committed_metrics` / `by_package[].metric_values` (`awareness` | `consideration` | `favorability` | `purchase_intent` | `ad_recall`); rows under different dimensions are different surveyed outcomes and must not be combined. Use `attribution_methodology: 'panel_based'` qualifier when the underlying methodology is a panel.", ge=0.0, ), ] = None foot_traffic: Annotated[ StrictFloat | None, Field( description="Store visits attributed to ad exposure. Count of incremental visits over baseline. Typically uses location-data panel methodology (`attribution_methodology: 'panel_based'`) or deterministic loyalty-card match (`attribution_methodology: 'deterministic_purchase'`).", ge=0.0, ), ] = None conversion_lift: Annotated[ StrictFloat | None, Field( description='Incremental conversions attributed to the campaign — conversions above the control/holdout baseline. Reported as a fraction (0.10 = 10% lift) or as an absolute count depending on seller convention. Distinct from `conversions` (raw count of attributed conversions); conversion_lift requires a control group and an incrementality methodology.', ge=0.0, ), ] = None brand_search_lift: Annotated[ StrictFloat | None, Field( description='Lift in brand search query volume attributed to the campaign — measured via search-data partnerships (Google, Microsoft) or survey methodology. Reported as a fraction (0.20 = 20% lift in branded search).', ge=0.0, ), ] = None plays: Annotated[ StrictFloat | None, Field( description="Number of times the ad creative was displayed or played on DOOH or broadcast inventory. Raw play count before any impression multiplier is applied. Mirrors `forecastable-metric.json`'s `plays` token for forecast↔delivery reconciliation. Distinct from `dooh_metrics.loop_plays` (scheduled-rotation count) and from `impressions` (multiplied audience figure).", ge=0.0, ), ] = None measurement_source: Annotated[ str | None, Field( description="Third-party measurement provider whose data produced this row's audience numbers. Mirrors delivery-forecast.json's measurement_source so forecast and delivery reconcile on the same declaration — distinct from demographic_system, which specifies demographic notation. Makes measured-channel rows (radio, broadcast, OOH) self-describing: a reconciliation join can tie delivered numbers to the system that measured them without consulting out-of-band context. Lowercase slug format.", examples=[ 'nielsen', 'nielsen_audio', 'videoamp', 'comscore', 'geopath', 'barb', 'agf', 'oztam', 'kantar', 'barc', 'route', 'rajar', 'triton', ], max_length=64, pattern='^[a-z0-9_]+$', ), ] = None by_event_type: Annotated[ list[ByEventTypeItem] | None, Field( description='Conversion metrics broken down by event type. Spend-derived metrics (ROAS, CPA) are only available at the package/totals level since spend cannot be attributed to individual event types.' ), ] = None grps: Annotated[ StrictFloat | None, Field(description='Gross Rating Points delivered (for CPP)', ge=0.0) ] = None reach: Annotated[ StrictFloat | None, Field( description='Unique reach in the units specified by reach_unit. When reach_unit is omitted, units are unspecified — do not compare reach values across packages or media buys without a common reach_unit. The measurement window for this value is declared in `reach_window`; when `reach_window` is omitted, the window is unspecified and buyers MUST NOT sum reach across reports (the value MAY be a daily snapshot, a cumulative total, or something else).', ge=0.0, ), ] = None reach_unit: Annotated[ reach_unit_1.ReachUnit | None, Field( description='Unit of measurement for the reach field. Aligns with the reach_unit declared on optimization goals and delivery forecasts. Required when reach is present to enable cross-platform comparison.' ), ] = None reach_window: Annotated[ ReachWindow | None, Field( description='Measurement window for the reported `reach` and `frequency` values in this row. Declares whether the values are a per-period snapshot, a trailing rolling window, or cumulative-to-date — without this declaration, buyers summing `reach` across rows (e.g., daily delivery reports) can silently double-count audiences. Sellers SHOULD populate this whenever `reach` is present.' ), ] = None frequency: Annotated[ StrictFloat | None, Field( description="Average frequency per reach unit, measured over the window declared in `reach_window`. When `reach_unit` is 'households', this is average exposures per household; when 'accounts', per logged-in account; etc. When `reach_window` is omitted, the window is unspecified — buyers MUST NOT compare or average frequency values across rows.", ge=0.0, ), ] = None quartile_data: Annotated[ QuartileData | None, Field( description="Audio/video quartile completion data. Null indicates the metric is not applicable to this package/buy (e.g. quartile data on a non-video buy). Individual quartiles are addressable via the leaf metric identities `quartile_25` (q1_views), `quartile_50` (q2_views), `quartile_75` (q3_views), and `quartile_100` (q4_views) for declaration, commitments, aggregates, and breakdown sorting; this object remains the canonical carrier of the values. Quartiles are player-fired events (VAST firstQuartile/midpoint/thirdQuartile/complete). `quartile_100` counts 100%-of-duration completions and is distinct from `completed_views`, which counts completions at the seller's billable view threshold (`view_duration_seconds`) when one is set." ), ] = None time_based_views: Annotated[ list[TimeBasedView] | None, Field( description="Time-threshold video view counts. Each entry reports views that met a continuous duration threshold under a stated basis, rather than a completion percentage (percentage-based completion is quartile_data). Thresholds of 2 and 6 seconds are RECOMMENDED cross-platform reporting points; any seller-defined threshold is permitted. One entry per (threshold_seconds, basis) pair per reporting period — sellers MUST de-duplicate before emission and MUST NOT emit the same pair twice; buyers MAY treat duplicate pairs as a seller-side conformance bug. Entries under different bases are different metrics and MUST NOT be summed (see view-threshold-basis). Primarily an autoplay/skippable-video metric (social, olv, in-feed video); completion metrics remain the currency for lean-back CTV/cinema inventory. Distinct from `views` (the single billable-threshold scalar) and from `viewability.viewed_seconds` (average in-view duration, not a threshold count). Array entries are not individually sortable in breakdown sort_by. Disclosure-grade surface: (threshold_seconds, basis) is not part of the committed-metric qualifier vocabulary, so a `committed_metrics` entry for `time_based_views` contracts the array's presence, not specific thresholds." ), ] = None dooh_metrics: Annotated[ DoohMetrics1 | None, Field(description='DOOH-specific metrics (only included for DOOH campaigns)'), ] = None ooh_metrics: Annotated[ OohMetrics | None, Field( description='Classic (static) OOH metrics — printed bulletins, posters, transit, and street furniture (only included for ooh campaigns). Experimental in AdCP 3.2. Static units have no play event: the delivery number is a period-level modeled audience estimate whose methodology tier is declared in estimation_basis (provider identity rides the row-level measurement_source), and the settlement artifact is the posting record — it proves the posting period, not an airing.' ), ] = None viewability: Annotated[ Viewability1 | None, Field( description="Viewability metrics. Viewable rate should be calculated as viewable_impressions / measurable_impressions (not total impressions), since some environments cannot measure viewability. Includes `viewed_seconds` — average in-view duration — plus optional percentile and histogram distributions over that duration; all three use the same `measurable_impressions` population and are governed by the same viewability threshold (`standard`). Sellers SHOULD include `standard` whenever measured viewability values are reported because MRC and GroupM rows are not interchangeable. The numeric leaves are addressable via the leaf metric identities `viewable_rate`, `viewable_impressions`, `measurable_impressions`, and `viewed_seconds` for declaration, commitments, aggregates, and breakdown sorting. The structured distribution carriers require explicit `viewed_seconds_percentiles` and `viewed_seconds_histogram` identities for declaration, commitment, and selection; they are not numeric aggregate rows or sort keys. This object remains the canonical carrier of every value. When a buy reports under more than one standard, contract a specific standard via the `viewability_standard` qualifier on `committed_metrics`; when the package's `committed_metrics` carry a `viewability_standard` qualifier, sellers MUST populate `standard` on reported viewability objects so reconciliation can match the qualifier." ), ] = None engagements: Annotated[ StrictFloat | None, Field( description="Total engagements — direct interactions with the ad beyond viewing. Includes social reactions/comments/shares, story/unit opens, interactive overlay taps on CTV, companion banner interactions on audio. Platform-specific; corresponds to the 'engagements' optimization metric. Maps to DBCFM KPI_INTERACTIONS (Interaktionen) in the Reporting/Performance block.", ge=0.0, ), ] = None follows: Annotated[ StrictFloat | None, Field( description='New followers, page likes, artist/podcast/channel follows, or free channel/feed subscribes attributed to this delivery. Paid subscriptions are conversion events with `event_type: subscribe`, not `follows`.', ge=0.0, ), ] = None saves: Annotated[ StrictFloat | None, Field( description='Saves, bookmarks, playlist adds, pins attributed to this delivery.', ge=0.0 ), ] = None profile_visits: Annotated[ StrictFloat | None, Field( description="Visits to the brand's in-platform page (profile, artist page, channel, or storefront) attributed to this delivery. Does not include external website clicks.", ge=0.0, ), ] = None engagement_rate: Annotated[ StrictFloat | None, Field( description='Platform-specific engagement rate (0.0 to 1.0). Typically engagements/impressions, but definition varies by platform.', ge=0.0, le=1.0, ), ] = None cost_per_click: Annotated[ StrictFloat | None, Field(description='Cost per click (spend / clicks)', ge=0.0) ] = None cost_per_completed_view: Annotated[ StrictFloat | None, Field( description="Cost per completed view (spend / completed_views). Primary CPCV pricing scalar for video/audio inventory; the package's `pricing_model` is `cpcv` when this field is the billing basis.", ge=0.0, ), ] = None cpm: Annotated[ StrictFloat | None, Field( description="Cost per thousand impressions, computed as (spend / impressions) × 1000. Universal pricing scalar across CTV, display, mobile/web video, native, audio, and DOOH inventory; the package's `pricing_model` is `cpm` when this field is the billing basis. Field name aligns with the canonical `cpm` token in `enums/pricing-model.json` and `pricing-options/cpm-option.json` so buyers cross-walk pricing model → reported scalar without a translation table.", ge=0.0, ), ] = None downloads: Annotated[ StrictFloat | None, Field( description="Audio/podcast downloads (IAB Podcast Measurement Technical Guidelines 2.x methodology). Distinct from `views` — for podcast inventory this is the count of podcast episode downloads; for streaming audio it is the count of stream starts that meet the platform's download threshold. Prefer this over `views` for audio inventory.", ge=0.0, ), ] = None units_sold: Annotated[ StrictFloat | None, Field( description='Items sold attributed to this delivery. Retail-media scalar distinct from `conversions` — a single conversion (transaction) may carry multiple `units_sold`. Used by retail media platforms where the buyer optimizes against unit movement, not transaction count. Attribution lookback windows are platform-specific (commonly 7/14/30 days, view-through and click-through variants); sellers SHOULD declare the window via `reporting_capabilities.measurement_windows` or `measurement_terms` rather than encoding it in this scalar.', ge=0.0, ), ] = None new_to_brand_units: Annotated[ StrictFloat | None, Field( description='Units sold to first-time brand buyers (count, not rate). Retail-media scalar — the unit-volume parallel to the conversion-fraction `new_to_brand_rate`. Used by retail media platforms where new-customer acquisition unit volume is a primary KPI. Same attribution-window note as `units_sold` applies.', ge=0.0, ), ] = None by_action_source: Annotated[ list[ByActionSourceItem] | None, Field( description='Conversion metrics broken down by action source (website, app, in_store, etc.). Useful for omnichannel sellers where conversions occur across digital and physical channels.' ), ] = None vendor_metric_values: Annotated[ list[vendor_metric_value.VendorMetricValue] | None, Field( description="Reported values for vendor-defined metrics that the product's `reporting_capabilities.vendor_metrics` declared. Each entry carries the vendor (BrandRef), the metric identifier within the vendor's vocabulary, the value, optional unit, and `measurable_impressions` as the coverage denominator — vendor measurement is rarely 100% of delivered impressions, since vendors only score impressions where their SDK fires or their panel matches. When a declared vendor metric is omitted from this array, buyers infer no measurement happened (no integration). One row per `(vendor.domain, vendor.brand_id, metric_id, qualifier)` per reporting period — the same vendor metric MAY appear in multiple rows only when each carries a distinct qualifier (e.g., 7-day and 30-day attribution windows); sellers MUST de-duplicate before emission and MUST NOT emit two rows with the same tuple; buyers MAY treat duplicate rows as a seller-side conformance bug. The structured `vendor_metric_values` array is the recommended path for vendor metrics; `additionalProperties: true` on this parent object is preserved so existing free-form vendor emissions remain conformant during migration." ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Subclasses
- CatalogItemDeliveryMetrics
- CollectionDeliveryMetrics
- CollectionPropertyDeliveryMetrics
- CreativeDeliveryMetrics
- CreativeVariant
- GeoDeliveryMetrics
- InstallmentDeliveryMetrics
- InstallmentPropertyDeliveryMetrics
- KeywordDeliveryMetrics
- PlacementDeliveryMetrics
- PlacementPropertyDeliveryMetrics
- PropertyDeliveryMetrics
- ByAudienceItem
- ByDemographicItem
- ByDevicePlatformItem
- ByDeviceTypeItem
- ByFormatItem
- ByPackageItem
- ByPackageItem1
- BySpotItem
- Totals
- ByPackageItem
- Totals
Class variables
var brand_lift : float | Nonevar brand_search_lift : float | Nonevar by_action_source : list[ByActionSourceItem] | Nonevar by_event_type : list[ByEventTypeItem] | Nonevar clicks : float | Nonevar commissionable_value : float | Nonevar completed_views : float | Nonevar completion_rate : float | Nonevar conversion_lift : float | Nonevar conversion_value : float | Nonevar conversions : float | Nonevar cost_per_acquisition : float | Nonevar cost_per_click : float | Nonevar cost_per_completed_view : float | Nonevar cpm : float | Nonevar ctr : float | Nonevar dooh_metrics : DoohMetrics1 | Nonevar downloads : float | Nonevar engagement_rate : float | Nonevar engagements : float | Nonevar follows : float | Nonevar foot_traffic : float | Nonevar frequency : float | Nonevar grps : float | Nonevar impressions : float | Nonevar incremental_sales_lift : float | Nonevar leads : float | Nonevar measurement_source : str | Nonevar model_configvar new_to_brand_rate : float | Nonevar new_to_brand_units : float | Nonevar ooh_metrics : OohMetrics | Nonevar plays : float | Nonevar profile_visits : float | Nonevar quartile_data : QuartileData | Nonevar reach : float | Nonevar reach_unit : ReachUnit | Nonevar reach_window : ReachWindow | Nonevar roas : float | Nonevar saves : float | Nonevar spend : float | Nonevar time_based_views : list[TimeBasedView] | Nonevar units_sold : float | Nonevar vendor_metric_values : list[VendorMetricValue] | Nonevar viewability : Viewability1 | Nonevar views : float | None
Inherited members
class DeliveryStatus (*args, **kwds)-
Expand source code
class DeliveryStatus(StrEnum): delivering = 'delivering' not_delivering = 'not_delivering' completed = 'completed' budget_exhausted = 'budget_exhausted' flight_ended = 'flight_ended' goal_met = 'goal_met'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var budget_exhaustedvar completedvar deliveringvar flight_endedvar goal_metvar not_delivering
class DeliveryType (*args, **kwds)-
Expand source code
class DeliveryType(StrEnum): guaranteed = 'guaranteed' non_guaranteed = 'non_guaranteed'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var guaranteedvar non_guaranteed
class FrequencyCap (**data: Any)-
Expand source code
class FrequencyCap(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) suppress: Annotated[ duration.Duration | None, Field( description='Cooldown period between consecutive exposures to the same entity. Prevents back-to-back ad delivery (e.g. {"interval": 60, "unit": "minutes"} for a 1-hour cooldown). Preferred over suppress_minutes.' ), ] = None suppress_minutes: Annotated[ StrictFloat | None, Field( deprecated=True, description='Deprecated — use suppress instead. Cooldown period in minutes between consecutive exposures to the same entity (e.g. 60 for a 1-hour cooldown).', ge=0.0, ), ] = None max_impressions: Annotated[ SchemaInt | None, Field( description="Maximum number of impressions per entity per window. For duration windows, implementations typically use a rolling window. campaign applies across the owning field's full flight: the package flight for a targeting overlay, or the MediaBuy flight for a root cap.", ge=1, ), ] = None per: Annotated[ reach_unit.ReachUnit | None, Field( description='Entity granularity for impression counting. Required when max_impressions is set.' ), ] = None window: Annotated[ duration.Duration | None, Field( description='Time window for the max_impressions cap (e.g. {"interval": 7, "unit": "days"} or {"interval": 1, "unit": "campaign"} for the full flight). Required when max_impressions is set.' ), ] = None @model_validator(mode='after') def _require_schema_required_group(self) -> FrequencyCap: # ``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 (('suppress',), ('suppress_minutes',), ('max_impressions',),): if all(name in self.model_fields_set for name in group): return self raise ValueError( 'FrequencyCap requires at least one of these field groups: suppress | suppress_minutes | max_impressions' )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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Subclasses
Class variables
var max_impressions : int | Nonevar model_configvar per : ReachUnit | Nonevar suppress : Duration | Nonevar suppress_minutes : float | Nonevar window : Duration | None
Inherited members
class FrequencyCapScope (root: RootModelRootType = PydanticUndefined, **data)-
Expand source code
class FrequencyCapScope(RootModel[Literal['package']]): root: Annotated[ Literal['package'], Field(description='Scope for frequency cap application', title='Frequency Cap Scope'), ] = 'package'Usage Documentation
A Pydantic
BaseModelfor the root object of the model.- Attributes
- -----=
root- The root object of the model.
__pydantic_root_model__- Whether the model is a RootModel.
__pydantic_private__- Private fields in the model.
__pydantic_extra__- Extra fields in the model.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- pydantic.root_model.RootModel[Literal['package']]
- pydantic.root_model.RootModel
- pydantic.main.BaseModel
- typing.Generic
Class variables
var model_configvar root : Literal['package']
class GetMediaBuyArtifactsRequest (**data: Any)-
Expand source code
class GetMediaBuyArtifactsRequest(AdcpRequest, AdcpVersionEnvelope): account: Annotated[ account_ref.AccountReference | None, Field( description='Filter artifacts to a specific account. When omitted, returns artifacts across all accessible accounts.' ), ] = None media_buy_id: Annotated[str, Field(description='Media buy to get artifacts from')] package_ids: Annotated[ list[str] | None, Field(description='Filter to specific packages within the media buy', min_length=1), ] = None failures_only: Annotated[ StrictBool | None, Field( description="When true, only return artifacts where the seller's local model returned local_verdict: 'fail'. Useful for auditing false positives. Not useful when the seller does not run a local evaluation model (all verdicts are 'unevaluated')." ), ] = False time_range: Annotated[TimeRange | None, Field(description='Filter to specific time period')] = ( None ) pagination: Annotated[ Pagination | None, Field( description='Pagination parameters. Uses higher limits than standard pagination because artifact result sets can be very large.' ), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = NoneThe 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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : AccountReference1 | AccountReference2 | Nonevar context : ContextObject | Nonevar ext : ExtensionObject | Nonevar failures_only : bool | Nonevar media_buy_id : strvar model_configvar package_ids : list[str] | Nonevar pagination : Pagination | Nonevar time_range : TimeRange | None
Inherited members
class GetMediaBuyDeliveryRequest (**data: Any)-
Expand source code
class GetMediaBuyDeliveryRequest(AdcpRequest, AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) account: Annotated[ account_ref.AccountReference | None, Field( description='Filter delivery data to a specific account. When omitted, returns data across all accessible accounts.' ), ] = None media_buy_ids: Annotated[ list[str] | None, Field(description='Array of media buy IDs to get delivery data for', min_length=1), ] = None reporting_revision_id: Annotated[ str | None, Field( description='Exact immutable reporting revision to retrieve. This additive Reliable Reporting selector returns content bound to that revision, including its immutable row count, control totals, and content SHA-256. It is mutually exclusive with media-buy, date, metric, and breakdown selectors.', max_length=255, min_length=1, pattern='^[A-Za-z0-9_.:-]{1,255}$', ), ] = None pagination: Annotated[ pagination_request.PaginationRequest | None, Field( description='Cursor pagination. With reporting_revision_id, pages immutable authoritative rows while all revision metadata repeats on every page.' ), ] = None status_filter: Annotated[ media_buy_status.MediaBuyStatus | StatusFilter | None, Field(description='Filter by status. Can be a single status or array of statuses'), ] = None start_date: Annotated[ str | None, Field( description="Inclusive start date for the reporting period (YYYY-MM-DD), as a calendar date in the reporting timezone: the reporting_capabilities.timezone of the products behind the in-scope packages. It is a UTC day only when that timezone is UTC. When omitted along with end_date, returns campaign lifetime data. Only accepted when the product's reporting_capabilities.date_range_support is 'date_range'. A date-bounded request whose in-scope packages span more than one reporting timezone MUST be rejected with VALIDATION_ERROR. The buyer narrows media_buy_ids to buys that share one reporting timezone, or omits both dates when a single buy's packages span reporting timezones.", pattern='^\\d{4}-\\d{2}-\\d{2}$', ), ] = None end_date: Annotated[ str | None, Field( description="Exclusive end date for the reporting period (YYYY-MM-DD), as a calendar date in the same reporting timezone as start_date. Must be later than start_date. When omitted along with start_date, returns campaign lifetime data. Only accepted when the product's reporting_capabilities.date_range_support is 'date_range'.", pattern='^\\d{4}-\\d{2}-\\d{2}$', ), ] = None include_package_daily_breakdown: Annotated[ StrictBool | None, Field( description='When true, include daily_breakdown arrays within each package in by_package. Useful for per-package pacing analysis and line-item monitoring. Omit or set false to reduce response size — package daily data can be large for multi-package buys over long flights.' ), ] = False requested_metrics: Annotated[ list[available_metric.AvailableMetric] | None, Field( description="Optional list of metrics to include in the response. When omitted, all available metrics are included (unchanged behavior). Applies to every metrics-bearing object in the response: totals, by_package, daily and window slices, and breakdown rows. impressions and spend are always included regardless of this list, except that a legacy or externally created mixed-currency buy MUST omit monetary and money-derived values from media-buy and window totals, MUST omit daily_breakdown, and MUST report monetary values only on currency-qualified package rows (including window package rows). Requesting a leaf metric identity returns its canonical nested carrier — e.g. requesting viewable_rate returns the viewability object, requesting quartile_75 returns quartile_data — never a flat duplicate. Metrics requested but not available for this buy are omitted from the response without error; contract accountability is unchanged — missing_metrics still reconciles against committed_metrics, but sellers MUST NOT list a metric in missing_metrics when its absence is solely due to this narrowing. Must be a subset of the product's reporting_capabilities.available_metrics; values outside the declared set are ignored. Subset evaluation follows the container-subsumption rule in enums/available-metric.json. Sort is evaluated before narrowing: excluding a metric from this list never triggers the sort_by fallback, and breakdown rows may be ordered by a metric absent from the narrowed payload — the applied-sort echo still names it. Same narrowing semantics as reporting_webhook.requested_metrics, with one shape difference: this field requires at least one entry when present (omit it entirely for full payloads), while the webhook field permits an empty array with the same meaning as omission.", min_length=1, ), ] = None time_granularity: Annotated[ reporting_frequency.ReportingFrequency | None, Field( description="Per-window slice granularity for the pull, using the same vocabulary as reporting_webhook.reporting_frequency. When set, the seller returns per-window delivery slices over the date range — useful for reconstructing data a buyer's webhook receiver missed, since the slice payload is shape-aligned with what reporting_webhook would have delivered for the same window. Capability-scoped: the value MUST be one of the seller's declared reporting_capabilities.windowed_pull_granularities; otherwise the seller MUST return UNSUPPORTED_GRANULARITY. When set to daily, weekly, monthly, or quarterly and the in-scope packages span more than one reporting timezone, the seller MUST return VALIDATION_ERROR. When omitted, behavior is unchanged (cumulative aggregates plus optional daily breakdowns per existing fields)." ), ] = None include_window_breakdown: Annotated[ StrictBool | None, Field( description="When true, the response includes media_buy_deliveries[].windows[] — an array of per-window delivery slices over the date range at the requested time_granularity. Ignored when time_granularity is omitted. Each window's payload mirrors what reporting_webhook would have delivered for the same window, enabling lossless GET-path recovery for buyers who missed webhook fires. Omit or set false to reduce response size when only cumulative aggregates are needed." ), ] = False attribution_window: Annotated[ AttributionWindow | None, Field( description='Attribution window to apply for conversion metrics. When provided, the seller returns conversion data using the requested lookback windows instead of their platform default. The seller echoes the applied window in the response. Sellers that do not support configurable windows ignore this field and return their default. Check get_adcp_capabilities conversion_tracking.attribution_windows for available options.' ), ] = None reporting_dimensions: Annotated[ ReportingDimensions | None, Field( description='Request dimensional breakdowns in delivery reporting. Each key enables a specific breakdown dimension within by_package — include as an empty object (e.g., "device_type": {}) to activate with defaults. Omit entirely for no breakdowns (backward compatible). Unsupported dimensions are silently omitted from the response. For every requested dimension that the product declares supported, the seller MUST return the corresponding array (possibly empty) and its truncated flag. Metric-sorted dimensions also return their applied-sort echoes; demographic and property-grain arrays also return their suppressed flag. Spot uses aired_at ordering and has no sort echoes. Note: keyword, catalog_item, and creative breakdowns are returned automatically when the seller supports them; including their keys here is optional and upgrades them to this negotiated contract without changing the automatic default.' ), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None @model_validator(mode='after') def _validate_delivery_selector_mode(self) -> GetMediaBuyDeliveryRequest: if self.reporting_revision_id is not None: if self.model_fields_set.intersection(('media_buy_ids', 'start_date', 'end_date', 'status_filter', 'requested_metrics', 'reporting_dimensions', 'attribution_window', 'include_package_daily_breakdown', 'time_granularity', 'include_window_breakdown')): raise ValueError('exact revision requests forbid aggregate selectors, even false or null') elif self.pagination is not None: raise ValueError('pagination requires reporting_revision_id') return self @model_serializer(mode='wrap') def _serialize_delivery_selector_mode(self, handler: SerializerFunctionWrapHandler) -> dict[str, Any]: value: dict[str, Any] = handler(self) if self.reporting_revision_id is not None: for name in ('media_buy_ids', 'start_date', 'end_date', 'status_filter', 'requested_metrics', 'reporting_dimensions', 'attribution_window', 'include_package_daily_breakdown', 'time_granularity', 'include_window_breakdown'): if name not in self.model_fields_set: value.pop(name, None) return valueThe 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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : AccountReference1 | AccountReference2 | Nonevar attribution_window : AttributionWindow | Nonevar context : ContextObject | Nonevar end_date : str | Nonevar ext : ExtensionObject | Nonevar include_package_daily_breakdown : bool | Nonevar include_window_breakdown : bool | Nonevar media_buy_ids : list[str] | Nonevar model_configvar pagination : PaginationRequest | Nonevar reporting_dimensions : ReportingDimensions | Nonevar reporting_revision_id : str | Nonevar requested_metrics : list[AvailableMetric] | Nonevar start_date : str | Nonevar status_filter : MediaBuyStatus | StatusFilter | Nonevar time_granularity : ReportingFrequency | None
Inherited members
class GetMediaBuyDeliveryResponse (**data: Any)-
Expand source code
class GetMediaBuyDeliveryResponse(_LegacyGetMediaBuyDeliveryResponse, CanonicalBoundaryModel): """Canonical media-buy delivery response."""Canonical media-buy delivery response.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- GetMediaBuyDeliveryResponse
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
class Results (**data: Any)-
Expand source code
class GetMediaBuyDeliveryResponse(_LegacyGetMediaBuyDeliveryResponse, CanonicalBoundaryModel): """Canonical media-buy delivery response."""Canonical media-buy delivery response.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- GetMediaBuyDeliveryResponse
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class GetMediaBuysRequest (**data: Any)-
Expand source code
class GetMediaBuysRequest(AdcpRequest, AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) account: Annotated[ account_ref.AccountReference | None, Field( description='Account to retrieve media buys for. When omitted, returns data across all accessible accounts.' ), ] = None media_buy_ids: Annotated[ list[str] | None, Field( description='Array of media buy IDs to retrieve. When omitted, returns a paginated set of accessible media buys matching status_filter.', min_length=1, ), ] = None status_filter: Annotated[ media_buy_status.MediaBuyStatus | StatusFilter | None, Field( description='Filter by status. Can be a single status or array of statuses. Defaults to ["active"] when media_buy_ids is omitted. When media_buy_ids is provided, no implicit status filter is applied.' ), ] = None indicator_types: Annotated[ list[indicator_type.IndicatorType] | None, Field( description='Return media buys with at least one matching current indicator on the media buy, a package, or a package–creative assignment. Values within this field use OR logic; this field composes with status_filter using AND logic. Buyers MUST NOT send this filter unless the seller advertises every requested type in get_adcp_capabilities.media_buy.supported_indicator_types. A seller MAY reject a request that violates this precondition with UNSUPPORTED_FEATURE rather than silently returning an unfiltered superset.', min_length=1, ), ] = None include_snapshot: Annotated[ StrictBool | None, Field( description='When true, include a near-real-time delivery snapshot for each package. Snapshots reflect the latest available entity-level stats from the platform (e.g., updated every ~15 minutes on GAM, ~1 hour on batch-only platforms). The staleness_seconds field on each snapshot indicates data freshness. If a snapshot cannot be returned, package.snapshot_unavailable_reason explains why. Defaults to false.' ), ] = False include_history: Annotated[ SchemaInt | None, Field( description='When present, include the last N revision history entries for each media buy (returns min(N, available entries)). Each entry contains revision number, timestamp, actor, and a summary of what changed. Omit or set to 0 to exclude history (default). Recommended: 5-10 for monitoring, 50+ for audit.', ge=0, le=1000, ), ] = 0 include_webhook_activity: Annotated[ StrictBool | None, Field( description="When true, each returned media buy includes a `webhook_activity` array describing recent delivery-report webhook fires for the calling principal. Used by buyer agents to verify whether a publisher actually fired against the buyer's registered endpoint and what the endpoint returned — closes the operator-ticket loop for webhook debugging. Scoped to the calling principal: a buyer sees only fires targeting its own endpoint, even when multiple principals share visibility into the same media buy. Defaults to false. See `webhook_activity_limit` for the per-buy cap." ), ] = False webhook_activity_limit: Annotated[ SchemaInt | None, Field( description="Maximum number of webhook delivery records to return per media buy, ordered most-recent first. Ignored when `include_webhook_activity` is false. Sellers that surface webhook activity MUST retain records for at least 30 days from each record's `completed_at` (see `webhook_activity` description in the response schema for the `pending`-status carve-out); sellers unable to honor that floor MUST omit the field entirely rather than truncate. When a buy has more historical fires than the limit, only the most recent are returned — there is no cursor for older fires; this surface is a debug aid, not a full audit log.", ge=1, le=200, ), ] = 50 pagination: Annotated[ pagination_request.PaginationRequest | None, Field( description='Cursor-based pagination controls. Strongly recommended when querying broad scopes (for example, all active media buys in an account).' ), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = NoneThe 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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : AccountReference1 | AccountReference2 | Nonevar context : ContextObject | Nonevar ext : ExtensionObject | Nonevar include_history : int | Nonevar include_snapshot : bool | Nonevar include_webhook_activity : bool | Nonevar indicator_types : list[IndicatorType] | Nonevar media_buy_ids : list[str] | Nonevar model_configvar pagination : PaginationRequest | Nonevar status_filter : MediaBuyStatus | StatusFilter | Nonevar webhook_activity_limit : int | None
Inherited members
class GetMediaBuysResponse (**data: Any)-
Expand source code
class GetMediaBuysResponse(_LegacyGetMediaBuysResponse, CanonicalBoundaryModel): """Canonical media-buy listing; rows are canonical media buys.""" media_buys: Sequence[MediaBuy]Canonical media-buy listing; rows are canonical media buys.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- GetMediaBuysResponse
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var media_buys : Sequence[MediaBuy]var model_config
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.' ), ] = NoneThe 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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : CanonicalAccountReference1 | CanonicalAccountReference2 | Nonevar brand : BrandKey | Nonevar context : ContextObject | Nonevar context_id : str | Nonevar criteria : ProductDiscoveryCriteria | Nonevar cursor : str | Nonevar fields : ProductResponseFields | Nonevar governance_context : str | Nonevar idempotency_key : str | Nonevar if_feed_version : str | Nonevar if_pricing_version : str | Nonevar max_results : int | Nonevar model_configvar push_notification_config : PushNotificationConfig | None
Inherited members
class MediaBuy (**data: Any)-
Expand source code
class MediaBuy(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) media_buy_id: Annotated[str, Field(description="Seller's unique identifier for the media buy")] 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. Sellers MUST include the persisted name on read surfaces such as get_media_buys when the media buy was created through AdCP with name. Sellers MAY omit name for media buys created outside AdCP or created without name. This display label is not an identifier or financial reference.', max_length=255, min_length=1, pattern='\\S', ), ] = None accepted_proposal_id: Annotated[ str | None, Field( description='Current accepted commercial snapshot. Compact-lifecycle buyers pass this ID to refine_proposals after restart or handoff. Updated atomically when an amendment or negotiated cancellation is accepted.', max_length=255, min_length=1, ), ] = None accepted_proposal_terms_digest: Annotated[ str | None, Field( description='Digest of the current accepted proposal commercial_terms, allowing buyers and governance agents to verify the recovered snapshot.', pattern='^sha256:[A-Za-z0-9_-]{43}$', ), ] = None account: Annotated[ account_1.Account | None, Field(description='Account billed for this media buy') ] = None status: media_buy_status.MediaBuyStatus health: Annotated[ media_buy_health.MediaBuyHealth | None, Field( description="Aggregate health based on open impairments[]. Orthogonal to status — a paused, pending, or active buy can each be impaired. Defaults to 'ok' when impairments[] is empty." ), ] = media_buy_health.MediaBuyHealth.ok impairments: Annotated[ list[impairment.Impairment] | None, Field( description="Open impairments — upstream dependency state changes that affect delivery for at least one package on this buy. Empty when health is 'ok'. Sellers MUST add an entry on next sync/poll response after a referenced resource transitions to an offline state, and MUST remove the entry (flipping health to 'ok' when the array empties) when the resource returns to a serviceable state. Staleness budget: the snapshot MUST reflect the impairment within 5 minutes of impairment.observed_at regardless of buyer poll cadence — sellers cannot rely on rare buyer polls to defer write propagation. See impairment.coherence assertion for the cross-resource invariant." ), ] = None rejection_reason: Annotated[ str | None, Field( description="Reason provided by the seller when status is 'rejected'. Present only when status is 'rejected'." ), ] = None confirmed_at: Annotated[ AwareDatetime | None, Field( description='ISO 8601 timestamp when the seller committed to this media buy. May be null until seller commitment occurs in deferred/manual approval flows. Once populated, remains stable through later pause, resume, activation, completion, cancellation, and reporting transitions.' ), ] cancellation: Annotated[ Cancellation | None, Field(description="Cancellation metadata. Present only when status is 'canceled'."), ] = None total_budget: Annotated[ StrictFloat, Field(description='Hard aggregate lifetime budget amount', ge=0.0) ] daily_budget_cap: Annotated[ StrictFloat | None, Field( description='Current hard aggregate spend ceiling per calendar day. Sellers MUST echo this whenever an aggregate daily cap is set. It bounds total media-buy spend without allocating or reserving spend for packages.', ge=0.0, ), ] = None frequency_cap: Annotated[ media_buy_frequency_cap.MediaBuyFrequencyCap | None, Field( description='Current hard MediaBuy-level cap. Sellers MUST echo it whenever set. Its counter aggregates exposures across all participating packages; each package targeting_overlay.frequency_cap remains independently binding.' ), ] = None budget_cap_timezone: Annotated[ str | None, Field( description='IANA timezone defining the shared calendar-day boundary for every aggregate and package daily cap on this media buy. Sellers MUST echo it whenever any daily cap is set.' ), ] = None currency: Annotated[ str | None, Field( description="Single ISO 4217 denomination for total_budget, every package budget/minimum, and every canonical BiddingPolicy monetary field. Every package's selected pricing option MUST declare this currency; packages requiring another currency belong in a separate media buy.", pattern='^[A-Z]{3}$', ), ] = None budget_allocation: Annotated[ budget_allocation_1.BudgetAllocation | None, Field( description='Accepted cross-package budget allocation configuration. Omitted means fixed allocation for legacy buys.' ), ] = None pacing: Annotated[ pacing_1.Pacing | None, Field( description='Aggregate pacing strategy for total_budget across the media-buy flight.' ), ] = None bidding: Annotated[ bidding_policy.BiddingPolicy | None, Field( description='Media-buy-authored bidding policy. This is the complete default inherited by packages that omit package.bidding; `{automatic:true}` is an explicit authored automatic policy. In seller-optimized mode, cost_per/roas bind to the primary budget_allocation optimization goal. In fixed mode, inherited cost_per requires compatible package primary-goal result units and inherited roas requires value-bearing primary goals. Monetary fields use media_buy.currency; every affected pricing option MUST declare the same currency. Package overrides are permitted only where advertised; conflicts MUST be rejected atomically with BIDDING_PLACEMENT_CONFLICT.' ), ] = None packages: Annotated[ list[package.Package], Field(description='Array of packages within this media buy') ] context: Annotated[ context_1.ContextObject | None, Field( description='Opaque media-buy-level correlation data echoed unchanged from the create_media_buy request. Sellers MUST include persisted context on read surfaces such as get_media_buys when the media buy was created through AdCP with context, so buyers can reconcile seller-assigned media_buy_id values with their own tracking state. Sellers MAY omit context for media buys created outside AdCP or created without context. Sellers MUST NOT parse this object for business logic.' ), ] = None invoice_recipient: Annotated[ business_entity.BusinessEntity | None, Field( description="Per-buy override for who receives the invoice. When provided, the seller invoices this entity instead of the account's default billing_entity. The seller MUST validate the invoice recipient is authorized for this account. When governance_agents are configured, the seller MUST include invoice_recipient in the check_governance request." ), ] = None creative_deadline: Annotated[ AwareDatetime | None, Field(description='ISO 8601 timestamp for creative upload deadline') ] = None revision: Annotated[ SchemaInt, Field( description='Monotonically increasing optimistic concurrency token. Incremented on every mutating state change or update; reads, validation-only calls, and exact idempotency replays do not increment it. Callers SHOULD include this in update_media_buy requests intended to change state — when provided, sellers MUST reject with CONFLICT if the revision does not match the current value, and MUST enforce that comparison atomically with the write.', ge=1, ), ] created_at: Annotated[AwareDatetime | None, Field(description='Creation timestamp')] = None updated_at: Annotated[AwareDatetime | None, Field(description='Last update timestamp')] = None ext: ext_1.ExtensionObject | None = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var accepted_proposal_id : str | Nonevar accepted_proposal_terms_digest : str | Nonevar account : Account | Nonevar bidding : BiddingPolicy | Nonevar budget_allocation : BudgetAllocation1 | BudgetAllocation2 | Nonevar budget_cap_timezone : str | Nonevar cancellation : Cancellation | Nonevar confirmed_at : pydantic.types.AwareDatetime | Nonevar context : ContextObject | Nonevar created_at : pydantic.types.AwareDatetime | Nonevar creative_deadline : pydantic.types.AwareDatetime | Nonevar currency : str | Nonevar daily_budget_cap : float | Nonevar ext : ExtensionObject | Nonevar frequency_cap : MediaBuyFrequencyCap | Nonevar health : MediaBuyHealth | Nonevar impairments : list[Impairment] | Nonevar invoice_recipient : BusinessEntity | Nonevar media_buy_id : strvar model_configvar name : str | Nonevar pacing : Pacing | Nonevar packages : list[Package]var rejection_reason : str | Nonevar revision : intvar status : MediaBuyStatusvar total_budget : floatvar updated_at : pydantic.types.AwareDatetime | None
Inherited members
class MediaBuyActionMode (*args, **kwds)-
Expand source code
class MediaBuyActionMode(StrEnum): self_serve = 'self_serve' conditional_self_serve = 'conditional_self_serve' seller_managed = 'seller_managed' requires_approval = 'requires_approval'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var conditional_self_servevar requires_approvalvar self_servevar seller_managed
class MediaBuyAvailableAction (**data: Any)-
Expand source code
class MediaBuyAvailableAction(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) action: Annotated[ media_buy_available_action_id.MediaBuyAvailableActionId, Field(description='The action identifier.'), ] mode: Annotated[ media_buy_action_mode.MediaBuyActionMode, Field( description='The single mode that applies right now on this buy for this action. Singular because the buy has a concrete state, exactly one mode applies. Buyer SDKs branch on this to decide whether to expect a synchronous response, conditional handling, or an asynchronous approval callback.' ), ] task: Annotated[ Task | None, Field( description='Compact-lifecycle task for this resolved action: operational control, commercial refinement, or creative lifecycle mutation.' ), ] = None sla: Annotated[ sla_window.SlaWindow | None, Field( description='Optional SLA commitment for this action on this buy. Absence means no commitment, not zero commitment.' ), ] = None change_term_id: media_buy_change_term_id.MediaBuyChangeTermId | None = None terms_ref: media_buy_legacy_terms_ref.MediaBuyTermsReference | None = None applicable_package_ids: Annotated[ list[applicable_package_id.ApplicablePackageId] | None, Field( description='For a package-scoped action, the exact packages currently eligible. Omission means every relevant package. Root actions omit this field.', min_length=1, ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var action : MediaBuyValidAction | Literal['update_media_buy_frequency_cap']var applicable_package_ids : list[ApplicablePackageId] | Nonevar change_term_id : MediaBuyChangeTermId | Nonevar mode : MediaBuyActionModevar model_configvar sla : SlaWindow | Nonevar task : Task | Nonevar terms_ref : MediaBuyTermsReference | None
Inherited members
class MediaBuyChangeTerm (**data: Any)-
Expand source code
class MediaBuyChangeTerm(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) term_id: Annotated[str, Field(pattern='^[A-Za-z0-9_.:-]+$')] action: canonical_media_buy_action.CanonicalMediaBuyActionName service_mode: canonical_media_buy_action_mode.CanonicalMediaBuyActionMode allowed_statuses: Annotated[ list[AllowedStatus] | None, Field( description='Non-terminal MediaBuy statuses in which this negotiated right may be exercised. When absent, the right applies in every non-terminal status where the canonical action itself is meaningful. This field describes contractual lifecycle scope; available_actions[] remains authoritative for the current instant.', min_length=1, ), ] = None processing_sla: Annotated[ sla_window.SlaWindow | None, Field( description='Binding elapsed-time acknowledgement and completion commitment. Sellers account for weekends and non-working periods when declaring the maximum.' ), ] = None conditions: Annotated[ list[Condition] | None, Field( description='Opaque stable condition identifiers defined by terms_ref or bilateral commercial documentation. Implementations compare identifiers; they MUST NOT execute or interpret them as instructions.', min_length=1, ), ] = None constraints: Annotated[ change_term_constraints.MediaBuyChangeTermConstraints | None, Field( description='Portable bounds that buyer and seller SDKs can preflight. Omission means no machine-readable bound was promised; opaque conditions remain unevaluated.' ), ] = None terms_ref: Annotated[ str | None, Field( description="Stable contract reference. Resolving it cannot expand the typed right and MUST use the caller's normal authenticated contract-document path, never ambient seller credentials.", max_length=1000, min_length=1, ), ] = None description: Annotated[ str | None, Field( description='Display-only summary; it cannot grant authority, add an action, or override typed fields.', max_length=1000, min_length=1, ), ] = None ext: ext_1.ExtensionObject | None = None @model_validator(mode='after') def _validate_constraint_action(self) -> MediaBuyChangeTerm: if self.constraints is None: return self kind = self.constraints.kind allowed = { 'budget': { 'increase_budget', 'decrease_budget', 'reallocate_budget', 'update_budget_allocation', 'update_spend_target', }, 'flight': {'extend_flight', 'shorten_flight', 'update_flight_dates'}, 'package_count': {'add_packages', 'remove_packages'}, 'effective_timing': {'pause', 'resume', 'cancel'}, } action = self.action.value if action not in allowed.get(kind, set()): raise ValueError('constraint kind is incompatible with action') return selfBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var action : CanonicalMediaBuyActionNamevar allowed_statuses : list[AllowedStatus] | Nonevar conditions : list[Condition] | Nonevar constraints : MediaBuyChangeTermConstraints1 | MediaBuyChangeTermConstraints2 | MediaBuyChangeTermConstraints3 | MediaBuyChangeTermConstraints4 | Nonevar description : str | Nonevar ext : ExtensionObject | Nonevar model_configvar processing_sla : SlaWindow | Nonevar service_mode : CanonicalMediaBuyActionModevar term_id : strvar terms_ref : str | None
Inherited members
class BudgetChangeConstraints (**data: Any)-
Expand source code
class MediaBuyChangeTermConstraints1(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) kind: Literal['budget'] = 'budget' max_delta_amount: Annotated[ Money | None, Field( description='Maximum absolute amount by which the affected budget may change in the direction named by the action.' ), ] = None max_delta_percent: Annotated[ StrictFloat | None, Field( description='Maximum percentage change relative to the current committed value. Values above 100 are valid for increases greater than the current value.', ge=0.0, ), ] = None min_result_amount: Annotated[ Money | None, Field(description='Minimum resulting committed value after the change.') ] = None max_result_amount: Annotated[ Money | None, Field(description='Maximum resulting committed value after the change.') ] = None @model_validator(mode='after') def _require_portable_bound(self) -> MediaBuyChangeTermConstraints1: if not any(getattr(self, name) is not None for name in ('max_delta_amount', 'max_delta_percent', 'min_result_amount', 'max_result_amount')): raise ValueError('at least one portable constraint bound is required') return selfBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var kind : Literal['budget']var max_delta_amount : Money | Nonevar max_delta_percent : float | Nonevar max_result_amount : Money | Nonevar min_result_amount : Money | Nonevar model_config
Inherited members
class FlightChangeConstraints (**data: Any)-
Expand source code
class MediaBuyChangeTermConstraints2(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) kind: Literal['flight'] = 'flight' max_change: Annotated[ duration.Duration | None, Field( description='Maximum extension, shortening, or shift in the direction named by the action.' ), ] = None earliest_result: Annotated[ AwareDatetime | None, Field(description='Earliest resulting start or end timestamp accepted for this action.'), ] = None latest_result: Annotated[ AwareDatetime | None, Field(description='Latest resulting start or end timestamp accepted for this action.'), ] = None minimum_notice: Annotated[ duration.Duration | None, Field( description='Minimum elapsed notice before the requested flight change may take effect.' ), ] = None @model_validator(mode='after') def _require_portable_bound(self) -> MediaBuyChangeTermConstraints2: if not any(getattr(self, name) is not None for name in ('max_change', 'earliest_result', 'latest_result', 'minimum_notice')): raise ValueError('at least one portable constraint bound is required') return selfBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var earliest_result : pydantic.types.AwareDatetime | Nonevar kind : Literal['flight']var latest_result : pydantic.types.AwareDatetime | Nonevar max_change : Duration | Nonevar minimum_notice : Duration | Nonevar model_config
Inherited members
class PackageCountChangeConstraints (**data: Any)-
Expand source code
class MediaBuyChangeTermConstraints3(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) kind: Literal['package_count'] = 'package_count' max_additions: Annotated[ SchemaInt | None, Field(description='Maximum packages that may be added by one exercise of the right.', ge=0), ] = None max_removals: Annotated[ SchemaInt | None, Field( description='Maximum packages that may be removed by one exercise of the right.', ge=0 ), ] = None max_result_count: Annotated[ SchemaInt | None, Field(description='Maximum active package count after the change.', ge=0) ] = None @model_validator(mode='after') def _require_portable_bound(self) -> MediaBuyChangeTermConstraints3: if not any(getattr(self, name) is not None for name in ('max_additions', 'max_removals', 'max_result_count')): raise ValueError('at least one portable constraint bound is required') return selfBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var kind : Literal['package_count']var max_additions : int | Nonevar max_removals : int | Nonevar max_result_count : int | Nonevar model_config
Inherited members
class EffectiveTimingChangeConstraints (**data: Any)-
Expand source code
class MediaBuyChangeTermConstraints4(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) kind: Literal['effective_timing'] = 'effective_timing' minimum_notice: Annotated[ duration.Duration | None, Field( description='Minimum elapsed notice before pause, resume, cancellation, or another operational action may take effect.' ), ] = None earliest_effective_at: AwareDatetime | None = None latest_effective_at: AwareDatetime | None = None @model_validator(mode='after') def _require_portable_bound(self) -> MediaBuyChangeTermConstraints4: if not any(getattr(self, name) is not None for name in ('minimum_notice', 'earliest_effective_at', 'latest_effective_at')): raise ValueError('at least one portable constraint bound is required') return selfBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var earliest_effective_at : pydantic.types.AwareDatetime | Nonevar kind : Literal['effective_timing']var latest_effective_at : pydantic.types.AwareDatetime | Nonevar minimum_notice : Duration | Nonevar model_config
Inherited members
class MediaBuyChangeTermId (value: Any = <object object>, *, root: Any = <object object>)-
Expand source code
class MediaBuyChangeTermId(ScalarStr): __slots__ = () _constraints = {'pattern': '^[A-Za-z0-9_.:-]+$'} _json_schema_extra = { 'description': 'The accepted proposal change_terms[].term_id from which this current-state action projection was derived.', 'title': 'Media Buy Change Term ID', }A
strgenerated from a JSON Schema string root.Ancestors
- adcp.types._scalar.ScalarStr
- adcp.types._scalar._ScalarRoot
- builtins.str
class MediaBuyDelivery (**data: Any)-
Expand source code
class MediaBuyDelivery(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) media_buy_id: Annotated[str, Field(description="Seller's media buy identifier")] currency: Annotated[ str | None, Field( description="ISO 4217 denomination for monetary values in this media-buy delivery row, including totals, package spend, and currency-denominated package rates. Sellers SHOULD populate this field whenever all monetary values in the row share one currency. For AdCP-authored buys it MUST equal the media-buy currency, and every by_package[].currency MUST equal it. For a legacy or externally created mixed-currency buy, omit this field, daily_breakdown, and all monetary or money-derived values from row and window totals; report those values only at package grain with each package's own currency. AdCP does not perform currency conversion.", pattern='^[A-Z]{3}$', ), ] = None status: Annotated[ Status, Field( description='Current media buy status. Lifecycle states use the same taxonomy as media-buy-status (`pending_creatives`, `pending_start`, `active`, `paused`, `completed`, `rejected`, `canceled`). In webhook context, reporting_delayed indicates data temporarily unavailable. `pending` is accepted as a legacy alias for pending_start.' ), ] expected_availability: Annotated[ AwareDatetime | None, Field( description='When delayed data is expected to be available (only present when status is reporting_delayed)' ), ] = None is_adjusted: Annotated[ StrictBool | None, Field( description='Indicates this delivery contains updated data for a previously reported period. Buyer should replace previous period data with these totals.' ), ] = None is_final: Annotated[ StrictBool | None, Field( description="Whether this row's delivery data is final for the reporting period. The row does not carry its own `measurement_window` — that lives on each `by_package[*]` entry. Reconciliation joins on per-package `measurement_window`; this row-level flag is a convenience roll-up. Sellers MUST NOT emit `is_final: true` at the row level unless every entry in `by_package` has `is_final: true` for the same `measurement_window` as the buy's `measurement_terms.billing_measurement.measurement_window` (or for the row's natural window when no `billing_measurement.measurement_window` is set). On any disagreement between row-level and package-level finality, package-level is authoritative. When true, the seller considers these numbers closed and is willing to invoice on them subject to `measurement_terms.billing_measurement`. When false, numbers may still move as measurement matures (broadcast C3 → C7) or processing completes (IVT scrubbing, dedup). When absent, the seller does not distinguish provisional from final at the row level — consult per-package `is_final`." ), ] = None finalized_at: Annotated[ AwareDatetime | None, Field( description="ISO 8601 timestamp at which this row became final. Present only when `is_final: true`. Anchors the buyer's reconciliation and (when later defined) dispute-window clocks against the buy's `measurement_terms.billing_measurement`. Computed as the latest `finalized_at` across the row's packages for the reconciliation window." ), ] = None pricing_model: Annotated[ pricing_model_1.PricingModel | None, Field(description='Pricing model used for this media buy'), ] = None pacing_index: Annotated[ StrictFloat | None, Field( description='Aggregate media-buy delivery pace relative to the media-buy pacing plan (1.0 = on track, <1.0 = behind, >1.0 = ahead). This is the authoritative pacing signal for seller-optimized buys; package pacing indexes are subordinate diagnostics.', ge=0.0, ), ] = None totals: Totals by_package: Annotated[list[ByPackageItem], Field(description='Metrics broken down by package')] windows: Annotated[ list[Window] | None, Field( description="Per-window delivery slices over the reporting period at the requested time_granularity. Only present when the request set time_granularity and include_window_breakdown: true. Each slice mirrors what reporting_webhook would have delivered for the same window — buyers who missed webhook fires can reconstruct identical data by reading this array. Slice rows are ordered by window_start ascending; consecutive rows are contiguous (each row's window_end equals the next row's window_start) and partition the requested date range at the chosen granularity. For a legacy or external mixed-currency media buy, monetary and money-derived values MUST be omitted from each window totals object and reported only in currency-qualified windows[].by_package rows. Sellers MUST exclude this field when time_granularity is omitted; when set, sellers MUST honor pulls at any granularity in reporting_capabilities.windowed_pull_granularities (otherwise return UNSUPPORTED_GRANULARITY). See snapshot-and-log Rule 4 for the two-paths-parity contract this surface anchors." ), ] = None daily_breakdown: Annotated[ list[DailyBreakdownItem1] | None, Field( description="Day-by-day delivery for a media-buy row with one currency. Sellers MUST omit this aggregate breakdown for a legacy or externally created mixed-currency buy because these rows have no package currency field. Sellers MUST also omit this aggregate breakdown when the media buy's packages span more than one reporting timezone; package-level daily_breakdown remains, each in its own product's reporting timezone." ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var by_package : list[ByPackageItem]var currency : str | Nonevar daily_breakdown : list[DailyBreakdownItem1] | Nonevar expected_availability : pydantic.types.AwareDatetime | Nonevar finalized_at : pydantic.types.AwareDatetime | Nonevar is_adjusted : bool | Nonevar is_final : bool | Nonevar media_buy_id : strvar model_configvar pacing_index : float | Nonevar pricing_model : PricingModel | Nonevar status : Statusvar totals : Totalsvar windows : list[Window] | None
Inherited members
class MediaBuyFeatures (**data: Any)-
Expand source code
class MediaBuyFeatures(AdCPBaseModel): __pydantic_extra__: Dict[str, StrictBool] model_config = ConfigDict( extra='allow', ) inline_creative_management: Annotated[ StrictBool | None, Field( deprecated=True, description='Deprecated 3.x compatibility capability for creatives provided inline in create_media_buy and update_media_buy package payloads. buy_products, accept_proposal, and control_media_buy never accept inline creatives. New integrations use the dedicated creative lifecycle. Removed in 4.0.', ), ] = None property_list_filtering: Annotated[ StrictBool | None, Field( description='Honors property_list parameter in get_products to filter results to buyer-approved properties' ), ] = None catalog_management: Annotated[ StrictBool | None, Field( description='Supports sync_catalogs task for catalog feed management with platform review and approval' ), ] = None catalog_item_availability_updates: Annotated[ StrictBool | None, Field( description='Supports buyer-pushed item_availability_updates and item_availability_queries on sync_catalogs for immediate suppression/restoration and current-state readback in buyer-managed catalogs. Seller declarations may be true only with catalog_management: true; buyer required_features filters may request this feature alone. Requests containing availability operations are synchronous and accept at most 1,000 combined update and query entries. A successful suppress covers selection, dynamic rendering, and cached or pre-generated creatives materialized from the item. Internal lineage MUST retain resolved_account_id, catalog_id, catalog_generation, and item_id. Static creatives supplied or promoted by the buyer without catalog lineage remain outside this automatic guarantee. Suppression persists across feed refreshes and ordinary upserts until restore, expires_at, or catalog deletion. A seller that does not declare true MUST reject availability operations with UNSUPPORTED_FEATURE before lookup or mutation and MUST NOT interpret them as discovery. This does not control seller-owned wholesale inventory or let restore bypass seller controls.' ), ] = None committed_metrics_supported: Annotated[ StrictBool | None, Field( description="Seller has per-package snapshot infrastructure for the reporting contract. When true, the seller MUST populate `package.committed_metrics` on committed `create_media_buy` responses where `confirmed_at` is non-null, MUST omit `package.committed_metrics` while `confirmed_at` is null for a provisional buy, and MUST honor append-only mid-flight metric additions via `update_media_buy`. The unified `committed_metrics` array (per the metric-accountability design) covers both standard and vendor-defined metric entries, so a single flag is load-bearing. Buyers filtering on this flag are detecting 'this seller can stamp the reporting contract,' which closes the audit gap from PR #3510 where absence of `committed_metrics` was indistinguishable between 'didn't snapshot' and 'snapshot infrastructure not implemented.'" ), ] = None seller_optimized_budget: Annotated[ StrictBool | None, Field( description="Supports the core seller-optimized shared-budget contract for budget_allocation.mode `seller_optimized`: one hard shared total_budget, seller allocation of that total across the buy's packages against budget_allocation.optimization_goals, media-buy-level pacing, and echo of the allocation configuration on buy read surfaces. Sellers declaring true MUST accept eligible explicit-package and proposal executions that use only these core controls and MUST enforce the aggregate budget. Core media-buy pacing: sellers declaring true MUST accept omitted media-buy pacing (which defaults to even when total_budget is present) and pacing `even` on seller-optimized buys; they MAY reject `asap` or `front_loaded` with `UNSUPPORTED_FEATURE` (error.field `pacing`) before any provider mutation, and MUST NOT silently coerce them to `even`. Package-level controls inside a seller-optimized buy are separate capabilities: package budget caps (seller_optimized_package_budgets), package minimum-spend targets (seller_optimized_min_spend_targets), and package pacing (seller_optimized_package_pacing). A seller declaring this feature but not one of those sub-capabilities MUST reject any request that would leave that package control on a seller-optimized buy with `UNSUPPORTED_FEATURE` before any over-subscription validation or provider mutation, and MUST NOT silently drop, soften, or coerce it. Over-subscription validation (`INVALID_REQUEST`) applies only to package controls the seller has declared; see seller_optimized_min_spend_targets. Product combinations may still be rejected when their currencies, optimization capabilities, pricing terms, or delivery constraints are incompatible. Sellers that do not declare this feature MUST reject any request carrying `budget_allocation.mode: 'seller_optimized'` with `UNSUPPORTED_FEATURE` before any provider mutation, and MUST NOT coerce the request to fixed allocation." ), ] = None seller_optimized_package_budgets: Annotated[ StrictBool | None, Field( description='Honors package `budget` as an optional hard lifetime package spend cap inside a seller-optimized buy: packages[].budget and new_packages[].budget on create_media_buy and update_media_buy, purchases[].budget on buy_products, package budget controls on control_media_buy, and max_spend_percentage on seller-optimized proposal allocations. The cap is a ceiling, not a reserved or current allocation, and package caps may sum above total_budget. Meaningful only with seller_optimized_budget: true; seller declarations may be true only with seller_optimized_budget: true, while buyer required_features filters may request this feature alone. A seller that declares seller_optimized_budget without this feature MUST reject a request that would leave a package budget on a seller-optimized buy, including an allocation-mode switch that retains fixed-mode package budgets (the buyer clears them with null in the same atomic update), with `UNSUPPORTED_FEATURE` before any over-subscription validation or provider mutation, and MUST NOT issue seller-optimized proposals carrying max_spend_percentage. Does not govern fixed allocation, where package budgets remain required.' ), ] = None seller_optimized_min_spend_targets: Annotated[ StrictBool | None, Field( description='Honors package `min_spend_target` as a soft lifetime minimum-spend target inside a seller-optimized buy: packages[].min_spend_target and new_packages[].min_spend_target on create_media_buy and update_media_buy, purchases[].min_spend_target on buy_products, package min_spend_target controls on control_media_buy, and min_spend_target_percentage on seller-optimized proposal allocations. The seller SHOULD attempt to deliver at least the target before allocating incremental spend elsewhere; it is not a billing or delivery guarantee. Meaningful only with seller_optimized_budget: true; seller declarations may be true only with seller_optimized_budget: true, while buyer required_features filters may request this feature alone. Sellers declaring this feature MUST reject package minimum-spend targets summing above total_budget with `INVALID_REQUEST` before mutation, and, when they also declare seller_optimized_package_budgets, MUST likewise reject a min_spend_target above its own package budget. A seller that declares seller_optimized_budget without this feature MUST reject a request carrying a numeric min_spend_target with `UNSUPPORTED_FEATURE` before any over-subscription validation or provider mutation, so an over-subscribed target sent to such a seller yields `UNSUPPORTED_FEATURE`, and MUST NOT issue seller-optimized proposals carrying min_spend_target_percentage.' ), ] = None seller_optimized_package_pacing: Annotated[ StrictBool | None, Field( description='Honors package `pacing` as subordinate per-package pacing inside a seller-optimized buy, in addition to the media-buy-level pacing covered by seller_optimized_budget: packages[].pacing and new_packages[].pacing on create_media_buy and update_media_buy, purchases[].pacing on buy_products, package pacing controls on control_media_buy, and allocation pacing on seller-optimized proposals. Package pacing MUST NOT cause delivery to exceed aggregate media-buy pacing. Meaningful only with seller_optimized_budget: true; seller declarations may be true only with seller_optimized_budget: true, while buyer required_features filters may request this feature alone. Package pacing equal to the effective media-buy pacing adds no subordinate constraint and does not require this feature; buyers SHOULD omit package pacing on seller-optimized buys unless this feature is advertised. A seller that declares seller_optimized_budget without this feature MUST reject a request that would leave package pacing differing from media-buy pacing on a seller-optimized buy, including an allocation-mode switch that retains such fixed-mode package pacing (the buyer can align it in the same update), with `UNSUPPORTED_FEATURE` before any provider mutation, and MUST NOT issue seller-optimized proposals carrying allocation pacing. Does not govern package pacing in fixed allocation.' ), ] = None bidding_policy: Annotated[ bidding_policy_capability.BiddingPolicyCapability | None, Field( description='Structured support for canonical bidding by authored scope, allocation context, mode, strength, and strength-qualified multi-field combination. Presence does not imply support for both scopes, both allocation modes, or every policy shape. Sellers MUST preserve every advertised semantic exactly and reject unadvertised policies rather than translating them.' ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var bidding_policy : BiddingPolicyCapability | Nonevar canonical_creatives : bool | Nonevar catalog_item_availability_updates : bool | Nonevar catalog_management : bool | Nonevar committed_metrics_supported : bool | Nonevar model_configvar property_list_filtering : bool | Nonevar seller_optimized_budget : bool | Nonevar seller_optimized_min_spend_targets : bool | Nonevar seller_optimized_package_budgets : bool | Nonevar seller_optimized_package_pacing : bool | None
Instance variables
var inline_creative_management : bool | 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 MediaBuyStatus (*args, **kwds)-
Expand source code
class MediaBuyStatus(StrEnum): pending_creatives = 'pending_creatives' pending_start = 'pending_start' active = 'active' paused = 'paused' completed = 'completed' rejected = 'rejected' canceled = 'canceled'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var activevar canceledvar completedvar pausedvar pending_creativesvar pending_startvar rejected
class MediaBuyValidAction (*args, **kwds)-
Expand source code
class MediaBuyValidAction(StrEnum): pause = 'pause' resume = 'resume' cancel = 'cancel' update_name = 'update_name' extend_flight = 'extend_flight' shorten_flight = 'shorten_flight' update_flight_dates = 'update_flight_dates' increase_budget = 'increase_budget' decrease_budget = 'decrease_budget' reallocate_budget = 'reallocate_budget' update_budget_allocation = 'update_budget_allocation' update_targeting = 'update_targeting' update_pacing = 'update_pacing' update_bidding = 'update_bidding' update_frequency_caps = 'update_frequency_caps' replace_creative = 'replace_creative' update_creative_assignments = 'update_creative_assignments' remove_creative = 'remove_creative' add_packages = 'add_packages' remove_packages = 'remove_packages' update_budget = 'update_budget' update_dates = 'update_dates' update_packages = 'update_packages' sync_creatives = 'sync_creatives'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var add_packagesvar cancelvar decrease_budgetvar extend_flightvar increase_budgetvar pausevar reallocate_budgetvar remove_creativevar remove_packagesvar replace_creativevar resumevar shorten_flightvar sync_creativesvar update_biddingvar update_budgetvar update_budget_allocationvar update_creative_assignmentsvar update_datesvar update_flight_datesvar update_frequency_capsvar update_namevar update_pacingvar update_packagesvar update_targeting
class Overlay (**data: Any)-
Expand source code
class Overlay(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) id: Annotated[ str, Field( description="Identifier for this overlay (e.g., 'play_pause', 'volume', 'publisher_logo', 'carousel_prev', 'carousel_next')" ), ] description: Annotated[ str | None, Field( description='Human-readable explanation of what this overlay is and how buyers should account for it' ), ] = None visual: Annotated[ Visual | None, Field( description='Optional visual reference for this overlay element. Useful for creative agents compositing previews and for buyers understanding what will appear over their content. Must include at least one of: url, light, or dark.' ), ] = None bounds: Annotated[ Bounds, Field( description="Position and size of the overlay relative to the asset's own top-left corner. See 'unit' for coordinate interpretation." ), ]Base model for AdCP types with spec-compliant serialization.
Defaults to
extra='ignore'so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var bounds : Boundsvar description : str | Nonevar id : strvar model_configvar visual : Visual | None
Inherited members
class Pacing (*args, **kwds)-
Expand source code
class Pacing(StrEnum): even = 'even' asap = 'asap' front_loaded = 'front_loaded'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var asapvar evenvar front_loaded
class MediaBuyPackage (**data: Any)-
Expand source code
class Package(IndicatorBearingResourceState): model_config = ConfigDict( extra='allow', ) indicator_types_evaluated: Annotated[ list[IndicatorTypesEvaluatedEnum1] | None, Field( description='Indicator types covered by this snapshot. Required whenever indicators is present. Types omitted from this list remain unknown even when indicators is empty. Every returned indicator.type MUST appear in this list.', min_length=1, ), ] = None indicators: Annotated[ list[Indicator1] | None, Field( description='Current seller assertions for the indicator types and publisher/placement coverage named by the sibling evaluation fields. Omitted means unknown or not evaluated. A present empty array means evaluated with no current assertion for indicator_types_evaluated in the evaluated scope.' ), ] = None package_id: Annotated[str, Field(description="Seller's package identifier")] product_id: Annotated[ str | None, Field( description="Product identifier this package is purchased from. For packages created from an explicit create_media_buy package request, sellers MUST echo the request package's product_id on every response package object that represents that requested package." ), ] = None budget: Annotated[ StrictFloat | None, Field( description='Hard lifetime package spend cap denominated in media_buy.currency. In seller-optimized mode this is not a current allocation.', ge=0.0, ), ] = None min_spend_target: Annotated[ StrictFloat | None, Field( description='Accepted soft lifetime spend target for this package under seller-optimized allocation.', ge=0.0, ), ] = None daily_budget_cap: Annotated[ StrictFloat | None, Field( description='Current hard package spend ceiling per shared media-buy cap day, denominated in media_buy.currency. It is a subordinate ceiling, not a reserved allocation; media_buy.budget_cap_timezone defines the day boundary.', ge=0.0, ), ] = None currency: Annotated[ str | None, Field( description='Legacy/readback package denomination for buys created outside the canonical 3.2 path. For AdCP-authored media buys this MUST equal media_buy.currency; canonical package budget and BiddingPolicy values always use media_buy.currency. Snapshot currency may still identify externally reported spend denomination.', pattern='^[A-Z]{3}$', ), ] = None bid_price: Annotated[ StrictFloat | None, Field( deprecated=True, description='DEPRECATED legacy bid representation. 3.2 sellers SHOULD normalize and echo package.bidding instead.', ge=0.0, ), ] = None bidding: Annotated[ bidding_policy.BiddingPolicy | None, Field( description='Package-authored bidding override. `{automatic:true}` explicitly overrides media_buy.bidding with provider automatic delivery. Omitted when this package inherits; sellers MUST NOT copy an inherited block here. Monetary fields use media_buy.currency.' ), ] = None optimization_goals: Annotated[ list[optimization_goal.OptimizationGoal] | None, Field( description='Current package objective functions. Currency-bearing execution controls are returned separately in package.bidding or inherited from media_buy.bidding.', min_length=1, ), ] = None format_ids: Annotated[ list[format_id.FormatReferenceStructuredObject] | None, Field( deprecated=True, description='Deprecated in AdCP 3.2; removed in AdCP 4.0. Legacy named-format IDs supplied for this package on create_media_buy. Sellers SHOULD echo this field whenever the request included it, including dual-emission cases where another selector won precedence.', min_length=1, ), ] = None format_option_refs: Annotated[ list[format_option_ref.FormatOptionReference] | None, Field( description='Structured 3.1+ format option references supplied for this package on create_media_buy. Sellers SHOULD echo this field whenever the request included it.', min_length=1, ), ] = None format_kind: Annotated[ str | None, Field( description='Direct canonical selector supplied for this package on create_media_buy. Sellers SHOULD echo this field whenever the request included it, including informational-echo cases where another selector won precedence.' ), ] = None params: Annotated[ dict[str, Any] | None, Field( description='Parameters for the direct canonical selector in `format_kind`, echoed from the create_media_buy request whenever the request included it. Requires `format_kind`.' ), ] = None impressions: Annotated[ StrictFloat | None, Field(description='Goal impression count for impression-based packages', ge=0.0), ] = None pacing: Annotated[ pacing_1.Pacing | None, Field( description='Package-level pacing preference. Under seller-optimized allocation this is subordinate to the media-buy aggregate pacing.' ), ] = None targeting_overlay: Annotated[ targeting.TargetingOverlay | None, Field( description='Complete effective targeting applied to this package, including configured-product targeting and the most recent package-specific overlay. Sellers SHOULD echo persisted targeting so buyers can verify stored state without replaying requests. Sellers MUST echo geo_places and geo_places_exclude whenever either was persisted, including the exact applied system_version and normalized values, so buyers can audit catalog-backed targeting. Sellers using placement, property-list, or collection-list targeting MUST include the committed inventory selection here. placement_selection mode default SHOULD resolve to mode selected with committed refs when enumerable; collection_selection follows the same rule, materializing the committed selectors even when the selection was produced through collection_list references.' ), ] = None targeting_resolution: Annotated[ package_targeting_resolution.PackageTargetingResolution | None, Field( description='Execution details for accepted package targeting. Sellers MUST include targeting_resolution.demographics whenever demographic targeting was requested or applied; its applied predicate and execution fields report the effective booked state.' ), ] = None start_time: Annotated[ AwareDatetime | None, Field( description='ISO 8601 flight start time for this package. Use to determine whether the package is within its scheduled flight before interpreting delivery status.' ), ] = None end_time: Annotated[ AwareDatetime | None, Field(description='ISO 8601 flight end time for this package') ] = None paused: Annotated[ StrictBool | None, Field(description='Whether this package is currently paused by the buyer'), ] = None canceled: Annotated[ StrictBool | None, Field( description='Whether this package has been canceled. Canceled packages stop delivery and cannot be reactivated.' ), ] = None cancellation: Annotated[ Cancellation1 | None, Field(description='Cancellation metadata. Present only when canceled is true.'), ] = None creative_deadline: Annotated[ AwareDatetime | None, Field( description="ISO 8601 timestamp for creative upload or change deadline for this package. After this deadline, creative changes are rejected. When absent, the media buy's creative_deadline applies." ), ] = None context: Annotated[ context_1.ContextObject | None, Field( description='Opaque package-level correlation data echoed unchanged from the create_media_buy package request. Sellers MUST include persisted package context on read surfaces when the package was created through AdCP with context, so buyers can reconcile seller-assigned package_id values with their own line items; this is the legacy-safe fallback when an older seller did not echo product_id on the create response. Sellers MAY omit context for packages created outside AdCP or created without context. Sellers MUST NOT parse this object for business logic.' ), ] = None creative_approvals: Annotated[ list[CreativeApproval] | None, Field( description='Approval status for each creative assigned to this package. Absent when no creatives have been assigned.' ), ] = None formats_to_provide: Annotated[ list[package_format_snapshot.PackageFormatSnapshot] | None, Field( description='The immutable PackageFormatSnapshot checklist established for this package at booking time. Contract-bearing snapshots remain present after creative coverage is complete so readback, assignment, and serving never fall back to a mutable live Product declaration.', min_length=1, ), ] = None formats_pending: Annotated[ list[package_format_snapshot.PackageFormatSnapshot] | None, Field( description='PackageFormatSnapshot entries from formats_to_provide that do not yet have creative coverage. Each entry MUST be canonically equal to the corresponding checklist snapshot and, when product_snapshot_digest is present, carry the identical digest. An empty emitted array means all requirements are covered; absence means readiness was not reported.' ), ] = None format_ids_to_provide: Annotated[ list[format_id.FormatReferenceStructuredObject] | None, Field( deprecated=True, description='**DEPRECATED in 3.2.** Legacy named-format projection of formats_to_provide retained for older 3.x peers. New sellers emit canonical formats_to_provide declarations.', ), ] = None format_ids_pending: Annotated[ list[format_id.FormatReferenceStructuredObject] | None, Field( deprecated=True, description='**DEPRECATED in 3.2.** Legacy named-format projection of formats_pending retained for older 3.x peers. New sellers emit canonical formats_pending declarations. An empty emitted array means every projected requirement is covered. Absence means legacy readiness was not reported and MUST NOT be interpreted as full coverage.', ), ] = None snapshot_unavailable_reason: Annotated[ snapshot_unavailable_reason_1.SnapshotUnavailableReason | None, Field( description='Machine-readable reason the snapshot is omitted. Present only when include_snapshot was true and snapshot is unavailable for this package.' ), ] = None snapshot: Annotated[ Snapshot | None, Field( description='Near-real-time delivery snapshot for this package. Only present when include_snapshot was true in the request. Represents the latest available entity-level stats from the platform — not billing-grade data.' ), ] = None ext: ext_1.ExtensionObject | None = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- IndicatorBearingResourceState
- AdCPBaseModel
- pydantic.main.BaseModel
Subclasses
Class variables
var bid_price : float | Nonevar bidding : BiddingPolicy | Nonevar budget : float | Nonevar canceled : bool | Nonevar cancellation : Cancellation1 | Nonevar context : ContextObject | Nonevar creative_approvals : list[CreativeApproval] | Nonevar creative_deadline : pydantic.types.AwareDatetime | Nonevar currency : str | Nonevar daily_budget_cap : float | Nonevar end_time : pydantic.types.AwareDatetime | Nonevar ext : ExtensionObject | Nonevar format_ids : list[FormatReferenceStructuredObject] | Nonevar format_ids_pending : list[FormatReferenceStructuredObject] | Nonevar format_ids_to_provide : list[FormatReferenceStructuredObject] | Nonevar format_kind : str | Nonevar format_option_refs : list[FormatOptionReference1 | FormatOptionReference2] | Nonevar formats_pending : list[PackageFormatSnapshot18 | PackageFormatSnapshot19 | PackageFormatSnapshot20 | PackageFormatSnapshot21 | PackageFormatSnapshot22 | PackageFormatSnapshot23 | PackageFormatSnapshot24 | PackageFormatSnapshot25 | PackageFormatSnapshot26 | PackageFormatSnapshot27 | PackageFormatSnapshot28 | PackageFormatSnapshot29 | PackageFormatSnapshot30 | PackageFormatSnapshot31 | PackageFormatSnapshot32 | PackageFormatSnapshot33] | Nonevar formats_to_provide : list[PackageFormatSnapshot18 | PackageFormatSnapshot19 | PackageFormatSnapshot20 | PackageFormatSnapshot21 | PackageFormatSnapshot22 | PackageFormatSnapshot23 | PackageFormatSnapshot24 | PackageFormatSnapshot25 | PackageFormatSnapshot26 | PackageFormatSnapshot27 | PackageFormatSnapshot28 | PackageFormatSnapshot29 | PackageFormatSnapshot30 | PackageFormatSnapshot31 | PackageFormatSnapshot32 | PackageFormatSnapshot33] | Nonevar impressions : float | Nonevar indicator_types_evaluated : list[IndicatorTypesEvaluatedEnum1] | Nonevar indicators : list[Indicator1] | Nonevar min_spend_target : float | Nonevar model_configvar optimization_goals : list[OptimizationGoal8 | OptimizationGoal9 | OptimizationGoal10] | Nonevar pacing : Pacing | Nonevar package_id : strvar params : dict[str, typing.Any] | Nonevar paused : bool | Nonevar product_id : str | Nonevar snapshot : Snapshot | Nonevar start_time : pydantic.types.AwareDatetime | Nonevar targeting_overlay : TargetingOverlay | Nonevar targeting_resolution : PackageTargetingResolution | None
class Package (**data: Any)-
Expand source code
class Package(_LegacyPackage, CanonicalBoundaryModel): """Canonical package; legacy format identity is absent.""" if TYPE_CHECKING: # the removed fields, hidden from the constructor too format_ids: _RemovedFormatIds = Field(default=None, init=False) format_ids_pending: _RemovedFormatIds = Field(default=None, init=False) format_ids_to_provide: _RemovedFormatIds = Field(default=None, init=False)Canonical package; legacy format identity is absent.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- Package
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var format_ids : list[FormatReferenceStructuredObject] | Nonevar format_ids_pending : list[FormatReferenceStructuredObject] | Nonevar format_ids_to_provide : list[FormatReferenceStructuredObject] | Nonevar model_config
Instance variables
var bid_price : float | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
Inherited members
class 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 selfCanonical 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- PackageRequest
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var creatives : list[CreativeAsset] | Nonevar model_configvar targeting_overlay : TargetingOverlayInput | TargetingOverlay | None
Inherited members
class PackageUpdate (**data: Any)-
Expand source code
class PackageUpdate(_LegacyPackageUpdate, CanonicalBoundaryModel): """Canonical package update; creatives are canonical assets.""" creatives: list[CreativeAsset] | None = Field(default=None, min_length=1) # type: ignore[assignment]Canonical package update; creatives are canonical assets.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- PackageUpdate
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var creatives : list[CreativeAsset] | Nonevar model_configvar targeting_overlay : TargetingOverlayInput | TargetingOverlay | None
Inherited members
class ProductAllowedAction (**data: Any)-
Expand source code
class ProductAllowedAction(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) action: Annotated[ media_buy_available_action_id.MediaBuyAvailableActionId, Field( description='The action identifier. Accepts every legacy valid_actions value plus structured-only actions such as update_media_buy_frequency_cap.' ), ] modes: Annotated[ list[media_buy_action_mode.MediaBuyActionMode], Field( description='Modes available for this action on this product. A product may declare multiple modes (for example `self_serve` within tolerances, escalating to `requires_approval` outside) — the buy-side `available_actions[<action>].mode` resolves to the singular mode in effect at mutation time. SDKs that see multiple modes MUST NOT assume which one will fire; they must read the resolved `mode` on the buy.', min_length=1, ), ] allowed_statuses: Annotated[ list[media_buy_status.MediaBuyStatus] | None, Field( description='Media buy statuses in which this action is permitted. When absent, the action is permitted in all non-terminal statuses (`pending_creatives`, `pending_start`, `active`, `paused`).', min_length=1, ), ] = None sla: Annotated[ sla_window.SlaWindow | None, Field( description='Optional SLA commitment for this action on this product. Absence means no commitment.' ), ] = None constraints: Annotated[ change_term_constraints.MediaBuyChangeTermConstraints | None, Field( description='Optional advisory machine-readable bounds buyers can use during product selection. The proposal must restate any binding bounds in commercial_terms.change_terms[].constraints.' ), ] = None terms_ref: Annotated[ str | None, Field( description='Optional advisory pointer to published commercial terms governing this product action. It is not a proposal change-term identity and never grants a binding change right; a proposal materializes binding rights under commercial_terms.change_terms[].term_id.' ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var action : MediaBuyValidAction | Literal['update_media_buy_frequency_cap']var allowed_statuses : list[MediaBuyStatus] | Nonevar constraints : MediaBuyChangeTermConstraints1 | MediaBuyChangeTermConstraints2 | MediaBuyChangeTermConstraints3 | MediaBuyChangeTermConstraints4 | Nonevar model_configvar modes : list[MediaBuyActionMode]var sla : SlaWindow | Nonevar terms_ref : str | None
Inherited members
class Proposal (**data: Any)-
Expand source code
class Proposal(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) proposal_id: Annotated[ str, Field( description='Unique identifier for this proposal. Used to finalize a draft proposal and to execute a committed proposal via create_media_buy.', max_length=255, ), ] name: Annotated[ str, Field(description='Human-readable name for this media plan proposal', max_length=500) ] description: Annotated[ str | None, Field( description='Explanation of the proposal strategy and what it achieves', max_length=2000 ), ] = None allocations: Annotated[ list[product_allocation.ProductAllocation], Field( description='Products and budget constraints in this plan. Fixed proposals require allocation_percentage on every entry and percentages MUST sum to 100. Seller-optimized proposals forbid exact allocation_percentage and may instead supply min_spend_target_percentage and max_spend_percentage, each only when the seller advertises the matching package-control capability (seller_optimized_min_spend_targets, seller_optimized_package_budgets). Publishers are responsible for validating cross-entry sums; buyers SHOULD validate them before execution.', min_length=1, ), ] budget_allocation: Annotated[ budget_allocation_1.BudgetAllocation | None, Field( description='How the executed total budget is allocated across proposal products. Omit for legacy fixed proposals.' ), ] = None pacing: Annotated[ pacing_1.Pacing | None, Field( description='Recommended aggregate pacing for the executed media-buy budget. On a committed proposal this is part of the firm delivery terms.' ), ] = None frequency_cap: Annotated[ media_buy_frequency_cap.MediaBuyFrequencyCap | None, Field( description='Aggregate cap bound into this legacy proposal. It is authoritative when the proposal is executed and uses one counter across its packages.' ), ] = None proposal_status: Annotated[ proposal_status_1.ProposalStatus | None, Field( description="Lifecycle status of this proposal and the per-proposal source of truth for whether finalization is required before create_media_buy. When absent, the proposal is ready to buy (backward compatible). 'draft' means indicative pricing — finalize via refine before purchasing. 'committed' means firm pricing with inventory reserved until expires_at and executable via create_media_buy." ), ] = None expires_at: Annotated[ AwareDatetime | None, Field( description='When this proposal expires and can no longer be executed. For draft proposals, indicates when indicative pricing becomes stale. For committed proposals, indicates when the inventory hold lapses — the buyer must call create_media_buy before this time.' ), ] = None insertion_order: Annotated[ insertion_order_1.InsertionOrder | None, Field( description='Formal insertion order attached to a committed proposal. Present when the seller requires a signed agreement before the media buy can proceed. The buyer references the io_id in io_acceptance on create_media_buy.' ), ] = None total_budget_guidance: Annotated[ TotalBudgetGuidance | None, Field(description='Optional budget guidance for this proposal') ] = None brief_alignment: Annotated[ str | None, Field( description='Explanation of how this proposal aligns with the campaign brief', max_length=2000, ), ] = None forecast: Annotated[ delivery_forecast.DeliveryForecast | None, Field( description='Aggregate forecasted delivery metrics for the entire proposal. When both proposal-level and allocation-level forecasts are present, the proposal-level forecast is authoritative for total delivery estimation.' ), ] = None ext: ext_1.ExtensionObject | None = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var allocations : list[ProductAllocation]var brief_alignment : str | Nonevar budget_allocation : BudgetAllocation1 | BudgetAllocation2 | Nonevar description : str | Nonevar expires_at : pydantic.types.AwareDatetime | Nonevar ext : ExtensionObject | Nonevar forecast : DeliveryForecast | Nonevar frequency_cap : MediaBuyFrequencyCap | Nonevar insertion_order : InsertionOrder | Nonevar model_configvar name : strvar pacing : Pacing | Nonevar proposal_id : strvar proposal_status : ProposalStatus | Nonevar total_budget_guidance : TotalBudgetGuidance | None
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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var context : ContextObject | Nonevar context_id : str | Nonevar governance_context : str | Nonevar idempotency_key : strvar model_configvar push_notification_config : PushNotificationConfig | Nonevar refinements : list[ProposalRefinement2 | ProposalRefinement3 | ProposalRefinement4 | ProposalRefinement5 | ProposalRefinement6 | ProposalRefinement7 | ProposalRefinement8 | ProposalRefinement9] | Refinements
Inherited members
class RegistryAcceptancePolicyProfileReference (**data: Any)-
Expand source code
class RegistryAcceptancePolicyProfileReference(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) policy_id: Annotated[str, Field(min_length=1)] policy_version: Annotated[str, Field(min_length=1)] policy_digest: Annotated[str, Field(pattern='^sha256:[a-f0-9]{64}$')] profile_id: Annotated[str, Field(pattern='^[A-Za-z0-9_.:-]+$')] profile_version: Annotated[str, Field(min_length=1)] profile_digest: Annotated[str, Field(pattern='^sha256:[a-f0-9]{64}$')]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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar policy_digest : strvar policy_id : strvar policy_version : strvar profile_digest : strvar profile_id : strvar profile_version : str
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
Nonewhen this tool's schema declares no such field. Only 49 of the 87 request schemas declare anaccountand only 43 anidempotency_key, so asking the request is what replacesgetattr(req, "account", None)againstAnyat 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : CanonicalAccountReference1 | CanonicalAccountReference2 | Nonevar brand : BrandKey | Nonevar brief : strvar context : ContextObject | Nonevar context_id : str | Nonevar criteria : ProductDiscoveryCriteria | Nonevar governance_context : str | Nonevar idempotency_key : strvar model_configvar opportunity : Opportunity | Nonevar push_notification_config : PushNotificationConfig | None
Inherited members
class MediaBuyDeliveryStatus (*args, **kwds)-
Expand source code
class Status(StrEnum): pending_creatives = 'pending_creatives' pending_start = 'pending_start' pending = 'pending' active = 'active' paused = 'paused' completed = 'completed' rejected = 'rejected' canceled = 'canceled' failed = 'failed' reporting_delayed = 'reporting_delayed'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var activevar canceledvar completedvar failedvar pausedvar pendingvar pending_creativesvar pending_startvar rejectedvar reporting_delayed
class TargetingOverlay (**data: Any)-
Expand source code
class TargetingOverlay(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) geo_countries: Annotated[ list[GeoCountry] | None, Field( description="Restrict delivery to specific countries. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').", min_length=1, ), ] = None geo_countries_exclude: Annotated[ Sequence[GeoCountriesExcludeItem] | None, Field( description="Exclude specific countries from delivery. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').", min_length=1, ), ] = None geo_regions: Annotated[ list[GeoRegion] | None, Field( description='Restrict delivery to 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', ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var age_restriction : AgeRestriction | Nonevar audience_exclude : list[str] | Nonevar audience_include : list[str] | Nonevar axe_exclude_segment : str | Nonevar axe_include_segment : str | Nonevar browser : list[BrowserFamily] | Nonevar browser_exclude : list[BrowserFamily] | Nonevar collection_list : CollectionListReference | Nonevar collection_list_exclude : CollectionListReference | Nonevar collection_selection : CollectionSelection1 | CollectionSelection2 | Nonevar daypart_targets : list[DaypartTarget] | Nonevar demographics : DemographicTargetingIntent | Nonevar device_platform : list[DevicePlatform] | Nonevar device_platform_exclude : list[DevicePlatform] | Nonevar device_type : list[DeviceType] | Nonevar device_type_exclude : list[DeviceType] | Nonevar frequency_cap : FrequencyCap | Nonevar geo_countries : list[GeoCountry] | Nonevar geo_countries_exclude : collections.abc.Sequence[GeoCountriesExcludeItem] | Nonevar geo_metros : list[GeoMetro] | Nonevar geo_metros_exclude : collections.abc.Sequence[GeoMetrosExcludeItem] | Nonevar geo_places : list[GeographicPlaceArea] | Nonevar geo_places_exclude : list[GeographicPlaceArea] | Nonevar geo_postal_areas : list[PostalArea] | Nonevar geo_postal_areas_exclude : collections.abc.Sequence[PostalArea] | Nonevar geo_proximity : list[GeoProximityItem] | Nonevar geo_regions : list[GeoRegion] | Nonevar geo_regions_exclude : collections.abc.Sequence[GeoRegionsExcludeItem] | Nonevar keyword_targets : list[KeywordTarget] | Nonevar language : list[LanguageTag] | Nonevar model_configvar negative_keywords : list[NegativeKeyword] | Nonevar placement_selection : PlacementSelection1 | PlacementSelection2 | Nonevar property_list : PropertyListReference | Nonevar property_list_exclude : PropertyListReference | Nonevar signal_targeting : list[SignalTargeting1 | SignalTargeting2 | SignalTargeting3] | Nonevar signal_targeting_groups : PackageSignalTargetingGroups | Nonevar 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', ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var age_restriction : AgeRestriction | Nonevar audience_exclude : list[str] | Nonevar audience_include : list[str] | Nonevar axe_exclude_segment : str | Nonevar axe_include_segment : str | Nonevar browser : list[BrowserFamily] | Nonevar browser_exclude : list[BrowserFamily] | Nonevar collection_list : CollectionListReference | Nonevar collection_list_exclude : CollectionListReference | Nonevar collection_selection : CollectionSelection1 | CollectionSelection2 | Nonevar daypart_targets : list[DaypartTarget] | Nonevar demographics : DemographicTargetingIntent | Nonevar device_platform : list[DevicePlatform] | Nonevar device_platform_exclude : list[DevicePlatform] | Nonevar device_type : list[DeviceType] | Nonevar device_type_exclude : list[DeviceType] | Nonevar frequency_cap : FrequencyCap | Nonevar geo_countries : list[GeoCountry] | Nonevar geo_countries_exclude : list[GeoCountriesExcludeItem] | Nonevar geo_metros : list[GeoMetro] | Nonevar geo_metros_exclude : list[GeoMetrosExcludeItem] | Nonevar geo_places : list[GeographicPlaceArea] | Nonevar geo_places_exclude : list[GeographicPlaceArea] | Nonevar geo_postal_areas : list[PostalArea] | Nonevar geo_postal_areas_exclude : list[PostalArea] | Nonevar geo_proximity : list[GeoProximityItem] | Nonevar geo_regions : list[GeoRegion] | Nonevar geo_regions_exclude : list[GeoRegionsExcludeItem] | Nonevar keyword_targets : list[KeywordTarget] | Nonevar language : list[LanguageTag] | Nonevar model_configvar negative_keywords : list[NegativeKeyword] | Nonevar placement_selection : PlacementSelection1 | PlacementSelection2 | Nonevar property_list : PropertyListReference | Nonevar property_list_exclude : PropertyListReference | Nonevar signal_targeting : list[SignalTargeting1 | SignalTargeting2 | SignalTargeting3] | Nonevar signal_targeting_groups : PackageSignalTargetingGroups | Nonevar store_catchments : list[StoreCatchment] | None
Inherited members
class Totals (**data: Any)-
Expand source code
class Totals(DeliveryMetrics): effective_rate: Annotated[ StrictFloat | None, Field( description="Effective rate paid per unit based on pricing_model (e.g., actual CPM for 'cpm', actual cost per completed view for 'cpcv', actual cost per point for 'cpp')", ge=0.0, ), ] = NoneBase 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 setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='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 adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport 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_configon 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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- DeliveryMetrics
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var effective_rate : float | Nonevar model_config
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyRequest
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar new_packages : list[PackageRequest] | Nonevar packages : list[PackageUpdate] | 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.
class UpdateMediaBuyPackagesRequest (**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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyRequest
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar new_packages : list[PackageRequest] | Nonevar packages : list[PackageUpdate] | 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.
class UpdateMediaBuyPropertiesRequest (**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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyRequest
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar new_packages : list[PackageRequest] | Nonevar packages : list[PackageUpdate] | None
Inherited members
class UpdateMediaBuySuccessResponse (**data: Any)-
Expand source code
class UpdateMediaBuyResponse1(_LegacyUpdateMediaBuyResponse1, CanonicalBoundaryModel): """Canonical update response preserving the 3.x legacy-status normalizer.""" affected_packages: Sequence[Package] | None = None @model_validator(mode="before") @classmethod def _normalize_legacy_status(cls, data: Any) -> Any: if not isinstance(data, dict): return data raw_status = unwrap_enum_value(data.get("status")) media_buy_status = unwrap_enum_value(data.get("media_buy_status")) if raw_status is None or raw_status == "completed": return {**data, "status": "completed"} if media_buy_status is None and raw_status in MEDIA_BUY_LEGACY_STATUS_VALUES: return {**data, "media_buy_status": raw_status, "status": "completed"} if media_buy_status is not None and raw_status == media_buy_status: return {**data, "status": "completed"} return dataCanonical update response preserving the 3.x legacy-status normalizer.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyResponse1
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var affected_packages : collections.abc.Sequence[Package] | Nonevar model_config
Inherited members
class UpdateMediaBuyErrorResponse (**data: Any)-
Expand source code
class UpdateMediaBuyResponse2(_LegacyUpdateMediaBuyResponse2, CanonicalBoundaryModel): """Canonical update-media-buy error arm."""Canonical update-media-buy error arm.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyResponse2
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class UpdateMediaBuySubmittedResponse (**data: Any)-
Expand source code
class UpdateMediaBuyResponse3(_LegacyUpdateMediaBuyResponse3, CanonicalBoundaryModel): """Canonical update-media-buy submitted arm."""Canonical update-media-buy submitted arm.
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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyResponse3
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members