Module adcp.types.domains.core.placement

Classes

class Identifier (**data: Any)
Expand source code
class Identifier(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    type: identifier_types.PropertyIdentifierTypes
    value: Annotated[
        str,
        Field(
            description='Identifier value, optionally authority-prefixed for externally governed IDs (e.g., space:1234931339).'
        ),
    ]

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Class variables

var model_config
var type : PropertyIdentifierTypes
var value : str

Inherited members

class Kind (*args, **kwds)
Expand source code
class Kind(StrEnum):
    publisher_ref = 'publisher_ref'
    seller_inline = 'seller_inline'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var publisher_ref
var seller_inline
class Mode (*args, **kwds)
Expand source code
class Mode(StrEnum):
    targetable = 'targetable'
    included = 'included'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var included
var targetable
class Placement (**data: Any)
Expand source code
class Placement(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    kind: Annotated[
        Kind,
        Field(
            description='Placement authority discriminator. `publisher_ref` is publisher-catalog identity; `seller_inline` is sales-agent-authored identity.'
        ),
    ]
    placement_id: Annotated[
        str,
        Field(
            description='Placement identifier. For publisher_ref it is scoped by publisher_domain and resolves in adagents.json. For seller_inline it is scoped by seller_agent, or by the enclosing seller and product for legacy rows.'
        ),
    ]
    publisher_domain: Annotated[
        str | None,
        Field(
            description="For publisher_ref, the domain whose adagents.json declares the placement and part of canonical identity. For seller_inline, optional inventory-publisher attribution only; it does not grant the seller authority to mint IDs in that publisher's catalog namespace.",
            pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$',
        ),
    ] = None
    seller_agent: Annotated[
        seller_agent_ref.SellerAgentReference | None,
        Field(
            description='Sales agent that defines a seller_inline placement. Together with placement_id this is its self-contained identity. New 3.2 sellers SHOULD populate it; legacy product-context inline placements may omit it. Not used for publisher_ref.'
        ),
    ] = None
    name: Annotated[
        str | None,
        Field(
            description='Human-readable name for the placement (e.g., \'Homepage Banner\', \'Article Sidebar\'). Required for `kind: "seller_inline"`. May be omitted for publisher-referenced placements because buyers resolve the name from the publisher declaration identified by `{publisher_domain, placement_id}`.'
        ),
    ] = None
    description: Annotated[
        str | None, Field(description='Detailed description of where and how the placement appears')
    ] = None
    mode: Annotated[
        Mode,
        Field(
            description="Required product-level relationship to this placement. targetable means the buyer may include the publisher-scoped ref in targeting_overlay.placement_selection; a creative may be routed there only after it is purchased. included means fixed product inventory: it cannot be independently selected, but across discovery, create, and update a selected request exactly equal to the product's complete included placement set is an inherent restatement and may be echoed on the package without overlay_support.placement_selection. A product containing any included placement MUST NOT declare overlay_support.placement_selection; partial selection requires a separately selectable product configuration. During the migration window ending 2026-11-25, buyers MAY tolerate legacy products that omit mode and treat them as targetable; after that date buyers SHOULD fail closed."
        ),
    ]
    tags: Annotated[
        list[str] | None,
        Field(
            description="Optional tags for grouping placements within a product (e.g., 'homepage', 'native', 'premium'). When the placement_id comes from the publisher registry, these should align with the registry tags unless the product is narrowing scope."
        ),
    ] = None
    format_ids: Annotated[
        Sequence[format_id.FormatReferenceStructuredObject] | None,
        Field(
            deprecated=True,
            description='Deprecated in AdCP 3.2; removed in AdCP 4.0. Legacy named-format placement narrowing. Can include concrete, template, or parameterized format IDs. When present on a product placement, this field narrows the product-level `format_ids` contract and MUST NOT introduce formats the product does not accept. Use canonical `format_options`.',
            min_length=1,
        ),
    ] = None
    format_options: Annotated[
        list[product_format_declaration.ProductFormatDeclaration] | None,
        Field(
            description="Canonical seller-side narrowing for this product placement. When present, these declarations are intersected with the product-level format_options and MUST NOT introduce a format outside that product upper bound. For kind publisher_ref, buyers MUST also resolve {publisher_domain, placement_id} in the publisher's adagents.json and intersect the publisher catalog constraint: use the public placement's format_options when present (resolving bare format_option_id references against same-file top-level formats[]), otherwise use applicable top-level formats[] scoped to that placement's properties. Omitting this inline field removes only the seller-inline layer; it does not bypass a publisher placement or property-scoped narrowing. The placement inherits the full product-level set only when no applicable publisher catalog narrowing exists. Unresolved publisher placement or format-option references fail closed. Locale policy participates in the same intersection: when the product policy is absent, a placement may introduce any concrete policy as a narrowing of the unconstrained option; when both are present, every placement accepted_language_range must be contained by a product range under RFC 4647 Basic Filtering (`fr-CA` narrows `fr`; `fr` does not narrow `fr-CA`). Buyers compute effective locale eligibility independently for each placement. Any effective locale-constrained route is canonical-only and has no projecting product or placement format_id.",
            min_length=1,
        ),
    ] = None
    video_placement_types: Annotated[
        list[video_placement_type.VideoPlacementType] | None,
        Field(
            description='Declared video placement types for this product placement, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    audio_distribution_types: Annotated[
        list[audio_distribution_type.AudioDistributionType] | None,
        Field(
            description='Declared audio distribution types for this product placement, using IAB Tech Lab/OpenRTB 2.6 audio.feed definitions with AdCP-native names. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    sponsored_placement_types: Annotated[
        list[sponsored_placement_type.SponsoredPlacementType] | None,
        Field(
            description='Declared sponsored-placement types for this product placement, distinguishing where the catalog-driven retail-media placement renders on the retailer surface. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    social_placement_surfaces: Annotated[
        list[social_placement_surface.SocialPlacementSurface] | None,
        Field(
            description='Declared social-placement surfaces for this product placement, distinguishing the in-app surface where the social placement renders. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.',
            min_length=1,
        ),
    ] = None
    identifiers: Annotated[
        list[Identifier] | None,
        Field(
            description='Optional external inventory identifiers for this placement, using the same {type, value} shape as property identifiers. Externally governed IDs should be authority-prefixed (e.g., space:1234931339, geopath:30961, fcc:73953). Seller-local IDs are opaque values scoped by the surrounding publisher namespace. Useful for DOOH venue and installed-endpoint IDs, broadcast facility IDs, and any channel where placements map to externally registered inventory. For kind: publisher_ref, the effective identifier set is the union of the resolved publisher declaration and this product declaration, de-duplicated by exact (type, value); a product cannot suppress a publisher-declared identifier by omission.',
            min_length=1,
        ),
    ] = None
    dooh_placement_attributes: ProductDoohPlacementAttributes | None = None

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

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Subclasses

Class variables

var audio_distribution_types : list[AudioDistributionType] | None
var description : str | None
var dooh_placement_attributes : ProductDoohPlacementAttributes | None
var format_ids : collections.abc.Sequence[FormatReferenceStructuredObject] | None
var format_options : list[ProductFormatDeclaration1 | ProductFormatDeclaration2 | ProductFormatDeclaration3 | ProductFormatDeclaration4 | ProductFormatDeclaration5 | ProductFormatDeclaration6 | ProductFormatDeclaration7 | ProductFormatDeclaration8 | ProductFormatDeclaration9 | ProductFormatDeclaration10 | ProductFormatDeclaration11 | ProductFormatDeclaration12 | ProductFormatDeclaration13 | ProductFormatDeclaration14 | ProductFormatDeclaration15 | ProductFormatDeclaration16] | None
var identifiers : list[Identifier] | None
var kind : Kind
var mode : Mode
var model_config
var name : str | None
var placement_id : str
var publisher_domain : str | None
var seller_agent : SellerAgentReference | None
var social_placement_surfaces : list[SocialPlacementSurface] | None
var sponsored_placement_types : list[SponsoredPlacementType] | None
var tags : list[str] | None
var video_placement_types : list[VideoPlacementType] | None

Inherited members

class ProductDoohPlacementAttributes (**data: Any)
Expand source code
class ProductDoohPlacementAttributes(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    slot_duration_seconds: Annotated[
        SchemaInt | None,
        Field(
            description='Scheduled duration of one ad slot in seconds. This is an inventory fact used for loop and share calculations, not the creative-duration contract.',
            ge=1,
        ),
    ] = None
    loop_duration_seconds: Annotated[
        SchemaInt | None,
        Field(
            description='Duration of the full ad loop rotation in seconds and the canonical source for loop duration.',
            ge=1,
        ),
    ] = None
    screen_resolution: ProductDoohScreenResolution | None = None
    motion: Annotated[
        dooh_motion_type.DoohMotionType | None,
        Field(
            description='Physical motion capability of a visual DOOH screen, not an accepted-format declaration. Omit for audio-only placements.'
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Class variables

var loop_duration_seconds : int | None
var model_config
var motion : DoohMotionType | None
var screen_resolution : ProductDoohScreenResolution | None
var slot_duration_seconds : int | None

Inherited members

class ProductDoohScreenResolution (**data: Any)
Expand source code
class ProductDoohScreenResolution(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    width: Annotated[SchemaInt, Field(description='Screen width in pixels.', ge=1)]
    height: Annotated[SchemaInt, Field(description='Screen height in pixels.', ge=1)]

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Class variables

var height : int
var model_config
var width : int

Inherited members