Module adcp.types.domains.media_buy.commercial_terms
Classes
class CancellationTerms (**data: Any)-
Expand source code
class CancellationTerms(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) effective_at: AwareDatetime fee: Fee | None = None reason: Annotated[str | None, Field(max_length=500, 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 effective_at : pydantic.types.AwareDatetimevar fee : Fee | Nonevar model_configvar reason : 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 Fee (**data: Any)-
Expand source code
class Fee(TotalBudget): passBase 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
- TotalBudget
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class ReportingCommitment (**data: Any)-
Expand source code
class ReportingCommitment(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) purchase_index: Annotated[SchemaInt, Field(ge=0)] metrics: Annotated[ list[canonical_reporting_commitment.CanonicalReportingCommitment], Field(min_length=1) ]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 metrics : list[CanonicalReportingCommitment1 | CanonicalReportingCommitment2]var model_configvar purchase_index : int
Inherited members
class TotalBudget (**data: Any)-
Expand source code
class TotalBudget(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) amount: Annotated[StrictFloat, Field(ge=0.0)] currency: Annotated[str, Field(pattern='^[A-Z]{3}$')]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 amount : floatvar currency : strvar model_config
Inherited members