Module adcp.types.domains.account

Types the AdCP account 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.account 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.account.<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.account.get_account_financials_request
adcp.types.domains.account.get_account_financials_response
adcp.types.domains.account.list_account_changes_request
adcp.types.domains.account.list_account_changes_response
adcp.types.domains.account.list_accounts_request
adcp.types.domains.account.list_accounts_response
adcp.types.domains.account.report_usage_request
adcp.types.domains.account.report_usage_response
adcp.types.domains.account.sync_accounts_request
adcp.types.domains.account.sync_accounts_response
adcp.types.domains.account.sync_governance_request
adcp.types.domains.account.sync_governance_response

Classes

class Accounts (**data: Any)
Expand source code
class Accounts(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description='Settings-update key. When present, this entry targets an existing account by `account_id` (seller-owned account namespace) or natural key (buyer-declared account settings-update against a previously-provisioned account). Mutually exclusive with the flat `brand` + `operator` + `billing` provisioning trio. When `account` is present, the seller MUST NOT create a new account — entries that would otherwise trigger provisioning are rejected with `UNSUPPORTED_PROVISIONING`.'
        ),
    ] = None
    revision: Annotated[
        SchemaInt | None,
        Field(
            description='Expected current account revision for optimistic concurrency in settings-update mode. Required whenever operator_identity is present; optional for existing non-identity settings updates. The seller MUST compare it atomically with the write, reject a mismatch with CONFLICT, and leave the account unchanged. Obtain it from list_accounts or the most recent sync_accounts result. Reads, dry runs, validation failures, and exact idempotency replays do not increment revision; every persisted settings or identity-change state transition does. MUST be absent in provisioning mode.',
            ge=1,
        ),
    ] = None
    operator_identity: Annotated[
        operator_identity_1.OperatorIdentity | None,
        Field(
            description='Complete desired operator identity for settings-update mode. Omit this field to leave operator identity unchanged. When present, omission of operator_unit within the object removes the existing unit. Changing only operator_unit_1.name updates display metadata; changing operator_unit_1.id or adding/removing a unit rekeys the same account within the current operator. Changing operator requests an inter-entity handoff and MUST enter pending_approval until the seller verifies the current account authority, verified brand authorization, destination-operator acceptance, and any operator-scoped billing and grant transition. The seller MUST preserve account_id and account-scoped historical resources, MUST reject collisions without merging, and MUST apply no identity change if continuity cannot be preserved. MUST be accompanied by revision and MUST be absent in provisioning mode.'
        ),
    ] = None
    destination_billing_entity: Annotated[
        business_entity.BusinessEntity | None,
        Field(
            description="Complete staged billing identity for the requested destination operator during an operator-domain handoff on an account whose billing party is operator. This value is write-only while approval is pending and MUST NOT replace or be echoed as the account's canonical billing_entity until the handoff applies atomically. Required by the protocol when an operator-billed account changes operator; otherwise MUST be absent. Requires operator_identity and revision and MUST be absent in provisioning mode."
        ),
    ] = None
    brand: Annotated[
        brand_ref.BrandReference,
        Field(
            description='Brand reference identifying the advertiser. Required for **provisioning mode**; MUST be absent in settings-update mode. Only the BrandKey projection — `domain`, `brand_id`, and the canonicalized `countries[]` set — participates in account identity. Mutable or per-call BrandRef fields such as `industries`, `data_subject_contestation`, and `brand_kit_override` MUST NOT affect lookup, idempotency, or account creation. New 3.2 producers SHOULD send only the BrandKey fields; the broader BrandRef remains accepted on this existing 3.x task for compatibility.'
        ),
    ]
    operator: Annotated[
        str,
        Field(
            description="Domain of the entity operating on the brand's behalf (e.g., 'pinnacle-media.com'). When the brand operates directly, this is the brand's domain. Verified against the brand's authorized_operators in brand.json. Required for **provisioning mode**; MUST be absent in settings-update mode.",
            pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$',
        ),
    ]
    operator_unit: Annotated[
        operator_unit_1.OperatorUnit | None,
        Field(
            description='Optional operator-owned business unit, agency seat, or platform account for provisioning mode. operator_unit_1.id participates in the natural key; name is mapping/display metadata. MUST be absent in settings-update mode.'
        ),
    ] = None
    currency: Annotated[
        str | None,
        Field(
            description='Optional immutable ISO 4217 transaction currency for a currency-bound advertiser object. Consult `account.supported_account_currency_modes` before provisioning. When supplied, it participates in the natural key and all media buys on the account use it. Omit for per-media-buy currency selection. MUST be absent in settings-update mode.',
            pattern='^[A-Z]{3}$',
        ),
    ] = None
    timezone: Annotated[
        str | None,
        Field(
            description='Immutable operational timezone selected for an account_fixed advertiser object. Required in provisioning mode when get_adcp_capabilities.account.timezone declares account_selection: buyer_selected, and the value MUST be one of supported_timezones. Omit for seller_fixed or seller_assigned modes. When supplied, it participates in the natural key. MUST be absent in settings-update mode.',
            min_length=1,
        ),
    ] = None
    billing: Annotated[
        billing_party.BillingParty,
        Field(
            description='Who the seller invoices for this buyer–storefront account relationship. Required for **provisioning mode**; MUST be absent in settings-update mode (the invoiced party is fixed at provisioning time and cannot be changed via settings-update). This field does not select a payment rail, clearing intermediary, or per-media-buy settlement route.'
        ),
    ]
    billing_entity: Annotated[
        business_entity.BusinessEntity | None,
        Field(
            description='Business entity details for the party responsible for payment. The agent provides this so the seller has the legal name, tax IDs, address, and bank details needed for formal B2B invoicing. Permitted in both modes — sellers MAY accept refinements in settings-update mode (e.g., updated bank details).'
        ),
    ] = None
    payment_terms: Annotated[
        payment_terms_1.PaymentTerms | None,
        Field(
            description='Payment terms for this account. The seller must either accept these terms or reject the account — terms are never silently remapped. When omitted, the seller applies its default terms. Permitted in both modes.'
        ),
    ] = None
    sandbox: Annotated[
        StrictBool | None,
        Field(
            description='When true, provision this as a sandbox account with no real platform calls or billing. Only applicable to buyer-declared accounts (require_operator_auth: false) in provisioning mode. For account-id namespaces, sandbox accounts are pre-existing test accounts discovered via list_accounts or supplied out-of-band.'
        ),
    ] = None
    preferred_reporting_protocol: Annotated[
        cloud_storage_protocol.CloudStorageProtocol | None,
        Field(
            description="Buyer's preferred cloud storage protocol for offline reporting delivery. The seller provisions the account's reporting_bucket using this protocol if supported. When omitted, the seller chooses from its supported offline_delivery_protocols. Only meaningful when the seller's reporting_delivery_methods includes 'offline'."
        ),
    ] = None
    reporting_delivery_configs: Annotated[
        list[reporting_delivery_config.ReportingDeliveryConfiguration] | None,
        Field(
            description="Caller-owned desired state for durable reporting delivery on this account. Declarative replacement is scoped to (authenticated caller, resolved account): omission leaves that caller's set unchanged; [] deactivates that caller's set and starts grant revocation; another caller's entries MUST NOT be read, replaced, or deleted. Entries are keyed by immutable (delivery_config_id, delivery_config_version); duplicate tuples MUST reject the entire account entry, and reusing a tuple with changed content MUST be rejected. Each generation binds the exact report_definition_id advertised by its offering. destination.mode provision asks the seller to verify caller disclosure authority and destination/recipient control from non-secret provider coordinates; destination.mode existing reuses a caller-scoped immutable destination-generation reference, including one registered through sync_agent_configuration. The account configuration independently authorizes disclosure for this feed and scope, so possession of a reusable reference is never account authority. Unknown, unauthorized, and cross-caller refs MUST be indistinguishable. Credentials never transit AdCP, including nested extension fields. Permitted in both provisioning and settings-update modes. Sellers accepting this field MUST advertise media_buy.reporting_delivery in experimental_features and echo resolved secret-free state on sync_accounts and list_accounts.",
            max_length=16,
        ),
    ] = None
    notification_configs: Annotated[
        list[notification_config.NotificationConfig] | None,
        Field(
            description='Account-level webhook subscriptions for notifications whose lifecycle outlives any single media buy (`creative.status_changed`, optional `creative.assignment_changed`, `indicators.changed`, `creative.purged`, `account.status_changed`, wholesale feed change payloads, and future account-anchored resource events after those event types are added to `notification-config.json`). Indicator and assignment registrations are prospective: activation does not replay current conditions, so buyers establish a complete baseline through `get_media_buys` by enumerating known IDs or requesting every status and exhausting pagination, without an indicator filter. Durable account lifecycle transitions such as later `payment_required`, `suspended`, `closed`, or recovery to `active` use `account.status_changed` on this surface; the one-shot `sync_accounts.push_notification_config` channel remains scoped to the async result of the original provisioning task. Declarative replace semantics: when this field is present, the buyer sends the full desired array and the seller replaces the account\'s current set with that array, keyed by account-scoped `subscriber_id`. Omit this field to leave existing subscribers unchanged; send `[]` to remove all subscribers. Re-sending an existing `subscriber_id` for the account replaces that subscriber\'s config rather than creating a duplicate; persisted entries whose `subscriber_id` does not appear in the sent array are removed, so the seller MUST NOT merge the new array with persisted state. Paused entries (`active: false`) use the same replacement semantics; a buyer that wants to preserve a paused subscriber MUST re-include it with `active: false`. Duplicate `subscriber_id` values within one submitted array are rejected. Permitted in both provisioning and settings-update modes. Each entry registers a URL, the event types the subscriber wants, and optional legacy auth — see [`notification-config.json`](/schemas/core/notification-config.json). The seller MUST echo applied state on the response and on `list_accounts` reads, with `authentication.credentials` omitted (write-only). Sellers MUST reject entries whose `event_types` include any type whose contract anchors at a media buy or below (today: `scheduled`, `final`, `delayed`, `adjusted`, `window_update`, `impairment`) or at the agent (today: `capabilities.changed`) as per-account validation failures with `INVALID_REQUEST` or `VALIDATION_ERROR` and `error.field` pointing at the invalid `event_types` entry — those events do not belong on this surface. Wholesale feed webhook registrations carry the actual change payload in `/schemas/core/wholesale-feed-webhook.json`; canonical product subscribers repair through `list_products(if_feed_version)`, legacy product subscribers through `get_products(if_wholesale_feed_version)`, and signal subscribers through `get_signals(if_wholesale_feed_version)`. Account status change registrations carry the invalidation payload in `/schemas/core/account-status-changed-webhook.json`; receivers use `list_accounts` to repair or reconcile. This is distinct from sync_catalogs, which manages buyer-provided campaign input feeds on a seller account.\n\nActivation proof: before activating a new or changed active subscriber, the seller MUST validate the URL, complete the account-level webhook proof-of-control challenge, and only then persist or expose the subscriber as `active: true`. For `account.status_changed`, sellers MUST assign `account_id` before completing proof so subsequent status transitions can identify the account and be repaired through `list_accounts`, even when external approval remains pending. A valid existing proof for the same `(account_id, subscriber_id, normalized url, authentication mode/credential binding, normalized event_types)` tuple MAY be reused; changing any element of that tuple requires fresh proof. The challenge POST itself MUST be signed with the seller\'s RFC 9421 webhook profile key and MUST include seller_agent_url, delivery_auth, and event_types so the receiver can verify the pending registration before echoing the challenge. New signers use `adcp_use: "request-signing"`; deprecated `webhook-signing` keys remain accepted during the compatibility window. Entries sent with `active: false` may skip only the outbound proof challenge while inactive; sellers MUST still enforce URL parsing, HTTPS, hostname normalization, and reserved-range rejection at write time, and those entries MUST NOT receive fires until reactivated. If proof fails or times out, the seller rejects the account entry with `action: "failed"`, leaves the prior notification_configs[] set unchanged, and reports `VALIDATION_ERROR` (or `INVALID_REQUEST` for malformed URLs) at the failing `notification_configs[j].url` field.\n\n**Cap rationale:** `maxItems: 16` is a practical fan-out cap (governance + buyer ingestion + audit bus + dx team + a few partner hooks). The cap exists to prevent unbounded subscriber arrays in storage and to bound the seller\'s per-event fan-out work. Sellers that hit the cap with legitimate subscribers should surface this on the protocol roadmap rather than work around it.',
            max_length=16,
        ),
    ] = 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 : AccountReference1 | AccountReference2 | None
var billing : BillingParty
var billing_entity : BusinessEntity | None
var brand : BrandReference
var currency : str | None
var destination_billing_entity : BusinessEntity | None
var model_config
var notification_configs : list[NotificationConfig] | None
var operator : str
var operator_identity : OperatorIdentity | None
var operator_unit : OperatorUnit | None
var payment_terms : PaymentTerms | None
var preferred_reporting_protocol : CloudStorageProtocol | None
var reporting_delivery_configs : list[ReportingDeliveryConfiguration] | None
var revision : int | None
var sandbox : bool | None
var timezone : str | None

Inherited members

class Accounts1 (**data: Any)
Expand source code
class Accounts1(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference,
        Field(
            description='Settings-update key. When present, this entry targets an existing account by `account_id` (seller-owned account namespace) or natural key (buyer-declared account settings-update against a previously-provisioned account). Mutually exclusive with the flat `brand` + `operator` + `billing` provisioning trio. When `account` is present, the seller MUST NOT create a new account — entries that would otherwise trigger provisioning are rejected with `UNSUPPORTED_PROVISIONING`.'
        ),
    ]
    revision: Annotated[
        SchemaInt | None,
        Field(
            description='Expected current account revision for optimistic concurrency in settings-update mode. Required whenever operator_identity is present; optional for existing non-identity settings updates. The seller MUST compare it atomically with the write, reject a mismatch with CONFLICT, and leave the account unchanged. Obtain it from list_accounts or the most recent sync_accounts result. Reads, dry runs, validation failures, and exact idempotency replays do not increment revision; every persisted settings or identity-change state transition does. MUST be absent in provisioning mode.',
            ge=1,
        ),
    ] = None
    operator_identity: Annotated[
        operator_identity_1.OperatorIdentity | None,
        Field(
            description='Complete desired operator identity for settings-update mode. Omit this field to leave operator identity unchanged. When present, omission of operator_unit within the object removes the existing unit. Changing only operator_unit_1.name updates display metadata; changing operator_unit_1.id or adding/removing a unit rekeys the same account within the current operator. Changing operator requests an inter-entity handoff and MUST enter pending_approval until the seller verifies the current account authority, verified brand authorization, destination-operator acceptance, and any operator-scoped billing and grant transition. The seller MUST preserve account_id and account-scoped historical resources, MUST reject collisions without merging, and MUST apply no identity change if continuity cannot be preserved. MUST be accompanied by revision and MUST be absent in provisioning mode.'
        ),
    ] = None
    destination_billing_entity: Annotated[
        business_entity.BusinessEntity | None,
        Field(
            description="Complete staged billing identity for the requested destination operator during an operator-domain handoff on an account whose billing party is operator. This value is write-only while approval is pending and MUST NOT replace or be echoed as the account's canonical billing_entity until the handoff applies atomically. Required by the protocol when an operator-billed account changes operator; otherwise MUST be absent. Requires operator_identity and revision and MUST be absent in provisioning mode."
        ),
    ] = None
    brand: Annotated[
        brand_ref.BrandReference | None,
        Field(
            description='Brand reference identifying the advertiser. Required for **provisioning mode**; MUST be absent in settings-update mode. Only the BrandKey projection — `domain`, `brand_id`, and the canonicalized `countries[]` set — participates in account identity. Mutable or per-call BrandRef fields such as `industries`, `data_subject_contestation`, and `brand_kit_override` MUST NOT affect lookup, idempotency, or account creation. New 3.2 producers SHOULD send only the BrandKey fields; the broader BrandRef remains accepted on this existing 3.x task for compatibility.'
        ),
    ] = None
    operator: Annotated[
        str | None,
        Field(
            description="Domain of the entity operating on the brand's behalf (e.g., 'pinnacle-media.com'). When the brand operates directly, this is the brand's domain. Verified against the brand's authorized_operators in brand.json. Required for **provisioning mode**; MUST be absent in settings-update mode.",
            pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$',
        ),
    ] = None
    operator_unit: Annotated[
        operator_unit_1.OperatorUnit | None,
        Field(
            description='Optional operator-owned business unit, agency seat, or platform account for provisioning mode. operator_unit_1.id participates in the natural key; name is mapping/display metadata. MUST be absent in settings-update mode.'
        ),
    ] = None
    currency: Annotated[
        str | None,
        Field(
            description='Optional immutable ISO 4217 transaction currency for a currency-bound advertiser object. Consult `account.supported_account_currency_modes` before provisioning. When supplied, it participates in the natural key and all media buys on the account use it. Omit for per-media-buy currency selection. MUST be absent in settings-update mode.',
            pattern='^[A-Z]{3}$',
        ),
    ] = None
    timezone: Annotated[
        str | None,
        Field(
            description='Immutable operational timezone selected for an account_fixed advertiser object. Required in provisioning mode when get_adcp_capabilities.account.timezone declares account_selection: buyer_selected, and the value MUST be one of supported_timezones. Omit for seller_fixed or seller_assigned modes. When supplied, it participates in the natural key. MUST be absent in settings-update mode.',
            min_length=1,
        ),
    ] = None
    billing: Annotated[
        billing_party.BillingParty | None,
        Field(
            description='Who the seller invoices for this buyer–storefront account relationship. Required for **provisioning mode**; MUST be absent in settings-update mode (the invoiced party is fixed at provisioning time and cannot be changed via settings-update). This field does not select a payment rail, clearing intermediary, or per-media-buy settlement route.'
        ),
    ] = None
    billing_entity: Annotated[
        business_entity.BusinessEntity | None,
        Field(
            description='Business entity details for the party responsible for payment. The agent provides this so the seller has the legal name, tax IDs, address, and bank details needed for formal B2B invoicing. Permitted in both modes — sellers MAY accept refinements in settings-update mode (e.g., updated bank details).'
        ),
    ] = None
    payment_terms: Annotated[
        payment_terms_1.PaymentTerms | None,
        Field(
            description='Payment terms for this account. The seller must either accept these terms or reject the account — terms are never silently remapped. When omitted, the seller applies its default terms. Permitted in both modes.'
        ),
    ] = None
    sandbox: Annotated[
        StrictBool | None,
        Field(
            description='When true, provision this as a sandbox account with no real platform calls or billing. Only applicable to buyer-declared accounts (require_operator_auth: false) in provisioning mode. For account-id namespaces, sandbox accounts are pre-existing test accounts discovered via list_accounts or supplied out-of-band.'
        ),
    ] = None
    preferred_reporting_protocol: Annotated[
        cloud_storage_protocol.CloudStorageProtocol | None,
        Field(
            description="Buyer's preferred cloud storage protocol for offline reporting delivery. The seller provisions the account's reporting_bucket using this protocol if supported. When omitted, the seller chooses from its supported offline_delivery_protocols. Only meaningful when the seller's reporting_delivery_methods includes 'offline'."
        ),
    ] = None
    reporting_delivery_configs: Annotated[
        list[reporting_delivery_config.ReportingDeliveryConfiguration] | None,
        Field(
            description="Caller-owned desired state for durable reporting delivery on this account. Declarative replacement is scoped to (authenticated caller, resolved account): omission leaves that caller's set unchanged; [] deactivates that caller's set and starts grant revocation; another caller's entries MUST NOT be read, replaced, or deleted. Entries are keyed by immutable (delivery_config_id, delivery_config_version); duplicate tuples MUST reject the entire account entry, and reusing a tuple with changed content MUST be rejected. Each generation binds the exact report_definition_id advertised by its offering. destination.mode provision asks the seller to verify caller disclosure authority and destination/recipient control from non-secret provider coordinates; destination.mode existing reuses a caller-scoped immutable destination-generation reference, including one registered through sync_agent_configuration. The account configuration independently authorizes disclosure for this feed and scope, so possession of a reusable reference is never account authority. Unknown, unauthorized, and cross-caller refs MUST be indistinguishable. Credentials never transit AdCP, including nested extension fields. Permitted in both provisioning and settings-update modes. Sellers accepting this field MUST advertise media_buy.reporting_delivery in experimental_features and echo resolved secret-free state on sync_accounts and list_accounts.",
            max_length=16,
        ),
    ] = None
    notification_configs: Annotated[
        list[notification_config.NotificationConfig] | None,
        Field(
            description='Account-level webhook subscriptions for notifications whose lifecycle outlives any single media buy (`creative.status_changed`, optional `creative.assignment_changed`, `indicators.changed`, `creative.purged`, `account.status_changed`, wholesale feed change payloads, and future account-anchored resource events after those event types are added to `notification-config.json`). Indicator and assignment registrations are prospective: activation does not replay current conditions, so buyers establish a complete baseline through `get_media_buys` by enumerating known IDs or requesting every status and exhausting pagination, without an indicator filter. Durable account lifecycle transitions such as later `payment_required`, `suspended`, `closed`, or recovery to `active` use `account.status_changed` on this surface; the one-shot `sync_accounts.push_notification_config` channel remains scoped to the async result of the original provisioning task. Declarative replace semantics: when this field is present, the buyer sends the full desired array and the seller replaces the account\'s current set with that array, keyed by account-scoped `subscriber_id`. Omit this field to leave existing subscribers unchanged; send `[]` to remove all subscribers. Re-sending an existing `subscriber_id` for the account replaces that subscriber\'s config rather than creating a duplicate; persisted entries whose `subscriber_id` does not appear in the sent array are removed, so the seller MUST NOT merge the new array with persisted state. Paused entries (`active: false`) use the same replacement semantics; a buyer that wants to preserve a paused subscriber MUST re-include it with `active: false`. Duplicate `subscriber_id` values within one submitted array are rejected. Permitted in both provisioning and settings-update modes. Each entry registers a URL, the event types the subscriber wants, and optional legacy auth — see [`notification-config.json`](/schemas/core/notification-config.json). The seller MUST echo applied state on the response and on `list_accounts` reads, with `authentication.credentials` omitted (write-only). Sellers MUST reject entries whose `event_types` include any type whose contract anchors at a media buy or below (today: `scheduled`, `final`, `delayed`, `adjusted`, `window_update`, `impairment`) or at the agent (today: `capabilities.changed`) as per-account validation failures with `INVALID_REQUEST` or `VALIDATION_ERROR` and `error.field` pointing at the invalid `event_types` entry — those events do not belong on this surface. Wholesale feed webhook registrations carry the actual change payload in `/schemas/core/wholesale-feed-webhook.json`; canonical product subscribers repair through `list_products(if_feed_version)`, legacy product subscribers through `get_products(if_wholesale_feed_version)`, and signal subscribers through `get_signals(if_wholesale_feed_version)`. Account status change registrations carry the invalidation payload in `/schemas/core/account-status-changed-webhook.json`; receivers use `list_accounts` to repair or reconcile. This is distinct from sync_catalogs, which manages buyer-provided campaign input feeds on a seller account.\n\nActivation proof: before activating a new or changed active subscriber, the seller MUST validate the URL, complete the account-level webhook proof-of-control challenge, and only then persist or expose the subscriber as `active: true`. For `account.status_changed`, sellers MUST assign `account_id` before completing proof so subsequent status transitions can identify the account and be repaired through `list_accounts`, even when external approval remains pending. A valid existing proof for the same `(account_id, subscriber_id, normalized url, authentication mode/credential binding, normalized event_types)` tuple MAY be reused; changing any element of that tuple requires fresh proof. The challenge POST itself MUST be signed with the seller\'s RFC 9421 webhook profile key and MUST include seller_agent_url, delivery_auth, and event_types so the receiver can verify the pending registration before echoing the challenge. New signers use `adcp_use: "request-signing"`; deprecated `webhook-signing` keys remain accepted during the compatibility window. Entries sent with `active: false` may skip only the outbound proof challenge while inactive; sellers MUST still enforce URL parsing, HTTPS, hostname normalization, and reserved-range rejection at write time, and those entries MUST NOT receive fires until reactivated. If proof fails or times out, the seller rejects the account entry with `action: "failed"`, leaves the prior notification_configs[] set unchanged, and reports `VALIDATION_ERROR` (or `INVALID_REQUEST` for malformed URLs) at the failing `notification_configs[j].url` field.\n\n**Cap rationale:** `maxItems: 16` is a practical fan-out cap (governance + buyer ingestion + audit bus + dx team + a few partner hooks). The cap exists to prevent unbounded subscriber arrays in storage and to bound the seller\'s per-event fan-out work. Sellers that hit the cap with legitimate subscribers should surface this on the protocol roadmap rather than work around it.',
            max_length=16,
        ),
    ] = 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 : AccountReference1 | AccountReference2
var billing : BillingParty | None
var billing_entity : BusinessEntity | None
var brand : BrandReference | None
var currency : str | None
var destination_billing_entity : BusinessEntity | None
var model_config
var notification_configs : list[NotificationConfig] | None
var operator : str | None
var operator_identity : OperatorIdentity | None
var operator_unit : OperatorUnit | None
var payment_terms : PaymentTerms | None
var preferred_reporting_protocol : CloudStorageProtocol | None
var reporting_delivery_configs : list[ReportingDeliveryConfiguration] | None
var revision : int | None
var sandbox : bool | None
var timezone : str | None

Inherited members

class Authentication (**data: Any)
Expand source code
class Authentication(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    schemes: Annotated[
        list[Literal['Bearer']],
        Field(
            description='The seller authenticates outbound check_governance calls with the registered Bearer credential. Other shared webhook authentication schemes are not valid for this agent-to-agent call.',
            max_length=1,
            min_length=1,
        ),
    ]
    credentials: Annotated[
        str, Field(description='Authentication credential (e.g., Bearer token).', min_length=32)
    ]

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 credentials : str
var model_config
var schemes : list[typing.Literal['Bearer']]

Inherited members

class Balance (**data: Any)
Expand source code
class Balance(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    available: Annotated[float, Field(ge=0)]
    last_top_up: LastTopUp | 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 available : float
var last_top_up : LastTopUp | None
var model_config

Inherited members

class Credit (**data: Any)
Expand source code
class Credit(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    credit_limit: Annotated[float, Field(ge=0)]
    available_credit: float
    utilization_percent: Annotated[float, Field(ge=0, le=100)] | 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 available_credit : float
var credit_limit : float
var model_config
var utilization_percent : float | None

Inherited members

class CreditLimit (**data: Any)
Expand source code
class CreditLimit(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    amount: Annotated[float, Field(ge=0)]
    currency: Annotated[str, StringConstraints(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 GetAccountFinancialsRequest (**data: Any)
Expand source code
class GetAccountFinancialsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference,
        Field(description='Account to query financials for. Must be an operator-billed account.'),
    ]
    period: Annotated[
        date_range.DateRange | None,
        Field(
            description='Date range for the spend summary. Defaults to the current billing cycle if omitted.'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = 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 : AccountReference1 | AccountReference2
var context : ContextObject | None
var ext : ExtensionObject | None
var model_config
var period : DateRange | None

Inherited members

class GetAccountFinancialsResponse1 (**data: Any)
Expand source code
class GetAccountFinancialsResponse1(AdcpResponse, AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(extra='allow')
    account: account_ref_1.AccountReference
    currency: Annotated[str, StringConstraints(pattern='^[A-Z]{3}$')]
    period: date_range_1.DateRange
    timezone: str
    spend: Spend | None = None
    credit: Credit | None = None
    balance: Balance | None = None
    payment_status: Literal['current', 'past_due', 'suspended'] | None = None
    payment_terms: payment_terms_1.PaymentTerms | None = None
    invoices: list[Invoice] | None = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

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

A consumer holding one can route on task state, pick up an async task_id, split envelope from payload and log uniformly, before knowing which tool answered. Which makes one generic poll-to-terminal loop possible for all 77 tasks, where today each arm has no common type at all.

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 : AccountReference1 | AccountReference2
var balance : Balance | None
var context : ContextObject | None
var credit : Credit | None
var currency : str
var ext : ExtensionObject | None
var invoices : list[Invoice] | None
var model_config
var payment_status : Literal['current', 'past_due', 'suspended'] | None
var payment_terms : PaymentTerms | None
var period : DateRange
var spend : Spend | None
var timezone : str

Inherited members

class GetAccountFinancialsResponse2 (**data: Any)
Expand source code
class GetAccountFinancialsResponse2(AdcpResponse, AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(extra='allow')
    errors: Annotated[list[error_1.Error], Field(min_length=1)]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

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

A consumer holding one can route on task state, pick up an async task_id, split envelope from payload and log uniformly, before knowing which tool answered. Which makes one generic poll-to-terminal loop possible for all 77 tasks, where today each arm has no common type at all.

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 errors : list[Error]
var ext : ExtensionObject | None
var model_config

Inherited members

class Invoice (**data: Any)
Expand source code
class Invoice(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    invoice_id: str
    period: date_range_1.DateRange | None = None
    amount: Annotated[float, Field(ge=0)]
    status: Literal['draft', 'issued', 'paid', 'past_due', 'void']
    due_date: date | None = None
    paid_date: date | 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 amount : float
var due_date : datetime.date | None
var invoice_id : str
var model_config
var paid_date : datetime.date | None
var period : DateRange | None
var status : Literal['draft', 'issued', 'paid', 'past_due', 'void']

Inherited members

class Kind (*args, **kwds)
Expand source code
class Kind(StrEnum):
    seller = 'seller'
    connected_platform = 'connected_platform'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var connected_platform
var seller
class LastTopUp (**data: Any)
Expand source code
class LastTopUp(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    amount: Annotated[float, Field(ge=0)]
    date: date

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 date : datetime.date
var model_config

Inherited members

class ListAccountChangesRequest (**data: Any)
Expand source code
class ListAccountChangesRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference,
        Field(
            description='Account whose change feed to read. The resolved account and returned cursor are bound to the authenticated principal.'
        ),
    ]
    cursor: Annotated[
        str | None,
        Field(
            description='Opaque checkpoint returned by a prior call using the same authenticated principal, authorization scope epoch, account, and normalized filters. Returns changes strictly after the scanned high-water represented by this value. Sellers MUST reject reuse under a different principal, account, or filter set with INVALID_REQUEST at field cursor; an authorization-scope epoch change returns CURSOR_EXPIRED and requires snapshot rebootstrap.',
            max_length=4096,
            min_length=1,
        ),
    ] = None
    starting_position: Annotated[
        StartingPosition | None,
        Field(
            description='Initial position when cursor is absent. Mutually exclusive with cursor; sellers enforce this semantic rule at runtime so the emitted MCP input schema can remain a plain root object. earliest intentionally begins at the oldest retained change. latest returns a checkpoint at the current seller-ingestion high-water and is used before a race-free snapshot bootstrap.'
        ),
    ] = StartingPosition.earliest
    resource_types: Annotated[
        list[ResourceType] | None,
        Field(
            description='Optional exact resource-type filter. The cursor is bound to the normalized filter. Unknown resource types are allowed for forward compatibility.',
            max_length=50,
            min_length=1,
        ),
    ] = None
    max_results: Annotated[
        SchemaInt | None,
        Field(
            description='Maximum changes to return. Sellers still scan through nonmatching records and advance the returned cursor.',
            ge=1,
            le=100,
        ),
    ] = 50
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = 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 : AccountReference1 | AccountReference2
var context : ContextObject | None
var cursor : str | None
var ext : ExtensionObject | None
var max_results : int | None
var model_config
var resource_types : list[ResourceType] | None
var starting_position : StartingPosition | None

Inherited members

class ListAccountChangesResponse (**data: Any)
Expand source code
class ListAccountChangesResponse(AdcpResponse, AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    changes: Annotated[
        list[account_change.AccountChange] | None,
        Field(
            description='Matching changes in oldest-first total account order. Timestamps are descriptive and do not define this order.',
            max_length=100,
        ),
    ] = None
    cursor: Annotated[
        str | None,
        Field(
            description='Opaque checkpoint strictly after the high-water scanned by this page. Always persist this value, including when changes is empty or has_more is false. A filtered empty page still advances past scanned nonmatching records.',
            max_length=4096,
            min_length=1,
        ),
    ] = None
    has_more: Annotated[
        StrictBool | None,
        Field(
            description='True when more retained matching changes were available at generation time. False means caught up to seller ingestion, not necessarily to an unavailable or delayed connected source.'
        ),
    ] = None
    available_since: Annotated[
        AwareDatetime | None,
        Field(
            description='Oldest time for which the seller currently retains change records for this account and caller. The capability guarantees at least 90 days after adoption; pre-adoption history is not fabricated.'
        ),
    ] = None
    generated_at: Annotated[
        AwareDatetime | None,
        Field(
            description='Seller time when this page and its source-coverage watermarks were generated.'
        ),
    ] = None
    source_coverage: Annotated[
        list[SourceCoverageItem] | None,
        Field(
            description='Account-specific feed and connector coverage. Buyers use this to distinguish feed catch-up from upstream freshness. Omission means no additional connected-source coverage is declared.',
            max_length=50,
        ),
    ] = None
    errors: list[error.Error] | None = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None
    status: Status22

    @model_validator(mode='after')
    def _require_schema_required_group(self) -> ListAccountChangesResponse:
        # ``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 (('status', 'changes', 'cursor', 'has_more', 'available_since', 'generated_at'), ('status', 'adcp_error', 'errors'),):
            if all(name in self.model_fields_set for name in group):
                return self
        raise ValueError(
            'ListAccountChangesResponse requires at least one of these field groups: status+changes+cursor+has_more+available_since+generated_at | status+adcp_error+errors'
        )

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

A consumer holding one can route on task state, pick up an async task_id, split envelope from payload and log uniformly, before knowing which tool answered. Which makes one generic poll-to-terminal loop possible for all 77 tasks, where today each arm has no common type at all.

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 available_since : pydantic.types.AwareDatetime | None
var changes : list[AccountChange] | None
var context : ContextObject | None
var cursor : str | None
var errors : list[Error] | None
var ext : ExtensionObject | None
var generated_at : pydantic.types.AwareDatetime | None
var has_more : bool | None
var model_config
var source_coverage : list[SourceCoverageItem] | None
var status : Status22

Inherited members

class ListAccountsRequest (**data: Any)
Expand source code
class ListAccountsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference | None,
        Field(
            description='Optional exact account filter. Use `account_id` to retrieve one known seller/storefront account, or the complete natural key (`brand` + `operator` + optional `operator_unit`, fixed `currency`, buyer-selected account `timezone`, and `sandbox`) for buyer-declared accounts. When present, the seller returns only matching accounts visible to the authenticated caller.'
        ),
    ] = None
    status: Annotated[
        Status | None,
        Field(description='Filter accounts by status. Omit to return accounts in all statuses.'),
    ] = None
    pagination: pagination_request.PaginationRequest | None = None
    sandbox: Annotated[
        StrictBool | None,
        Field(
            description='Filter by sandbox status. true returns only sandbox accounts, false returns only production accounts. Omit to return all accounts. Primarily used with account-id namespaces where sandbox accounts are pre-existing test accounts on the platform.'
        ),
    ] = None
    include_webhook_activity: Annotated[
        StrictBool | None,
        Field(
            description='When true, request recent webhook delivery attempts for each returned account in account.webhook_activity[]. Sellers MAY omit webhook_activity if they do not expose this debug log; when present, three-state semantics match the shared webhook_activity[] contract.'
        ),
    ] = False
    webhook_activity_limit: Annotated[
        SchemaInt | None,
        Field(
            description='Maximum number of webhook_activity[] records to return per account when include_webhook_activity is true.',
            ge=1,
            le=200,
        ),
    ] = 50
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = 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 : AccountReference1 | AccountReference2 | None
var context : ContextObject | None
var ext : ExtensionObject | None
var include_webhook_activity : bool | None
var model_config
var pagination : PaginationRequest | None
var sandbox : bool | None
var status : Status | None
var webhook_activity_limit : int | None

Inherited members

class ListAccountsResponse (**data: Any)
Expand source code
class ListAccountsResponse(AdcpResponse, AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    accounts: Annotated[
        list[account_with_authorization.AccountWithAuthorization],
        Field(
            description='Array of accounts accessible to the authenticated agent. Each entry is the full Account object plus optional authorization. Buyer-declared entries include brand, operator, and any operator_unit, fixed currency, buyer-selected account timezone, and sandbox qualifiers so the natural AccountRef round-trips after a cold start.'
        ),
    ]
    errors: Annotated[
        list[error.Error] | None, Field(description='Task-specific errors and warnings')
    ] = None
    pagination: pagination_response.PaginationResponse | None = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

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

A consumer holding one can route on task state, pick up an async task_id, split envelope from payload and log uniformly, before knowing which tool answered. Which makes one generic poll-to-terminal loop possible for all 77 tasks, where today each arm has no common type at all.

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 accounts : list[AccountWithAuthorization]
var context : ContextObject | None
var errors : list[Error] | None
var ext : ExtensionObject | None
var model_config
var pagination : PaginationResponse | None

Inherited members

class ReportUsageRequest (**data: Any)
Expand source code
class ReportUsageRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated unique key for this request. If a request with the same key has already been accepted, the server returns the original response without re-processing. MUST be unique per (seller, request) pair to prevent cross-seller correlation. Use a fresh UUID v4 for each request. Prevents duplicate billing on retries.'
        ),
    ]
    reporting_period: Annotated[
        datetime_range.DatetimeRange,
        Field(
            description='The time range covered by this usage report. Applies to all records in the request.'
        ),
    ]
    usage: Annotated[
        list[UsageItem],
        Field(
            description='One or more usage records. Each record is self-contained: it carries its own account, allowing a single request to span multiple accounts.',
            min_length=1,
        ),
    ]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = 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 context : ContextObject | None
var ext : ExtensionObject | None
var idempotency_key : str
var model_config
var reporting_period : DatetimeRange
var usage : list[UsageItem]

Inherited members

class ReportUsageResponse (**data: Any)
Expand source code
class ReportUsageResponse(AdcpResponse, AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    accepted: Annotated[
        SchemaInt, Field(description='Number of usage records successfully stored.', ge=0)
    ]
    errors: Annotated[
        list[error.Error] | None,
        Field(
            description="Validation errors for individual records. The field property identifies which record failed (e.g., 'usage[1].pricing_option_id')."
        ),
    ] = None
    sandbox: Annotated[
        StrictBool | None,
        Field(description='When true, the account is a sandbox account and no billing occurred.'),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

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

A consumer holding one can route on task state, pick up an async task_id, split envelope from payload and log uniformly, before knowing which tool answered. Which makes one generic poll-to-terminal loop possible for all 77 tasks, where today each arm has no common type at all.

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 accepted : int
var context : ContextObject | None
var errors : list[Error] | None
var ext : ExtensionObject | None
var model_config
var sandbox : bool | None

Inherited members

class Setup (**data: Any)
Expand source code
class Setup(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    url: AnyUrl | None = None
    message: str
    expires_at: AwareDatetime | 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 expires_at : pydantic.types.AwareDatetime | None
var message : str
var model_config
var url : pydantic.networks.AnyUrl | None

Inherited members

class SourceCoverageItem (**data: Any)
Expand source code
class SourceCoverageItem(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    source_id: Annotated[
        str, Field(description='Opaque seller or connection reference.', max_length=255)
    ]
    kind: Kind
    status: Annotated[
        Status,
        Field(
            description='Connector freshness classification. For connected_platform, current means last_successful_sync_at is no older than stale_after_seconds at generated_at and the seller knows of no ingestion gap; delayed means that threshold is exceeded or a gap is known.'
        ),
    ]
    coverage_start: Annotated[
        AwareDatetime | None,
        Field(
            description='Earliest upstream time covered by this source after connection or retention limits.'
        ),
    ] = None
    observed_through: Annotated[
        AwareDatetime | None,
        Field(description='Latest upstream point the seller has successfully observed.'),
    ] = None
    last_successful_sync_at: AwareDatetime | None = None
    stale_after_seconds: Annotated[
        SchemaInt | None,
        Field(
            description='Maximum age of last_successful_sync_at at generated_at for this connected source to self-classify as current. Required by the protocol contract whenever a connected source reports current.',
            ge=1,
            le=2592000,
        ),
    ] = None
    resource_types: Annotated[list[ResourceType], Field(max_length=50)]

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 coverage_start : pydantic.types.AwareDatetime | None
var kind : Kind
var last_successful_sync_at : pydantic.types.AwareDatetime | None
var model_config
var observed_through : pydantic.types.AwareDatetime | None
var resource_types : list[ResourceType]
var source_id : str
var stale_after_seconds : int | None
var status : Status

Inherited members

class Spend (**data: Any)
Expand source code
class Spend(AdcpVersionEnvelope):
    model_config = ConfigDict(extra='allow')
    total_spend: Annotated[float, Field(ge=0)]
    media_buy_count: Annotated[int, Field(ge=0)] | 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 media_buy_count : int | None
var model_config
var total_spend : float

Inherited members

class StartingPosition (*args, **kwds)
Expand source code
class StartingPosition(StrEnum):
    earliest = 'earliest'
    latest = 'latest'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var earliest
var latest
class Status22 (*args, **kwds)
Expand source code
class Status22(StrEnum):
    completed = 'completed'
    failed = 'failed'

Enum where members are also (and must be) strings

Ancestors

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

Class variables

var completed
var failed
class SyncAccountsRequest (**data: Any)
Expand source code
class SyncAccountsRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated unique key for at-most-once execution. Natural per-account upsert keys handle resource-level dedup, but the envelope triggers onboarding webhooks, billing setup, and audit events — this key prevents those side effects from firing twice on retry. MUST be unique per (seller, request) pair. Use a fresh UUID v4 for each request.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ]
    accounts: Annotated[
        list[Accounts | Accounts1],
        Field(
            description='Per-account sync entries. Each entry uses one of two key shapes: the `account` field (AccountRef) for settings-update mode, or the flat `brand` + `operator` + `billing` trio for provisioning mode. An operator_identity settings update MUST carry the latest account revision.',
            max_length=1000,
        ),
    ]
    delete_missing: Annotated[
        StrictBool | None,
        Field(
            description='When true, accounts previously synced by this agent but not included in this request will be deactivated. Scoped to the authenticated agent — does not affect accounts managed by other agents. Use with caution.'
        ),
    ] = False
    dry_run: Annotated[
        StrictBool | None,
        Field(
            description='When true, preview what would change without applying. Returns what would be created/updated/deactivated.'
        ),
    ] = False
    push_notification_config: Annotated[
        push_notification_config_1.PushNotificationConfig | None,
        Field(
            description='Webhook for async notifications when account status changes (e.g., pending_approval transitions to active).'
        ),
    ] = None
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = 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 accounts : list[Accounts | Accounts1]
var context : ContextObject | None
var delete_missing : bool | None
var dry_run : bool | None
var ext : ExtensionObject | None
var idempotency_key : str
var model_config
var push_notification_config : PushNotificationConfig | None

Inherited members

class SyncAccountsResponse1 (**data: Any)
Expand source code
class SyncAccountsResponse1(AdcpResponse, AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(extra='allow')
    dry_run: bool | None = None
    accounts: list[Account]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

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

A consumer holding one can route on task state, pick up an async task_id, split envelope from payload and log uniformly, before knowing which tool answered. Which makes one generic poll-to-terminal loop possible for all 77 tasks, where today each arm has no common type at all.

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 accounts : list[Account]
var context : ContextObject | None
var dry_run : bool | None
var ext : ExtensionObject | None
var model_config

Inherited members

class SyncAccountsResponse2 (**data: Any)
Expand source code
class SyncAccountsResponse2(AdcpResponse, AdcpVersionEnvelope, ProtocolEnvelope):
    model_config = ConfigDict(extra='allow')
    errors: Annotated[list[error_1.Error], Field(min_length=1)]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = None

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

A consumer holding one can route on task state, pick up an async task_id, split envelope from payload and log uniformly, before knowing which tool answered. Which makes one generic poll-to-terminal loop possible for all 77 tasks, where today each arm has no common type at all.

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 errors : list[Error]
var ext : ExtensionObject | None
var model_config

Inherited members

class SyncGovernanceRequest (**data: Any)
Expand source code
class SyncGovernanceRequest(AdcpRequest, AdcpVersionEnvelope):
    model_config = ConfigDict(
        extra='allow',
    )
    idempotency_key: Annotated[
        str,
        Field(
            description='Client-generated unique key for at-most-once execution. `account` gives resource-level dedup, but governance changes emit audit events and can trigger reapproval flows — this key prevents those side effects from firing twice on retry. MUST be unique per (seller, request) pair. Use a fresh UUID v4 for each request.',
            max_length=255,
            min_length=16,
            pattern='^[A-Za-z0-9_.:-]{16,255}$',
        ),
    ]
    accounts: Annotated[
        list[Account],
        Field(
            description='Per-account governance agent configuration. Each entry pairs an account reference with the governance agents for that account.',
            max_length=100,
            min_length=1,
        ),
    ]
    context: context_1.ContextObject | None = None
    ext: ext_1.ExtensionObject | None = 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 accounts : list[Account]
var context : ContextObject | None
var ext : ExtensionObject | None
var idempotency_key : str
var model_config

Inherited members

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

    @classmethod
    def _response_arm_models(cls) -> tuple[type[SyncGovernanceResponse], ...]:
        return (
            SyncGovernanceResponse1,
            SyncGovernanceResponse2,
        )

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 SyncGovernanceResponse1 (**data: Any)
Expand source code
class SyncGovernanceResponse1(SyncGovernanceResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    accounts: Annotated[list[Account], Field(description='Per-account sync results')]
    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 accounts : list[Account]
var context : ContextObject | None
var ext : ExtensionObject | None
var model_config

Inherited members

class SyncGovernanceResponse2 (**data: Any)
Expand source code
class SyncGovernanceResponse2(SyncGovernanceResponse):
    model_config = ConfigDict(
        extra='allow',
    )
    errors: Annotated[
        list[error.Error],
        Field(
            description='Operation-level errors (e.g., authentication failure, service unavailable)',
            min_length=1,
        ),
    ]
    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 errors : list[Error]
var ext : ExtensionObject | None
var model_config

Inherited members

class UsageItem (**data: Any)
Expand source code
class UsageItem(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    account: Annotated[
        account_ref.AccountReference, Field(description='Account for this usage record.')
    ]
    media_buy_id: Annotated[
        str | None,
        Field(
            description='Seller-assigned media buy identifier. Links this usage record to a specific media buy.'
        ),
    ] = None
    vendor_cost: Annotated[
        StrictFloat,
        Field(
            description='Amount owed to the vendor for this record, denominated in currency.',
            ge=0.0,
        ),
    ]
    currency: Annotated[str, Field(description='ISO 4217 currency code.', pattern='^[A-Z]{3}$')]
    pricing_option_id: Annotated[
        str | None,
        Field(
            description="Pricing option identifier from the vendor's discovery response (e.g., get_signals, list_content_standards). The vendor uses this to verify the correct rate was applied."
        ),
    ] = None
    impressions: Annotated[
        SchemaInt | None,
        Field(description='Impressions delivered using this vendor service.', ge=0),
    ] = None
    media_spend: Annotated[
        StrictFloat | None,
        Field(
            description='Media spend in currency for the period. Required when a percent_of_media pricing model was used, so the vendor can verify the applied rate.',
            ge=0.0,
        ),
    ] = None
    conversions: Annotated[
        StrictFloat | None,
        Field(
            description='Number of attributed conversion events for the reporting period. Optional analytics context for revenue_share reconciliation.',
            ge=0.0,
        ),
    ] = None
    conversion_value: Annotated[
        StrictFloat | None,
        Field(
            description='Total monetary value of attributed conversions for the reporting period, in currency. Optional analytics context for revenue_share reconciliation; it is not the billing basis.',
            ge=0.0,
        ),
    ] = None
    commissionable_value: Annotated[
        StrictFloat | None,
        Field(
            description='Settled attributed value eligible for commission, in currency. Required when pricing_option_id selects a revenue_share option. The receiver verifies vendor_cost = round_currency(commissionable_value × the selected commission_rate).',
            ge=0.0,
        ),
    ] = None
    signal_agent_segment_id: Annotated[
        str | None,
        Field(description='Signal identifier from get_signals. Required for signals agents.'),
    ] = None
    standards_id: Annotated[
        str | None,
        Field(
            description='Content standards configuration identifier. Required for governance agents.'
        ),
    ] = None
    rights_id: Annotated[
        str | None,
        Field(
            description='Rights grant identifier from acquire_rights. Required for brand/rights agents. Links usage records to specific rights grants for cap tracking, billing verification, and overage calculation.'
        ),
    ] = None
    creative_id: Annotated[
        str | None,
        Field(
            description='Creative identifier from build_creative or list_creatives. Required for creative agents. Links usage records to specific creatives for billing verification.'
        ),
    ] = None
    build_variant_id: Annotated[
        str | None,
        Field(
            description='Optional. When the reported creative_id was promoted from a specific build_creative variant leaf but the creative_id differs from the source build_variant_id, carry that source build_variant_id so billing reconciliation can link this usage record back to the exact produced leaf for audit (pricing_option_id alone is not unique across leaves). On the canonical path where creative_id is the build_variant_id, omit this field and use creative_id as the join key. Omit for creatives with no build-variant lineage.'
        ),
    ] = None
    property_list_id: Annotated[
        str | None,
        Field(
            description='Property list identifier from list_property_lists. Required for property list agents. Links usage records to specific property lists for billing verification.'
        ),
    ] = None
    final: Annotated[
        StrictBool | None,
        Field(
            description="Whether this usage record represents the reporter's final, billing-authoritative numbers for the reporting period. **Absent means unknown** — the reporter has not declared finality on this record. Set `true` only when the reporter has actually settled the numbers (e.g., 3PAS month-end close after SIVT scrubbing, conversion dedup, and view-through windows have closed; vendor file post-C7 for broadcast). Set `false` when pushing preliminary measurements (daily pacing pushes, intra-period progress) that are still settling. Receivers MUST NOT invoice on `final: false` records, and MUST NOT invoice on records where `final` is absent for buys whose `measurement_terms.billing_measurement` names this reporter as authoritative — request a final record first. Receivers MAY invoice on absent for buys with no `measurement_terms.billing_measurement` (3.0-style usage where the receiver treats reports as authoritative on receipt) and for non-media-buy variants (signals, governance, creative, brand — domains with no provisional state concept). When the same `(account, media_buy_id, reporting_period)` is later reported with `final: true`, that record supersedes any prior records for the period."
        ),
    ] = None
    finalized_at: Annotated[
        AwareDatetime | None,
        Field(
            description="ISO 8601 timestamp at which the reporter considered these numbers final. Present only when `final: true`. Anchors any deadline declared in the buy's `measurement_terms.billing_measurement.finalization_deadline_hours`."
        ),
    ] = None
    measurement_window: Annotated[
        str | None,
        Field(
            description="Which measurement window this record represents, referencing a window_id from the product's reporting_capabilities.measurement_windows or from `measurement_terms.billing_measurement.measurement_window`. Examples: 'c7' for broadcast TV, 'post_sivt' for digital post-IVT, 'downloads_30d' for podcast. When absent, the record is not windowed (standard digital reporting). When the buy's `measurement_terms.billing_measurement.measurement_window` is set, reporters SHOULD include `measurement_window` so the receiver can reconcile against the correct stage.",
            examples=['live', 'c3', 'c7', 'post_ivt', 'post_sivt', 'downloads_30d'],
            max_length=50,
        ),
    ] = 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 : AccountReference1 | AccountReference2
var build_variant_id : str | None
var commissionable_value : float | None
var conversion_value : float | None
var conversions : float | None
var creative_id : str | None
var currency : str
var final : bool | None
var finalized_at : pydantic.types.AwareDatetime | None
var impressions : int | None
var measurement_window : str | None
var media_buy_id : str | None
var media_spend : float | None
var model_config
var pricing_option_id : str | None
var property_list_id : str | None
var rights_id : str | None
var signal_agent_segment_id : str | None
var standards_id : str | None
var vendor_cost : float

Inherited members