Module adcp.types.domains.compliance

Types the AdCP compliance schemas declare.

Importing from the domain says which variant you mean, where the flat adcp.types namespace can only bind one class per name:

from adcp.types.domains.compliance import <Type>

A type this domain declares in more than one schema is not here: import it from its own schema's module, adcp.types.domains.compliance.<schema>. Nothing here is renamed.

Auto-generated from the generated domain tree. DO NOT EDIT MANUALLY. Generation date: 2026-10-04 18:45:11 UTC

Sub-modules

adcp.types.domains.compliance.comply_test_controller_request
adcp.types.domains.compliance.comply_test_controller_response
adcp.types.domains.compliance.get_creative_features_completion
adcp.types.domains.compliance.task_completion_data

Classes

class Account (**data: Any)
Expand source code
class Account(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    sandbox: Annotated[
        Literal[True],
        Field(
            description='MUST be true. The seller MUST verify the targeted account is sandbox by looking up the persisted account record, not by trusting this field. A request asserting sandbox: false schema-rejects before reaching the seller — defense-in-depth on top of the per-request gate.'
        ),
    ]

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 sandbox : Literal[True]

Inherited members

class AdvanceTo (*args, **kwds)
Expand source code
class AdvanceTo(StrEnum):
    within_grace = 'within_grace'
    past_grace = 'past_grace'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var past_grace
var within_grace
class Arm (*args, **kwds)
Expand source code
class Arm(StrEnum):
    submitted = 'submitted'
    completed = 'completed'
    input_required = 'input-required'
    rejected = 'rejected'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var completed
var input_required
var rejected
var submitted
class AttestationMode (*args, **kwds)
Expand source code
class AttestationMode(StrEnum):
    raw = 'raw'
    digest = 'digest'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var digest
var raw
class ComplyResponseArm (*args, **kwds)
Expand source code
class ComplyResponseArm(StrEnum):
    submitted = 'submitted'
    completed = 'completed'
    input_required = 'input-required'
    rejected = 'rejected'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var completed
var input_required
var rejected
var submitted
class ComplyTestControllerRequest (**data: Any)
Expand source code
class ComplyTestControllerRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    scenario: Annotated[
        str,
        Field(
            description="Test scenario to execute. 'list_scenarios' discovers supported scenarios. 'force_*' and 'simulate_*' trigger state transitions. 'reporting_core_lifecycle_probe' installs a caller/account-scoped Core fixture whose first elapsed obligation is visible before any report, advances its virtual clock into delayed or action_required, and can publish deterministic zero-row or non-empty revisions, restate a provisional revision, restate one the caller already received, or cross the consumer-status deadline and consumer-mismatch escalation boundaries, without waiting for wall-clock boundaries. Other scenarios provide deterministic sandbox probes for their documented lifecycle checks. Runners and sellers MUST accept unknown scenario strings - new scenarios may be added in additive releases."
        ),
    ]
    params: Annotated[
        Params | None,
        Field(
            description='Scenario-specific parameters. Required for all scenarios except list_scenarios.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None
    account: Annotated[
        Account | None,
        Field(
            description="Sandbox account assertion. The runner MUST set sandbox: true on every comply_test_controller request. The seller MUST refuse the request (returning a structured error) if the targeted account is not a sandbox account in the seller's persisted records. This field is a caller-side declaration of intent — it does not grant sandbox status; sellers verify against their own account state. The (Sandbox) verification tier is defined by this gate: real production endpoints accept sandbox-flagged traffic and process it without real-world side effects, no separate test-mode endpoint required. See spec issue #3755 and the (Sandbox) framing in #4379."
        ),
    ] = None

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

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

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

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

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

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

Ancestors

Class variables

var account : Account | None
var context : ContextObject | None
var ext : ExtensionObject | None
var model_config
var params : Params | None
var scenario : str

Inherited members

class ComplyTestControllerResponse (**data: Any)
Expand source code
class ComplyTestControllerResponse(AdcpResponse, ResponseArmDispatchMixin, AdcpVersionEnvelope, ProtocolEnvelope):
    """Constructible compatibility base for generated response arms."""

    @classmethod
    def _response_arm_models(cls) -> tuple[type[ComplyTestControllerResponse], ...]:
        return (
            ComplyTestControllerResponse1,
            ComplyTestControllerResponse2,
            ComplyTestControllerResponse3,
            ComplyTestControllerResponse4,
            ComplyTestControllerResponse5,
            ComplyTestControllerResponse6,
            ComplyTestControllerResponse7,
            ComplyTestControllerResponse8,
        )

Constructible compatibility base for generated response arms.

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 model_config

Inherited members

class ComplyTestControllerResponse1 (**data: Any)
Expand source code
class ComplyTestControllerResponse1(ComplyTestControllerResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    success: Literal[True]
    scenarios: Annotated[
        list[str],
        Field(
            description='Scenarios this seller has implemented. Runners and sellers MUST accept unknown scenario strings (open-for-extension) — new scenarios may be added in additive releases. Adopters who advertise `catalog_item_availability_probe` support deterministic cross-principal reference, eligibility-gate, expiry-clock, and catalog-generation tests for the catalog availability storyboard. Adopters who advertise `compact_product_lifecycle_probe` support deterministic synchronous list/request/finalize/decline/accept/control/readback behavior for a prepared product and strict post-deadline expiry of a committed proposal. Adopters who advertise `compact_direct_buy_lifecycle_probe` support deterministic synchronous list/buy/control/readback behavior for a prepared product. Adopters who advertise `reporting_core_lifecycle_probe` support deterministic obligation-before-report, clock-health, zero-row reporting, provisional-restatement, and post-received restatement-grace tests without wall-clock waits. `reliable_reporting_core_integrity_probe`, `reliable_reporting_managed_delivery_probe`, and `reliable_reporting_reconciled_billing_probe` seed the source-calendar/checkpoint, managed-resource, and receipt/adjustment workflows used by the Reliable Reporting tier storyboards. Adopters who advertise `force_creative_purge` opt in to deterministic creative purge coverage for account-level lifecycle webhooks. Adopters who advertise `force_media_buy_purge` opt in to deterministic deletion-independent idempotency replay coverage. Adopters who advertise `seed_measurement_catalog` opt in to deterministic measurement-catalog fixtures used by vendor_metric precondition storyboards. Adopters who advertise `query_upstream_traffic` opt in to the upstream-traffic conformance contract; storyboards that declare `check: upstream_traffic` grade not_applicable against adopters who do not advertise it. Adopters who advertise `query_provenance_audit_observations` opt in to sandbox-only audit-observation assertions for accepted creatives. Adopters who advertise `force_upstream_unavailable` opt in to stale-cache conformance testing via the `stale_response_advisory` storyboard.'
        ),
    ]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Constructible compatibility base for generated response arms.

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

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

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

Ancestors

Class variables

var context : ContextObject | None
var ext : ExtensionObject | None
var model_config
var scenarios : list[str]
var success : Literal[True]

Inherited members

class ComplyTestControllerResponse2 (**data: Any)
Expand source code
class ComplyTestControllerResponse2(ComplyTestControllerResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    success: Literal[True]
    previous_state: Annotated[str, Field(description='State before this transition')]
    current_state: Annotated[str, Field(description='State after this transition')]
    message: Annotated[
        str | None, Field(description='Human-readable description of the transition')
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Constructible compatibility base for generated response arms.

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

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

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

Ancestors

Class variables

var context : ContextObject | None
var current_state : str
var ext : ExtensionObject | None
var message : str | None
var model_config
var previous_state : str
var success : Literal[True]

Inherited members

class ComplyTestControllerResponse3 (**data: Any)
Expand source code
class ComplyTestControllerResponse3(ComplyTestControllerResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    success: Literal[True]
    simulated: Annotated[
        dict[str, Any],
        Field(description='Values injected or applied by this call. Shape depends on scenario.'),
    ]
    cumulative: Annotated[
        dict[str, Any] | None,
        Field(description='Running totals across all simulation calls (simulate_delivery only)'),
    ] = None
    message: str | None = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Constructible compatibility base for generated response arms.

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

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

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

Ancestors

Class variables

var context : ContextObject | None
var cumulative : dict[str, typing.Any] | None
var ext : ExtensionObject | None
var message : str | None
var model_config
var simulated : dict[str, typing.Any]
var success : Literal[True]

Inherited members

class ComplyTestControllerResponse4 (**data: Any)
Expand source code
class ComplyTestControllerResponse4(ComplyTestControllerResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    success: Literal[True]
    forced: Annotated[
        Forced,
        Field(
            description='Echo of the registered directive. The next matching operation call from this sandbox account will return the named arm.'
        ),
    ]
    message: Annotated[str | None, Field(description='Human-readable acknowledgement.')] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Constructible compatibility base for generated response arms.

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

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

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

Ancestors

Class variables

var context : ContextObject | None
var ext : ExtensionObject | None
var forced : Forced
var message : str | None
var model_config
var success : Literal[True]

Inherited members

class ComplyTestControllerResponse5 (**data: Any)
Expand source code
class ComplyTestControllerResponse5(ComplyTestControllerResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    success: Literal[True]
    message: Annotated[str | None, Field(description='Human-readable acknowledgement.')] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Constructible compatibility base for generated response arms.

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

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

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

Ancestors

Class variables

var context : ContextObject | None
var ext : ExtensionObject | None
var message : str | None
var model_config
var success : Literal[True]

Inherited members

class ComplyTestControllerResponse6 (**data: Any)
Expand source code
class ComplyTestControllerResponse6(ComplyTestControllerResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    success: Literal[True]
    creative_id: Annotated[
        str, Field(description='Creative ID whose audit observations were queried.')
    ]
    audit_observations: Annotated[
        list[audit_observation.CreativeAuditObservation],
        Field(description='Audit observations recorded for the creative in the sandbox session.'),
    ]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Constructible compatibility base for generated response arms.

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 audit_observations : list[CreativeAuditObservation]
var context : ContextObject | None
var creative_id : str
var ext : ExtensionObject | None
var model_config
var success : Literal[True]

Inherited members

class ComplyTestControllerResponse7 (**data: Any)
Expand source code
class ComplyTestControllerResponse7(ComplyTestControllerResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    success: Literal[True]
    recorded_calls: Annotated[
        list[RecordedCalls],
        Field(
            description="Outbound HTTP calls caused by the requesting principal in the requested window, ordered by `timestamp` ascending. Cross-caller calls MUST NOT appear here. Each item declares its `attestation_mode`: `raw` items carry the full `payload`; `digest` items carry `payload_digest_sha256` + `payload_length` + optional `identifier_match_proofs[]` instead, for adopters who can't return raw payloads under their privacy/data-residency policy."
        ),
    ]
    total_count: Annotated[
        SchemaInt,
        Field(
            description='Total calls in the requested window before any pagination — `recorded_calls.length` may be smaller when `params.limit` truncated the response.',
            ge=0,
        ),
    ]
    truncated: Annotated[
        StrictBool | None,
        Field(
            description='True when `total_count > recorded_calls.length`. Runners MAY raise the `limit` and re-query, but storyboards SHOULD declare assertions that fit within the default 100-call window — a truncated response is a signal that the storyboard step is causing more upstream activity than expected.'
        ),
    ] = None
    since_timestamp: Annotated[
        AwareDatetime,
        Field(
            description="Echo of the `since_timestamp` the runner requested (or the session-start timestamp the adopter substituted when the runner omitted it). Informational — the runner SHOULD use its own clock-bracket of when it issued the AdCP step request, not this echo, when attributing recorded_calls to a specific step. The controller is part of the adopter's claimed conformance; the echo is not adversarially trustworthy."
        ),
    ]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Constructible compatibility base for generated response arms.

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

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

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

Ancestors

Class variables

var context : ContextObject | None
var ext : ExtensionObject | None
var model_config
var recorded_calls : list[RecordedCalls1 | RecordedCalls2]
var since_timestamp : pydantic.types.AwareDatetime
var success : Literal[True]
var total_count : int
var truncated : bool | None

Inherited members

class ComplyTestControllerResponse8 (**data: Any)
Expand source code
class ComplyTestControllerResponse8(ComplyTestControllerResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    success: Literal[False]
    error: Annotated[
        Error,
        Field(
            description='Structured error code. `JCS_NON_FINITE_NUMBER` is reserved for digest-mode upstream_traffic responses that cannot be RFC 8785/JCS-canonicalized because the parsed JSON-like value tree contains a non-finite numeric value (`NaN`, `+Infinity`, or `-Infinity`); controllers MUST NOT coerce those values during digest computation, and runners grade that validation `not_applicable`, not failed.'
        ),
    ]
    error_detail: Annotated[
        str | None, Field(description='Human-readable explanation of the failure')
    ] = None
    current_state: Annotated[
        str | None, Field(description='Current state of the entity, or null if not found')
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

Constructible compatibility base for generated response arms.

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

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

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

Ancestors

Class variables

var context : ContextObject | None
var current_state : str | None
var error : Error
var error_detail : str | None
var ext : ExtensionObject | None
var model_config
var success : Literal[False]

Inherited members

class Error (*args, **kwds)
Expand source code
class Error(StrEnum):
    INVALID_TRANSITION = 'INVALID_TRANSITION'
    INVALID_STATE = 'INVALID_STATE'
    NOT_FOUND = 'NOT_FOUND'
    UNKNOWN_SCENARIO = 'UNKNOWN_SCENARIO'
    INVALID_PARAMS = 'INVALID_PARAMS'
    FORBIDDEN = 'FORBIDDEN'
    JCS_NON_FINITE_NUMBER = 'JCS_NON_FINITE_NUMBER'
    INTERNAL_ERROR = 'INTERNAL_ERROR'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var FORBIDDEN
var INTERNAL_ERROR
var INVALID_PARAMS
var INVALID_STATE
var INVALID_TRANSITION
var JCS_NON_FINITE_NUMBER
var NOT_FOUND
var UNKNOWN_SCENARIO
class Forced (**data: Any)
Expand source code
class Forced(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    arm: Annotated[
        ComplyResponseArm, Field(description='ComplyResponseArm the seller will emit on the next forced operation response.')
    ]
    task_id: Annotated[
        str | None,
        Field(
            description="Echo of the registered task_id. Present only when arm is 'submitted' (the arm that emits a task envelope).",
            max_length=128,
        ),
    ] = None
    evaluation_id: Annotated[
        str | None,
        Field(
            description='Echo of the provider evaluation identity registered by force_get_creative_features_arm.',
            max_length=255,
            min_length=1,
        ),
    ] = None
    reason: Annotated[
        str | None,
        Field(
            description="Echo of the deterministic buyer-facing rejection reason. Required when arm is 'rejected'.",
            max_length=2000,
            min_length=1,
        ),
    ] = None
    suggestions: Annotated[
        list[Suggestion] | None,
        Field(
            description='Echo of the optional deterministic alternatives registered for a rejected get_products response.',
            max_length=20,
            min_length=1,
        ),
    ] = 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 arm : ComplyResponseArm
var evaluation_id : str | None
var model_config
var reason : str | None
var suggestions : list[Suggestion] | None
var task_id : str | None

Inherited members

class GetCreativeFeaturesComplianceCompletion (**data: Any)
Expand source code
class GetCreativeFeaturesComplianceCompletion(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    status: Literal['completed'] = 'completed'
    evaluation_id: Annotated[str, Field(min_length=1)]
    results: list[creative_feature_result.CreativeFeatureResult]
    pricing_option_id: str | None = None
    vendor_cost: Annotated[StrictFloat | None, Field(ge=0.0)] = None
    currency: Annotated[str | None, Field(pattern='^[A-Z]{3}$')] = None
    consumption: creative_consumption.CreativeConsumption | None = None

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Class variables

var consumption : CreativeConsumption | None
var currency : str | None
var evaluation_id : str
var model_config
var pricing_option_id : str | None
var results : list[CreativeFeatureResult]
var status : Literal['completed']
var vendor_cost : float | None

Inherited members

class IdentifierMatchProof (**data: Any)
Expand source code
class IdentifierMatchProof(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    identifier_value_sha256: Annotated[
        str,
        Field(
            description='Echo of one digest from `params.identifier_value_digests` so the runner can pair this proof with the identifier it queried.',
            pattern='^[a-f0-9]{64}$',
        ),
    ]
    found: Annotated[
        StrictBool,
        Field(
            description='True if any string token in the recorded payload hashes to the queried digest. False otherwise.'
        ),
    ]

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 found : bool
var identifier_value_sha256 : str
var model_config

Inherited members

class Kind (*args, **kwds)
Expand source code
class Kind(StrEnum):
    cumulative = 'cumulative'
    period = 'period'
    rolling = 'rolling'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var cumulative
var period
var rolling
class Method (*args, **kwds)
Expand source code
class Method(StrEnum):
    GET = 'GET'
    POST = 'POST'
    PUT = 'PUT'
    PATCH = 'PATCH'
    DELETE = 'DELETE'
    HEAD = 'HEAD'
    OPTIONS = 'OPTIONS'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var DELETE
var GET
var HEAD
var OPTIONS
var PATCH
var POST
var PUT
class Metric (**data: Any)
Expand source code
class Metric(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    metric_id: vendor_metric_id.VendorMetricId

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 metric_id : VendorMetricId
var model_config

Inherited members

class NotYetMeasurableVendorMetric (**data: Any)
Expand source code
class NotYetMeasurableVendorMetric(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    vendor: brand_ref.BrandReference
    metric_id: vendor_metric_id.VendorMetricId
    qualifier: Annotated[
        committed_metric.Qualifier | None,
        Field(
            description='Qualifier for the exact committed vendor-metric row whose measurement is deferred.'
        ),
    ] = None

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Subclasses

Class variables

var metric_id : VendorMetricId
var model_config
var qualifier : Qualifier | None
var vendor : BrandReference

Inherited members

class NotYetMeasurableVendorMetricsByPackageItem (**data: Any)
Expand source code
class NotYetMeasurableVendorMetricsByPackageItem(NotYetMeasurableVendorMetric):
    pass

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

Inherited members

class Operation (*args, **kwds)
Expand source code
class Operation(StrEnum):
    seed_inaccessible_item = 'seed_inaccessible_item'
    query_eligibility = 'query_eligibility'
    advance_time = 'advance_time'
    recreate_catalog = 'recreate_catalog'
    prepare = 'prepare'
    expire_proposal = 'expire_proposal'
    publish_zero_row = 'publish_zero_row'
    publish_nonempty = 'publish_nonempty'
    restate_snapshot = 'restate_snapshot'
    restate_after_received = 'restate_after_received'
    omit_obligation = 'omit_obligation'
    advance_past_status_deadline = 'advance_past_status_deadline'
    advance_past_escalation = 'advance_past_escalation'
    publish_official_adjustment = 'publish_official_adjustment'
    probe_scheduler_dst = 'probe_scheduler_dst'
    suppress_readiness = 'suppress_readiness'
    advance_within_retention = 'advance_within_retention'
    revoke_access = 'revoke_access'
    publish_adjustment = 'publish_adjustment'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var advance_past_escalation
var advance_past_status_deadline
var advance_time
var advance_within_retention
var expire_proposal
var omit_obligation
var prepare
var probe_scheduler_dst
var publish_adjustment
var publish_nonempty
var publish_official_adjustment
var publish_zero_row
var query_eligibility
var recreate_catalog
var restate_after_received
var restate_snapshot
var revoke_access
var seed_inaccessible_item
var suppress_readiness
class Params (**data: Any)
Expand source code
class Params(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    creative_id: Annotated[
        str | None,
        Field(
            description='Creative to transition (force_creative_status) or seed (seed_creative).'
        ),
    ] = None
    account_id: Annotated[
        str | None,
        Field(
            description='Account to transition, simulate, or seed. Used by force_account_status, simulate_budget_spend, and seed_account.'
        ),
    ] = None
    media_buy_id: Annotated[
        str | None,
        Field(
            description='Media buy to transition or purge (force_media_buy_status, force_media_buy_purge), simulate (simulate_delivery, simulate_budget_spend), or seed (seed_media_buy).'
        ),
    ] = None
    session_id: Annotated[
        str | None, Field(description='Session to transition. Used by force_session_status.')
    ] = None
    product_id: Annotated[
        str | None,
        Field(
            description='Product to seed or prepare for deterministic compact lifecycle testing. Used by seed_product, seed_pricing_option, compact_product_lifecycle_probe prepare, and compact_direct_buy_lifecycle_probe prepare.'
        ),
    ] = None
    proposal_id: Annotated[
        str | None,
        Field(
            description='Committed proposal whose hold the compact_product_lifecycle_probe expires.',
            min_length=1,
        ),
    ] = None
    pricing_option_id: Annotated[
        str | None,
        Field(
            description='Pricing option to seed, scoped to a product. Used by seed_pricing_option.'
        ),
    ] = None
    plan_id: Annotated[str | None, Field(description='Plan to seed. Used by seed_plan.')] = None
    rights_id: Annotated[
        str | None, Field(description='Rights grant to seed. Used by seed_rights_grant.')
    ] = None
    fixture: Annotated[
        dict[str, Any] | None,
        Field(
            description='Arbitrary fixture payload carried by seed_* scenarios. Shape matches the domain object the seed scenario creates (account, product, creative, plan, media buy, pricing option, rights grant). Seller MAY reject malformed fixtures with INVALID_PARAMS. Kept permissive so storyboard authors can declare the minimum shape each test needs without the spec locking down every field.'
        ),
    ] = None
    operation: Annotated[
        Operation | None,
        Field(
            description="Scenario-specific probe operation. catalog_item_availability_probe uses seed_inaccessible_item, query_eligibility, advance_time, and recreate_catalog. compact_product_lifecycle_probe uses prepare to make one seeded product's compact proposal, acceptance, operational-control, and MediaBuy readback path deterministic and expire_proposal to advance strictly beyond a committed proposal's stored expires_at and process the hold lapse. compact_direct_buy_lifecycle_probe uses prepare to make one seeded product's list, direct-purchase, operational-control, and readback path deterministic. reporting_core_lifecycle_probe uses prepare, advance_time, publish_zero_row, publish_nonempty, restate_snapshot, restate_after_received, omit_obligation, advance_past_status_deadline, and advance_past_escalation to exercise obligation availability, health deadlines, explicit reporting, provisional restatement, stale-received grace, buyer-side missing-obligation detection, counted consumer-status silence, and consumer-mismatch escalation. advance_past_status_deadline moves the clock strictly past expected_at plus the advertised automated_recovery_window_seconds without recording any consumer status, so obligation_counts.consumer_status_pending is gradable; advance_past_escalation moves it strictly past the open CONSUMER_STATUS_MISMATCH issue opened_at plus the advertised consumer_mismatch_escalation_seconds and returns both that boundary and any still-future stale_received_grace_deadline, so the escalation precedence rule is gradable. restate_snapshot publishes a new snapshot revision that immediately supersedes the current snapshot for the same logical slice and is invalid when the current revision is official. restate_after_received does the same restatement but only against the revision named in received_reporting_revision_id, so the stale-received grace projection can be graded live; it returns the grace deadline and advance_to positions the virtual clock inside or past it. Reliable Reporting tier probes use prepare plus publish_official_adjustment, probe_scheduler_dst, suppress_readiness, advance_within_retention, revoke_access, or publish_adjustment to seed deterministic Core-integrity, Managed Delivery, and Reconciled Billing lifecycle evidence."
        ),
    ] = None
    target_health: Annotated[
        TargetHealth | None,
        Field(
            description='Clock-derived health boundary selected by reporting_core_lifecycle_probe advance_time. The controller chooses the corresponding deterministic target time; callers do not supply timestamps.'
        ),
    ] = None
    received_reporting_revision_id: Annotated[
        str | None,
        Field(
            description="Revision the caller currently reports as received, required by reporting_core_lifecycle_probe restate_after_received. The seller MUST reject the operation unless this names the caller's current required revision for the fixture obligation, and a seller advertising consumer_status_task MUST additionally require a current received consumer status from this caller naming it. This binds the restatement to a real prior read instead of restating into a vacuum.",
            max_length=255,
            min_length=1,
            pattern='^[A-Za-z0-9_.:-]{1,255}$',
        ),
    ] = None
    advance_to: Annotated[
        AdvanceTo | None,
        Field(
            description='Where reporting_core_lifecycle_probe restate_after_received leaves the virtual clock relative to the returned stale_received_grace_deadline. within_grace grades the delayed projection; past_grace grades the escalation to action_required. Repeating the operation is convergent: it reuses the committed restatement and only moves the clock.'
        ),
    ] = AdvanceTo.within_grace
    catalog_id: Annotated[
        str | None,
        Field(
            description='Catalog operated on by catalog_item_availability_probe.',
            max_length=255,
            min_length=1,
        ),
    ] = None
    catalog_generation: Annotated[
        str | None,
        Field(
            description='Catalog incarnation operated on by catalog_item_availability_probe.',
            max_length=255,
            min_length=1,
        ),
    ] = None
    item_id: Annotated[
        str | None,
        Field(
            description='Catalog item operated on by catalog_item_availability_probe.',
            max_length=255,
            min_length=1,
        ),
    ] = None
    target_time: Annotated[
        AwareDatetime | None,
        Field(
            description='Deterministic sandbox clock target used by catalog_item_availability_probe advance_time.'
        ),
    ] = None
    status: Annotated[
        str | None,
        Field(
            description="Target status for the resource. Type depends on scenario: creative-status for force_creative_status, account-status for force_account_status, media-buy-status for force_media_buy_status. For force_session_status, must be 'complete' or 'terminated'."
        ),
    ] = None
    rejection_reason: Annotated[
        str | None,
        Field(
            description='Reason for rejection. Used by force_creative_status and force_media_buy_status when status = rejected.'
        ),
    ] = None
    purge_kind: Annotated[
        PurgeKind | None,
        Field(
            description='Purge mode for force_creative_purge. soft retains a list_creatives tombstone; hard removes the creative entirely.'
        ),
    ] = None
    reason_code: Annotated[
        creative_event_reason_code.CreativeEventReasonCode | None,
        Field(
            description='Creative lifecycle reason code for force_creative_status and force_creative_purge.'
        ),
    ] = None
    reason_detail: Annotated[
        str | None,
        Field(
            description='Human-readable detail for force_creative_status and force_creative_purge.'
        ),
    ] = None
    termination_reason: Annotated[
        str | None,
        Field(
            description='Reason for termination (e.g., session_timeout, host_terminated, policy_violation). Used by force_session_status when status = terminated.'
        ),
    ] = None
    impressions: Annotated[
        SchemaInt | None,
        Field(description='Impressions to simulate. Used by simulate_delivery.', ge=0),
    ] = None
    clicks: Annotated[
        SchemaInt | None, Field(description='Clicks to simulate. Used by simulate_delivery.', ge=0)
    ] = None
    plays: Annotated[
        SchemaInt | None,
        Field(
            description='Raw DOOH or broadcast plays to add to delivery. Used by simulate_delivery for single-package buys; sellers MUST surface the cumulative value at totals.plays and by_package[0].plays in the next get_media_buy_delivery response. Multi-package simulations require a future package-scoped form and MUST reject this media-buy-scoped field.',
            ge=0,
        ),
    ] = None
    dooh_metrics: Annotated[
        delivery_metrics.DoohMetrics | None,
        Field(
            description='DOOH delivery detail to inject. Used by simulate_delivery for single-package buys; the latest injected block replaces the previous simulated DOOH detail and MUST surface at totals.dooh_metrics and by_package[0].dooh_metrics. Multi-package simulations require a future package-scoped form and MUST reject this media-buy-scoped field.'
        ),
    ] = None
    conversions: Annotated[
        SchemaInt | None,
        Field(description='Conversions to simulate. Used by simulate_delivery.', ge=0),
    ] = None
    delivery_date: Annotated[
        date | None,
        Field(
            description="Calendar date, in the product's reporting_capabilities.timezone, attributable to this simulated delivery batch. Used by simulate_delivery to seed deterministic date-range tests. When get_media_buy_delivery supplies start_date or end_date, dated batches are included when delivery_date is greater than or equal to start_date and strictly less than end_date. Omit to preserve cumulative, unfiltered simulation behavior."
        ),
    ] = None
    conversion_value: Annotated[
        StrictFloat | None,
        Field(
            description='Total attributed conversion value to simulate in the delivery reporting currency. Used by simulate_delivery.',
            ge=0.0,
        ),
    ] = None
    commissionable_value: Annotated[
        StrictFloat | None,
        Field(
            description='Settled attributed value eligible for revenue-share commission to simulate in the delivery reporting currency. Used by simulate_delivery.',
            ge=0.0,
        ),
    ] = None
    reported_spend: Annotated[
        ReportedSpend | None,
        Field(
            description='Spend as reported in delivery data. Does not affect budget. Used by simulate_delivery.'
        ),
    ] = None
    reach: Annotated[
        StrictFloat | None,
        Field(
            description="Unique reach count to inject into the simulated delivery row. Used by simulate_delivery. The unit of measurement matches the reach_unit declared on the media buy's optimization goal. When supplied, sellers MUST surface this value at `totals.reach` in the next get_media_buy_delivery response.",
            ge=0.0,
        ),
    ] = None
    frequency: Annotated[
        StrictFloat | None,
        Field(
            description='Average frequency per reach unit to inject. Used by simulate_delivery. When supplied, sellers MUST surface this value at `totals.frequency`, including frequency-only delivery. The measurement window for this frequency value is declared in `reach_window` when also present.',
            ge=0.0,
        ),
    ] = None
    reach_unit: Annotated[
        reach_unit_1.ReachUnit | None,
        Field(
            description='Unit for an injected reach or frequency value. Used by simulate_delivery. When supplied with reach or frequency, sellers MUST surface it on the corresponding delivery row.'
        ),
    ] = None
    reach_window: Annotated[
        ReachWindow | None,
        Field(
            description='Measurement window semantics to attach to the simulated reach and frequency values. Used by simulate_delivery. When present, sellers MUST populate `reach_window` on the delivery row so buyers can determine the window semantics (cumulative vs. period vs. rolling). Omitting this param produces a row with no `reach_window` — valid per schema but sum-unsafe. Mirrors the `reach_window` shape in delivery-metrics.json.'
        ),
    ] = None
    viewability: Annotated[
        delivery_metrics.Viewability | None,
        Field(
            description='Viewability metrics to inject into simulated delivery. Uses the canonical delivery viewability shape, including viewed-seconds distributions. This media-buy-scoped form is valid only for a single-package buy, where the reference seller surfaces the same values at package and media-buy totals grain.'
        ),
    ] = None
    vendor_metric_values: Annotated[
        list[vendor_metric_value.VendorMetricValue] | None,
        Field(
            description="Vendor-defined metric values to inject into the next delivery report. Used by simulate_delivery. The reference seller reconciles these rows against each package's seller-stamped committed_metrics contract."
        ),
    ] = None
    vendor_metric_values_by_package: Annotated[
        dict[str, list[vendor_metric_value.VendorMetricValue]] | None,
        Field(
            description='Package-scoped vendor-defined values to inject, keyed by package_id. Used by simulate_delivery for multi-package buys. Sellers MUST use this form whenever more than one package could carry the same vendor/metric_id key; the legacy media-buy-scoped vendor_metric_values form is unambiguous only for a single-package buy.'
        ),
    ] = None
    not_yet_measurable_vendor_metrics: Annotated[
        list[NotYetMeasurableVendorMetric] | None,
        Field(
            description='Committed vendor metrics that are not yet measurable for the simulated measurement window. Used by simulate_delivery to prove that a future metric is omitted from missing_metrics until its measurement window matures.'
        ),
    ] = None
    not_yet_measurable_vendor_metrics_by_package: Annotated[
        dict[str, list[NotYetMeasurableVendorMetricsByPackageItem]] | None,
        Field(
            description="Package-scoped committed vendor metrics that are not yet measurable for the simulated window, keyed by package_id. Used by simulate_delivery for multi-package buys so a deferral on one package never suppresses another package's overdue gap."
        ),
    ] = None
    spend_percentage: Annotated[
        StrictFloat | None,
        Field(
            description='Spend to this percentage of budget (0–100). Used by simulate_budget_spend.',
            ge=0.0,
            le=100.0,
        ),
    ] = None
    arm: Annotated[
        Arm | None,
        Field(
            description="Response arm for the next forced operation call. Used by force_create_media_buy_arm, force_get_products_arm, force_get_signals_arm, and force_get_creative_features_arm. 'submitted' is supported for all four operations; get_creative_features also supports 'completed' with a deterministic result; create_media_buy also supports 'input-required'; get_products also supports 'rejected'. Async completion after a submitted task is covered by force_task_completion; 'working' is an out-of-band progress signal, not an initial response arm."
        ),
    ] = None
    task_id: Annotated[
        str | None,
        Field(
            description="Deterministic task handle the seller MUST emit verbatim on the next forced operation response when arm is 'submitted'. The seller MUST accept this exact value on subsequent tasks/get or get_task_status calls within the same authenticated sandbox account + principal pair and MUST return REFERENCE_NOT_FOUND for the same task_id under any other account or principal. Sandbox task_ids are caller-opaque strings - the seller's production task-id format rules do not apply.",
            max_length=128,
        ),
    ] = None
    evaluation_id: Annotated[
        str | None,
        Field(
            description='Deterministic provider evaluation identity the seller MUST emit on the next forced get_creative_features submitted acknowledgement and preserve on its terminal completion result.',
            max_length=255,
            min_length=1,
        ),
    ] = None
    message: Annotated[
        str | None,
        Field(
            description='Optional human-readable explanation surfaced on the next forced operation response. Used by force_create_media_buy_arm, force_get_products_arm, force_get_signals_arm, and force_get_creative_features_arm for the submitted arm. Plain text only.',
            max_length=2000,
        ),
    ] = None
    reason: Annotated[
        str | None,
        Field(
            description="Deterministic buyer-facing reason the seller MUST emit on the next get_products response when force_get_products_arm uses arm 'rejected'. Plain text only; MUST NOT expose confidential internal rules, inventory identifiers, credentials, or stack traces.",
            max_length=2000,
            min_length=1,
        ),
    ] = None
    suggestions: Annotated[
        list[Suggestion] | None,
        Field(
            description="Optional deterministic alternatives the seller MUST emit on the next get_products rejection. Used only by force_get_products_arm with arm 'rejected'.",
            max_length=20,
            min_length=1,
        ),
    ] = None
    format_id: Annotated[
        str | None,
        Field(
            deprecated=True,
            description='**DEPRECATED 3.x compatibility fixture.** Legacy named-format ID to seed for seed_creative_format scenarios. The seller MUST expose it through the deprecated list_creative_formats projection for the duration of the compliance session. Canonical 3.2 scenarios seed creative.supported_formats capabilities instead.',
        ),
    ] = None
    vendor: Annotated[
        brand_ref.BrandReference | None,
        Field(
            description="Measurement vendor whose catalog is being seeded. Used by seed_measurement_catalog. The seller MUST treat `metrics[]` as this vendor's `get_adcp_capabilities.measurement.metrics[]` snapshot for the duration of the compliance session."
        ),
    ] = None
    metrics: Annotated[
        list[Metric] | None,
        Field(
            description='Measurement catalog entries to seed for the vendor. Used by seed_measurement_catalog. Shape mirrors `get_adcp_capabilities.measurement.metrics[]`; each metric_id is unique within the seeded vendor catalog.',
            min_length=1,
        ),
    ] = None
    tool: Annotated[
        str | None,
        Field(
            description="Tool name whose upstream dependency to affect. Used by force_upstream_unavailable. The seller marks the named upstream as unreachable for subsequent calls to this tool within the compliance session. Sellers MAY accept a wildcard ('*') to affect all tools."
        ),
    ] = None
    upstream_name: Annotated[
        str | None,
        Field(
            description="Human-readable identifier for the upstream dependency to force unavailable (e.g., 'inventory-service', 'creative-agent'). Used by force_upstream_unavailable. When omitted, the seller marks its default upstream for the specified tool as unavailable. Sellers MUST include the same name in STALE_RESPONSE error.details.upstream.name on the affected response."
        ),
    ] = None
    cache_age_seconds: Annotated[
        SchemaInt | None,
        Field(
            description='Deterministic age of the stale cache entry used by force_upstream_unavailable. When supplied, the seller MUST emit this exact value in the matching STALE_RESPONSE error.details.cache_age_seconds on the next affected response. This lets the conformance runner bind the advisory code and its required detail fields to the same errors[] entry without assuming array order.',
            ge=0,
        ),
    ] = None
    result: Annotated[
        task_completion_data.ComplianceTaskCompletionData | None,
        Field(
            description="Deterministic result payload. force_get_creative_features_arm uses it when arm is completed and returns it on the next matching operation call. force_task_completion records it against an existing task and supports the bounded get_products, get_signals, create_media_buy, and get_creative_features completion union; polling and production SDKs resolve all task results through the originating task's manifest response mapping instead of embedding a global result union. The seller MUST preserve caller-supplied fields. Sellers MUST emit INVALID_PARAMS when the payload does not match the required response branch and MAY reject payloads exceeding 256 KB."
        ),
    ] = 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 account_id : str | None
var advance_to : AdvanceTo | None
var arm : Arm | None
var cache_age_seconds : int | None
var catalog_generation : str | None
var catalog_id : str | None
var clicks : int | None
var commissionable_value : float | None
var conversion_value : float | None
var conversions : int | None
var creative_id : str | None
var delivery_date : datetime.date | None
var dooh_metrics : DoohMetrics | None
var evaluation_id : str | None
var fixture : dict[str, typing.Any] | None
var format_id : str | None
var frequency : float | None
var impressions : int | None
var item_id : str | None
var media_buy_id : str | None
var message : str | None
var metrics : list[Metric] | None
var model_config
var not_yet_measurable_vendor_metrics : list[NotYetMeasurableVendorMetric] | None
var not_yet_measurable_vendor_metrics_by_package : dict[str, list[NotYetMeasurableVendorMetricsByPackageItem]] | None
var operation : Operation | None
var plan_id : str | None
var plays : int | None
var pricing_option_id : str | None
var product_id : str | None
var proposal_id : str | None
var purge_kind : PurgeKind | None
var reach : float | None
var reach_unit : ReachUnit | None
var reach_window : ReachWindow | None
var reason : str | None
var reason_code : CreativeEventReasonCode | None
var reason_detail : str | None
var received_reporting_revision_id : str | None
var rejection_reason : str | None
var reported_spend : ReportedSpend | None
var result : GetProductsResponse | GetSignalsResponse | CreateMediaBuyResponse1 | GetCreativeFeaturesComplianceCompletion | None
var rights_id : str | None
var session_id : str | None
var spend_percentage : float | None
var status : str | None
var suggestions : list[Suggestion] | None
var target_health : TargetHealth | None
var target_time : pydantic.types.AwareDatetime | None
var task_id : str | None
var termination_reason : str | None
var tool : str | None
var upstream_name : str | None
var vendor : BrandReference | None
var vendor_metric_values : list[VendorMetricValue] | None
var vendor_metric_values_by_package : dict[str, list[VendorMetricValue]] | None
var viewability : Viewability | None

Inherited members

class PurgeKind (*args, **kwds)
Expand source code
class PurgeKind(StrEnum):
    soft = 'soft'
    hard = 'hard'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var hard
var soft
class Purpose (*args, **kwds)
Expand source code
class Purpose(StrEnum):
    platform_primary = 'platform_primary'
    measurement = 'measurement'
    attribution = 'attribution'
    creative_serving = 'creative_serving'
    identity = 'identity'
    other = 'other'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var attribution
var creative_serving
var identity
var measurement
var other
var platform_primary
class ReachWindow (**data: Any)
Expand source code
class ReachWindow(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    kind: Annotated[
        Kind,
        Field(
            description='Window kind. `cumulative` — no period field required. `period` and `rolling` — period field REQUIRED.'
        ),
    ]
    period: Annotated[
        duration.Duration | None,
        Field(
            description="Duration of the measurement window. REQUIRED when kind is `period` or `rolling`. Matches the `period` field in delivery-metrics.json's reach_window block."
        ),
    ] = 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 kind : Kind
var model_config
var period : Duration | None

Inherited members

class RecordedCalls1 (**data: Any)
Expand source code
class RecordedCalls1(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    method: Annotated[Method, Field(description='HTTP method of the outbound call.')]
    endpoint: Annotated[
        str,
        Field(
            description="Composed `<METHOD> <URL>` string used for `endpoint_pattern` matching, e.g. 'POST https://api.tiktok.com/v2/audience/upload'. Convenience field — the runner can also reconstruct from `method` + URL components."
        ),
    ]
    url: Annotated[
        AnyUrl,
        Field(
            description='Full URL of the outbound call (scheme + host + path + query). Treated as untrusted agent-controlled input by report renderers — see runner-output-contract.yaml > security.rendered_output_fencing.'
        ),
    ]
    host: Annotated[
        str | None,
        Field(
            description='Host portion of the URL, useful for grouping calls by upstream platform.'
        ),
    ] = None
    path: Annotated[
        str | None, Field(description='Path portion of the URL (without query string).')
    ] = None
    content_type: Annotated[
        str,
        Field(
            description="Media type of the outbound request body, mirroring the agent's outbound `Content-Type` header (e.g., `application/json`, `application/x-www-form-urlencoded`, `multipart/form-data`, `text/plain`). In raw mode this describes the returned `payload`; in digest mode it describes the body the digest was computed over. Storyboard `payload_must_contain` JSONPath-lite assertions are valid only when content_type is `application/json` or has a `+json` suffix AND attestation_mode is `raw` — digest mode and non-JSON content types grade `payload_must_contain` as not_applicable. Required so the runner can choose the right matcher deterministically."
        ),
    ]
    attestation_mode: Annotated[
        Literal['raw'],
        Field(
            description="Per-call attestation mode echoing the request's `params.attestation_mode`. Required on every recorded_call so the `oneOf` discriminator always has an explicit value to dispatch on — no implicit defaults inside oneOf branches. Adopters MAY unilaterally downgrade a `raw` request to `digest` for a specific call when their policy requires it (e.g., the call carried regulated PII the adopter can't return raw). The runner reads this field to know which assertions to apply."
        ),
    ] = 'raw'
    purpose: Annotated[
        Purpose | None,
        Field(
            description="Optional adopter-supplied semantic tag for the call's role. Values: `platform_primary` for the primary upstream platform the adapter is integrating with (e.g., a TikTok audience-upload call from a sales-social adapter); `measurement` for ancillary calls to measurement vendors (DV, IAS, Nielsen, MOAT); `attribution` for server-side conversion APIs (TTD Trans-API, Meta CAPI, AppsFlyer/Branch postbacks) that flow alongside primary platform calls in a buy-step; `creative_serving` for ad-server / CDN / tag-build calls (GAM tag generation, VAST/CDN fetches, creative trafficking); `identity` for ID-graph / hashing-service calls (LiveRamp, ID5, UID2); `other` for everything else (config fetches, internal telemetry, consent signal exchange). Lets storyboards scope `upstream_traffic` assertions via `purpose_filter` so a buyer-agent adapter that legitimately calls measurement vendors during a single buy step doesn't muddy the platform-primary assertion. Calls without a `purpose` field are treated as `purpose: other` for `purpose_filter` matching — adopters who haven't classified are matched only by storyboards filtering on `other` (or by storyboards with no `purpose_filter`). Self-reported, not adversarially trustworthy — same trust model as the rest of recorded_calls; misclassification by a façade is bounded by the runner's reporting of unclassified-call counts in `actual` when filters match zero."
        ),
    ] = None
    payload: Annotated[
        Any,
        Field(
            description="Request body the agent sent. Required when `attestation_mode` is `raw` (or omitted); MUST be absent when `attestation_mode` is `digest`. Object when content_type is JSON-shaped and the controller decoded it; string otherwise. The `x-adcp-open-payload: true` annotation applies to the decoded JSON/object arm of this mixed field; non-JSON string payloads remain scalar values governed by the surrounding schema. Adopters MUST apply the recursive secret-key redaction described in this branch's top-level description before emission — secrets at any depth (Authorization values inlined into JSON bodies, embedded JWTs, presigned-URL tokens, OAuth refresh tokens) MUST be replaced with the literal string `[redacted]`. Storyboards that assert `payload_must_contain` or `identifier_paths` are matching against THIS field — secrets MUST be redacted but storyboard-supplied identifiers (hashed PII, request correlation values) MUST NOT be redacted. Adopters SHOULD cap individual payload size at 64 KiB; payloads exceeding that SHOULD be truncated with a trailing `[…truncated]` marker — large payloads bloat compliance reports and the LLM-rendered context windows that consume them.",
            max_length=65536,
        ),
    ]
    payload_digest_sha256: Annotated[
        str | None,
        Field(
            description='SHA-256 digest of the canonicalized outbound request body, lowercase hex (64 chars). Required when `attestation_mode` is `digest`; MUST be absent when `attestation_mode` is `raw`. Canonicalization order is normative: (1) controllers MUST apply the recursive secret-key redaction (same pattern as the raw-mode payload field) BEFORE computing the digest; (2) for `application/json` and `*+json` content types, controllers MUST then serialize the redacted body to RFC 8785 (JCS) canonical form — sorted keys, no extraneous whitespace — and digest the resulting bytes. Storyboard-supplied identifiers (hashed PII, request correlation values) MUST NOT be redacted before digest computation; they are the load-bearing match target for `identifier_match_proofs` and digesting them away makes echo verification impossible. Both `payload_digest_sha256` AND `identifier_match_proofs` MUST be computed against the same post-redaction canonical bytes — diverging the two surfaces breaks coherence between digest replay and identifier echo. JCS edge cases: when a digest-mode `query_upstream_traffic` response cannot be produced because the parsed JSON-like value tree contains a non-finite numeric value (`NaN`, `+Infinity`, or `-Infinity`), controllers MUST NOT coerce that value to `null`, a string, or any other placeholder for digest computation; they MUST return the typed ControllerError code `JCS_NON_FINITE_NUMBER`. Runners MUST grade the affected upstream_traffic digest validation `not_applicable` because RFC 8785 forbids non-finite numbers. Payloads carrying numeric identifiers MUST serialize them as JSON strings before digest computation (adtech bid payloads regularly carry IDs outside ±2^53 where I-JSON / RFC 7493 number round-tripping diverges across implementations). For non-JSON content types the digest is computed over the post-redaction raw body bytes.',
            pattern='^[a-f0-9]{64}$',
        ),
    ] = None
    payload_length: Annotated[
        SchemaInt,
        Field(
            description='Byte length of the post-redaction body bytes represented by this recorded_call. Required in both `raw` and `digest` modes — symmetric across modes so runners can detect adopter-side truncation regardless of attestation choice. In `raw` mode this MUST equal the UTF-8 byte length of the emitted `payload` value after the same recursive secret-key redaction the controller applied before returning it. In `digest` mode this MUST equal the exact number of bytes fed into SHA-256 for `payload_digest_sha256`: RFC 8785 (JCS) canonical bytes for JSON-shaped content after redaction, or the post-redaction raw body bytes for non-JSON content. Digest-mode `payload_length` is therefore NOT the original outbound body length before JSON parsing, redaction, or canonicalization. Mismatch between observed payload length and reported `payload_length` is a controller-side bug worth surfacing in the report.',
            ge=0,
        ),
    ]
    identifier_match_proofs: Annotated[
        list[IdentifierMatchProof] | None,
        Field(
            description='Per-identifier echo proofs for digest-mode calls. Required when `attestation_mode` is `digest` AND the request supplied `params.identifier_value_digests`; MUST be absent or empty otherwise. Each entry corresponds to one digest from the request. Capped at 64 to match the request-side `params.identifier_value_digests` cap. Lets storyboards verify `identifier_paths` echo in digest mode without ever transmitting plaintext identifiers to the controller. SHA-256 is a privacy mechanism here, not a trust mechanism — controllers self-report `found` and a determined façade can return any boolean; consumers MUST NOT treat digest-mode passing as cryptographically more trustworthy than raw mode. Tokenization is normative: for `application/json` and `*+json` content types, controllers MUST scan exactly the JSON string-typed leaf values of the post-redaction canonicalized body — no substring matching, no word splitting, no case folding, no Unicode normalization. A token matches when its SHA-256 hash equals one of the requested digests byte-for-byte. For non-JSON content types (form-urlencoded, multipart, plain text), `identifier_match_proofs` MUST be empty and runner-side `identifier_paths` assertions targeting those calls grade `not_applicable` — token boundaries are not portably defined across non-JSON shapes.',
            max_length=64,
        ),
    ] = None
    timestamp: Annotated[
        AwareDatetime,
        Field(
            description="ISO 8601 timestamp the adopter recorded the outbound call. MUST reflect the adopter's wall clock at the moment the outbound request was sent (not log-flush time), and MUST be monotonically non-decreasing across recorded_calls of a single response. Used by runners to scope assertions to a specific storyboard step's window — see runner-output-contract.yaml > validation_result for the timestamp boundary semantics."
        ),
    ]
    status_code: Annotated[
        SchemaInt | None,
        Field(
            description='HTTP status code returned by the upstream. Optional — adopters MAY omit when the call was instrumented before the response arrived.',
            ge=100,
            le=599,
        ),
    ] = 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 attestation_mode : Literal['raw']
var content_type : str
var endpoint : str
var host : str | None
var identifier_match_proofs : list[IdentifierMatchProof] | None
var method : Method
var model_config
var path : str | None
var payload : Any
var payload_digest_sha256 : str | None
var payload_length : int
var purpose : Purpose | None
var status_code : int | None
var timestamp : pydantic.types.AwareDatetime
var url : pydantic.networks.AnyUrl

Inherited members

class RecordedCalls2 (**data: Any)
Expand source code
class RecordedCalls2(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    method: Annotated[Method, Field(description='HTTP method of the outbound call.')]
    endpoint: Annotated[
        str,
        Field(
            description="Composed `<METHOD> <URL>` string used for `endpoint_pattern` matching, e.g. 'POST https://api.tiktok.com/v2/audience/upload'. Convenience field — the runner can also reconstruct from `method` + URL components."
        ),
    ]
    url: Annotated[
        AnyUrl,
        Field(
            description='Full URL of the outbound call (scheme + host + path + query). Treated as untrusted agent-controlled input by report renderers — see runner-output-contract.yaml > security.rendered_output_fencing.'
        ),
    ]
    host: Annotated[
        str | None,
        Field(
            description='Host portion of the URL, useful for grouping calls by upstream platform.'
        ),
    ] = None
    path: Annotated[
        str | None, Field(description='Path portion of the URL (without query string).')
    ] = None
    content_type: Annotated[
        str,
        Field(
            description="Media type of the outbound request body, mirroring the agent's outbound `Content-Type` header (e.g., `application/json`, `application/x-www-form-urlencoded`, `multipart/form-data`, `text/plain`). In raw mode this describes the returned `payload`; in digest mode it describes the body the digest was computed over. Storyboard `payload_must_contain` JSONPath-lite assertions are valid only when content_type is `application/json` or has a `+json` suffix AND attestation_mode is `raw` — digest mode and non-JSON content types grade `payload_must_contain` as not_applicable. Required so the runner can choose the right matcher deterministically."
        ),
    ]
    attestation_mode: Annotated[
        Literal['digest'],
        Field(
            description="Per-call attestation mode echoing the request's `params.attestation_mode`. Required on every recorded_call so the `oneOf` discriminator always has an explicit value to dispatch on — no implicit defaults inside oneOf branches. Adopters MAY unilaterally downgrade a `raw` request to `digest` for a specific call when their policy requires it (e.g., the call carried regulated PII the adopter can't return raw). The runner reads this field to know which assertions to apply."
        ),
    ] = 'digest'
    purpose: Annotated[
        Purpose | None,
        Field(
            description="Optional adopter-supplied semantic tag for the call's role. Values: `platform_primary` for the primary upstream platform the adapter is integrating with (e.g., a TikTok audience-upload call from a sales-social adapter); `measurement` for ancillary calls to measurement vendors (DV, IAS, Nielsen, MOAT); `attribution` for server-side conversion APIs (TTD Trans-API, Meta CAPI, AppsFlyer/Branch postbacks) that flow alongside primary platform calls in a buy-step; `creative_serving` for ad-server / CDN / tag-build calls (GAM tag generation, VAST/CDN fetches, creative trafficking); `identity` for ID-graph / hashing-service calls (LiveRamp, ID5, UID2); `other` for everything else (config fetches, internal telemetry, consent signal exchange). Lets storyboards scope `upstream_traffic` assertions via `purpose_filter` so a buyer-agent adapter that legitimately calls measurement vendors during a single buy step doesn't muddy the platform-primary assertion. Calls without a `purpose` field are treated as `purpose: other` for `purpose_filter` matching — adopters who haven't classified are matched only by storyboards filtering on `other` (or by storyboards with no `purpose_filter`). Self-reported, not adversarially trustworthy — same trust model as the rest of recorded_calls; misclassification by a façade is bounded by the runner's reporting of unclassified-call counts in `actual` when filters match zero."
        ),
    ] = None
    payload: Annotated[
        Any | None,
        Field(
            description="Request body the agent sent. Required when `attestation_mode` is `raw` (or omitted); MUST be absent when `attestation_mode` is `digest`. Object when content_type is JSON-shaped and the controller decoded it; string otherwise. The `x-adcp-open-payload: true` annotation applies to the decoded JSON/object arm of this mixed field; non-JSON string payloads remain scalar values governed by the surrounding schema. Adopters MUST apply the recursive secret-key redaction described in this branch's top-level description before emission — secrets at any depth (Authorization values inlined into JSON bodies, embedded JWTs, presigned-URL tokens, OAuth refresh tokens) MUST be replaced with the literal string `[redacted]`. Storyboards that assert `payload_must_contain` or `identifier_paths` are matching against THIS field — secrets MUST be redacted but storyboard-supplied identifiers (hashed PII, request correlation values) MUST NOT be redacted. Adopters SHOULD cap individual payload size at 64 KiB; payloads exceeding that SHOULD be truncated with a trailing `[…truncated]` marker — large payloads bloat compliance reports and the LLM-rendered context windows that consume them.",
            max_length=65536,
        ),
    ] = None
    payload_digest_sha256: Annotated[
        str,
        Field(
            description='SHA-256 digest of the canonicalized outbound request body, lowercase hex (64 chars). Required when `attestation_mode` is `digest`; MUST be absent when `attestation_mode` is `raw`. Canonicalization order is normative: (1) controllers MUST apply the recursive secret-key redaction (same pattern as the raw-mode payload field) BEFORE computing the digest; (2) for `application/json` and `*+json` content types, controllers MUST then serialize the redacted body to RFC 8785 (JCS) canonical form — sorted keys, no extraneous whitespace — and digest the resulting bytes. Storyboard-supplied identifiers (hashed PII, request correlation values) MUST NOT be redacted before digest computation; they are the load-bearing match target for `identifier_match_proofs` and digesting them away makes echo verification impossible. Both `payload_digest_sha256` AND `identifier_match_proofs` MUST be computed against the same post-redaction canonical bytes — diverging the two surfaces breaks coherence between digest replay and identifier echo. JCS edge cases: when a digest-mode `query_upstream_traffic` response cannot be produced because the parsed JSON-like value tree contains a non-finite numeric value (`NaN`, `+Infinity`, or `-Infinity`), controllers MUST NOT coerce that value to `null`, a string, or any other placeholder for digest computation; they MUST return the typed ControllerError code `JCS_NON_FINITE_NUMBER`. Runners MUST grade the affected upstream_traffic digest validation `not_applicable` because RFC 8785 forbids non-finite numbers. Payloads carrying numeric identifiers MUST serialize them as JSON strings before digest computation (adtech bid payloads regularly carry IDs outside ±2^53 where I-JSON / RFC 7493 number round-tripping diverges across implementations). For non-JSON content types the digest is computed over the post-redaction raw body bytes.',
            pattern='^[a-f0-9]{64}$',
        ),
    ]
    payload_length: Annotated[
        SchemaInt,
        Field(
            description='Byte length of the post-redaction body bytes represented by this recorded_call. Required in both `raw` and `digest` modes — symmetric across modes so runners can detect adopter-side truncation regardless of attestation choice. In `raw` mode this MUST equal the UTF-8 byte length of the emitted `payload` value after the same recursive secret-key redaction the controller applied before returning it. In `digest` mode this MUST equal the exact number of bytes fed into SHA-256 for `payload_digest_sha256`: RFC 8785 (JCS) canonical bytes for JSON-shaped content after redaction, or the post-redaction raw body bytes for non-JSON content. Digest-mode `payload_length` is therefore NOT the original outbound body length before JSON parsing, redaction, or canonicalization. Mismatch between observed payload length and reported `payload_length` is a controller-side bug worth surfacing in the report.',
            ge=0,
        ),
    ]
    identifier_match_proofs: Annotated[
        list[IdentifierMatchProof] | None,
        Field(
            description='Per-identifier echo proofs for digest-mode calls. Required when `attestation_mode` is `digest` AND the request supplied `params.identifier_value_digests`; MUST be absent or empty otherwise. Each entry corresponds to one digest from the request. Capped at 64 to match the request-side `params.identifier_value_digests` cap. Lets storyboards verify `identifier_paths` echo in digest mode without ever transmitting plaintext identifiers to the controller. SHA-256 is a privacy mechanism here, not a trust mechanism — controllers self-report `found` and a determined façade can return any boolean; consumers MUST NOT treat digest-mode passing as cryptographically more trustworthy than raw mode. Tokenization is normative: for `application/json` and `*+json` content types, controllers MUST scan exactly the JSON string-typed leaf values of the post-redaction canonicalized body — no substring matching, no word splitting, no case folding, no Unicode normalization. A token matches when its SHA-256 hash equals one of the requested digests byte-for-byte. For non-JSON content types (form-urlencoded, multipart, plain text), `identifier_match_proofs` MUST be empty and runner-side `identifier_paths` assertions targeting those calls grade `not_applicable` — token boundaries are not portably defined across non-JSON shapes.',
            max_length=64,
        ),
    ] = None
    timestamp: Annotated[
        AwareDatetime,
        Field(
            description="ISO 8601 timestamp the adopter recorded the outbound call. MUST reflect the adopter's wall clock at the moment the outbound request was sent (not log-flush time), and MUST be monotonically non-decreasing across recorded_calls of a single response. Used by runners to scope assertions to a specific storyboard step's window — see runner-output-contract.yaml > validation_result for the timestamp boundary semantics."
        ),
    ]
    status_code: Annotated[
        SchemaInt | None,
        Field(
            description='HTTP status code returned by the upstream. Optional — adopters MAY omit when the call was instrumented before the response arrived.',
            ge=100,
            le=599,
        ),
    ] = 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 attestation_mode : Literal['digest']
var content_type : str
var endpoint : str
var host : str | None
var identifier_match_proofs : list[IdentifierMatchProof] | None
var method : Method
var model_config
var path : str | None
var payload : typing.Any | None
var payload_digest_sha256 : str
var payload_length : int
var purpose : Purpose | None
var status_code : int | None
var timestamp : pydantic.types.AwareDatetime
var url : pydantic.networks.AnyUrl

Inherited members

class ReportedSpend (**data: Any)
Expand source code
class ReportedSpend(AdCPBaseModel):
    amount: Annotated[StrictFloat, Field(ge=0.0)]
    currency: Annotated[str, Field(pattern='^[A-Z]{3}$')]

Base model for AdCP types with spec-compliant serialization.

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

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

Important

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

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

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

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

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

Ancestors

Class variables

var amount : float
var currency : str
var model_config

Inherited members

class TargetHealth (*args, **kwds)
Expand source code
class TargetHealth(StrEnum):
    delayed = 'delayed'
    action_required = 'action_required'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var action_required
var delayed