Module adcp.types.buyer
AdCP buyer types — curated partial surface.
Buy-side (DSP / agency) surface — product discovery, briefs / refine, pricing, media buys the buyer sends, performance feedback, brand rights.
A stable, narrow alternative to importing the whole :mod:adcp.types
namespace. Every name here is also exported from :mod:adcp.types; this
module simply groups the ones a buyer integration reaches for, and never
exposes the internal generated layer.
This module is for curation and discoverability, not a separate
performance tier: importing it is cheap, but the first access to any AdCP
type (here or via :mod:adcp.types / :mod:adcp) realizes the full generated
Pydantic graph — there is no per-domain graph. Use it for a smaller, focused
import surface.
from adcp.types.buyer import GetProductsRequest
Classes
class AcquireRightsRequest (**data: Any)-
Expand source code
class AcquireRightsRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) rights_id: Annotated[ str, Field(description='Rights offering identifier from get_rights response') ] pricing_option_id: Annotated[ str, Field(description='Selected pricing option from the rights offering') ] buyer: Annotated[brand_ref.BrandReference, Field(description="The buyer's brand identity")] account: Annotated[ account_ref.AccountReference | None, Field( description='Account context for this acquisition. Used by the brand agent to resolve any governance agent previously bound for this brand+operator pair via sync_governance. When both an inline governance_context token (on the protocol envelope) and a bound governance agent are present, the inline token wins — brand agents MUST consult the agent identified by the inline token. When the request omits both `account` and an inline governance_context token, the brand agent treats the acquisition as ungoverned and the CPM-projection rule on `campaign.estimated_impressions` does not apply (sellers MAY refuse to transact ungoverned requests as a matter of commercial policy). Pass a natural key (brand, operator, optional sandbox) or a seller-assigned account_id from list_accounts.' ), ] = None campaign: Annotated[Campaign, Field(description='Campaign details for rights clearance')] revocation_webhook: Annotated[ push_notification_config_1.PushNotificationConfig, Field( description='Webhook for rights revocation notifications. If the rights holder needs to revoke rights (talent scandal, contract violation, etc.), they POST a revocation-notification to this URL. The buyer is responsible for stopping creative delivery upon receipt.' ), ] push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( description='Webhook for async status updates if the acquisition requires approval. The rights agent sends a webhook notification when the status transitions to acquired or rejected.' ), ] = None idempotency_key: Annotated[ str, Field( description='Client-generated key for safe retries. Resubmitting with the same key returns the original response rather than creating a duplicate acquisition. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.', max_length=255, min_length=16, pattern='^[A-Za-z0-9_.:-]{16,255}$', ), ] context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : adcp.types.generated_poc.core.account_ref.AccountReference | Nonevar buyer : adcp.types.generated_poc.core.brand_ref.BrandReferencevar campaign : adcp.types.generated_poc.brand.acquire_rights_request.Campaignvar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar idempotency_key : strvar model_configvar pricing_option_id : strvar push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | Nonevar revocation_webhook : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfigvar rights_id : str
Inherited members
class BrandReference (**data: Any)-
Expand source code
class BrandReference(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) domain: Annotated[ str, Field( description="Domain where /.well-known/brand.json is hosted, or the brand's operating domain", pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$', ), ] brand_id: Annotated[ brand_id_1.BrandId | None, Field( description='Brand identifier within the house portfolio. Optional for single-brand domains.' ), ] = None industries: Annotated[ list[str] | None, Field( description="Inline override for the brand's industries. Useful when the caller cannot modify the brand's canonical brand.json but needs to declare industries for governance (e.g., Annex III vertical detection). brand.json remains the canonical source; when omitted here, governance agents SHOULD resolve from brand.json." ), ] = None data_subject_contestation: Annotated[ DataSubjectContestation | None, Field( description="Inline override for the brand's contestation contact point. Useful when the operator does not control brand.json but needs to discharge Art 22(3) for this plan. brand.json is canonical; when omitted, governance agents resolve brand → house → missing." ), ] = None brand_kit_override: Annotated[ BrandKitOverride | None, Field( description="Inline override for brand-kit fields normally resolved from `/.well-known/brand.json` on `domain` (logo, colors, voice, tagline). Use when brand.json is missing, stale, or inappropriate for this specific call — e.g., a campaign-scoped tagline, a co-branded creative, a freshly-rebranded color palette the brand.json hasn't shipped yet. Same inline-override pattern as `industries` and `data_subject_contestation` above: brand.json is canonical, the override is per-call. Adopters needing to override fields outside this subset (`voice_attributes`, `prohibited_terms`, etc.) MUST publish a different brand.json and reference it via a different `domain` — the inline override is intentionally narrow to a small high-traffic subset.\n\n**Merge semantics (normative).** The merge is **field-level**, not whole-object replacement. Each field within `brand_kit_override` (`logo`, `colors`, `voice`, `tagline`) is evaluated independently — when a field is present on the override the override value applies; when a field is absent the brand.json value applies (or is absent if brand.json doesn't carry one either). For composite fields (`colors.primary`, `colors.secondary`, `colors.accent`), the merge is one level deeper: each color slot is evaluated independently — a producer can override `colors.primary` while still inheriting `colors.secondary` from brand.json. SDKs MUST NOT treat a present `brand_kit_override.colors` as wiping the brand.json `colors` block entirely; only the per-slot fields present in the override take precedence. Without this rule, a partial-override semantics would diverge across SDKs and produce inconsistent rendering for the same payload." ), ] = 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 brand_id : adcp.types.generated_poc.core.brand_id.BrandId | Nonevar brand_kit_override : adcp.types.generated_poc.core.brand_ref.BrandKitOverride | Nonevar data_subject_contestation : adcp.types.generated_poc.core.brand_ref.DataSubjectContestation | Nonevar domain : strvar industries : list[str] | Nonevar model_config
Inherited members
class BrandSource (*args, **kwds)-
Expand source code
class BrandSource(Enum): brand_json = "brand_json" community = "community" enriched = "enriched"Create a collection of name/value pairs.
Example enumeration:
>>> class Color(Enum): ... RED = 1 ... BLUE = 2 ... GREEN = 3Access them by:
- attribute access::
>>> Color.RED <Color.RED: 1>- value lookup:
>>> Color(1) <Color.RED: 1>- name lookup:
>>> Color['RED'] <Color.RED: 1>Enumerations can be iterated over, and know how many members they have:
>>> len(Color) 3>>> list(Color) [<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]Methods can be added to enumerations, and members can have their own attributes – see the documentation for details.
Ancestors
- enum.Enum
Class variables
var brand_jsonvar communityvar enriched
class CpaPricingOption (**data: Any)-
Expand source code
class CpaPricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) pricing_option_id: Annotated[ str, Field(description='Unique identifier for this pricing option within the product') ] pricing_model: Annotated[ Literal['cpa'], Field(description='Cost per acquisition (conversion event)') ] = 'cpa' event_type: Annotated[ event_type_1.EventType, Field( description='The conversion event type that triggers billing (e.g., purchase, lead, app_install)' ), ] custom_event_name: Annotated[ str | None, Field( description="Name of the custom event when event_type is 'custom'. Required when event_type is 'custom', ignored otherwise." ), ] = None event_source_id: Annotated[ str | None, Field( description='When present, only events from this specific event source count toward billing. Allows different CPA rates for different sources (e.g., online vs in-store purchases). Must match an event source configured via sync_event_sources.' ), ] = None currency: Annotated[ str, Field( description='ISO 4217 currency code', examples=['USD', 'EUR', 'GBP', 'JPY'], pattern='^[A-Z]{3}$', ), ] fixed_price: Annotated[ float, Field(description='Fixed price per acquisition in the specified currency', gt=0.0) ] min_spend_per_package: Annotated[ float | None, Field( description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None price_breakdown: Annotated[ price_breakdown_1.PriceBreakdown | None, Field( description='Breakdown of how fixed_price was derived from the list (rate card) price. Only meaningful when fixed_price is present.' ), ] = None eligible_adjustments: Annotated[ list[adjustment_kind.PriceAdjustmentKind] | None, Field( description='Adjustment kinds applicable to this pricing option. Tells buyer agents which adjustments are available before negotiation. When absent, no adjustments are pre-declared — the buyer should check price_breakdown if present.' ), ] = 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 currency : strvar custom_event_name : str | Nonevar eligible_adjustments : list[adcp.types.generated_poc.enums.adjustment_kind.PriceAdjustmentKind] | Nonevar event_source_id : str | Nonevar event_type : adcp.types.generated_poc.enums.event_type.EventTypevar fixed_price : floatvar min_spend_per_package : float | Nonevar model_configvar price_breakdown : adcp.types.generated_poc.pricing_options.price_breakdown.PriceBreakdown | Nonevar pricing_model : Literal['cpa']var pricing_option_id : str
Inherited members
class CpcPricingOption (**data: Any)-
Expand source code
class CpcPricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) pricing_option_id: Annotated[ str, Field(description='Unique identifier for this pricing option within the product') ] pricing_model: Annotated[Literal['cpc'], Field(description='Cost per click')] = 'cpc' currency: Annotated[ str, Field( description='ISO 4217 currency code', examples=['USD', 'EUR', 'GBP', 'JPY'], pattern='^[A-Z]{3}$', ), ] fixed_price: Annotated[ float | None, Field( description='Fixed price per click. If present, this is fixed pricing. If absent, auction-based.', ge=0.0, ), ] = None floor_price: Annotated[ float | None, Field( description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', ge=0.0, ), ] = None max_bid: Annotated[ bool | None, Field( description="When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor." ), ] = False price_guidance: Annotated[ price_guidance_1.PriceGuidance | None, Field(description='Optional pricing guidance for auction-based bidding'), ] = None min_spend_per_package: Annotated[ float | None, Field( description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None price_breakdown: Annotated[ price_breakdown_1.PriceBreakdown | None, Field( description='Breakdown of how fixed_price was derived from the list (rate card) price. Only meaningful when fixed_price is present.' ), ] = None eligible_adjustments: Annotated[ list[adjustment_kind.PriceAdjustmentKind] | None, Field( description='Adjustment kinds applicable to this pricing option. Tells buyer agents which adjustments are available before negotiation. When absent, no adjustments are pre-declared — the buyer should check price_breakdown if present.' ), ] = 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 currency : strvar eligible_adjustments : list[adcp.types.generated_poc.enums.adjustment_kind.PriceAdjustmentKind] | Nonevar fixed_price : float | Nonevar floor_price : float | Nonevar max_bid : bool | Nonevar min_spend_per_package : float | Nonevar model_configvar price_breakdown : adcp.types.generated_poc.pricing_options.price_breakdown.PriceBreakdown | Nonevar price_guidance : adcp.types.generated_poc.pricing_options.price_guidance.PriceGuidance | Nonevar pricing_model : Literal['cpc']var pricing_option_id : str
Inherited members
class CpmPricingOption (**data: Any)-
Expand source code
class CpmPricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) pricing_option_id: Annotated[ str, Field(description='Unique identifier for this pricing option within the product') ] pricing_model: Annotated[Literal['cpm'], Field(description='Cost per 1,000 impressions')] = 'cpm' currency: Annotated[ str, Field( description='ISO 4217 currency code', examples=['USD', 'EUR', 'GBP', 'JPY'], pattern='^[A-Z]{3}$', ), ] fixed_price: Annotated[ float | None, Field( description='Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.', ge=0.0, ), ] = None floor_price: Annotated[ float | None, Field( description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', ge=0.0, ), ] = None max_bid: Annotated[ bool | None, Field( description="When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor." ), ] = False price_guidance: Annotated[ price_guidance_1.PriceGuidance | None, Field(description='Optional pricing guidance for auction-based bidding'), ] = None min_spend_per_package: Annotated[ float | None, Field( description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None price_breakdown: Annotated[ price_breakdown_1.PriceBreakdown | None, Field( description='Breakdown of how fixed_price was derived from the list (rate card) price. Only meaningful when fixed_price is present.' ), ] = None eligible_adjustments: Annotated[ list[adjustment_kind.PriceAdjustmentKind] | None, Field( description='Adjustment kinds applicable to this pricing option. Tells buyer agents which adjustments are available before negotiation. When absent, no adjustments are pre-declared — the buyer should check price_breakdown if present.' ), ] = 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 currency : strvar eligible_adjustments : list[adcp.types.generated_poc.enums.adjustment_kind.PriceAdjustmentKind] | Nonevar fixed_price : float | Nonevar floor_price : float | Nonevar max_bid : bool | Nonevar min_spend_per_package : float | Nonevar model_configvar price_breakdown : adcp.types.generated_poc.pricing_options.price_breakdown.PriceBreakdown | Nonevar price_guidance : adcp.types.generated_poc.pricing_options.price_guidance.PriceGuidance | Nonevar pricing_model : Literal['cpm']var pricing_option_id : str
Inherited members
class CreateMediaBuyRequest (**data: Any)-
Expand source code
class CreateMediaBuyRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) idempotency_key: Annotated[ str, Field( description='Client-generated unique key for this request. If a request with the same idempotency_key and account has already been processed, the seller returns the existing media buy rather than creating a duplicate. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.', max_length=255, min_length=16, pattern='^[A-Za-z0-9_.:-]{16,255}$', ), ] plan_id: Annotated[ str | None, Field( description='Campaign governance plan identifier. Required when the account has governance_agents. The seller includes this in the committed check_governance request so the governance agent can validate against the correct plan.' ), ] = None account: Annotated[ account_ref.AccountReference, Field( description='Account to bill for this media buy. Pass a natural key (brand, operator, optional sandbox) or a seller-assigned account_id from list_accounts.' ), ] proposal_id: Annotated[ str | None, Field( description="ID of a committed proposal from get_products to execute. When provided with total_budget, the publisher converts the proposal's allocation percentages into packages automatically. Alternative to providing packages array. If the referenced proposal has proposal_status: 'draft', the seller MUST reject with PROPOSAL_NOT_COMMITTED; the buyer finalizes first via get_products refine action 'finalize'." ), ] = None total_budget: Annotated[ TotalBudget | None, Field( description="Total budget for the media buy when executing a proposal. The publisher applies the proposal's allocation percentages to this amount to derive package budgets." ), ] = None packages: Annotated[ Sequence[package_request.PackageRequest] | None, Field( description="Array of package configurations. Required when not using proposal_id. When executing a proposal, this can be omitted and packages will be derived from the proposal's allocations.", min_length=1, ), ] = None brand: Annotated[ brand_ref.BrandReference, Field( description='Brand reference for this media buy. Resolved to full brand identity at execution time from brand.json or the registry.' ), ] advertiser_industry: Annotated[ advertiser_industry_1.AdvertiserIndustry | None, Field( description="Industry classification for this specific campaign. A brand may operate across multiple industries (brand.json industries field), but each media buy targets one. For example, a consumer health company running a wellness campaign sends 'healthcare.wellness', not 'cpg'. Sellers map this to platform-native codes (e.g., Spotify ADV categories, LinkedIn industry IDs). When omitted, sellers may infer from the brand manifest's industries field." ), ] = None invoice_recipient: Annotated[ business_entity.BusinessEntity | None, Field( description="Override the account's default billing entity for this specific buy. When provided, the seller invoices this entity instead. The seller MUST validate the invoice recipient is authorized for this account. When governance_agents are configured, the seller MUST include invoice_recipient in the check_governance request." ), ] = None io_acceptance: Annotated[ IoAcceptance | None, Field( description="Acceptance of an insertion order from a committed proposal. Required when the proposal's insertion_order has requires_signature: true. References the io_id from the proposal's insertion_order." ), ] = None po_number: Annotated[str | None, Field(description='Purchase order number for tracking')] = None agency_estimate_number: Annotated[ str | None, Field( description="Agency estimate or authorization number. Primary financial reference for broadcast buys — links the order to the agency's media plan and billing system. Travels with the order and creative traffic identifiers through the transaction lifecycle.", max_length=100, ), ] = None start_time: start_timing.StartTiming end_time: Annotated[ AwareDatetime, Field(description='Campaign end date/time in ISO 8601 format') ] paused: Annotated[ bool | None, Field( description="Create the media buy in a paused delivery state. When true, and the buy would otherwise be active because creatives are assigned and the flight has started, the seller returns media_buy_status 'paused'. Setup blockers still take precedence: a buy with no creatives remains 'pending_creatives', and a future-dated buy remains 'pending_start' until its flight can start. Defaults to false." ), ] = False push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( description='Optional webhook configuration for async task status notifications. Publisher will send webhooks when status changes (working, input-required, completed, failed, canceled). Buyers SHOULD supply `push_notification_config_1.operation_id` as the canonical correlation value; publishers echo that field back verbatim in webhook payloads and MUST NOT parse the URL to derive it.' ), ] = None reporting_webhook: Annotated[ reporting_webhook_1.ReportingWebhook | None, Field(description='Optional webhook configuration for automated reporting delivery'), ] = None artifact_webhook: Annotated[ ArtifactWebhook | None, Field( description='Optional webhook configuration for content artifact delivery. Used by governance agents to validate content adjacency. Seller pushes artifacts to this endpoint; orchestrator forwards to governance agent for validation.' ), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : adcp.types.generated_poc.core.account_ref.AccountReferencevar advertiser_industry : adcp.types.generated_poc.enums.advertiser_industry.AdvertiserIndustry | Nonevar agency_estimate_number : str | Nonevar artifact_webhook : adcp.types.generated_poc.media_buy.create_media_buy_request.ArtifactWebhook | Nonevar brand : adcp.types.generated_poc.core.brand_ref.BrandReferencevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar end_time : pydantic.types.AwareDatetimevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar idempotency_key : strvar invoice_recipient : adcp.types.generated_poc.core.business_entity.BusinessEntity | Nonevar io_acceptance : adcp.types.generated_poc.media_buy.create_media_buy_request.IoAcceptance | Nonevar model_configvar packages : collections.abc.Sequence[adcp.types.generated_poc.media_buy.package_request.PackageRequest] | Nonevar paused : bool | Nonevar plan_id : str | Nonevar po_number : str | Nonevar proposal_id : str | Nonevar push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | Nonevar reporting_webhook : adcp.types.generated_poc.core.reporting_webhook.ReportingWebhook | Nonevar start_time : adcp.types.generated_poc.core.start_timing.StartTimingvar total_budget : adcp.types.generated_poc.media_buy.create_media_buy_request.TotalBudget | None
Inherited members
class FeedbackSource (*args, **kwds)-
Expand source code
class FeedbackSource(StrEnum): buyer_attribution = 'buyer_attribution' third_party_measurement = 'third_party_measurement' platform_analytics = 'platform_analytics' verification_partner = 'verification_partner'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var buyer_attributionvar platform_analyticsvar third_party_measurementvar verification_partner
class FlatRatePricingOption (**data: Any)-
Expand source code
class FlatRatePricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) pricing_option_id: Annotated[ str, Field(description='Unique identifier for this pricing option within the product') ] pricing_model: Annotated[ Literal['flat_rate'], Field(description='Fixed cost regardless of delivery volume') ] = 'flat_rate' currency: Annotated[ str, Field( description='ISO 4217 currency code', examples=['USD', 'EUR', 'GBP', 'JPY'], pattern='^[A-Z]{3}$', ), ] fixed_price: Annotated[ float | None, Field( description='Flat rate cost. If present, this is fixed pricing. If absent, auction-based.', ge=0.0, ), ] = None floor_price: Annotated[ float | None, Field( description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', ge=0.0, ), ] = None price_guidance: Annotated[ price_guidance_1.PriceGuidance | None, Field(description='Optional pricing guidance for auction-based bidding'), ] = None parameters: Annotated[ Parameters | None, Field( description='DOOH inventory allocation parameters. Sponsorship and takeover flat_rate options omit this field entirely — only include for digital out-of-home inventory.', title='DoohParameters', ), ] = None min_spend_per_package: Annotated[ float | None, Field( description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None price_breakdown: Annotated[ price_breakdown_1.PriceBreakdown | None, Field( description='Breakdown of how fixed_price was derived from the list (rate card) price. Only meaningful when fixed_price is present.' ), ] = None eligible_adjustments: Annotated[ list[adjustment_kind.PriceAdjustmentKind] | None, Field( description='Adjustment kinds applicable to this pricing option. Tells buyer agents which adjustments are available before negotiation. When absent, no adjustments are pre-declared — the buyer should check price_breakdown if present.' ), ] = 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 currency : strvar eligible_adjustments : list[adcp.types.generated_poc.enums.adjustment_kind.PriceAdjustmentKind] | Nonevar fixed_price : float | Nonevar floor_price : float | Nonevar min_spend_per_package : float | Nonevar model_configvar parameters : adcp.types.generated_poc.pricing_options.flat_rate_option.Parameters | Nonevar price_breakdown : adcp.types.generated_poc.pricing_options.price_breakdown.PriceBreakdown | Nonevar price_guidance : adcp.types.generated_poc.pricing_options.price_guidance.PriceGuidance | Nonevar pricing_model : Literal['flat_rate']var pricing_option_id : str
Inherited members
class GetBrandIdentityRequest (**data: Any)-
Expand source code
class GetBrandIdentityRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) brand_id: Annotated[str, Field(description='Brand identifier from brand.json brands array')] fields: Annotated[ list[FieldModel] | None, Field( description='Optional identity sections to include in the response. When omitted, all sections the caller is authorized to see are returned. Core fields (brand_id, house, names) are always returned and do not need to be requested.', min_length=1, ), ] = None use_case: Annotated[ str | None, Field( description="Intended use case, so the agent can tailor the response. A 'voice_synthesis' use case returns voice configs; a 'likeness' use case returns high-res photos and appearance guidelines." ), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var brand_id : strvar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar fields : list[adcp.types.generated_poc.brand.get_brand_identity_request.FieldModel] | Nonevar model_configvar use_case : str | None
Inherited members
class GetProductsInputRequiredResponse (**data: Any)-
Expand source code
class GetProductsInputRequired(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) reason: Annotated[ Reason | None, Field(description='Reason code indicating why input is needed') ] = None partial_results: Annotated[ list[product.Product] | None, Field(description='Partial product results that may help inform the clarification'), ] = None suggestions: Annotated[ list[str] | None, Field(description='Suggested values or options for the required input') ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = 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 context : adcp.types.generated_poc.core.context.ContextObject | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar model_configvar partial_results : list[adcp.types.generated_poc.core.product.Product] | Nonevar reason : adcp.types.generated_poc.core.async_response_refs.media_buy.get_products_async_response_input_required.Reason | Nonevar suggestions : list[str] | None
Inherited members
class GetProductsRequest (**data: Any)-
Expand source code
class GetProductsRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) buying_mode: Annotated[ BuyingMode, Field( description="Declares buyer intent for this request. 'brief': publisher curates product recommendations from the provided brief. 'wholesale': buyer requests raw product inventory to apply their own audiences — brief must not be provided, and proposals are omitted. 'refine': iterate on products and proposals from a previous get_products response using the refine array of change requests. v3 clients MUST include buying_mode. Sellers receiving requests from pre-v3 clients without buying_mode SHOULD default to 'brief'. Timing semantics: 'wholesale' is a wholesale product feed read — sellers SHOULD return a synchronous response and MUST NOT route a 'wholesale' request through the async/Submitted arm; partial completion is signalled via the response's incomplete[] field (with optional estimated_wait), not via a task-handoff envelope. 'brief' and 'refine' MAY complete synchronously, or MAY return a Submitted envelope (see get-products-async-response-submitted.json) when curation requires upstream-system queries or HITL review the seller cannot complete inside time_budget. Buyers needing predictable fast wholesale product feed access MUST use 'wholesale'; buyers open to slower curation use 'brief' or 'refine'." ), ] brief: Annotated[ str | None, Field( description="Natural language description of campaign requirements. Required when buying_mode is 'brief'. Must not be provided when buying_mode is 'wholesale' or 'refine'." ), ] = None refine: Annotated[ list[Refine] | None, Field( description="Array of change requests for iterating on products and proposals from a previous get_products response. Each entry declares a scope (request, product, or proposal) and what the buyer is asking for. Only valid when buying_mode is 'refine'. The seller responds to each entry via refinement_applied in the response, matched by position.\n\nFinalize-exclusivity rule: if any entry has `action: 'finalize'`, ALL entries in the array MUST be proposal-scoped with `action: 'finalize'` — mixing finalize entries with `include`/`omit` entries or with request- / product-scoped entries MUST be rejected by the seller with `INVALID_REQUEST`. Finalize is a commit, not a refinement; the buyer expressing intent to commit means refinements have already converged. Buyers needing to refine AND commit in close succession sequence the calls: first a refine call (no finalize), then a finalize call against the resulting `proposal_id`(s).\n\nMulti-finalize semantics: multiple finalize entries against different `proposal_id` values in a single call are allowed and MUST be **atomic at the observation point** — sellers MUST NOT return a success response unless every named proposal has both completed and been persisted as committed. Pre-commit validation runs before any side-effects (inventory pull, terms lock, governance attestation); if any proposal fails validation, the seller MUST reject the entire call without committing any of the named proposals. There is no rollback operation in the spec — an `unfinalize` would itself be a new mutation surface; the atomicity guarantee runs entirely on the seller's pre-commit validation gate, not on post-commit reversal. Sellers that cannot guarantee atomic pre-commit validation MUST reject multi-finalize arrays with `MULTI_FINALIZE_UNSUPPORTED` (preferred — distinguishes seller-side capability gap from a malformed request) or `INVALID_REQUEST` (acceptable fallback for sellers on a pre-3.1 error catalog). If a mid-commit failure occurs *after* validation passed but before all proposals persist (e.g., a downstream ad server fails between commits one and two), the seller MUST return `INTERNAL_ERROR` with `refinement_applied[]` carrying per-position outcomes — the spec does NOT define a recovery path for this case, and buyers SHOULD treat the resulting state as undefined and re-read via `get_media_buys` / equivalent before retrying. Buyers MUST NOT assume multi-finalize support without a successful first attempt — there is no capability flag for this; the failure response is the discovery surface. Buyers whose intent specifically requires atomic commit (e.g., budget-shared proposals where one finalizing without the other is incoherent) MUST be prepared to abandon the intent if the seller returns `MULTI_FINALIZE_UNSUPPORTED` — there is no recovery for that loss of buyer intent beyond sequencing single-finalize calls and accepting the looser commit guarantee.", min_length=1, ), ] = None brand: Annotated[ brand_ref.BrandReference | None, Field( description='Brand reference for product discovery context. Resolved to full brand identity at execution time.' ), ] = None catalog: Annotated[ catalog_1.Catalog | None, Field( description='Catalog of items the buyer wants to promote. The seller matches catalog items against its inventory and returns products where matches exist. Supports all catalog types: a job catalog finds job ad products, a product catalog finds sponsored product slots. Reference a synced catalog by catalog_id, or provide inline items.' ), ] = None account: Annotated[ account_ref.AccountReference | None, Field( description="Account for product lookup. Returns products with pricing specific to this account's rate card." ), ] = None preferred_delivery_types: Annotated[ list[delivery_type_1.DeliveryType] | None, Field( description='Delivery types the buyer prefers, in priority order. Unlike filters.delivery_type which excludes non-matching products, this signals preference for curation — the publisher may still include other delivery types when they match the brief well.', min_length=1, ), ] = None filters: product_filters.ProductFilters | None = None property_list: Annotated[ property_list_ref.PropertyListReference | None, Field( description='[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list.' ), ] = None fields: Annotated[ list[Field1] | None, Field( description='Specific product fields to include in the response. When omitted, all fields are returned. Use for lightweight discovery calls where only a subset of product data is needed (e.g., just IDs and pricing for comparison). Required fields (product_id, name) are always included regardless of selection.', min_length=1, ), ] = None time_budget: Annotated[ duration.Duration | None, Field( description='Maximum time the buyer will commit to this request. The seller returns the best results achievable within this budget and does not start processes (human approvals, expensive external queries) that cannot complete in time. When omitted, the seller decides timing.' ), ] = None push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( description='Optional webhook configuration for async terminal completion/failure notifications on curated discovery. Meaningful only for `buying_mode: "brief"` and `buying_mode: "refine"` requests that enter the async lifecycle. Submitted envelopes with `task_id` remain pollable through `get_task_status` (legacy `tasks/get`) whether or not this field is present. If a brief/refine request includes this field and the seller returns a Submitted envelope, the seller MUST deliver at least the terminal completion/failure notification to the configured URL; intermediate progress notifications are MAY. If the seller cannot honor the webhook channel, it MUST reject the request with a structured error instead of silently accepting. This field does not change wholesale timing semantics: sellers MUST NOT route `buying_mode: "wholesale"` requests through the async/Submitted arm or emit async delivery solely because `push_notification_config` is present; partial wholesale completion is reported via `incomplete[]`.' ), ] = None pagination: Annotated[ pagination_request.PaginationRequest | None, Field( description="Cursor-based pagination controls for get_products. Valid in all buying modes. In brief mode, pagination bounds the seller's returned products[] for the curated answer to the brief and is not an exhaustive catalog-enumeration contract. In refine mode, pagination bounds the refined products[] result implied by refine[] and filters; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope. In wholesale mode, pagination walks the wholesale product feed and may be combined with wholesale feed versioning." ), ] = None if_wholesale_feed_version: Annotated[ str | None, Field( description="Opaque wholesale_feed_version token returned by a prior wholesale-mode get_products response from this agent. Only valid when buying_mode is wholesale. When provided, the seller compares against its current wholesale product feed version for the buyer's cache_scope and MAY return an unchanged: true response (with products omitted) if nothing has changed. The token is scope-keyed: buyers cache `(cache_scope, wholesale_feed_version)` pairs. Scoping dimensions: (agent, buying_mode, filters, property_list, catalog) for cache_scope: 'public'; that tuple plus account_id for cache_scope: 'account'. pagination.cursor is NOT part of the scoping tuple. Backward-compatible: pre-v3.1 agents that ignore this field simply return the full payload, same as the unchanged-server path. See specs/wholesale-feed-webhooks.md for the full sync pattern." ), ] = None if_pricing_version: Annotated[ str | None, Field( description="Opaque pricing_version token from a prior get_products response. MUST only be sent together with if_wholesale_feed_version — pricing version has no structural baseline to compare against on its own. Evaluation order: (1) if_wholesale_feed_version mismatch → seller returns the full payload (pricing is implicitly stale); (2) if_wholesale_feed_version matches but if_pricing_version mismatches → seller returns the full payload so the buyer sees updated pricing_options; (3) both match → seller MAY return unchanged: true. Agents that don't track pricing separately ignore if_pricing_version and fall back to if_wholesale_feed_version semantics. Useful for storefronts that re-price compositions far more often than they re-render product mirrors." ), ] = None context: context_1.ContextObject | None = None required_policies: Annotated[ list[str] | None, Field( description='Registry policy IDs that the buyer requires to be enforced for products in this response. Sellers filter products to only those that comply with or already enforce the requested policies.' ), ] = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : adcp.types.generated_poc.core.account_ref.AccountReference | Nonevar brand : adcp.types.generated_poc.core.brand_ref.BrandReference | Nonevar brief : str | Nonevar buying_mode : adcp.types.generated_poc.media_buy.get_products_request.BuyingMode | Nonevar catalog : adcp.types.generated_poc.core.catalog.Catalog | Nonevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar fields : list[adcp.types.generated_poc.media_buy.get_products_request.Field1] | Nonevar filters : adcp.types.generated_poc.core.product_filters.ProductFilters | Nonevar if_pricing_version : str | Nonevar if_wholesale_feed_version : str | Nonevar model_configvar pagination : adcp.types.generated_poc.core.pagination_request.PaginationRequest | Nonevar preferred_delivery_types : list[adcp.types.generated_poc.enums.delivery_type.DeliveryType] | Nonevar property_list : adcp.types.generated_poc.core.property_list_ref.PropertyListReference | Nonevar push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | Nonevar refine : list[adcp.types.generated_poc.media_buy.get_products_request.Refine] | Nonevar required_policies : list[str] | Nonevar time_budget : adcp.types.generated_poc.core.duration.Duration | None
class GetProductsBriefRequest (**data: Any)-
Expand source code
class GetProductsRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) buying_mode: Annotated[ BuyingMode, Field( description="Declares buyer intent for this request. 'brief': publisher curates product recommendations from the provided brief. 'wholesale': buyer requests raw product inventory to apply their own audiences — brief must not be provided, and proposals are omitted. 'refine': iterate on products and proposals from a previous get_products response using the refine array of change requests. v3 clients MUST include buying_mode. Sellers receiving requests from pre-v3 clients without buying_mode SHOULD default to 'brief'. Timing semantics: 'wholesale' is a wholesale product feed read — sellers SHOULD return a synchronous response and MUST NOT route a 'wholesale' request through the async/Submitted arm; partial completion is signalled via the response's incomplete[] field (with optional estimated_wait), not via a task-handoff envelope. 'brief' and 'refine' MAY complete synchronously, or MAY return a Submitted envelope (see get-products-async-response-submitted.json) when curation requires upstream-system queries or HITL review the seller cannot complete inside time_budget. Buyers needing predictable fast wholesale product feed access MUST use 'wholesale'; buyers open to slower curation use 'brief' or 'refine'." ), ] brief: Annotated[ str | None, Field( description="Natural language description of campaign requirements. Required when buying_mode is 'brief'. Must not be provided when buying_mode is 'wholesale' or 'refine'." ), ] = None refine: Annotated[ list[Refine] | None, Field( description="Array of change requests for iterating on products and proposals from a previous get_products response. Each entry declares a scope (request, product, or proposal) and what the buyer is asking for. Only valid when buying_mode is 'refine'. The seller responds to each entry via refinement_applied in the response, matched by position.\n\nFinalize-exclusivity rule: if any entry has `action: 'finalize'`, ALL entries in the array MUST be proposal-scoped with `action: 'finalize'` — mixing finalize entries with `include`/`omit` entries or with request- / product-scoped entries MUST be rejected by the seller with `INVALID_REQUEST`. Finalize is a commit, not a refinement; the buyer expressing intent to commit means refinements have already converged. Buyers needing to refine AND commit in close succession sequence the calls: first a refine call (no finalize), then a finalize call against the resulting `proposal_id`(s).\n\nMulti-finalize semantics: multiple finalize entries against different `proposal_id` values in a single call are allowed and MUST be **atomic at the observation point** — sellers MUST NOT return a success response unless every named proposal has both completed and been persisted as committed. Pre-commit validation runs before any side-effects (inventory pull, terms lock, governance attestation); if any proposal fails validation, the seller MUST reject the entire call without committing any of the named proposals. There is no rollback operation in the spec — an `unfinalize` would itself be a new mutation surface; the atomicity guarantee runs entirely on the seller's pre-commit validation gate, not on post-commit reversal. Sellers that cannot guarantee atomic pre-commit validation MUST reject multi-finalize arrays with `MULTI_FINALIZE_UNSUPPORTED` (preferred — distinguishes seller-side capability gap from a malformed request) or `INVALID_REQUEST` (acceptable fallback for sellers on a pre-3.1 error catalog). If a mid-commit failure occurs *after* validation passed but before all proposals persist (e.g., a downstream ad server fails between commits one and two), the seller MUST return `INTERNAL_ERROR` with `refinement_applied[]` carrying per-position outcomes — the spec does NOT define a recovery path for this case, and buyers SHOULD treat the resulting state as undefined and re-read via `get_media_buys` / equivalent before retrying. Buyers MUST NOT assume multi-finalize support without a successful first attempt — there is no capability flag for this; the failure response is the discovery surface. Buyers whose intent specifically requires atomic commit (e.g., budget-shared proposals where one finalizing without the other is incoherent) MUST be prepared to abandon the intent if the seller returns `MULTI_FINALIZE_UNSUPPORTED` — there is no recovery for that loss of buyer intent beyond sequencing single-finalize calls and accepting the looser commit guarantee.", min_length=1, ), ] = None brand: Annotated[ brand_ref.BrandReference | None, Field( description='Brand reference for product discovery context. Resolved to full brand identity at execution time.' ), ] = None catalog: Annotated[ catalog_1.Catalog | None, Field( description='Catalog of items the buyer wants to promote. The seller matches catalog items against its inventory and returns products where matches exist. Supports all catalog types: a job catalog finds job ad products, a product catalog finds sponsored product slots. Reference a synced catalog by catalog_id, or provide inline items.' ), ] = None account: Annotated[ account_ref.AccountReference | None, Field( description="Account for product lookup. Returns products with pricing specific to this account's rate card." ), ] = None preferred_delivery_types: Annotated[ list[delivery_type_1.DeliveryType] | None, Field( description='Delivery types the buyer prefers, in priority order. Unlike filters.delivery_type which excludes non-matching products, this signals preference for curation — the publisher may still include other delivery types when they match the brief well.', min_length=1, ), ] = None filters: product_filters.ProductFilters | None = None property_list: Annotated[ property_list_ref.PropertyListReference | None, Field( description='[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list.' ), ] = None fields: Annotated[ list[Field1] | None, Field( description='Specific product fields to include in the response. When omitted, all fields are returned. Use for lightweight discovery calls where only a subset of product data is needed (e.g., just IDs and pricing for comparison). Required fields (product_id, name) are always included regardless of selection.', min_length=1, ), ] = None time_budget: Annotated[ duration.Duration | None, Field( description='Maximum time the buyer will commit to this request. The seller returns the best results achievable within this budget and does not start processes (human approvals, expensive external queries) that cannot complete in time. When omitted, the seller decides timing.' ), ] = None push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( description='Optional webhook configuration for async terminal completion/failure notifications on curated discovery. Meaningful only for `buying_mode: "brief"` and `buying_mode: "refine"` requests that enter the async lifecycle. Submitted envelopes with `task_id` remain pollable through `get_task_status` (legacy `tasks/get`) whether or not this field is present. If a brief/refine request includes this field and the seller returns a Submitted envelope, the seller MUST deliver at least the terminal completion/failure notification to the configured URL; intermediate progress notifications are MAY. If the seller cannot honor the webhook channel, it MUST reject the request with a structured error instead of silently accepting. This field does not change wholesale timing semantics: sellers MUST NOT route `buying_mode: "wholesale"` requests through the async/Submitted arm or emit async delivery solely because `push_notification_config` is present; partial wholesale completion is reported via `incomplete[]`.' ), ] = None pagination: Annotated[ pagination_request.PaginationRequest | None, Field( description="Cursor-based pagination controls for get_products. Valid in all buying modes. In brief mode, pagination bounds the seller's returned products[] for the curated answer to the brief and is not an exhaustive catalog-enumeration contract. In refine mode, pagination bounds the refined products[] result implied by refine[] and filters; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope. In wholesale mode, pagination walks the wholesale product feed and may be combined with wholesale feed versioning." ), ] = None if_wholesale_feed_version: Annotated[ str | None, Field( description="Opaque wholesale_feed_version token returned by a prior wholesale-mode get_products response from this agent. Only valid when buying_mode is wholesale. When provided, the seller compares against its current wholesale product feed version for the buyer's cache_scope and MAY return an unchanged: true response (with products omitted) if nothing has changed. The token is scope-keyed: buyers cache `(cache_scope, wholesale_feed_version)` pairs. Scoping dimensions: (agent, buying_mode, filters, property_list, catalog) for cache_scope: 'public'; that tuple plus account_id for cache_scope: 'account'. pagination.cursor is NOT part of the scoping tuple. Backward-compatible: pre-v3.1 agents that ignore this field simply return the full payload, same as the unchanged-server path. See specs/wholesale-feed-webhooks.md for the full sync pattern." ), ] = None if_pricing_version: Annotated[ str | None, Field( description="Opaque pricing_version token from a prior get_products response. MUST only be sent together with if_wholesale_feed_version — pricing version has no structural baseline to compare against on its own. Evaluation order: (1) if_wholesale_feed_version mismatch → seller returns the full payload (pricing is implicitly stale); (2) if_wholesale_feed_version matches but if_pricing_version mismatches → seller returns the full payload so the buyer sees updated pricing_options; (3) both match → seller MAY return unchanged: true. Agents that don't track pricing separately ignore if_pricing_version and fall back to if_wholesale_feed_version semantics. Useful for storefronts that re-price compositions far more often than they re-render product mirrors." ), ] = None context: context_1.ContextObject | None = None required_policies: Annotated[ list[str] | None, Field( description='Registry policy IDs that the buyer requires to be enforced for products in this response. Sellers filter products to only those that comply with or already enforce the requested policies.' ), ] = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : adcp.types.generated_poc.core.account_ref.AccountReference | Nonevar brand : adcp.types.generated_poc.core.brand_ref.BrandReference | Nonevar brief : str | Nonevar buying_mode : adcp.types.generated_poc.media_buy.get_products_request.BuyingMode | Nonevar catalog : adcp.types.generated_poc.core.catalog.Catalog | Nonevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar fields : list[adcp.types.generated_poc.media_buy.get_products_request.Field1] | Nonevar filters : adcp.types.generated_poc.core.product_filters.ProductFilters | Nonevar if_pricing_version : str | Nonevar if_wholesale_feed_version : str | Nonevar model_configvar pagination : adcp.types.generated_poc.core.pagination_request.PaginationRequest | Nonevar preferred_delivery_types : list[adcp.types.generated_poc.enums.delivery_type.DeliveryType] | Nonevar property_list : adcp.types.generated_poc.core.property_list_ref.PropertyListReference | Nonevar push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | Nonevar refine : list[adcp.types.generated_poc.media_buy.get_products_request.Refine] | Nonevar required_policies : list[str] | Nonevar time_budget : adcp.types.generated_poc.core.duration.Duration | None
class GetProductsRefineRequest (**data: Any)-
Expand source code
class GetProductsRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) buying_mode: Annotated[ BuyingMode, Field( description="Declares buyer intent for this request. 'brief': publisher curates product recommendations from the provided brief. 'wholesale': buyer requests raw product inventory to apply their own audiences — brief must not be provided, and proposals are omitted. 'refine': iterate on products and proposals from a previous get_products response using the refine array of change requests. v3 clients MUST include buying_mode. Sellers receiving requests from pre-v3 clients without buying_mode SHOULD default to 'brief'. Timing semantics: 'wholesale' is a wholesale product feed read — sellers SHOULD return a synchronous response and MUST NOT route a 'wholesale' request through the async/Submitted arm; partial completion is signalled via the response's incomplete[] field (with optional estimated_wait), not via a task-handoff envelope. 'brief' and 'refine' MAY complete synchronously, or MAY return a Submitted envelope (see get-products-async-response-submitted.json) when curation requires upstream-system queries or HITL review the seller cannot complete inside time_budget. Buyers needing predictable fast wholesale product feed access MUST use 'wholesale'; buyers open to slower curation use 'brief' or 'refine'." ), ] brief: Annotated[ str | None, Field( description="Natural language description of campaign requirements. Required when buying_mode is 'brief'. Must not be provided when buying_mode is 'wholesale' or 'refine'." ), ] = None refine: Annotated[ list[Refine] | None, Field( description="Array of change requests for iterating on products and proposals from a previous get_products response. Each entry declares a scope (request, product, or proposal) and what the buyer is asking for. Only valid when buying_mode is 'refine'. The seller responds to each entry via refinement_applied in the response, matched by position.\n\nFinalize-exclusivity rule: if any entry has `action: 'finalize'`, ALL entries in the array MUST be proposal-scoped with `action: 'finalize'` — mixing finalize entries with `include`/`omit` entries or with request- / product-scoped entries MUST be rejected by the seller with `INVALID_REQUEST`. Finalize is a commit, not a refinement; the buyer expressing intent to commit means refinements have already converged. Buyers needing to refine AND commit in close succession sequence the calls: first a refine call (no finalize), then a finalize call against the resulting `proposal_id`(s).\n\nMulti-finalize semantics: multiple finalize entries against different `proposal_id` values in a single call are allowed and MUST be **atomic at the observation point** — sellers MUST NOT return a success response unless every named proposal has both completed and been persisted as committed. Pre-commit validation runs before any side-effects (inventory pull, terms lock, governance attestation); if any proposal fails validation, the seller MUST reject the entire call without committing any of the named proposals. There is no rollback operation in the spec — an `unfinalize` would itself be a new mutation surface; the atomicity guarantee runs entirely on the seller's pre-commit validation gate, not on post-commit reversal. Sellers that cannot guarantee atomic pre-commit validation MUST reject multi-finalize arrays with `MULTI_FINALIZE_UNSUPPORTED` (preferred — distinguishes seller-side capability gap from a malformed request) or `INVALID_REQUEST` (acceptable fallback for sellers on a pre-3.1 error catalog). If a mid-commit failure occurs *after* validation passed but before all proposals persist (e.g., a downstream ad server fails between commits one and two), the seller MUST return `INTERNAL_ERROR` with `refinement_applied[]` carrying per-position outcomes — the spec does NOT define a recovery path for this case, and buyers SHOULD treat the resulting state as undefined and re-read via `get_media_buys` / equivalent before retrying. Buyers MUST NOT assume multi-finalize support without a successful first attempt — there is no capability flag for this; the failure response is the discovery surface. Buyers whose intent specifically requires atomic commit (e.g., budget-shared proposals where one finalizing without the other is incoherent) MUST be prepared to abandon the intent if the seller returns `MULTI_FINALIZE_UNSUPPORTED` — there is no recovery for that loss of buyer intent beyond sequencing single-finalize calls and accepting the looser commit guarantee.", min_length=1, ), ] = None brand: Annotated[ brand_ref.BrandReference | None, Field( description='Brand reference for product discovery context. Resolved to full brand identity at execution time.' ), ] = None catalog: Annotated[ catalog_1.Catalog | None, Field( description='Catalog of items the buyer wants to promote. The seller matches catalog items against its inventory and returns products where matches exist. Supports all catalog types: a job catalog finds job ad products, a product catalog finds sponsored product slots. Reference a synced catalog by catalog_id, or provide inline items.' ), ] = None account: Annotated[ account_ref.AccountReference | None, Field( description="Account for product lookup. Returns products with pricing specific to this account's rate card." ), ] = None preferred_delivery_types: Annotated[ list[delivery_type_1.DeliveryType] | None, Field( description='Delivery types the buyer prefers, in priority order. Unlike filters.delivery_type which excludes non-matching products, this signals preference for curation — the publisher may still include other delivery types when they match the brief well.', min_length=1, ), ] = None filters: product_filters.ProductFilters | None = None property_list: Annotated[ property_list_ref.PropertyListReference | None, Field( description='[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list.' ), ] = None fields: Annotated[ list[Field1] | None, Field( description='Specific product fields to include in the response. When omitted, all fields are returned. Use for lightweight discovery calls where only a subset of product data is needed (e.g., just IDs and pricing for comparison). Required fields (product_id, name) are always included regardless of selection.', min_length=1, ), ] = None time_budget: Annotated[ duration.Duration | None, Field( description='Maximum time the buyer will commit to this request. The seller returns the best results achievable within this budget and does not start processes (human approvals, expensive external queries) that cannot complete in time. When omitted, the seller decides timing.' ), ] = None push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( description='Optional webhook configuration for async terminal completion/failure notifications on curated discovery. Meaningful only for `buying_mode: "brief"` and `buying_mode: "refine"` requests that enter the async lifecycle. Submitted envelopes with `task_id` remain pollable through `get_task_status` (legacy `tasks/get`) whether or not this field is present. If a brief/refine request includes this field and the seller returns a Submitted envelope, the seller MUST deliver at least the terminal completion/failure notification to the configured URL; intermediate progress notifications are MAY. If the seller cannot honor the webhook channel, it MUST reject the request with a structured error instead of silently accepting. This field does not change wholesale timing semantics: sellers MUST NOT route `buying_mode: "wholesale"` requests through the async/Submitted arm or emit async delivery solely because `push_notification_config` is present; partial wholesale completion is reported via `incomplete[]`.' ), ] = None pagination: Annotated[ pagination_request.PaginationRequest | None, Field( description="Cursor-based pagination controls for get_products. Valid in all buying modes. In brief mode, pagination bounds the seller's returned products[] for the curated answer to the brief and is not an exhaustive catalog-enumeration contract. In refine mode, pagination bounds the refined products[] result implied by refine[] and filters; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope. In wholesale mode, pagination walks the wholesale product feed and may be combined with wholesale feed versioning." ), ] = None if_wholesale_feed_version: Annotated[ str | None, Field( description="Opaque wholesale_feed_version token returned by a prior wholesale-mode get_products response from this agent. Only valid when buying_mode is wholesale. When provided, the seller compares against its current wholesale product feed version for the buyer's cache_scope and MAY return an unchanged: true response (with products omitted) if nothing has changed. The token is scope-keyed: buyers cache `(cache_scope, wholesale_feed_version)` pairs. Scoping dimensions: (agent, buying_mode, filters, property_list, catalog) for cache_scope: 'public'; that tuple plus account_id for cache_scope: 'account'. pagination.cursor is NOT part of the scoping tuple. Backward-compatible: pre-v3.1 agents that ignore this field simply return the full payload, same as the unchanged-server path. See specs/wholesale-feed-webhooks.md for the full sync pattern." ), ] = None if_pricing_version: Annotated[ str | None, Field( description="Opaque pricing_version token from a prior get_products response. MUST only be sent together with if_wholesale_feed_version — pricing version has no structural baseline to compare against on its own. Evaluation order: (1) if_wholesale_feed_version mismatch → seller returns the full payload (pricing is implicitly stale); (2) if_wholesale_feed_version matches but if_pricing_version mismatches → seller returns the full payload so the buyer sees updated pricing_options; (3) both match → seller MAY return unchanged: true. Agents that don't track pricing separately ignore if_pricing_version and fall back to if_wholesale_feed_version semantics. Useful for storefronts that re-price compositions far more often than they re-render product mirrors." ), ] = None context: context_1.ContextObject | None = None required_policies: Annotated[ list[str] | None, Field( description='Registry policy IDs that the buyer requires to be enforced for products in this response. Sellers filter products to only those that comply with or already enforce the requested policies.' ), ] = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : adcp.types.generated_poc.core.account_ref.AccountReference | Nonevar brand : adcp.types.generated_poc.core.brand_ref.BrandReference | Nonevar brief : str | Nonevar buying_mode : adcp.types.generated_poc.media_buy.get_products_request.BuyingMode | Nonevar catalog : adcp.types.generated_poc.core.catalog.Catalog | Nonevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar fields : list[adcp.types.generated_poc.media_buy.get_products_request.Field1] | Nonevar filters : adcp.types.generated_poc.core.product_filters.ProductFilters | Nonevar if_pricing_version : str | Nonevar if_wholesale_feed_version : str | Nonevar model_configvar pagination : adcp.types.generated_poc.core.pagination_request.PaginationRequest | Nonevar preferred_delivery_types : list[adcp.types.generated_poc.enums.delivery_type.DeliveryType] | Nonevar property_list : adcp.types.generated_poc.core.property_list_ref.PropertyListReference | Nonevar push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | Nonevar refine : list[adcp.types.generated_poc.media_buy.get_products_request.Refine] | Nonevar required_policies : list[str] | Nonevar time_budget : adcp.types.generated_poc.core.duration.Duration | None
class GetProductsWholesaleRequest (**data: Any)-
Expand source code
class GetProductsRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) buying_mode: Annotated[ BuyingMode, Field( description="Declares buyer intent for this request. 'brief': publisher curates product recommendations from the provided brief. 'wholesale': buyer requests raw product inventory to apply their own audiences — brief must not be provided, and proposals are omitted. 'refine': iterate on products and proposals from a previous get_products response using the refine array of change requests. v3 clients MUST include buying_mode. Sellers receiving requests from pre-v3 clients without buying_mode SHOULD default to 'brief'. Timing semantics: 'wholesale' is a wholesale product feed read — sellers SHOULD return a synchronous response and MUST NOT route a 'wholesale' request through the async/Submitted arm; partial completion is signalled via the response's incomplete[] field (with optional estimated_wait), not via a task-handoff envelope. 'brief' and 'refine' MAY complete synchronously, or MAY return a Submitted envelope (see get-products-async-response-submitted.json) when curation requires upstream-system queries or HITL review the seller cannot complete inside time_budget. Buyers needing predictable fast wholesale product feed access MUST use 'wholesale'; buyers open to slower curation use 'brief' or 'refine'." ), ] brief: Annotated[ str | None, Field( description="Natural language description of campaign requirements. Required when buying_mode is 'brief'. Must not be provided when buying_mode is 'wholesale' or 'refine'." ), ] = None refine: Annotated[ list[Refine] | None, Field( description="Array of change requests for iterating on products and proposals from a previous get_products response. Each entry declares a scope (request, product, or proposal) and what the buyer is asking for. Only valid when buying_mode is 'refine'. The seller responds to each entry via refinement_applied in the response, matched by position.\n\nFinalize-exclusivity rule: if any entry has `action: 'finalize'`, ALL entries in the array MUST be proposal-scoped with `action: 'finalize'` — mixing finalize entries with `include`/`omit` entries or with request- / product-scoped entries MUST be rejected by the seller with `INVALID_REQUEST`. Finalize is a commit, not a refinement; the buyer expressing intent to commit means refinements have already converged. Buyers needing to refine AND commit in close succession sequence the calls: first a refine call (no finalize), then a finalize call against the resulting `proposal_id`(s).\n\nMulti-finalize semantics: multiple finalize entries against different `proposal_id` values in a single call are allowed and MUST be **atomic at the observation point** — sellers MUST NOT return a success response unless every named proposal has both completed and been persisted as committed. Pre-commit validation runs before any side-effects (inventory pull, terms lock, governance attestation); if any proposal fails validation, the seller MUST reject the entire call without committing any of the named proposals. There is no rollback operation in the spec — an `unfinalize` would itself be a new mutation surface; the atomicity guarantee runs entirely on the seller's pre-commit validation gate, not on post-commit reversal. Sellers that cannot guarantee atomic pre-commit validation MUST reject multi-finalize arrays with `MULTI_FINALIZE_UNSUPPORTED` (preferred — distinguishes seller-side capability gap from a malformed request) or `INVALID_REQUEST` (acceptable fallback for sellers on a pre-3.1 error catalog). If a mid-commit failure occurs *after* validation passed but before all proposals persist (e.g., a downstream ad server fails between commits one and two), the seller MUST return `INTERNAL_ERROR` with `refinement_applied[]` carrying per-position outcomes — the spec does NOT define a recovery path for this case, and buyers SHOULD treat the resulting state as undefined and re-read via `get_media_buys` / equivalent before retrying. Buyers MUST NOT assume multi-finalize support without a successful first attempt — there is no capability flag for this; the failure response is the discovery surface. Buyers whose intent specifically requires atomic commit (e.g., budget-shared proposals where one finalizing without the other is incoherent) MUST be prepared to abandon the intent if the seller returns `MULTI_FINALIZE_UNSUPPORTED` — there is no recovery for that loss of buyer intent beyond sequencing single-finalize calls and accepting the looser commit guarantee.", min_length=1, ), ] = None brand: Annotated[ brand_ref.BrandReference | None, Field( description='Brand reference for product discovery context. Resolved to full brand identity at execution time.' ), ] = None catalog: Annotated[ catalog_1.Catalog | None, Field( description='Catalog of items the buyer wants to promote. The seller matches catalog items against its inventory and returns products where matches exist. Supports all catalog types: a job catalog finds job ad products, a product catalog finds sponsored product slots. Reference a synced catalog by catalog_id, or provide inline items.' ), ] = None account: Annotated[ account_ref.AccountReference | None, Field( description="Account for product lookup. Returns products with pricing specific to this account's rate card." ), ] = None preferred_delivery_types: Annotated[ list[delivery_type_1.DeliveryType] | None, Field( description='Delivery types the buyer prefers, in priority order. Unlike filters.delivery_type which excludes non-matching products, this signals preference for curation — the publisher may still include other delivery types when they match the brief well.', min_length=1, ), ] = None filters: product_filters.ProductFilters | None = None property_list: Annotated[ property_list_ref.PropertyListReference | None, Field( description='[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list.' ), ] = None fields: Annotated[ list[Field1] | None, Field( description='Specific product fields to include in the response. When omitted, all fields are returned. Use for lightweight discovery calls where only a subset of product data is needed (e.g., just IDs and pricing for comparison). Required fields (product_id, name) are always included regardless of selection.', min_length=1, ), ] = None time_budget: Annotated[ duration.Duration | None, Field( description='Maximum time the buyer will commit to this request. The seller returns the best results achievable within this budget and does not start processes (human approvals, expensive external queries) that cannot complete in time. When omitted, the seller decides timing.' ), ] = None push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( description='Optional webhook configuration for async terminal completion/failure notifications on curated discovery. Meaningful only for `buying_mode: "brief"` and `buying_mode: "refine"` requests that enter the async lifecycle. Submitted envelopes with `task_id` remain pollable through `get_task_status` (legacy `tasks/get`) whether or not this field is present. If a brief/refine request includes this field and the seller returns a Submitted envelope, the seller MUST deliver at least the terminal completion/failure notification to the configured URL; intermediate progress notifications are MAY. If the seller cannot honor the webhook channel, it MUST reject the request with a structured error instead of silently accepting. This field does not change wholesale timing semantics: sellers MUST NOT route `buying_mode: "wholesale"` requests through the async/Submitted arm or emit async delivery solely because `push_notification_config` is present; partial wholesale completion is reported via `incomplete[]`.' ), ] = None pagination: Annotated[ pagination_request.PaginationRequest | None, Field( description="Cursor-based pagination controls for get_products. Valid in all buying modes. In brief mode, pagination bounds the seller's returned products[] for the curated answer to the brief and is not an exhaustive catalog-enumeration contract. In refine mode, pagination bounds the refined products[] result implied by refine[] and filters; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope. In wholesale mode, pagination walks the wholesale product feed and may be combined with wholesale feed versioning." ), ] = None if_wholesale_feed_version: Annotated[ str | None, Field( description="Opaque wholesale_feed_version token returned by a prior wholesale-mode get_products response from this agent. Only valid when buying_mode is wholesale. When provided, the seller compares against its current wholesale product feed version for the buyer's cache_scope and MAY return an unchanged: true response (with products omitted) if nothing has changed. The token is scope-keyed: buyers cache `(cache_scope, wholesale_feed_version)` pairs. Scoping dimensions: (agent, buying_mode, filters, property_list, catalog) for cache_scope: 'public'; that tuple plus account_id for cache_scope: 'account'. pagination.cursor is NOT part of the scoping tuple. Backward-compatible: pre-v3.1 agents that ignore this field simply return the full payload, same as the unchanged-server path. See specs/wholesale-feed-webhooks.md for the full sync pattern." ), ] = None if_pricing_version: Annotated[ str | None, Field( description="Opaque pricing_version token from a prior get_products response. MUST only be sent together with if_wholesale_feed_version — pricing version has no structural baseline to compare against on its own. Evaluation order: (1) if_wholesale_feed_version mismatch → seller returns the full payload (pricing is implicitly stale); (2) if_wholesale_feed_version matches but if_pricing_version mismatches → seller returns the full payload so the buyer sees updated pricing_options; (3) both match → seller MAY return unchanged: true. Agents that don't track pricing separately ignore if_pricing_version and fall back to if_wholesale_feed_version semantics. Useful for storefronts that re-price compositions far more often than they re-render product mirrors." ), ] = None context: context_1.ContextObject | None = None required_policies: Annotated[ list[str] | None, Field( description='Registry policy IDs that the buyer requires to be enforced for products in this response. Sellers filter products to only those that comply with or already enforce the requested policies.' ), ] = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : adcp.types.generated_poc.core.account_ref.AccountReference | Nonevar brand : adcp.types.generated_poc.core.brand_ref.BrandReference | Nonevar brief : str | Nonevar buying_mode : adcp.types.generated_poc.media_buy.get_products_request.BuyingMode | Nonevar catalog : adcp.types.generated_poc.core.catalog.Catalog | Nonevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar fields : list[adcp.types.generated_poc.media_buy.get_products_request.Field1] | Nonevar filters : adcp.types.generated_poc.core.product_filters.ProductFilters | Nonevar if_pricing_version : str | Nonevar if_wholesale_feed_version : str | Nonevar model_configvar pagination : adcp.types.generated_poc.core.pagination_request.PaginationRequest | Nonevar preferred_delivery_types : list[adcp.types.generated_poc.enums.delivery_type.DeliveryType] | Nonevar property_list : adcp.types.generated_poc.core.property_list_ref.PropertyListReference | Nonevar push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | Nonevar refine : list[adcp.types.generated_poc.media_buy.get_products_request.Refine] | Nonevar required_policies : list[str] | Nonevar time_budget : adcp.types.generated_poc.core.duration.Duration | None
Inherited members
class GetProductsResponse (**data: Any)-
Expand source code
class GetProductsResponse(AdcpVersionEnvelope, ProtocolEnvelope): model_config = ConfigDict( extra='allow', ) products: Annotated[ list[product.Product] | None, Field(description='Array of matching products') ] = None extensions: Annotated[ dict[Annotated[str, StringConstraints(pattern=r'^https?://[^@]+@sha256:[a-f0-9]{64}$')], Extensions] | None, Field( description='Bundled platform-extension definitions referenced by any product in `products`. Keyed by `<extension_uri>@<digest>` (e.g., `https://creative.adcontextprotocol.org/translated/meta/extensions/meta_pixel@sha256:abc...`). When present, lets buyers resolve `platform_extensions` references on product format declarations without a separate fetch. Buyer SDKs cache by URI@digest; subsequent get_products responses MAY omit definitions the buyer already has cached and rely on the digest match. Each value is an extension definition with `extends` (the canonical concept it extends, e.g., `tracking`), `fields` (the schema for additional fields the extension contributes), `version`, and optional `description`.' ), ] = None proposals: Annotated[ list[proposal.Proposal] | None, Field( description='Optional array of proposed media plans with budget allocations across products. Publishers include proposals when they can provide strategic guidance based on the brief. Proposals are actionable - buyers can refine them via follow-up get_products calls within the same session, or execute them directly via create_media_buy.' ), ] = None errors: Annotated[ list[error.Error] | None, Field(description='Task-specific errors and warnings (e.g., product filtering issues)'), ] = None property_list_applied: Annotated[ bool | None, Field( description='[AdCP 3.0] Indicates whether property_list filtering was applied. True if the agent filtered products based on the provided property_list. Absent or false if property_list was not provided or not supported by this agent.' ), ] = None catalog_applied: Annotated[ bool | None, Field( description='Whether the seller filtered results based on the provided catalog. True if the seller matched catalog items against its inventory. Absent or false if no catalog was provided or the seller does not support catalog matching.' ), ] = None refinement_applied: Annotated[ list[RefinementApplied] | None, Field( description="Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'. Each entry MUST echo the request entry's scope and — for product and proposal scopes — the matching id field (product_id or proposal_id), so orchestrators can cross-validate alignment." ), ] = None incomplete: Annotated[ list[IncompleteItem] | None, Field( description="Declares what the seller could not finish within the buyer's time_budget or due to internal limits. Each entry identifies a scope that is missing or partial. Absent when the response is fully complete.", min_length=1, ), ] = None filter_diagnostics: Annotated[ FilterDiagnostics | None, Field( description="Optional non-fatal diagnostic block describing how the request's `filters` narrowed the candidate set. Use this to disambiguate empty/small result lists between 'no inventory matches the brief' and 'a specific filter excluded everything', without breaking the filter-not-fail convention (sellers still silently exclude unmatched products; this block is observability, not error reporting). Sellers MAY populate this when meaningful narrowing occurred; buyers MAY use it for triage UX without depending on its presence. Counts only — products are not enumerated by name to avoid leaking competitive intelligence about adjacent campaigns or seller inventory. `total_candidates` and `excluded_by` are independently optional — sellers whose baseline candidate set size is sensitive MAY emit `excluded_by` without `total_candidates`, or vice versa.", examples=[ { 'semantics': 'only', 'total_candidates': 47, 'excluded_by': { 'required_metrics': {'count': 31, 'values': ['completed_views']}, 'required_geo_targeting': {'count': 9}, 'pricing_currencies': {'count': 3, 'values': ['USD']}, 'budget_range': {'count': 7}, }, } ], ), ] = None pagination: Annotated[ pagination_response.PaginationResponse | None, Field( description="Cursor metadata for paginated get_products responses. In brief/refine mode, continuation pages bound returned products[] for the seller's curated or refined answer; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope, and pagination does not convert the response into an exhaustive feed contract. In wholesale mode, continuation pages walk the wholesale product feed." ), ] = None wholesale_feed_version: Annotated[ str | None, Field( description="Opaque token representing the version of the wholesale product feed state used to compose this response. Sellers that implement conditional-fetch (if_wholesale_feed_version) MUST return this on every wholesale-mode response so buyers can cache and probe later. Buyers MUST treat the value as opaque — no format, no ordering, no inspection. The token is scope-keyed: it describes a version for the cache_scope declared on this response, NOT a global agent version. A buyer caches `(cache_scope, wholesale_feed_version)` pairs and presents the matching token on the next request. Scoping dimensions: (agent, buying_mode, filters, property_list, catalog) for cache_scope: 'public'; that tuple plus account_id for cache_scope: 'account'. pagination.cursor is NOT part of the scoping tuple. See specs/wholesale-feed-webhooks.md for the full cache layering model." ), ] = None pricing_version: Annotated[ str | None, Field( description='Opaque token representing the version of the pricing layer, including product pricing_options and nested signal_targeting_options pricing_options. When the seller supports independent pricing versioning, pricing_version changes when prices move but wholesale_feed_version changes only when structure/metadata moves. Same cache_scope keying as wholesale_feed_version. Sellers not separating these MAY omit pricing_version and use wholesale_feed_version for both.' ), ] = None cache_scope: Annotated[ CacheScope | None, Field( description="Declares whether the wholesale_feed_version and pricing_version on this response describe a universal layer or an account-specific overlay. REQUIRED on every 3.1+ response (the 3.1 schema enforces this — the safety property of the two-layer cache model depends on it). 'public': this response describes the seller's published rate card; the buyer MAY dedupe under (agent, buying_mode, filters, property_list, catalog) without scoping by account. 'account': this response includes account-specific overrides; the buyer MUST cache the version under (agent, buying_mode, filters, property_list, catalog, account_id). When the request did NOT include `account`, the seller MUST return `cache_scope: 'public'`. When the request included `account`, the seller MUST return either: 'public' (this account prices off the public rate card — buyer dedupes) or 'account' (account-specific overrides exist — buyer caches under the account key). Sellers MAY return 'public' on an account-scoped request that previously had overrides — buyers SHOULD interpret this as a downgrade and drop their account-overlay for the (agent, filters, mode) tuple. Without schema-required cache_scope, a seller silently omitting the field on an account-scoped response would cause buyers to mis-key the cache and serve account-overlay payloads to other accounts — the canonical safety invariant of the entire cache layering model. **Backward-compatibility note for 3.1 validators:** SDKs that validate strictly against the 3.1 schema MUST select the validator based on the server-declared `adcp_version` (release-precision version negotiation, 3.1). For responses with `adcp_version` starting `3.0`, the 3.1 cache_scope-required constraint MUST be relaxed — pre-3.1 sellers correctly emit no cache_scope and remain conformant to their declared version. This is a tightening within 3.1, not a 3.0 break." ), ] = CacheScope.public unchanged: Annotated[ Literal[True] | None, Field( description="Present and `true` ONLY on wholesale-mode responses when the request carried if_wholesale_feed_version (and/or if_pricing_version) matching the seller's current version for the buyer's cache_scope, in which case products[] MUST be omitted; wholesale_feed_version (echoed), cache_scope (echoed), and pricing_version (echoed when used) MUST still be present. Buyers receiving unchanged: true MUST NOT mutate their local wholesale product mirror. **One shape per state:** sellers MUST NOT emit `unchanged: false` — the absence of the field IS the signal that the response carries products. Two shapes ({ unchanged: false, products: [...] } vs. { products: [...] }) for the same state would let some sellers always emit the field and some never would, creating an inconsistency the wire shouldn't carry." ), ] = None sandbox: Annotated[ bool | None, Field(description='When true, this response contains simulated data from sandbox mode.'), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- adcp.types.generated_poc.core.protocol_envelope.ProtocolEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var cache_scope : adcp.types.generated_poc.media_buy.get_products_response.CacheScope | Nonevar catalog_applied : bool | Nonevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar errors : list[adcp.types.generated_poc.core.error.Error] | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar extensions : dict[str, adcp.types.generated_poc.media_buy.get_products_response.Extensions] | Nonevar filter_diagnostics : adcp.types.generated_poc.media_buy.get_products_response.FilterDiagnostics | Nonevar incomplete : list[adcp.types.generated_poc.media_buy.get_products_response.IncompleteItem] | Nonevar model_configvar pagination : adcp.types.generated_poc.core.pagination_response.PaginationResponse | Nonevar pricing_version : str | Nonevar products : list[adcp.types.generated_poc.core.product.Product] | Nonevar property_list_applied : bool | Nonevar proposals : list[adcp.types.generated_poc.core.proposal.Proposal] | Nonevar refinement_applied : list[adcp.types.generated_poc.media_buy.get_products_response.RefinementApplied] | Nonevar sandbox : bool | Nonevar status : adcp.types.generated_poc.enums.task_status.TaskStatus | Nonevar unchanged : Literal[True] | Nonevar wholesale_feed_version : str | None
class GetProductsSuccessResponse (**data: Any)-
Expand source code
class GetProductsResponse(AdcpVersionEnvelope, ProtocolEnvelope): model_config = ConfigDict( extra='allow', ) products: Annotated[ list[product.Product] | None, Field(description='Array of matching products') ] = None extensions: Annotated[ dict[Annotated[str, StringConstraints(pattern=r'^https?://[^@]+@sha256:[a-f0-9]{64}$')], Extensions] | None, Field( description='Bundled platform-extension definitions referenced by any product in `products`. Keyed by `<extension_uri>@<digest>` (e.g., `https://creative.adcontextprotocol.org/translated/meta/extensions/meta_pixel@sha256:abc...`). When present, lets buyers resolve `platform_extensions` references on product format declarations without a separate fetch. Buyer SDKs cache by URI@digest; subsequent get_products responses MAY omit definitions the buyer already has cached and rely on the digest match. Each value is an extension definition with `extends` (the canonical concept it extends, e.g., `tracking`), `fields` (the schema for additional fields the extension contributes), `version`, and optional `description`.' ), ] = None proposals: Annotated[ list[proposal.Proposal] | None, Field( description='Optional array of proposed media plans with budget allocations across products. Publishers include proposals when they can provide strategic guidance based on the brief. Proposals are actionable - buyers can refine them via follow-up get_products calls within the same session, or execute them directly via create_media_buy.' ), ] = None errors: Annotated[ list[error.Error] | None, Field(description='Task-specific errors and warnings (e.g., product filtering issues)'), ] = None property_list_applied: Annotated[ bool | None, Field( description='[AdCP 3.0] Indicates whether property_list filtering was applied. True if the agent filtered products based on the provided property_list. Absent or false if property_list was not provided or not supported by this agent.' ), ] = None catalog_applied: Annotated[ bool | None, Field( description='Whether the seller filtered results based on the provided catalog. True if the seller matched catalog items against its inventory. Absent or false if no catalog was provided or the seller does not support catalog matching.' ), ] = None refinement_applied: Annotated[ list[RefinementApplied] | None, Field( description="Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'. Each entry MUST echo the request entry's scope and — for product and proposal scopes — the matching id field (product_id or proposal_id), so orchestrators can cross-validate alignment." ), ] = None incomplete: Annotated[ list[IncompleteItem] | None, Field( description="Declares what the seller could not finish within the buyer's time_budget or due to internal limits. Each entry identifies a scope that is missing or partial. Absent when the response is fully complete.", min_length=1, ), ] = None filter_diagnostics: Annotated[ FilterDiagnostics | None, Field( description="Optional non-fatal diagnostic block describing how the request's `filters` narrowed the candidate set. Use this to disambiguate empty/small result lists between 'no inventory matches the brief' and 'a specific filter excluded everything', without breaking the filter-not-fail convention (sellers still silently exclude unmatched products; this block is observability, not error reporting). Sellers MAY populate this when meaningful narrowing occurred; buyers MAY use it for triage UX without depending on its presence. Counts only — products are not enumerated by name to avoid leaking competitive intelligence about adjacent campaigns or seller inventory. `total_candidates` and `excluded_by` are independently optional — sellers whose baseline candidate set size is sensitive MAY emit `excluded_by` without `total_candidates`, or vice versa.", examples=[ { 'semantics': 'only', 'total_candidates': 47, 'excluded_by': { 'required_metrics': {'count': 31, 'values': ['completed_views']}, 'required_geo_targeting': {'count': 9}, 'pricing_currencies': {'count': 3, 'values': ['USD']}, 'budget_range': {'count': 7}, }, } ], ), ] = None pagination: Annotated[ pagination_response.PaginationResponse | None, Field( description="Cursor metadata for paginated get_products responses. In brief/refine mode, continuation pages bound returned products[] for the seller's curated or refined answer; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope, and pagination does not convert the response into an exhaustive feed contract. In wholesale mode, continuation pages walk the wholesale product feed." ), ] = None wholesale_feed_version: Annotated[ str | None, Field( description="Opaque token representing the version of the wholesale product feed state used to compose this response. Sellers that implement conditional-fetch (if_wholesale_feed_version) MUST return this on every wholesale-mode response so buyers can cache and probe later. Buyers MUST treat the value as opaque — no format, no ordering, no inspection. The token is scope-keyed: it describes a version for the cache_scope declared on this response, NOT a global agent version. A buyer caches `(cache_scope, wholesale_feed_version)` pairs and presents the matching token on the next request. Scoping dimensions: (agent, buying_mode, filters, property_list, catalog) for cache_scope: 'public'; that tuple plus account_id for cache_scope: 'account'. pagination.cursor is NOT part of the scoping tuple. See specs/wholesale-feed-webhooks.md for the full cache layering model." ), ] = None pricing_version: Annotated[ str | None, Field( description='Opaque token representing the version of the pricing layer, including product pricing_options and nested signal_targeting_options pricing_options. When the seller supports independent pricing versioning, pricing_version changes when prices move but wholesale_feed_version changes only when structure/metadata moves. Same cache_scope keying as wholesale_feed_version. Sellers not separating these MAY omit pricing_version and use wholesale_feed_version for both.' ), ] = None cache_scope: Annotated[ CacheScope | None, Field( description="Declares whether the wholesale_feed_version and pricing_version on this response describe a universal layer or an account-specific overlay. REQUIRED on every 3.1+ response (the 3.1 schema enforces this — the safety property of the two-layer cache model depends on it). 'public': this response describes the seller's published rate card; the buyer MAY dedupe under (agent, buying_mode, filters, property_list, catalog) without scoping by account. 'account': this response includes account-specific overrides; the buyer MUST cache the version under (agent, buying_mode, filters, property_list, catalog, account_id). When the request did NOT include `account`, the seller MUST return `cache_scope: 'public'`. When the request included `account`, the seller MUST return either: 'public' (this account prices off the public rate card — buyer dedupes) or 'account' (account-specific overrides exist — buyer caches under the account key). Sellers MAY return 'public' on an account-scoped request that previously had overrides — buyers SHOULD interpret this as a downgrade and drop their account-overlay for the (agent, filters, mode) tuple. Without schema-required cache_scope, a seller silently omitting the field on an account-scoped response would cause buyers to mis-key the cache and serve account-overlay payloads to other accounts — the canonical safety invariant of the entire cache layering model. **Backward-compatibility note for 3.1 validators:** SDKs that validate strictly against the 3.1 schema MUST select the validator based on the server-declared `adcp_version` (release-precision version negotiation, 3.1). For responses with `adcp_version` starting `3.0`, the 3.1 cache_scope-required constraint MUST be relaxed — pre-3.1 sellers correctly emit no cache_scope and remain conformant to their declared version. This is a tightening within 3.1, not a 3.0 break." ), ] = CacheScope.public unchanged: Annotated[ Literal[True] | None, Field( description="Present and `true` ONLY on wholesale-mode responses when the request carried if_wholesale_feed_version (and/or if_pricing_version) matching the seller's current version for the buyer's cache_scope, in which case products[] MUST be omitted; wholesale_feed_version (echoed), cache_scope (echoed), and pricing_version (echoed when used) MUST still be present. Buyers receiving unchanged: true MUST NOT mutate their local wholesale product mirror. **One shape per state:** sellers MUST NOT emit `unchanged: false` — the absence of the field IS the signal that the response carries products. Two shapes ({ unchanged: false, products: [...] } vs. { products: [...] }) for the same state would let some sellers always emit the field and some never would, creating an inconsistency the wire shouldn't carry." ), ] = None sandbox: Annotated[ bool | None, Field(description='When true, this response contains simulated data from sandbox mode.'), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- adcp.types.generated_poc.core.protocol_envelope.ProtocolEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var cache_scope : adcp.types.generated_poc.media_buy.get_products_response.CacheScope | Nonevar catalog_applied : bool | Nonevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar errors : list[adcp.types.generated_poc.core.error.Error] | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar extensions : dict[str, adcp.types.generated_poc.media_buy.get_products_response.Extensions] | Nonevar filter_diagnostics : adcp.types.generated_poc.media_buy.get_products_response.FilterDiagnostics | Nonevar incomplete : list[adcp.types.generated_poc.media_buy.get_products_response.IncompleteItem] | Nonevar model_configvar pagination : adcp.types.generated_poc.core.pagination_response.PaginationResponse | Nonevar pricing_version : str | Nonevar products : list[adcp.types.generated_poc.core.product.Product] | Nonevar property_list_applied : bool | Nonevar proposals : list[adcp.types.generated_poc.core.proposal.Proposal] | Nonevar refinement_applied : list[adcp.types.generated_poc.media_buy.get_products_response.RefinementApplied] | Nonevar sandbox : bool | Nonevar status : adcp.types.generated_poc.enums.task_status.TaskStatus | Nonevar unchanged : Literal[True] | Nonevar wholesale_feed_version : str | None
Inherited members
class GetProductsSubmittedResponse (**data: Any)-
Expand source code
class GetProductsSubmitted(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) status: Annotated[ Literal['submitted'], Field( description='Task-level status literal. Discriminates this async envelope from the synchronous success shape, whose products array is issued in-line. See task-status.json for the full task-status enum.' ), ] = 'submitted' task_id: Annotated[ str, Field( description='Task handle the buyer uses with tasks/get, and that the seller references on push-notification callbacks. The products array is issued on the completion artifact, not here. Per AdCP wire conventions this is snake_case; A2A adapters MAY surface it as taskId, but the payload field emitted by the agent is task_id.' ), ] message: Annotated[ str | None, Field( description="Optional human-readable explanation of why the task is submitted — e.g., 'Custom curation queued; typical turnaround 10–30 minutes.' Plain text only. Buyers MUST treat this as untrusted seller input: escape before rendering to HTML UIs, and sanitize or isolate before passing to an LLM prompt context — a hostile seller may inject prompt-injection payloads aimed at the buyer's agent.", max_length=2000, ), ] = None estimated_completion: Annotated[ AwareDatetime | None, Field(description='Estimated completion time for the search') ] = None errors: Annotated[ list[error.Error] | None, Field( description='Optional advisory errors accompanying the submitted envelope. Use only for non-blocking warnings (e.g., throttled_severity advisories, governance observations). Terminal failures belong in the error branch, not here.' ), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = 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 context : adcp.types.generated_poc.core.context.ContextObject | Nonevar errors : list[adcp.types.generated_poc.core.error.Error] | Nonevar estimated_completion : pydantic.types.AwareDatetime | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar message : str | Nonevar model_configvar status : Literal['submitted']var task_id : str
Inherited members
class GetProductsWorkingResponse (**data: Any)-
Expand source code
class GetProductsWorking(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) percentage: Annotated[ float | None, Field(description='Progress percentage of the search operation', ge=0.0, le=100.0), ] = None current_step: Annotated[ str | None, Field( description="Current step in the search process (e.g., 'searching_inventory', 'validating_availability')" ), ] = None total_steps: Annotated[ int | None, Field(description='Total number of steps in the search process') ] = None step_number: Annotated[int | None, Field(description='Current step number (1-indexed)')] = None context: context_1.ContextObject | 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 context : adcp.types.generated_poc.core.context.ContextObject | Nonevar current_step : str | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar model_configvar percentage : float | Nonevar step_number : int | Nonevar total_steps : int | None
Inherited members
class GetRightsRequest (**data: Any)-
Expand source code
class GetRightsRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) query: Annotated[ str, Field( description='Natural language description of desired rights. The agent interprets intent, budget signals, and compatibility from this text.', max_length=2000, ), ] uses: Annotated[ list[right_use.RightUse], Field( description='Rights uses being requested. The agent returns options covering these uses, potentially bundled into composite pricing.', min_length=1, ), ] buyer_brand: Annotated[ brand_ref.BrandReference | None, Field( description="The buyer's brand. The agent fetches the buyer's brand.json for compatibility filtering (e.g., dietary conflicts, competitor exclusions)." ), ] = None countries: Annotated[ list[Country] | None, Field( description='Countries where rights are needed (ISO 3166-1 alpha-2). Filters to rights available in these markets.' ), ] = None brand_id: Annotated[ str | None, Field( description="Search within a specific brand's rights. If omitted, searches across the agent's full roster." ), ] = None right_type: Annotated[ right_type_1.RightType | None, Field(description='Filter by type of rights (talent, music, stock_media, etc.)'), ] = None include_excluded: Annotated[ bool | None, Field( description='Include filtered-out results in the excluded array with reasons. Defaults to false.' ), ] = False pagination: Annotated[ pagination_request.PaginationRequest | None, Field(description='Pagination parameters for large result sets'), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var brand_id : str | Nonevar buyer_brand : adcp.types.generated_poc.core.brand_ref.BrandReference | Nonevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar countries : list[adcp.types.generated_poc.brand.get_rights_request.Country] | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar include_excluded : bool | Nonevar model_configvar pagination : adcp.types.generated_poc.core.pagination_request.PaginationRequest | Nonevar query : strvar right_type : adcp.types.generated_poc.enums.right_type.RightType | Nonevar uses : list[adcp.types.generated_poc.enums.right_use.RightUse]
Inherited members
class PackageRequest (**data: Any)-
Expand source code
class PackageRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) product_id: Annotated[ str, Field( description='Product ID for this package. Sellers MUST echo this value on every response package object that represents this requested package.' ), ] format_ids: Annotated[ list[format_id.FormatReferenceStructuredObject] | None, Field( description="Legacy named-format selector. Array of format IDs that will be used for this package - must be supported by the product. If omitted (and no 3.1+ format-option selector or direct canonical selector is present), defaults to all formats supported by the product.\n\nSellers comparing this selector to a product's `format_options[]` MUST first normalize each legacy `format_id` through the canonical mapping path (`canonical`, `v1_format_ref`, or registry projection). Exact `(agent_url, id)` comparison after projection is insufficient: a legacy fixed-size display ID can satisfy a canonical `image` product declaration with matching `width`/`height`. Product gating remains directional: if the product declares fixed dimensions or duration, the selected format must declare and match those constraints; an under-specified canonical request is not a wildcard for a fixed-size or fixed-duration product. Range constraints use containment, not overlap: a range-based request satisfies the product only when every value it permits falls within the product's accepted range.", min_length=1, ), ] = None format_option_refs: Annotated[ list[format_option_ref.FormatOptionReference] | None, Field( description='3.1+ format-option selector. Array of structured format option references, each matching one of the target product\'s `format_options[]` entries. Publisher-catalog-backed options match by `{ scope: "publisher", publisher_domain, format_option_id }`; product-local options match by `{ scope: "product", format_option_id }`. If omitted along with `format_ids` and direct `format_kind`, all product formats are active.\n\n**Resolution rules (normative).**\n- **Both `format_option_refs` and `format_ids` present.** `format_option_refs` wins; the seller routes by structured references and MUST NOT validate `format_ids` for consistency with the resolved declarations. The `format_ids` value is a legacy-compat hint for intermediaries on the wire path; the resolving seller ignores it.\n- **`format_option_refs` only.** Seller looks up each entry against the package\'s target product `format_options[]` and uses the matching declaration (and that declaration\'s `v1_format_ref[]` when projecting to legacy named-format surfaces). This is the 3.1+ format-option authoring path. `scope: "product"` is scoped only by this target product; it is not a seller-wide identifier.\n- **`format_ids` only.** Existing named-format behavior; unchanged.\n- **`format_kind` only.** Direct canonical selector behavior; seller compares `{ format_kind, params }` against the product\'s `format_options[]` declarations using directional product satisfaction.\n- **None of `format_option_refs`, `format_ids`, or `format_kind`.** Default — all formats supported by the product are active.\n\n**Failure modes (normative).** Sellers MUST reject with `UNSUPPORTED_FEATURE` (with `field` pointing at the failing package and entry, e.g. `packages[0].format_option_refs[1]`) when:\n- Any entry references a format option not present in the target product\'s `format_options[]`, OR\n- The target product carries `format_ids` but no `format_options[]` (legacy-format-only product — there is no closed set to resolve against), OR\n- The target product carries `format_options[]` but none of the entries publish selectable `format_option_id` values. Sellers SHOULD set `error.details.reason` to `format_option_refs_not_published` in this case so buyers can distinguish it from an outright mismatch and fall back to `format_ids[]`.\n\n**Seller obligation.** For buyers to use the 3.1+ format-option path against a product, the seller MUST publish a selectable `format_option_id` on each `format_options[]` entry it expects buyers to select; if the option is publisher-catalog backed, include `publisher_domain` on the product declaration and require buyers to use `scope: "publisher"` in `FormatOptionRef`.\n\n**No legacy capability selector.** `capability_ids` was removed before GA; schemas reject it instead of treating it as an extension.\n\n**Dual emission.** Format-option-aware buyer SDKs targeting a heterogeneous seller population SHOULD emit `format_ids` alongside `format_option_refs` so legacy-format-only sellers — which ignore unknown fields per `additionalProperties: true` — still receive an explicit format set rather than silently defaulting to all formats supported by the product.', min_length=1, ), ] = None format_kind: Annotated[ canonical_format_kind.CanonicalFormatKind | None, Field( description='3.1+ direct canonical selector. Names the canonical format shape this package targets when the buyer is authoring by canonical kind rather than by a product-local `format_option_ref` or legacy `format_id`. Pair with `params` when the product declaration requires dimensions, duration, sizes, codecs, or other canonical parameters. If `format_option_refs` is present, it wins over this direct selector. If `format_ids` is present without `format_option_refs`, sellers MUST normalize and validate the legacy selector; buyers SHOULD NOT also send `format_kind` unless it is an informational echo of the same normalized shape.\n\nProduct satisfaction is directional: a broad selector such as `{ format_kind: "image" }` does not satisfy a product whose `format_options[]` fixes `params.width` and `params.height`. Sellers MUST reject under-specified direct selectors with `UNSUPPORTED_FEATURE` or an equivalent format-selector validation error.' ), ] = None params: Annotated[ dict[str, Any] | None, Field( description="Parameters for the direct canonical selector in `format_kind`. Shape follows the selected canonical's parameter vocabulary: dimensions (`width`, `height`, `sizes`), duration (`duration_ms_exact`, `duration_ms_range`), codecs, asset-source and slot narrowing, or other canonical-specific constraints. Omit when selecting by `format_option_refs` or `format_ids`; those selectors resolve their parameters from the product declaration or legacy catalog projection." ), ] = None budget: Annotated[ float, Field(description="Budget allocation for this package in the media buy's currency", ge=0.0), ] pacing: pacing_1.Pacing | None = None pricing_option_id: Annotated[ str, Field( description="ID of the selected pricing option from the product's pricing_options array" ), ] bid_price: Annotated[ float | None, Field( description="Bid price for auction-based pricing options. This is the exact bid/price to honor unless selected pricing_option has max_bid=true, in which case bid_price is the buyer's maximum willingness to pay (ceiling).", ge=0.0, ), ] = None impressions: Annotated[ float | None, Field(description='Impression goal for this package', ge=0.0) ] = None start_time: Annotated[ AwareDatetime | None, Field( description="Flight start date/time for this package in ISO 8601 format. When omitted, the package inherits the media buy's start_time. Must fall within the media buy's date range." ), ] = None end_time: Annotated[ AwareDatetime | None, Field( description="Flight end date/time for this package in ISO 8601 format. When omitted, the package inherits the media buy's end_time. Must fall within the media buy's date range." ), ] = None paused: Annotated[ bool | None, Field( description='Whether this package should be created in a paused state. Paused packages do not deliver impressions. Defaults to false.' ), ] = False catalogs: Annotated[ list[catalog.Catalog] | None, Field( description='Catalogs this package promotes. Each catalog MUST have a distinct type (e.g., one product catalog, one store catalog). This constraint is enforced at the application level — sellers MUST reject requests containing multiple catalogs of the same type with a validation_error. Makes the package catalog-driven: one budget envelope, platform optimizes across items.' ), ] = None optimization_goals: Annotated[ list[optimization_goal.OptimizationGoal] | None, Field( description='Optimization targets for this package. The seller optimizes delivery toward these goals in priority order. Common pattern: event goals (purchase, install) as primary targets at priority 1; metric goals (clicks, views) as secondary proxy signals at priority 2+.', min_length=1, ), ] = None targeting_overlay: targeting.TargetingOverlay | None = None measurement_terms: Annotated[ measurement_terms_1.MeasurementTerms | None, Field( description="Buyer's proposed billing measurement and makegood terms. Overrides product defaults. Seller accepts (echoed on confirmed package), rejects with TERMS_REJECTED, or adjusts. When absent, product's measurement_terms apply." ), ] = None performance_standards: Annotated[ list[performance_standard.PerformanceStandard] | None, Field( description="Buyer's proposed performance standards for this package. Overrides product defaults. Seller accepts, rejects with TERMS_REJECTED, or adjusts. When absent, product's performance_standards apply.", min_length=1, ), ] = None committed_metrics: Annotated[ list[CommittedMetrics6] | None, Field( description="Buyer's proposed reporting contract for this package — the metrics the buyer wants the seller to commit to populating in delivery reports. Same negotiation pattern as `measurement_terms` and `performance_standards`: seller accepts (echoes on confirmed package with `committed_at` stamped), rejects with `TERMS_REJECTED` (with explanation of which entries were unworkable), or normalizes (echoes a different but compatible list — buyer can accept by retrying with the normalized terms). When absent, the seller decides what to commit based on the product's `available_metrics` and the buyer's `required_metrics` filter on `get_products`. Each entry uses an explicit `scope` discriminator (`standard` or `vendor`) and identifies the metric — request-side entries do NOT carry `committed_at`; that timestamp is stamped by the seller on accept. Constraints on what the buyer MAY propose: each `scope: standard` entry's `metric_id` MUST be in the product's `available_metrics`, and each `scope: vendor` entry's `(vendor, metric_id)` MUST appear in the product's `vendor_metrics` — sellers SHOULD reject with `TERMS_REJECTED` and reference the offending entry when the proposal exceeds product capability.", min_length=1, ), ] = None creative_assignments: Annotated[ list[creative_assignment.CreativeAssignment] | None, Field( description='Assign existing library creatives to this package with optional weights and placement targeting', min_length=1, ), ] = None creatives: Annotated[ Sequence[creative_asset.CreativeAsset] | None, Field( description="Upload creative assets inline and assign to this package. When the seller also advertises creative.has_creative_library: true, these creatives enter the seller's creative library and can be reused by creative_id while retained; inline-only sellers may store them as package-scoped assets. Use creative_assignments instead for existing library creatives.", max_length=100, min_length=1, ), ] = None agency_estimate_number: Annotated[ str | None, Field( description='Agency estimate or authorization number for this package. Overrides the media buy-level estimate number when different packages correspond to different agency estimates (e.g., different stations or flights within the same buy).', max_length=100, ), ] = None context: Annotated[ context_1.ContextObject | None, Field( description='Opaque package-level correlation data echoed unchanged in the package response, webhooks, and read surfaces. Buyers targeting mixed seller populations SHOULD include a per-package correlation value here, commonly context_1.buyer_ref, so responses from legacy sellers that do not echo product_id can still be mapped back to the requested product or line item. Do not use deprecated top-level buyer_ref for v3 correlation.' ), ] = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var agency_estimate_number : str | Nonevar bid_price : float | Nonevar budget : floatvar catalogs : list[adcp.types.generated_poc.core.catalog.Catalog] | Nonevar committed_metrics : list[adcp.types.generated_poc.media_buy.package_request.CommittedMetrics6] | Nonevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar creative_assignments : list[adcp.types.generated_poc.core.creative_assignment.CreativeAssignment] | Nonevar creatives : collections.abc.Sequence[adcp.types.generated_poc.core.creative_asset.CreativeAsset] | Nonevar end_time : pydantic.types.AwareDatetime | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | Nonevar format_kind : adcp.types.generated_poc.core.canonical_format_kind.CanonicalFormatKind | Nonevar format_option_refs : list[adcp.types.generated_poc.core.format_option_ref.FormatOptionReference] | Nonevar impressions : float | Nonevar measurement_terms : adcp.types.generated_poc.core.measurement_terms.MeasurementTerms | Nonevar model_configvar optimization_goals : list[adcp.types.generated_poc.core.optimization_goal.OptimizationGoal] | Nonevar pacing : adcp.types.generated_poc.enums.pacing.Pacing | Nonevar params : dict[str, typing.Any] | Nonevar paused : bool | Nonevar performance_standards : list[adcp.types.generated_poc.core.performance_standard.PerformanceStandard] | Nonevar pricing_option_id : strvar product_id : strvar start_time : pydantic.types.AwareDatetime | Nonevar targeting_overlay : adcp.types.generated_poc.core.targeting.TargetingOverlay | None
Inherited members
class PerformanceFeedback (**data: Any)-
Expand source code
class PerformanceFeedback(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) feedback_id: Annotated[ str, Field(description='Unique identifier for this performance feedback submission') ] media_buy_id: Annotated[str, Field(description="Publisher's media buy identifier")] package_id: Annotated[ str | None, Field( description='Specific package within the media buy (if feedback is package-specific)' ), ] = None creative_id: Annotated[ str | None, Field(description='Specific creative asset (if feedback is creative-specific)') ] = None measurement_period: Annotated[ MeasurementPeriod, Field(description='Time period for performance measurement') ] performance_index: Annotated[ float, Field( description='Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)', ge=0.0, ), ] metric_type: Annotated[ metric_type_1.MetricTypeDeprecated | None, Field( description='**Deprecated as of this minor.** The legacy free-form metric enum that mixes metrics, verification, and attribution into one list. New implementations SHOULD use `metric` (the discriminated `(scope, metric_id, qualifier)` row shape) and populate `metric_type` with a best-effort string for one-minor backwards compatibility. When both `metric` and `metric_type` are present, consumers MUST use `metric` for dispatch. Removed at the next major. See [docs/measurement/taxonomy](https://docs.adcontextprotocol.org/docs/measurement/taxonomy) for why the layered shape replaces the flat enum.' ), ] = None metric: Annotated[ Metric | Metric7 | None, Field( description='The metric this feedback row pertains to, using the same `(scope, metric_id, qualifier)` row shape as `committed_metrics` and `metric_aggregates`. Preferred over the legacy `metric_type` field for new implementations. Brings performance-feedback into the same atomic unit and dispatch model as the rest of the measurement surface — buyer agents reconcile feedback against the contract surface using the row-level join on `(scope, metric_id, qualifier)`. **Optional and may be omitted entirely for holistic feedback** (e.g., a trader flagging a campaign as underperforming without a specific metric in mind — `performance_index` plus the response narrative carry the signal). Senders SHOULD populate `metric` when the feedback is metric-specific so consumers can route it to the right optimization path; senders MAY omit it for general performance feedback.', discriminator='scope', ), ] = None feedback_source: Annotated[ feedback_source_1.FeedbackSource, Field(description='Source of the performance data') ] vendor: Annotated[ brand_ref.BrandReference | None, Field( description="Vendor that produced this feedback. SHOULD be populated when `feedback_source` is `third_party_measurement` or `verification_partner` AND a single attesting vendor exists — without it, the row is unattributed and consumers can't verify authorization, resolve metric definitions, or route disputes. OMIT for blended outputs where no single vendor owns the result: MMM mixes (Nielsen MMM, Analytic Partners, in-house mix models combining multiple vendor inputs), multi-touch attribution outputs that join across vendors, and clean-room outputs (LiveRamp, Habu, AWS Clean Rooms) where the clean room is not the measurement source. For these cases, leave `vendor` absent and use the response's narrative payload to describe provenance. Optional for `buyer_attribution` and `platform_analytics` (those sources are implicit from context). The vendor's `brand.json` `agents[type='measurement']` is the discovery anchor; metric definitions live on the agent's `get_adcp_capabilities.measurement.metrics[]` block. Same identity discipline as `vendor_metric_value.vendor` and `performance-standard.vendor`." ), ] = None status: Annotated[Status, Field(description='Processing status of the performance feedback')] submitted_at: Annotated[ AwareDatetime, Field(description='ISO 8601 timestamp when feedback was submitted') ] applied_at: Annotated[ AwareDatetime | None, Field( description='ISO 8601 timestamp when feedback was applied to optimization algorithms' ), ] = 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 applied_at : pydantic.types.AwareDatetime | Nonevar creative_id : str | Nonevar feedback_id : strvar feedback_source : adcp.types.generated_poc.enums.feedback_source.FeedbackSourcevar measurement_period : adcp.types.generated_poc.core.performance_feedback.MeasurementPeriodvar media_buy_id : strvar metric : adcp.types.generated_poc.core.performance_feedback.Metric | adcp.types.generated_poc.core.performance_feedback.Metric7 | Nonevar metric_type : adcp.types.generated_poc.enums.metric_type.MetricTypeDeprecated | Nonevar model_configvar package_id : str | Nonevar performance_index : floatvar status : adcp.types.generated_poc.core.performance_feedback.Statusvar submitted_at : pydantic.types.AwareDatetimevar vendor : adcp.types.generated_poc.core.brand_ref.BrandReference | None
Inherited members
class PriceGuidance (**data: Any)-
Expand source code
class PriceGuidance(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) p25: Annotated[ float | None, Field(description='25th percentile of recent winning bids', ge=0.0) ] = None p50: Annotated[float | None, Field(description='Median of recent winning bids', ge=0.0)] = None p75: Annotated[ float | None, Field(description='75th percentile of recent winning bids', ge=0.0) ] = None p90: Annotated[ float | None, Field(description='90th percentile of recent winning bids', 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
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar p25 : float | Nonevar p50 : float | Nonevar p75 : float | Nonevar p90 : float | None
Inherited members
class PricingCurrency (root: RootModelRootType = PydanticUndefined, **data)-
Expand source code
class PricingCurrency(RootModel[str]): root: Annotated[ str, Field( description="ISO 4217 currency code (e.g., 'USD', 'EUR', 'GBP')", pattern='^[A-Z]{3}$' ), ]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[str]
- pydantic.root_model.RootModel
- pydantic.main.BaseModel
- typing.Generic
Class variables
var model_configvar root : str
class PricingModel (*args, **kwds)-
Expand source code
class PricingModel(StrEnum): cpm = 'cpm' vcpm = 'vcpm' cpc = 'cpc' cpcv = 'cpcv' cpv = 'cpv' cpp = 'cpp' cpa = 'cpa' flat_rate = 'flat_rate' time = 'time'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var cpavar cpcvar cpcvvar cpmvar cppvar cpvvar flat_ratevar timevar vcpm
class Product (**data: Any)-
Expand source code
class Product(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @model_validator(mode='before') @classmethod def _coerce_publisher_property_models(cls, data: Any) -> Any: if isinstance(data, dict) and isinstance(data.get('publisher_properties'), list): coerced = [] changed = False for item in data['publisher_properties']: if hasattr(item, 'model_dump'): coerced.append(item.model_dump(mode='json', exclude_none=True)) changed = True else: coerced.append(item) if changed: data = dict(data) data['publisher_properties'] = coerced return data product_id: Annotated[str, Field(description='Unique identifier for the product')] name: Annotated[str, Field(description='Human-readable product name')] description: Annotated[ str, Field(description='Detailed description of the product and its inventory') ] publisher_properties: Annotated[ list[PublisherProperty], Field( description="SDK implementers MUST enforce singular-only at runtime: each entry uses the singular `publisher_domain` form; the compact `publisher_domains[]` form is rejected on products. Codegen toolchains (json-schema-to-typescript, quicktype, datamodel-code-generator, openapi-typescript-codegen) often flatten the `allOf + $ref + not.required` restriction below poorly and may drop the rejection constraint silently, emitting an unrestricted type — runtime enforcement is the safety net. Publisher properties covered by this product. Buyers fetch actual property definitions from each publisher's adagents.json and validate agent authorization. Selection patterns mirror the authorization patterns in adagents.json for consistency. The compact `publisher_domains[]` form is reserved for adagents.json `authorized_agents[].publisher_properties[]` so that buy-side traffic-and-pricing flatteners can always treat each entry as exactly one publisher.", min_length=1, ), ] channels: Annotated[ list[channels_1.MediaChannel] | None, Field( description="Advertising channels this product is sold as. Products inherit from their properties' supported_channels but may narrow the scope. For example, a product covering YouTube properties might be sold as ['ctv'] even though those properties support ['olv', 'social', 'ctv']." ), ] = None format_ids: Annotated[ list[format_id.FormatReferenceStructuredObject] | None, Field( description="Legacy named-format path: array of supported creative format IDs (structured format_id objects with agent_url and id). Products MUST carry `format_ids`, `format_options`, or BOTH; at least one is required. Named formats predate 3.1 and remain supported through the deprecation calendar (2027-Q4 floor / 2029-Q1 ceiling).\n\n**Dual emission**: A product MAY carry both `format_ids` and `format_options` simultaneously during the migration window. This is the recommended seller pattern — author once, SDK projects to both wire shapes via the [canonical mapping registry](/schemas/registries/v1-canonical-mapping.json), every buyer reads what it knows. When both are present, the two MUST refer to the SAME underlying format declaration (the `format_options[i]` narrows the canonical that the named format in `format_ids[i]` resolves to via the registry / explicit `canonical` field). SDKs that derive both shapes from one source guarantee this invariant; SDKs that don't MUST treat divergence as a build error and refuse to emit. **Buyer rule**: when both are present, prefer `format_options`; treat `format_ids` as fallback for legacy-format buyers. **Non-projectable formats**: when a named format has no clean 3.1+ format-option projection (no registry entry, no explicit `canonical` declaration on the named format, no structural match), SDKs MUST NOT emit `format_options` for that product — only `format_ids` ships, and the product remains legacy-format-only until the seller adds an explicit `canonical` field or files a registry entry." ), ] = None format_options: Annotated[ list[product_format_declaration.ProductFormatDeclaration] | None, Field( description="3.1+ format-option path: one or more inline format declarations the product accepts. Each element narrows a canonical format with parameters, slots, and platform_extensions. The 90% case is a single-element array (one canonical narrowed for the product). Multi-element use cases: a product that accepts EITHER a third-party-hosted creative (for example, externally served `html5`) OR an internal `display_tag`; a video product that accepts a hosted `video_hosted` upload OR a `video_vast` tag. Buyers pick which option they're shipping at `sync_creatives` time by aligning their manifest to the matching declaration's `format_kind` and slots.\n\nProducts MUST carry `format_ids`, `format_options`, or BOTH; at least one is required. See `format_ids` description for the dual-emission contract (same underlying declaration when both are present; SDK derives one from the other; buyers prefer `format_options` when both are present).\n\nWhen `placements[]` also declare `format_ids` or `format_options`, product-level formats are the upper bound for the sellable product. Placement-level formats narrow the product-wide accepted set for that placement; they MUST NOT introduce a format the product does not accept. Buyers compute the effective accepted set for a placement as the intersection of product-level and placement-level declarations. For format options, match publisher-declared options by `{ publisher_domain, format_option_id }`, match product-local options by `format_option_id` when `publisher_domain` is omitted, and otherwise match declarations with the same `format_kind` whose placement parameters narrow the product declaration. If a placement has no format declaration, it inherits the product-level formats.", min_length=1, ), ] = None placements: Annotated[ list[placement.Placement] | None, Field( description="Optional array of specific public placements within this product. Placement IDs are scoped by publisher domain. Product placements declare `kind` to distinguish publisher-referenced placements (`publisher_ref`) from seller-defined inline placements (`seller_inline`). Publisher-referenced placements carry `publisher_domain` plus `placement_id` and may omit `name` because buyers resolve the name from the publisher's adagents.json placement declarations. Seller-inline placements carry buyer-facing `name` directly; when `publisher_domain` is omitted, buyers MAY interpret the placement ID relative to the seller agent's own publisher domain only during the legacy single-publisher transition. Community-maintained fallback files are resolver/source metadata, not a distinct placement kind. Each placement MUST declare `mode: 'targetable'` (buyer may select the placement by PlacementRef, for example in creative assignments) or `mode: 'included'` (part of the public product composition but not buyer-selectable). Placement-level format declarations narrow the product-level creative contract and MUST NOT broaden it. Seller-private delivery objects, source/origin details, and ad-server mappings MUST NOT be exposed here.", min_length=1, ), ] = None video_placement_types: Annotated[ list[video_placement_type.VideoPlacementType] | None, Field( description='Declared video placement types that may be included in this product, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. Use on OLV, CTV, and other video products when buyers need to distinguish instream, accompanying-content, interstitial, and standalone/no-content inventory. Aggregate products and ad-network products MAY declare multiple values. When `placements[]` also carry `video_placement_types`, this product-level array SHOULD be the union of the placement-level declarations the seller may deliver under the product. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.', min_length=1, ), ] = None audio_distribution_types: Annotated[ list[audio_distribution_type.AudioDistributionType] | None, Field( description='Declared audio distribution types that may be included in this product, using IAB Tech Lab/OpenRTB 2.6 audio.feed definitions with AdCP-native names. Use on radio, streaming-audio, podcast, gaming, and other audio products when buyers need to distinguish music streaming services, FM/AM broadcast, podcasts, catch-up radio, web radio, video-game audio, and text-to-speech inventory without changing the buyer-facing channel or adagents.json property type. Aggregate products and ad-network products MAY declare multiple values. When `placements[]` also carry `audio_distribution_types`, this product-level array SHOULD be the union of the placement-level declarations the seller may deliver under the product. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.', min_length=1, ), ] = None sponsored_placement_types: Annotated[ list[sponsored_placement_type.SponsoredPlacementType] | None, Field( description='Declared sponsored-placement types that may be included in this product, distinguishing where catalog-driven retail-media placements render on the retailer surface (sponsored search, sponsored display, or sponsored native). Use on retail-media products when buyers need to distinguish search-keyed, display, and native in-grid sponsored inventory. Aggregate products and ad-network products MAY declare multiple values. When `placements[]` also carry `sponsored_placement_types`, this product-level array SHOULD be the union of the placement-level declarations the seller may deliver under the product. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.', min_length=1, ), ] = None social_placement_surfaces: Annotated[ list[social_placement_surface.SocialPlacementSurface] | None, Field( description='Declared social-placement surfaces that may be included in this product, distinguishing the in-app surface where social placements render (feed, stories, short_video, explore, or search). Use on social products when buyers need to distinguish feed, story, short-video, and discovery surfaces. Aggregate products and ad-network products MAY declare multiple values. When `placements[]` also carry `social_placement_surfaces`, this product-level array SHOULD be the union of the placement-level declarations the seller may deliver under the product. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.', min_length=1, ), ] = None delivery_type: delivery_type_1.DeliveryType exclusivity: Annotated[ exclusivity_1.Exclusivity | None, Field( description="Whether this product offers exclusive access to its inventory. Defaults to 'none' when absent. Most relevant for guaranteed products tied to specific collections or placements." ), ] = None pricing_options: Annotated[ list[pricing_option.PricingOption], Field(description='Available pricing models for this product', min_length=1), ] forecast: Annotated[ delivery_forecast.DeliveryForecast | None, Field( description='Forecasted delivery metrics for this product. Gives buyers an estimate of expected performance before requesting a proposal.' ), ] = None outcome_measurement: Annotated[ outcome_measurement_1.OutcomeMeasurementDeprecated | None, Field( description='**Deprecated as of this minor.** Outcome capabilities (incremental sales lift, brand lift, foot traffic, etc.) are now declared via `reporting_capabilities.available_metrics` (the same path used for impressions, conversions, ROAS) with `qualifier.attribution_methodology` and `qualifier.attribution_window` carrying the methodology and window on commit. New implementations SHOULD use the unified pattern; this field is retained for one-minor backwards compatibility and removed at the next major. See `outcome-measurement.json` description for migration guidance.' ), ] = None delivery_measurement: Annotated[ DeliveryMeasurement | None, Field( description='Measurement vendors and methodology for delivery metrics. The buyer accepts the declared vendors as the source of truth for the buy. When absent, buyers should apply their own measurement defaults. Senders SHOULD populate `vendors` (structured BrandRef array) for new implementations; the legacy `provider` string field is deprecated and retained for one-minor backwards compatibility.' ), ] = None measurement_terms: Annotated[ measurement_terms_1.MeasurementTerms | None, Field( description="Seller's default billing measurement and makegood terms. Declares who counts the billing metric and what remedies apply when thresholds are breached. Buyers may propose different terms at media buy creation — sellers accept, reject (TERMS_REJECTED), or adjust per their policy." ), ] = None performance_standards: Annotated[ list[performance_standard.PerformanceStandard] | None, Field( description="Seller's default performance standards for this product: viewability, IVT, completion rate, brand safety, attention score. Buyers may propose different standards at media buy creation. When absent, no structured performance standards apply.", min_length=1, ), ] = None cancellation_policy: Annotated[ cancellation_policy_1.CancellationPolicy | None, Field( description='Cancellation terms for this product. Declares the minimum notice period required before cancellation takes effect and any penalties for insufficient notice. Relevant for guaranteed delivery products. Buyers accept these terms by creating a media buy against the product.' ), ] = None allowed_actions: Annotated[ list[product_allowed_action.ProductAllowedAction] | None, Field( description='Actions buyers may perform on buys created against this product, scoped to statuses and modes. Advisory template — the authoritative per-buy capability is `available_actions[]` on the buy response, which resolves modes against current buy state, account tier, and negotiated terms. Buyers SHOULD use this for pre-flight product selection ("which products let me self-serve cancel within 72hr?") and read `available_actions[]` for runtime decisions. The array is uniquely keyed by `action` — sellers MUST NOT emit two entries with the same `action` value. Absence means the seller has not declared a structured action surface for this product — buyers fall back to `valid_actions[]` on buy responses for the flat string vocabulary.', min_length=1, ), ] = None reporting_capabilities: reporting_capabilities_1.ReportingCapabilities creative_policy: creative_policy_1.CreativePolicy | None = None is_custom: Annotated[bool | None, Field(description='Whether this is a custom product')] = None property_targeting_allowed: Annotated[ bool | None, Field( description="Whether buyers can filter this product to a subset of its publisher_properties. When false (default), the product is 'all or nothing' - buyers must accept all properties or the product is excluded from property_list filtering results." ), ] = False data_provider_signals: Annotated[ list[data_provider_signal_selector.DataProviderSignalSelector] | None, Field( deprecated=True, description='Deprecated. Legacy/non-selectable metadata for data-provider signals already bundled into or associated with this product. This field does not provide buyer-selectable options, prices, or seller activation handles. Use included_signals for non-selectable product signal metadata, or signal_targeting_options for selectable package-level signal groups.', ), ] = None included_signals: Annotated[ list[signal_listing.SignalListing] | None, Field( description="Non-selectable signal metadata for signals already included in, bundled with, or planned into this product. These signals describe what the product is; buyers do not select them in packages[].targeting_overlay.signal_targeting_groups and this field does not imply package-level signal targeting. Use signal_ref scope 'data_provider' or 'signal_source' to reference externally defined signals without redefining their name or value_type. Use signal_ref scope 'product' with name and value_type when the included signal is defined only by this product.", min_length=1, ), ] = None signal_targeting_options: Annotated[ list[product_signal_targeting_option.ProductSignalTargetingOption] | None, Field( description="Inline seller-offered signals that may be applied to packages for this product at create_media_buy time. Each entry references a named signal definition with signal_ref scope 'product' for a product-local signal option, scope 'data_provider' for an external signal definition published in adagents.json signals[] that the seller is authorized to apply, or scope 'signal_source' for a source-native signal. Product-local options define name and value_type inline; data-provider and signal-source options may omit those fields when the referenced definition or source is authoritative. Use this field when the selectable menu is product-specific, has product-specific pricing or activation handles, is the relevant subset for a brief/refine result, or should be rendered without an additional get_signals call. Wholesale products may omit this field and rely on get_signals for the selectable signal feed. Buyers select eligible signals through packages[].targeting_overlay.signal_targeting_groups when signal_targeting_rules allow; fixed/default entries are applied by the seller and echoed on the package state. Sellers MUST set signal_targeting_allowed to true whenever this field is present. Bundled, non-selectable signal metadata belongs in included_signals; legacy data_provider_signals may appear only for backwards compatibility.", min_length=1, ), ] = None signal_targeting_rules: Annotated[ signal_targeting_rules_1.SignalTargetingRules | None, Field( description='Composition rules for selecting signals on this product. The selectable signal menu may come from inline signal_targeting_options or from get_signals when a wholesale product omits inline options. This is product-scoped because products may be backed by different ad servers with different Boolean targeting support and group limits.' ), ] = None signal_targeting_allowed: Annotated[ bool | None, Field( description='Whether this product has a package-level signal_targeting_groups surface. When false (default), signals are bundled into the product terms and cannot be selected or explicitly echoed as package signal groups. When true, eligible signals from inline signal_targeting_options or from get_signals may be buyer-selected or seller-applied according to signal_targeting_rules and are represented through packages[].targeting_overlay.signal_targeting_groups. Editability is controlled by signal_targeting_rules; fixed/default-only products still set this to true when applied signal groups are echoed.' ), ] = False catalog_types: Annotated[ list[catalog_type.CatalogType] | None, Field( description='Catalog types this product supports for catalog-driven campaigns. A sponsored product listing declares ["product"], a job board declares ["job", "offering"]. Buyers match synced catalogs to products via this field.', min_length=1, ), ] = None metric_optimization: Annotated[ MetricOptimization | None, Field( description="Metric optimization capabilities for this product. Presence indicates the product supports optimization_goals with kind: 'metric'. No event source or conversion tracking setup required — the seller tracks these metrics natively." ), ] = None vendor_metric_optimization: Annotated[ vendor_metric_optimization_1.VendorMetricOptimization | None, Field( description="Vendor-attested metric optimization capabilities for this product. Presence indicates the product supports `optimization_goals` with `kind: 'vendor_metric'` — the seller's bidding stack can steer delivery toward a specific vendor's measurement (e.g., DV/IAS/Adelaide attention, Scope3 emissions, Kantar brand lift, retail-media partner metrics). Distinct from `metric_optimization` (seller-native metrics with no vendor binding) and from `reporting_capabilities.vendor_metrics` (which declares what the product can *report* rather than what it can *optimize against*). A product may report a vendor metric without being able to optimize for it. Buyers MUST verify the goal's `(vendor, metric_id)` is in `supported_metrics` AND that the package's `committed_metrics[]` includes a matching `{ scope: 'vendor', vendor, metric_id }` entry — optimization without committed reporting is unverifiable and is rejected at the wire level." ), ] = None max_optimization_goals: Annotated[ int | None, Field( description='Maximum number of optimization_goals this product accepts on a package. When absent, no limit is declared. Most social platforms accept only 1 goal — buyers sending arrays longer than this value should expect the seller to use only the highest-priority (lowest priority number) goal.', ge=1, ), ] = None measurement_readiness: Annotated[ measurement_readiness_1.MeasurementReadiness | None, Field( description="Assessment of whether the buyer's event source setup is sufficient for this product to optimize effectively. Only present when the seller can evaluate the buyer's account context. Buyers should check this before creating media buys with event-based optimization goals." ), ] = None conversion_tracking: Annotated[ ConversionTracking | None, Field( description="Conversion event tracking for this product. Presence indicates the product supports optimization_goals with kind: 'event'. Seller-level capabilities (supported event types, UID types, attribution windows) are declared in get_adcp_capabilities." ), ] = None catalog_match: Annotated[ CatalogMatch | None, Field( description='When the buyer provides a catalog on get_products, indicates which catalog items are eligible for this product. Only present for products where catalog matching is relevant (e.g., sponsored product listings, job boards, hotel ads).' ), ] = None brief_relevance: Annotated[ str | None, Field( description='Explanation of why this product matches the brief (only included when brief is provided)' ), ] = None expires_at: Annotated[ AwareDatetime | None, Field( description='Expiration timestamp. After this time, the product may no longer be available for purchase and create_media_buy may reject packages referencing it.' ), ] = None product_card: Annotated[ ProductCard | None, Field( description='Optional standard visual card for displaying this product in user interfaces (catalog browsers, dashboards, agent UIs). Distinct from `format` — product_card describes the UI rendering of the product itself, not the ad creative the product accepts. Typed inline; no format_id indirection. Receivers render the card directly from these fields.' ), ] = None product_card_detailed: Annotated[ ProductCardDetailed | None, Field( description='Optional detailed card with hero + carousel + structured specifications, for rich product presentation (media-kit-style pages, full product detail views). Distinct from `format` — describes the UI rendering of the product itself, not the ad creative the product accepts. Typed inline; no format_id indirection.' ), ] = None collections: Annotated[ list[collection_selector.CollectionSelector] | None, Field( description='Collections available in this product. Each entry references collections declared in an adagents.json by domain and collection ID. Buyers resolve full collection objects from the referenced adagents.json.', min_length=1, ), ] = None collection_targeting_allowed: Annotated[ bool | None, Field( description="Whether buyers can target a subset of this product's collections. When false (default), the product is a bundle — buyers get all listed collections. When true, buyers can select specific collections in the media buy." ), ] = False installments: Annotated[ list[installment.Installment] | None, Field( description='Specific installments included in this product. Each installment references its parent collection via collection_id when the product spans multiple collections. When absent with collections present, the product covers the collections broadly (run-of-collection).' ), ] = None enforced_policies: Annotated[ list[str] | None, Field( description='Registry policy IDs the seller enforces for this product. Enforcement level comes from the policy registry. Buyers can filter products by required policies.' ), ] = None trusted_match: Annotated[ TrustedMatch | None, Field( description='Trusted Match Protocol capabilities for this product. When present, the product supports real-time contextual and/or identity matching via TMP. Buyers use this to determine what response types the publisher can accept and whether brands can be selected dynamically at match time.' ), ] = None material_submission: Annotated[ MaterialSubmission | None, Field( description="Instructions for submitting physical creative materials (print, static OOH, cinema). Present only for products requiring physical delivery outside the digital creative assignment flow. Buyer agents MUST validate url and email domains against the seller's known domains (from adagents.json) before submitting materials. Never auto-submit without human confirmation." ), ] = None ext: ext_1.ExtensionObject | None = 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 allowed_actions : list[adcp.types.generated_poc.core.product_allowed_action.ProductAllowedAction] | Nonevar audio_distribution_types : list[adcp.types.generated_poc.enums.audio_distribution_type.AudioDistributionType] | Nonevar brief_relevance : str | Nonevar cancellation_policy : adcp.types.generated_poc.core.cancellation_policy.CancellationPolicy | Nonevar catalog_match : adcp.types.generated_poc.core.product.CatalogMatch | Nonevar catalog_types : list[adcp.types.generated_poc.enums.catalog_type.CatalogType] | Nonevar channels : list[adcp.types.generated_poc.enums.channels.MediaChannel] | Nonevar collection_targeting_allowed : bool | Nonevar collections : list[adcp.types.generated_poc.core.collection_selector.CollectionSelector] | Nonevar conversion_tracking : adcp.types.generated_poc.core.product.ConversionTracking | Nonevar creative_policy : adcp.types.generated_poc.core.creative_policy.CreativePolicy | Nonevar data_provider_signals : list[adcp.types.generated_poc.core.data_provider_signal_selector.DataProviderSignalSelector] | Nonevar delivery_measurement : adcp.types.generated_poc.core.product.DeliveryMeasurement | Nonevar delivery_type : adcp.types.generated_poc.enums.delivery_type.DeliveryTypevar description : strvar enforced_policies : list[str] | Nonevar exclusivity : adcp.types.generated_poc.enums.exclusivity.Exclusivity | Nonevar expires_at : pydantic.types.AwareDatetime | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar forecast : adcp.types.generated_poc.core.delivery_forecast.DeliveryForecast | Nonevar format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | Nonevar format_options : list[adcp.types.generated_poc.core.product_format_declaration.ProductFormatDeclaration] | Nonevar included_signals : list[adcp.types.generated_poc.core.signal_listing.SignalListing] | Nonevar installments : list[adcp.types.generated_poc.core.installment.Installment] | Nonevar is_custom : bool | Nonevar material_submission : adcp.types.generated_poc.core.product.MaterialSubmission | Nonevar max_optimization_goals : int | Nonevar measurement_readiness : adcp.types.generated_poc.core.measurement_readiness.MeasurementReadiness | Nonevar measurement_terms : adcp.types.generated_poc.core.measurement_terms.MeasurementTerms | Nonevar metric_optimization : adcp.types.generated_poc.core.product.MetricOptimization | Nonevar model_configvar name : strvar outcome_measurement : adcp.types.generated_poc.core.outcome_measurement.OutcomeMeasurementDeprecated | Nonevar performance_standards : list[adcp.types.generated_poc.core.performance_standard.PerformanceStandard] | Nonevar placements : list[adcp.types.generated_poc.core.placement.Placement] | Nonevar pricing_options : list[adcp.types.generated_poc.core.pricing_option.PricingOption]var product_card : adcp.types.generated_poc.core.product.ProductCard | Nonevar product_card_detailed : adcp.types.generated_poc.core.product.ProductCardDetailed | Nonevar product_id : strvar property_targeting_allowed : bool | Nonevar publisher_properties : list[adcp.types.generated_poc.core.product.PublisherProperty]var reporting_capabilities : adcp.types.generated_poc.core.reporting_capabilities.ReportingCapabilitiesvar signal_targeting_allowed : bool | Nonevar signal_targeting_options : list[adcp.types.generated_poc.core.product_signal_targeting_option.ProductSignalTargetingOption] | Nonevar signal_targeting_rules : adcp.types.generated_poc.core.signal_targeting_rules.SignalTargetingRules | Nonevar sponsored_placement_types : list[adcp.types.generated_poc.enums.sponsored_placement_type.SponsoredPlacementType] | Nonevar trusted_match : adcp.types.generated_poc.core.product.TrustedMatch | Nonevar vendor_metric_optimization : adcp.types.generated_poc.core.vendor_metric_optimization.VendorMetricOptimization | Nonevar video_placement_types : list[adcp.types.generated_poc.enums.video_placement_type.VideoPlacementType] | None
Inherited members
class ProductCard (**data: Any)-
Expand source code
class ProductCard(AdCPBaseModel): title: Annotated[bound_value.A2UiBoundValue, Field(description='Product name')] price: Annotated[bound_value.A2UiBoundValue, Field(description='Price display string')] image: Annotated[bound_value.A2UiBoundValue | None, Field(description='Product image URL')] = ( None ) description: Annotated[ bound_value.A2UiBoundValue | None, Field(description='Product description') ] = None badge: Annotated[ bound_value.A2UiBoundValue | None, Field(description="Badge text (e.g., 'Best Seller')") ] = None ctaLabel: Annotated[ bound_value.A2UiBoundValue | None, Field(description='CTA button label') ] = None action: Action6 | 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 action : adcp.types.generated_poc.a2ui.si_catalog.Action6 | Nonevar badge : adcp.types.generated_poc.a2ui.bound_value.A2UiBoundValue | Nonevar ctaLabel : adcp.types.generated_poc.a2ui.bound_value.A2UiBoundValue | Nonevar description : adcp.types.generated_poc.a2ui.bound_value.A2UiBoundValue | Nonevar image : adcp.types.generated_poc.a2ui.bound_value.A2UiBoundValue | Nonevar model_configvar price : adcp.types.generated_poc.a2ui.bound_value.A2UiBoundValuevar title : adcp.types.generated_poc.a2ui.bound_value.A2UiBoundValue
Inherited members
class ProductCardDetailed (**data: Any)-
Expand source code
class ProductCardDetailed(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) hero_image: Annotated[ image_asset.ImageAsset | None, Field(description='Primary hero image at the top of the detailed view.'), ] = None carousel_images: Annotated[ list[image_asset.ImageAsset] | None, Field(description='Additional images for a swipeable carousel below the hero.'), ] = None title: Annotated[str | None, Field(description='Page title (typically the product name).')] = ( None ) description: Annotated[ str | None, Field( description='Full descriptive copy. Markdown allowed in client renderers that support it; otherwise treat as plain text.' ), ] = None specifications: Annotated[ list[Specification] | None, Field( description="Structured key/value specifications (e.g., 'Aspect ratio: 9:16', 'Duration: 30s'). Each item is a labeled fact about the product." ), ] = None price_label: Annotated[str | None, Field(description='Formatted price or pricing summary.')] = ( None ) cta_label: Annotated[str | None, Field(description='Call-to-action button label.')] = 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 carousel_images : list[adcp.types.generated_poc.core.assets.image_asset.ImageAsset] | Nonevar cta_label : str | Nonevar description : str | Nonevar hero_image : adcp.types.generated_poc.core.assets.image_asset.ImageAsset | Nonevar model_configvar price_label : str | Nonevar specifications : list[adcp.types.generated_poc.core.product.Specification] | Nonevar title : str | None
Inherited members
class ProductFilters (**data: Any)-
Expand source code
class ProductFilters(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) delivery_type: delivery_type_1.DeliveryType | None = None exclusivity: Annotated[ exclusivity_1.Exclusivity | None, Field( description="Filter by exclusivity level. Returns products matching the specified exclusivity (e.g., 'exclusive' returns only sole-sponsorship products)." ), ] = None is_fixed_price: Annotated[ bool | None, Field( description='Filter by pricing availability and returned pricing options: true = products offering fixed pricing (at least one option with fixed_price), false = products offering auction pricing (at least one option without fixed_price). Products with both fixed and auction options match both true and false, but sellers MUST return only the pricing_options entries matching the requested pricing type so buyers can deterministically select from the returned options.' ), ] = None pricing_currencies: Annotated[ list[PricingCurrency] | None, Field( description='Filter by currencies the buyer can use for the media product transaction, using ISO 4217 currency codes. Products match when they offer at least one product-level pricing_options entry in one of the requested currencies and any seller-applied or otherwise mandatory product-scoped signal charges are satisfiable in one of those currencies or have no incremental price. Mandatory custom signal pricing without currency is not satisfiable for this filter unless the seller can truthfully treat it as having no incremental price. Sellers MUST return only product pricing_options entries whose currency is in this list so buyers can select deterministically from discovery. This filter does not require pruning optional signal or vendor add-on pricing; buyers should avoid optional add-ons priced only in unsupported currencies.', min_length=1, ), ] = None format_ids: Annotated[ list[format_id.FormatReferenceStructuredObject] | None, Field(description='Filter by specific format IDs', min_length=1), ] = None standard_formats_only: Annotated[ bool | None, Field(description='Only return products accepting IAB standard formats') ] = None min_exposures: Annotated[ int | None, Field(description='Minimum exposures/impressions needed for measurement validity', ge=1), ] = None start_date: Annotated[ date_aliased | None, Field( description='Campaign start date (ISO 8601 date format: YYYY-MM-DD) for availability checks' ), ] = None end_date: Annotated[ date_aliased | None, Field( description='Campaign end date (ISO 8601 date format: YYYY-MM-DD) for availability checks' ), ] = None budget_range: Annotated[ BudgetRange | None, Field(description='Budget range to filter appropriate products') ] = None countries: Annotated[ list[Country] | None, Field( description="Filter by country coverage using ISO 3166-1 alpha-2 codes (e.g., ['US', 'CA', 'GB']). Works for all inventory types.", min_length=1, ), ] = None regions: Annotated[ list[Region] | None, Field( description="Filter by region coverage using ISO 3166-2 codes (e.g., ['US-NY', 'US-CA', 'GB-SCT']). Use for locally-bound inventory (regional OOH, local TV) where products have region-specific coverage.", min_length=1, ), ] = None metros: Annotated[ list[Metro] | None, Field( description='Filter by metro coverage for locally-bound inventory (radio, DOOH, local TV). Use when products have DMA/metro-specific coverage. For digital inventory where products have broad coverage, use required_geo_targeting instead to filter by seller capability.', min_length=1, ), ] = None channels: Annotated[ list[channels_1.MediaChannel] | None, Field( description="Filter by advertising channels (e.g., ['display', 'ctv', 'dooh'])", min_length=1, ), ] = None video_placement_types: Annotated[ list[video_placement_type.VideoPlacementType] | None, Field( description='Filter video products by acceptable declared video placement types, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. Sellers SHOULD return only products they can satisfy with at least one requested type. Products whose only available delivery is a mixed, non-targetable bundle that includes unrequested video placement types SHOULD NOT match unless the seller can constrain delivery to the requested type during planning or purchase. This filter has set semantics for wholesale feed canonicalization.', min_length=1, ), ] = None audio_distribution_types: Annotated[ list[audio_distribution_type.AudioDistributionType] | None, Field( description='Filter audio products by acceptable declared audio distribution types, using IAB Tech Lab/OpenRTB 2.6 audio.feed definitions with AdCP-native names. Sellers SHOULD return only products they can satisfy with at least one requested type. Products whose only available delivery is a mixed, non-targetable bundle that includes unrequested audio distribution types SHOULD NOT match unless the seller can constrain delivery to the requested type during planning or purchase. This filter has set semantics for wholesale feed canonicalization.', min_length=1, ), ] = None sponsored_placement_types: Annotated[ list[sponsored_placement_type.SponsoredPlacementType] | None, Field( description='Filter retail-media products by acceptable declared sponsored-placement types (sponsored search, sponsored display, or sponsored native). Sellers SHOULD return only products they can satisfy with at least one requested type. Products whose only available delivery is a mixed, non-targetable bundle that includes unrequested sponsored-placement types SHOULD NOT match unless the seller can constrain delivery to the requested type during planning or purchase. This filter has set semantics for wholesale feed canonicalization.', min_length=1, ), ] = None social_placement_surfaces: Annotated[ list[social_placement_surface.SocialPlacementSurface] | None, Field( description='Filter social products by acceptable declared social-placement surfaces (feed, stories, short_video, explore, or search). Sellers SHOULD return only products they can satisfy with at least one requested surface. Products whose only available delivery is a mixed, non-targetable bundle that includes unrequested surfaces SHOULD NOT match unless the seller can constrain delivery to the requested surface during planning or purchase. This filter has set semantics for wholesale feed canonicalization.', min_length=1, ), ] = None required_axe_integrations: Annotated[ list[AnyUrl] | None, Field( deprecated=True, description='Deprecated: Use trusted_match filter instead. Filter to products executable through specific agentic ad exchanges. URLs are canonical identifiers.', ), ] = None trusted_match: Annotated[ TrustedMatch | None, Field( description='Filter products by Trusted Match Protocol capabilities. Only products with matching TMP support are returned.' ), ] = None required_features: Annotated[ media_buy_features.MediaBuyFeatures | None, Field( description='Filter to products from sellers supporting specific protocol features. Only features set to true are used for filtering.' ), ] = None required_geo_targeting: Annotated[ list[RequiredGeoTargetingItem] | None, Field( description='Filter to products from sellers supporting specific geo targeting capabilities. Each entry specifies a targeting level (country, region, metro, postal_area) and optionally a system for levels that have multiple classification systems. For native postal_area filters, include country plus the country-local postal system.', min_length=1, ), ] = None signal_targeting: Annotated[ list[SignalTargetingItem] | None, Field( description="Filter to products where the requested signals are buyer-selectable and jointly composable: the signals are available through inline signal_targeting_options and/or through get_signals for wholesale products that allow signal targeting but omit inline options, signal_targeting_allowed is true, and the requested set can coexist under the product's signal_targeting_rules. Each filter entry uses signal_ref, with deprecated signal_id accepted during the SignalRef migration window, and may include targeting_mode='include' or 'exclude' to require the product option or product rules to support that use. When targeting_mode is omitted, include is assumed. SignalRef scope 'product' is seller-local exact option matching only, not a portable semantic identifier across products or sellers; buyers wanting portable discovery should use scope 'data_provider' or get_signals. included_signals and deprecated bundled/non-selectable data_provider_signals do not satisfy this filter because they cannot be selected on create_media_buy.", min_length=1, ), ] = None postal_areas: Annotated[ list[postal_area.PostalArea] | None, Field( description='Filter by postal area coverage for locally-bound inventory (direct mail, DOOH, local campaigns). Prefer the native country + postal system form. Deprecated legacy country-fused postal-system tokens remain accepted for compatibility. For digital inventory where products have broad coverage, use required_geo_targeting instead to filter by seller capability.', min_length=1, ), ] = None geo_proximity: Annotated[ list[GeoProximityItem] | None, Field( description='Filter by proximity to geographic points. Returns products with inventory coverage near these locations. Follows the same format as the targeting overlay — each entry uses exactly one method: travel_time + transport_mode, radius, or geometry. For locally-bound inventory (DOOH, radio), filters to products with coverage in the area. For digital inventory, filters to products from sellers supporting geo_proximity targeting.', min_length=1, ), ] = None required_performance_standards: Annotated[ list[performance_standard.PerformanceStandard] | None, Field( description="Filter to products that can meet the buyer's performance standard requirements. Each entry specifies a metric, minimum threshold, and optionally a required vendor and standard. Products that cannot meet these thresholds or do not support the specified vendors are excluded. Use this to tell the seller upfront: 'I need DoubleVerify for viewability at 70% MRC.'", min_length=1, ), ] = None required_metrics: Annotated[ list[available_metric.AvailableMetric] | None, Field( description="Filter to products whose `reporting_capabilities.available_metrics` is a superset of these metrics — i.e., products that commit to reporting all listed metrics in delivery responses. Use this for capability-level discovery (e.g., 'I need products that report `completed_views` for a CTV CPCV buy'); guarantee-level requirements with thresholds belong in `required_performance_standards` and `measurement_terms`. Sellers MUST silently exclude products that cannot meet this list (filter-not-fail; do not return an error). The product's declared `available_metrics` becomes the binding reporting contract carried into the resulting media buy — the same metric vocabulary is used to compute `missing_metrics` on `get_media_buy_delivery`.", examples=[ ['completed_views'], ['completed_views', 'completion_rate'], ['impressions', 'spend', 'engagements'], ], min_length=1, ), ] = None required_vendor_metrics: Annotated[ list[RequiredVendorMetric] | None, Field( description="Filter to products whose `reporting_capabilities.vendor_metrics` matches these criteria. Each entry pins a `vendor` (matches any metric from that vendor), a `metric_id` (matches the metric across any vendor that uses that identifier), or both (specific vendor's specific metric). A product matches if its declared `vendor_metrics` covers ALL listed entries (AND across entries; pins within an entry are conjunctive). Cross-vendor discovery (e.g., 'I need attention measurement from any vendor that does it') is the buyer agent's responsibility — the agent resolves which vendors offer a category via the vendors' `brand.json` records, then enumerates them as filter entries. AdCP does not carry vendor-side metric metadata (category, methodology, standard alignment) in the filter surface; that lives at the vendor and is queried out-of-band. Sellers MUST silently exclude non-matching products (filter-not-fail; do not return an error) — same convention as the other `required_*` filters.", examples=[ [{'vendor': {'domain': 'attentionvendor.example'}}], [ { 'vendor': {'domain': 'panelmeasurement.example'}, 'metric_id': 'demographic_reach', } ], [ {'vendor': {'domain': 'attentionvendor.example'}}, {'vendor': {'domain': 'secondattentionvendor.example'}}, ], ], min_length=1, ), ] = None keywords: Annotated[ list[Keyword] | None, Field( description='Filter by keyword relevance for search and retail media platforms. Returns products that support keyword targeting for these terms. Allows the sell-side agent to assess keyword availability and recommend appropriate products. Use match_type to indicate the desired precision.', min_length=1, ), ] = None ext: Annotated[ ext_1.ExtensionObject | None, Field( description='Vendor-namespaced extension parameters for seller-specific filter criteria not covered by standard fields. Keys MUST be namespaced under a vendor or platform key (e.g., ext.gam, ext.platform_x). Sellers MUST treat all values as untrusted buyer input; do not interpolate into LLM prompts, SQL queries, or system commands without sanitization. Persistent use of an extension key across multiple buyers is a signal to propose standardization.' ), ] = 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 audio_distribution_types : list[adcp.types.generated_poc.enums.audio_distribution_type.AudioDistributionType] | Nonevar budget_range : adcp.types.generated_poc.core.product_filters.BudgetRange | Nonevar channels : list[adcp.types.generated_poc.enums.channels.MediaChannel] | Nonevar countries : list[adcp.types.generated_poc.core.product_filters.Country] | Nonevar delivery_type : adcp.types.generated_poc.enums.delivery_type.DeliveryType | Nonevar end_date : datetime.date | Nonevar exclusivity : adcp.types.generated_poc.enums.exclusivity.Exclusivity | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar format_ids : list[adcp.types.generated_poc.core.format_id.FormatReferenceStructuredObject] | Nonevar geo_proximity : list[adcp.types.generated_poc.core.product_filters.GeoProximityItem] | Nonevar is_fixed_price : bool | Nonevar keywords : list[adcp.types.generated_poc.core.product_filters.Keyword] | Nonevar metros : list[adcp.types.generated_poc.core.product_filters.Metro] | Nonevar min_exposures : int | Nonevar model_configvar postal_areas : list[adcp.types.generated_poc.core.postal_area.PostalArea] | Nonevar pricing_currencies : list[adcp.types.generated_poc.core.product_filters.PricingCurrency] | Nonevar regions : list[adcp.types.generated_poc.core.product_filters.Region] | Nonevar required_axe_integrations : list[pydantic.networks.AnyUrl] | Nonevar required_features : adcp.types.generated_poc.core.media_buy_features.MediaBuyFeatures | Nonevar required_geo_targeting : list[adcp.types.generated_poc.core.product_filters.RequiredGeoTargetingItem] | Nonevar required_metrics : list[adcp.types.generated_poc.enums.available_metric.AvailableMetric] | Nonevar required_performance_standards : list[adcp.types.generated_poc.core.performance_standard.PerformanceStandard] | Nonevar required_vendor_metrics : list[adcp.types.generated_poc.core.product_filters.RequiredVendorMetric] | Nonevar signal_targeting : list[adcp.types.generated_poc.core.product_filters.SignalTargetingItem] | Nonevar sponsored_placement_types : list[adcp.types.generated_poc.enums.sponsored_placement_type.SponsoredPlacementType] | Nonevar standard_formats_only : bool | Nonevar start_date : datetime.date | Nonevar trusted_match : adcp.types.generated_poc.core.product_filters.TrustedMatch | Nonevar video_placement_types : list[adcp.types.generated_poc.enums.video_placement_type.VideoPlacementType] | None
Inherited members
class ProvidePerformanceFeedbackRequest (**data: Any)-
Expand source code
class ProvidePerformanceFeedbackRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) media_buy_id: Annotated[str, Field(description="Seller's media buy identifier", min_length=1)] idempotency_key: Annotated[ str, Field( description='Client-generated unique key for this request. Prevents duplicate feedback submissions on retries. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.', max_length=255, min_length=16, pattern='^[A-Za-z0-9_.:-]{16,255}$', ), ] measurement_period: Annotated[ datetime_range.DatetimeRange, Field(description='Time period for performance measurement') ] performance_index: Annotated[ float, Field( description='Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)', ge=0.0, ), ] package_id: Annotated[ str | None, Field( description='Specific package within the media buy (if feedback is package-specific)', min_length=1, ), ] = None creative_id: Annotated[ str | None, Field( description='Specific creative asset (if feedback is creative-specific)', min_length=1 ), ] = None metric_type: Annotated[ metric_type_1.MetricTypeDeprecated | None, Field(description='The business metric being measured'), ] = metric_type_1.MetricTypeDeprecated.overall_performance feedback_source: Annotated[ feedback_source_1.FeedbackSource | None, Field(description='Source of the performance data') ] = feedback_source_1.FeedbackSource.buyer_attribution context: context_1.ContextObject | 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var context : adcp.types.generated_poc.core.context.ContextObject | Nonevar creative_id : str | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar feedback_source : adcp.types.generated_poc.enums.feedback_source.FeedbackSource | Nonevar idempotency_key : strvar measurement_period : adcp.types.generated_poc.core.datetime_range.DatetimeRangevar media_buy_id : strvar metric_type : adcp.types.generated_poc.enums.metric_type.MetricTypeDeprecated | Nonevar model_configvar package_id : str | Nonevar performance_index : float
class ProvidePerformanceFeedbackByMediaBuyRequest (**data: Any)-
Expand source code
class ProvidePerformanceFeedbackRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) media_buy_id: Annotated[str, Field(description="Seller's media buy identifier", min_length=1)] idempotency_key: Annotated[ str, Field( description='Client-generated unique key for this request. Prevents duplicate feedback submissions on retries. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.', max_length=255, min_length=16, pattern='^[A-Za-z0-9_.:-]{16,255}$', ), ] measurement_period: Annotated[ datetime_range.DatetimeRange, Field(description='Time period for performance measurement') ] performance_index: Annotated[ float, Field( description='Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)', ge=0.0, ), ] package_id: Annotated[ str | None, Field( description='Specific package within the media buy (if feedback is package-specific)', min_length=1, ), ] = None creative_id: Annotated[ str | None, Field( description='Specific creative asset (if feedback is creative-specific)', min_length=1 ), ] = None metric_type: Annotated[ metric_type_1.MetricTypeDeprecated | None, Field(description='The business metric being measured'), ] = metric_type_1.MetricTypeDeprecated.overall_performance feedback_source: Annotated[ feedback_source_1.FeedbackSource | None, Field(description='Source of the performance data') ] = feedback_source_1.FeedbackSource.buyer_attribution context: context_1.ContextObject | 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var context : adcp.types.generated_poc.core.context.ContextObject | Nonevar creative_id : str | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar feedback_source : adcp.types.generated_poc.enums.feedback_source.FeedbackSource | Nonevar idempotency_key : strvar measurement_period : adcp.types.generated_poc.core.datetime_range.DatetimeRangevar media_buy_id : strvar metric_type : adcp.types.generated_poc.enums.metric_type.MetricTypeDeprecated | Nonevar model_configvar package_id : str | Nonevar performance_index : float
class ProvidePerformanceFeedbackByBuyerRefRequest (**data: Any)-
Expand source code
class ProvidePerformanceFeedbackRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) media_buy_id: Annotated[str, Field(description="Seller's media buy identifier", min_length=1)] idempotency_key: Annotated[ str, Field( description='Client-generated unique key for this request. Prevents duplicate feedback submissions on retries. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.', max_length=255, min_length=16, pattern='^[A-Za-z0-9_.:-]{16,255}$', ), ] measurement_period: Annotated[ datetime_range.DatetimeRange, Field(description='Time period for performance measurement') ] performance_index: Annotated[ float, Field( description='Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)', ge=0.0, ), ] package_id: Annotated[ str | None, Field( description='Specific package within the media buy (if feedback is package-specific)', min_length=1, ), ] = None creative_id: Annotated[ str | None, Field( description='Specific creative asset (if feedback is creative-specific)', min_length=1 ), ] = None metric_type: Annotated[ metric_type_1.MetricTypeDeprecated | None, Field(description='The business metric being measured'), ] = metric_type_1.MetricTypeDeprecated.overall_performance feedback_source: Annotated[ feedback_source_1.FeedbackSource | None, Field(description='Source of the performance data') ] = feedback_source_1.FeedbackSource.buyer_attribution context: context_1.ContextObject | 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var context : adcp.types.generated_poc.core.context.ContextObject | Nonevar creative_id : str | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar feedback_source : adcp.types.generated_poc.enums.feedback_source.FeedbackSource | Nonevar idempotency_key : strvar measurement_period : adcp.types.generated_poc.core.datetime_range.DatetimeRangevar media_buy_id : strvar metric_type : adcp.types.generated_poc.enums.metric_type.MetricTypeDeprecated | Nonevar model_configvar package_id : str | Nonevar performance_index : float
Inherited members
class Refine (root: RootModelRootType = PydanticUndefined, **data)-
Expand source code
class Refine(RootModel[Refine1 | Refine2 | Refine3]): root: Annotated[Refine1 | Refine2 | Refine3, Field(discriminator='scope')] def __getattr__(self, name: str) -> Any: """Proxy attribute access to the wrapped type.""" if name.startswith('_'): raise AttributeError(name) return getattr(self.root, name)Usage Documentation
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[Union[Refine1, Refine2, Refine3]]
- pydantic.root_model.RootModel
- pydantic.main.BaseModel
- typing.Generic
Class variables
var model_configvar root : adcp.types.generated_poc.media_buy.get_products_request.Refine1 | adcp.types.generated_poc.media_buy.get_products_request.Refine2 | adcp.types.generated_poc.media_buy.get_products_request.Refine3
class RefinementApplied (root: RootModelRootType = PydanticUndefined, **data)-
Expand source code
class RefinementApplied(RootModel[RefinementApplied1 | RefinementApplied2 | RefinementApplied3]): root: Annotated[ RefinementApplied1 | RefinementApplied2 | RefinementApplied3, Field(discriminator='scope') ] def __getattr__(self, name: str) -> Any: """Proxy attribute access to the wrapped type.""" if name.startswith('_'): raise AttributeError(name) return getattr(self.root, name)Usage Documentation
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[Union[RefinementApplied1, RefinementApplied2, RefinementApplied3]]
- pydantic.root_model.RootModel
- pydantic.main.BaseModel
- typing.Generic
Class variables
var model_configvar root : adcp.types.generated_poc.media_buy.get_products_response.RefinementApplied1 | adcp.types.generated_poc.media_buy.get_products_response.RefinementApplied2 | adcp.types.generated_poc.media_buy.get_products_response.RefinementApplied3
class RightsPricingOption (**data: Any)-
Expand source code
class RightsPricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) pricing_option_id: Annotated[ str, Field( description='Unique identifier for this pricing option. Referenced in acquire_rights and report_usage.' ), ] model: Annotated[ pricing_model.PricingModel, Field(description='Pricing model (cpm, flat_rate, etc.)') ] price: Annotated[ float, Field( description='Price amount. Interpretation depends on model: CPM = cost per 1,000 impressions, flat_rate = fixed cost per period.', ge=0.0, ), ] currency: Annotated[str, Field(description='ISO 4217 currency code', pattern='^[A-Z]{3}$')] uses: Annotated[ list[right_use.RightUse], Field( description='Which rights uses this pricing option covers. A single option can bundle multiple uses (e.g., likeness + voice).', min_length=1, ), ] period: Annotated[ rights_billing_period.RightsBillingPeriod | None, Field(description='Billing period for flat_rate and time-based models'), ] = None impression_cap: Annotated[ int | None, Field(description='Maximum impressions included in this pricing option per period', ge=1), ] = None overage_cpm: Annotated[ float | None, Field(description='CPM rate applied to impressions exceeding the impression_cap', ge=0.0), ] = None description: Annotated[ str | None, Field(description='Human-readable description of this pricing option') ] = None ext: ext_1.ExtensionObject | None = 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 currency : strvar description : str | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar impression_cap : int | Nonevar model : adcp.types.generated_poc.enums.pricing_model.PricingModelvar model_configvar overage_cpm : float | Nonevar period : adcp.types.generated_poc.enums.rights_billing_period.RightsBillingPeriod | Nonevar price : floatvar pricing_option_id : strvar uses : list[adcp.types.generated_poc.enums.right_use.RightUse]
Inherited members
class RightsTerms (**data: Any)-
Expand source code
class RightsTerms(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) pricing_option_id: str amount: Annotated[float, Field(ge=0.0)] currency: Annotated[str, Field(pattern='^[A-Z]{3}$')] period: rights_billing_period.RightsBillingPeriod | None = None uses: list[right_use.RightUse] impression_cap: Annotated[int | None, Field(ge=1)] = None overage_cpm: Annotated[float | None, Field(ge=0.0)] = None start_date: date_aliased | None = None end_date: date_aliased | None = None exclusivity: Annotated[ Exclusivity | None, Field(description='Exclusivity terms if applicable') ] = 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 amount : floatvar currency : strvar end_date : datetime.date | Nonevar exclusivity : adcp.types.generated_poc.brand.rights_terms.Exclusivity | Nonevar impression_cap : int | Nonevar model_configvar overage_cpm : float | Nonevar period : adcp.types.generated_poc.enums.rights_billing_period.RightsBillingPeriod | Nonevar pricing_option_id : strvar start_date : datetime.date | Nonevar uses : list[adcp.types.generated_poc.enums.right_use.RightUse]
Inherited members
class TargetingOverlay (**data: Any)-
Expand source code
class TargetingOverlay(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) geo_countries: Annotated[ list[GeoCountry] | None, Field( description="Restrict delivery to specific countries. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').", min_length=1, ), ] = None geo_countries_exclude: Annotated[ Sequence[GeoCountriesExcludeItem] | None, Field( description="Exclude specific countries from delivery. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').", min_length=1, ), ] = None geo_regions: Annotated[ list[GeoRegion] | None, Field( description="Restrict delivery to specific regions/states. ISO 3166-2 subdivision codes (e.g., 'US-CA', 'GB-SCT').", min_length=1, ), ] = None geo_regions_exclude: Annotated[ Sequence[GeoRegionsExcludeItem] | None, Field( description="Exclude specific regions/states from delivery. ISO 3166-2 subdivision codes (e.g., 'US-CA', 'GB-SCT').", min_length=1, ), ] = None geo_metros: Annotated[ list[GeoMetro] | None, Field( description='Restrict delivery to specific metro areas. Each entry specifies the classification system and target values. Seller must declare supported systems in get_adcp_capabilities.', min_length=1, ), ] = None geo_metros_exclude: Annotated[ Sequence[GeoMetrosExcludeItem] | None, Field( description='Exclude specific metro areas from delivery. Each entry specifies the classification system and excluded values. Seller must declare supported systems in get_adcp_capabilities.', min_length=1, ), ] = None geo_postal_areas: Annotated[ list[postal_area.PostalArea] | None, Field( description='Restrict delivery to specific postal areas. Prefer the native country + postal system form. The deprecated legacy country-fused postal-system tokens remain accepted for compatibility. Seller must declare supported systems in get_adcp_capabilities.', min_length=1, ), ] = None geo_postal_areas_exclude: Annotated[ Sequence[postal_area.PostalArea] | None, Field( description='Exclude specific postal areas from delivery. Prefer the native country + postal system form. The deprecated legacy country-fused postal-system tokens remain accepted for compatibility. Seller must declare supported systems in get_adcp_capabilities.', min_length=1, ), ] = None daypart_targets: Annotated[ list[daypart_target.DaypartTarget] | None, Field( description='Restrict delivery to specific time windows. Each entry specifies days of week and an hour range.', min_length=1, ), ] = None axe_include_segment: Annotated[ str | None, Field( deprecated=True, description='Deprecated: Use TMP provider fields instead. AXE segment ID to include for targeting.', ), ] = None axe_exclude_segment: Annotated[ str | None, Field( deprecated=True, description='Deprecated: Use TMP provider fields instead. AXE segment ID to exclude from targeting.', ), ] = None audience_include: Annotated[ list[str] | None, Field( description='Restrict delivery to members of these first-party CRM audiences. Only users present in the uploaded lists are eligible. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Not for lookalike expansion — express that intent in the campaign brief. Seller must declare support in get_adcp_capabilities.', min_length=1, ), ] = None audience_exclude: Annotated[ list[str] | None, Field( description='Suppress delivery to members of these first-party CRM audiences. Matched users are excluded regardless of other targeting. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Seller must declare support in get_adcp_capabilities.', min_length=1, ), ] = None signal_targeting_groups: Annotated[ package_signal_targeting_groups.PackageSignalTargetingGroups | None, Field( description="Basic Boolean grouping for seller-offered signals. v1 supports a required top-level operator 'all' and child groups with operator 'any' for include groups or 'none' for exclusion groups. Example semantics: group 1 any(A, B) plus group 2 none(C, D) means (A OR B) AND NOT (C OR D). Signal entries reference named signal definitions with signal_ref scope 'product' for product-local signal options or scope 'data_provider' for external signals published in adagents.json signals[]. For simple include-only targeting, send one child group with operator 'any'. Sellers SHOULD reject entries that are not available for the product through inline signal_targeting_options or get_signals, are not active for the account, or exceed the product's signal_targeting_allowed/signal_targeting_rules/product terms. Signal targeting limits are product-scoped, not declared in get_adcp_capabilities, because products may be backed by different ad servers. Sellers MUST echo applied signal_targeting_groups on the resulting package state, including fixed/default selections. On update_media_buy, sellers MAY reject changes that require repricing with REQUOTE_REQUIRED." ), ] = None signal_targeting: Annotated[ list[signal_targeting_1.SignalTargeting] | None, Field( deprecated=True, description='DEPRECATED. Use signal_targeting_groups for package-level signal targeting. Legacy flat signal_targeting remains accepted during the SignalRef migration window but cannot express grouped include/exclude composition or product-scoped pricing.', min_length=1, ), ] = None frequency_cap: frequency_cap_1.FrequencyCap | None = None property_list: Annotated[ property_list_ref.PropertyListReference | None, Field( description="Reference to a property list for targeting specific properties within this product. The package runs on the intersection of the product's publisher_properties and this list. Sellers SHOULD return a validation error if the product has property_targeting_allowed: false." ), ] = None collection_list: Annotated[ collection_list_ref.CollectionListReference | None, Field( description='Reference to a collection list for including specific collections (programs, shows) within this product. The package runs on the intersection of matched collections and this list. Use for inclusion-based collection targeting. Seller must declare support in get_adcp_capabilities.' ), ] = None collection_list_exclude: Annotated[ collection_list_ref.CollectionListReference | None, Field( description="Reference to a collection list for excluding specific collections (programs, shows) from this product. Matched collections must not carry the buyer's ads. Use for brand safety do-not-air lists. Seller must declare support in get_adcp_capabilities." ), ] = None age_restriction: Annotated[ AgeRestriction | None, Field( description='Age restriction for compliance. Use for legal requirements (alcohol, gambling), not audience targeting.' ), ] = None device_platform: Annotated[ list[device_platform_1.DevicePlatform] | None, Field( description='Restrict to specific platforms. Use for technical compatibility (app only works on iOS). Values from Sec-CH-UA-Platform standard, extended for CTV.', min_length=1, ), ] = None device_type: Annotated[ list[device_type_1.DeviceType] | None, Field( description='Restrict to specific device form factors. Use for campaigns targeting hardware categories rather than operating systems (e.g., mobile-only promotions, CTV campaigns).', min_length=1, ), ] = None device_type_exclude: Annotated[ list[device_type_1.DeviceType] | None, Field( description='Exclude specific device form factors from delivery (e.g., exclude CTV for app-install campaigns).', min_length=1, ), ] = None store_catchments: Annotated[ list[StoreCatchment] | None, Field( description='Target users within store catchment areas from a synced store catalog. Each entry references a store-type catalog and optionally narrows to specific stores or catchment zones.', min_length=1, ), ] = None geo_proximity: Annotated[ list[GeoProximityItem] | None, Field( description='Target users within travel time, distance, or a custom boundary around arbitrary geographic points. Multiple entries use OR semantics — a user within range of any listed point is eligible. For campaigns targeting 10+ locations, consider using store_catchments with a location catalog instead. Seller must declare support in get_adcp_capabilities.', min_length=1, ), ] = None language: Annotated[ list[LanguageItem] | None, Field( description="Restrict to users with specific language preferences. ISO 639-1 codes (e.g., 'en', 'es', 'fr').", min_length=1, ), ] = None keyword_targets: Annotated[ list[KeywordTarget] | None, Field( description='Keyword targeting for search and retail media platforms. Restricts delivery to queries matching the specified keywords. Each keyword is identified by the tuple (keyword, match_type) — the same keyword string with different match types are distinct targets. Sellers SHOULD reject duplicate (keyword, match_type) pairs within a single request. Seller must declare support in get_adcp_capabilities.', min_length=1, ), ] = None negative_keywords: Annotated[ list[NegativeKeyword] | None, Field( description='Keywords to exclude from delivery. Queries matching these keywords will not trigger the ad. Each negative keyword is identified by the tuple (keyword, match_type). Seller must declare support in get_adcp_capabilities.', min_length=1, ), ] = 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 : adcp.types.generated_poc.core.targeting.AgeRestriction | Nonevar audience_exclude : list[str] | Nonevar audience_include : list[str] | Nonevar axe_exclude_segment : str | Nonevar axe_include_segment : str | Nonevar collection_list : adcp.types.generated_poc.core.collection_list_ref.CollectionListReference | Nonevar collection_list_exclude : adcp.types.generated_poc.core.collection_list_ref.CollectionListReference | Nonevar daypart_targets : list[adcp.types.generated_poc.core.daypart_target.DaypartTarget] | Nonevar device_platform : list[adcp.types.generated_poc.enums.device_platform.DevicePlatform] | Nonevar device_type : list[adcp.types.generated_poc.enums.device_type.DeviceType] | Nonevar device_type_exclude : list[adcp.types.generated_poc.enums.device_type.DeviceType] | Nonevar frequency_cap : adcp.types.generated_poc.core.frequency_cap.FrequencyCap | Nonevar geo_countries : list[adcp.types.generated_poc.core.targeting.GeoCountry] | Nonevar geo_countries_exclude : collections.abc.Sequence[adcp.types.generated_poc.core.targeting.GeoCountriesExcludeItem] | Nonevar geo_metros : list[adcp.types.generated_poc.core.targeting.GeoMetro] | Nonevar geo_metros_exclude : collections.abc.Sequence[adcp.types.generated_poc.core.targeting.GeoMetrosExcludeItem] | Nonevar geo_postal_areas : list[adcp.types.generated_poc.core.postal_area.PostalArea] | Nonevar geo_postal_areas_exclude : collections.abc.Sequence[adcp.types.generated_poc.core.postal_area.PostalArea] | Nonevar geo_proximity : list[adcp.types.generated_poc.core.targeting.GeoProximityItem] | Nonevar geo_regions : list[adcp.types.generated_poc.core.targeting.GeoRegion] | Nonevar geo_regions_exclude : collections.abc.Sequence[adcp.types.generated_poc.core.targeting.GeoRegionsExcludeItem] | Nonevar keyword_targets : list[adcp.types.generated_poc.core.targeting.KeywordTarget] | Nonevar language : list[adcp.types.generated_poc.core.targeting.LanguageItem] | Nonevar model_configvar negative_keywords : list[adcp.types.generated_poc.core.targeting.NegativeKeyword] | Nonevar property_list : adcp.types.generated_poc.core.property_list_ref.PropertyListReference | Nonevar signal_targeting : list[adcp.types.generated_poc.core.signal_targeting.SignalTargeting] | Nonevar signal_targeting_groups : adcp.types.generated_poc.core.package_signal_targeting_groups.PackageSignalTargetingGroups | Nonevar store_catchments : list[adcp.types.generated_poc.core.targeting.StoreCatchment] | None
Inherited members
class UpdateMediaBuyRequest (**data: Any)-
Expand source code
class UpdateMediaBuyRequest(AdcpVersionEnvelope): model_config = ConfigDict( extra='allow', ) account: Annotated[ account_ref.AccountReference, Field( description='Account that owns this media buy. Pass a natural key (brand, operator, optional sandbox) or a seller-assigned account_id from list_accounts. Required for governance checks and account resolution.' ), ] media_buy_id: Annotated[str, Field(description="Seller's ID of the media buy to update")] revision: Annotated[ int | None, Field( description="Expected current revision for optimistic concurrency. Optional for backward compatibility. When provided, sellers MUST reject the update with CONFLICT if the media buy's current revision does not match, and MUST enforce that comparison atomically with the write. Obtain from get_media_buys or the most recent create/update response.", ge=1, ), ] = None paused: Annotated[ bool | None, Field(description='Pause/resume the entire media buy (true = paused, false = active)'), ] = None canceled: Annotated[ Literal[True] | None, Field( description='Cancel the entire media buy. Cancellation is irreversible — canceled media buys cannot be reactivated. Sellers MAY reject with NOT_CANCELLABLE if the media buy cannot be canceled in its current state.' ), ] = None cancellation_reason: Annotated[ str | None, Field( description='Reason for cancellation. Sellers SHOULD store this and return it in subsequent get_media_buys responses.', max_length=500, ), ] = None start_time: start_timing.StartTiming | None = None end_time: Annotated[ AwareDatetime | None, Field(description='New end date/time in ISO 8601 format') ] = None packages: Annotated[ Sequence[package_update.PackageUpdate] | None, Field(description='Package-specific updates for existing packages', min_length=1), ] = None invoice_recipient: Annotated[ business_entity.BusinessEntity | None, Field( description="Update who receives the invoice for this buy. When provided, the seller invoices this entity instead of the account's default billing_entity. The seller MUST validate the invoice recipient is authorized for this account. When governance_agents are configured, the seller MUST include invoice_recipient in the check_governance request." ), ] = None new_packages: Annotated[ list[package_request.PackageRequest] | None, Field( description='New packages to add to this media buy. Uses the same schema as create_media_buy packages. Sellers that support mid-flight package additions advertise `add_packages` in both `valid_actions[]` (deprecated) and as an entry in `available_actions[]` (authoritative). Sellers that do not support this MUST reject with ACTION_NOT_ALLOWED (preferred) or UNSUPPORTED_FEATURE (legacy).', min_length=1, ), ] = None reporting_webhook: Annotated[ reporting_webhook_1.ReportingWebhook | None, Field( description='Optional webhook configuration for automated reporting delivery. Updates the reporting configuration for this media buy.' ), ] = None push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( description='Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time. This is separate from reporting_webhook which configures ongoing campaign reporting.' ), ] = None idempotency_key: Annotated[ str, Field( description='Client-generated idempotency key for safe retries. If an update fails without a response, resending with the same idempotency_key guarantees the update is applied at most once. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request.', max_length=255, min_length=16, pattern='^[A-Za-z0-9_.:-]{16,255}$', ), ] context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = 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
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var account : adcp.types.generated_poc.core.account_ref.AccountReferencevar canceled : Literal[True] | Nonevar cancellation_reason : str | Nonevar context : adcp.types.generated_poc.core.context.ContextObject | Nonevar end_time : pydantic.types.AwareDatetime | Nonevar ext : adcp.types.generated_poc.core.ext.ExtensionObject | Nonevar idempotency_key : strvar invoice_recipient : adcp.types.generated_poc.core.business_entity.BusinessEntity | Nonevar media_buy_id : strvar model_configvar new_packages : list[adcp.types.generated_poc.media_buy.package_request.PackageRequest] | Nonevar packages : collections.abc.Sequence[adcp.types.generated_poc.media_buy.package_update.PackageUpdate] | Nonevar paused : bool | Nonevar push_notification_config : adcp.types.generated_poc.core.push_notification_config.PushNotificationConfig | Nonevar reporting_webhook : adcp.types.generated_poc.core.reporting_webhook.ReportingWebhook | Nonevar revision : int | Nonevar start_time : adcp.types.generated_poc.core.start_timing.StartTiming | None
Inherited members
class VerifyBrandClaimsRequest (**data: Any)-
Expand source code
class VerifyBrandClaimsRequest(VerifyBrandClaimsRequestBulk): 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
- adcp.types.generated_poc.brand.verify_brand_claims_request.VerifyBrandClaimsRequestBulk
- adcp.types.generated_poc.core.version_envelope.AdcpVersionEnvelope
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members